improved sql parser.

This commit is contained in:
wenshao
2017-09-11 16:41:40 +08:00
parent 20c3f9304e
commit a9474ac6d0
33 changed files with 536 additions and 150 deletions
@@ -15,16 +15,20 @@
*/
package com.alibaba.druid.sql.parser;
import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;
import com.alibaba.druid.sql.dialect.db2.ast.stmt.DB2SelectQueryBlock;
import com.alibaba.druid.sql.dialect.db2.parser.DB2ExprParser;
import com.alibaba.druid.sql.dialect.db2.parser.DB2Lexer;
import com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser;
import com.alibaba.druid.sql.dialect.h2.parser.H2StatementParser;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock;
import com.alibaba.druid.sql.dialect.mysql.parser.MySqlExprParser;
import com.alibaba.druid.sql.dialect.mysql.parser.MySqlLexer;
import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;
import com.alibaba.druid.sql.dialect.odps.parser.OdpsExprParser;
import com.alibaba.druid.sql.dialect.odps.parser.OdpsLexer;
import com.alibaba.druid.sql.dialect.odps.parser.OdpsStatementParser;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectQueryBlock;
import com.alibaba.druid.sql.dialect.oracle.parser.OracleExprParser;
import com.alibaba.druid.sql.dialect.oracle.parser.OracleLexer;
import com.alibaba.druid.sql.dialect.oracle.parser.OracleStatementParser;
@@ -173,4 +177,32 @@ public class SQLParserUtils {
return new Lexer(sql);
}
public static SQLSelectQueryBlock createSelectQueryBlock(String dbType) {
if (JdbcConstants.MYSQL.equals(dbType)) {
return new MySqlSelectQueryBlock();
}
if (JdbcConstants.ORACLE.equals(dbType)) {
return new OracleSelectQueryBlock();
}
if (JdbcConstants.DB2.equals(dbType)) {
return new DB2SelectQueryBlock();
}
if (JdbcConstants.POSTGRESQL.equals(dbType)) {
return new DB2SelectQueryBlock();
}
if (JdbcConstants.ODPS.equals(dbType)) {
return new DB2SelectQueryBlock();
}
if (JdbcConstants.SQL_SERVER.equals(dbType)) {
return new DB2SelectQueryBlock();
}
return new SQLSelectQueryBlock();
}
}
@@ -0,0 +1,78 @@
/*
* Copyright 1999-2017 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.druid.sql.parser;
import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class SQLSelectListCache {
private final String dbType;
private List<String> sqlCache = new ArrayList<String>();
private List<SQLSelectQueryBlock> queryBlockCache = new ArrayList<SQLSelectQueryBlock>();
private List<String> printSqlList = new ArrayList<String>();
public SQLSelectListCache(String dbType) {
this.dbType = dbType;
}
public void add(String select) {
if (select == null || select.length() == 0) {
return;
}
SQLSelectParser selectParser = SQLParserUtils.createSQLStatementParser(select, dbType)
.createSQLSelectParser();
SQLSelectQueryBlock queryBlock = SQLParserUtils.createSelectQueryBlock(dbType);
selectParser.accept(Token.SELECT);
selectParser.parseSelectList(queryBlock);
selectParser.accept(Token.FROM);
selectParser.accept(Token.EOF);
sqlCache.add(select.substring(6));
queryBlockCache.add(queryBlock);
printSqlList.add(queryBlock.toString());
}
public boolean match(Lexer lexer, SQLSelectQueryBlock queryBlock) {
if (lexer.token != Token.SELECT) {
return false;
}
int pos = lexer.pos;
String text = lexer.text;
for (int i = 0; i < sqlCache.size(); i++) {
String block = sqlCache.get(i);
if (text.startsWith(block, pos)) {
//SQLSelectQueryBlock queryBlockCached = queryBlockCache.get(i);
// queryBlockCached.cloneSelectListTo(queryBlock);
String printSql = printSqlList.get(i);
queryBlock.setCachedSelectList(printSql);
int len = pos + block.length();
lexer.reset(len, text.charAt(len), Token.FROM);
return true;
}
}
return false;
}
}
@@ -27,7 +27,8 @@ import com.alibaba.druid.util.FnvHash;
import com.alibaba.druid.util.JdbcConstants;
public class SQLSelectParser extends SQLParser {
protected SQLExprParser exprParser;
protected SQLExprParser exprParser;
protected SQLSelectListCache selectListCache;
public SQLSelectParser(String sql){
super(sql);
@@ -38,8 +39,13 @@ public class SQLSelectParser extends SQLParser {
}
public SQLSelectParser(SQLExprParser exprParser){
this(exprParser, null);
}
public SQLSelectParser(SQLExprParser exprParser, SQLSelectListCache selectListCache){
super(exprParser.getLexer(), exprParser.getDbType());
this.exprParser = exprParser;
this.selectListCache = selectListCache;
}
public SQLSelect select() {
@@ -29,9 +29,10 @@ import com.alibaba.druid.util.JdbcConstants;
public class SQLStatementParser extends SQLParser {
protected SQLExprParser exprParser;
protected boolean parseCompleteValues = true;
protected int parseValuesSize = 3;
protected SQLExprParser exprParser;
protected boolean parseCompleteValues = true;
protected int parseValuesSize = 3;
protected SQLSelectListCache selectListCache = null;
public SQLStatementParser(String sql){
this(sql, null);
@@ -83,6 +84,20 @@ public class SQLStatementParser extends SQLParser {
}
public void parseStatementList(List<SQLStatement> statementList, int max, SQLObject parent) {
if ("select @@session.tx_read_only".equals(lexer.text)
&& lexer.token == Token.SELECT) {
SQLSelect select = new SQLSelect();
MySqlSelectQueryBlock queryBlock = new MySqlSelectQueryBlock();
queryBlock.addSelectItem(new SQLPropertyExpr(new SQLVariantRefExpr("@@session"), "tx_read_only"));
select.setQuery(queryBlock);
SQLSelectStatement stmt = new SQLSelectStatement(select);
statementList.add(stmt);
lexer.reset(29, '\u001A', Token.EOF);
return;
}
for (;;) {
if (max != -1) {
if (statementList.size() >= max) {
@@ -2150,7 +2165,7 @@ public class SQLStatementParser extends SQLParser {
}
public SQLSelectParser createSQLSelectParser() {
return new SQLSelectParser(this.exprParser);
return new SQLSelectParser(this.exprParser, selectListCache);
}
public SQLUpdateStatement parseUpdateStatement() {
@@ -2959,4 +2974,12 @@ public class SQLStatementParser extends SQLParser {
}
}
}
public SQLSelectListCache getSelectListCache() {
return selectListCache;
}
public void setSelectListCache(SQLSelectListCache selectListCache) {
this.selectListCache = selectListCache;
}
}