mirror of
https://github.com/alibaba/druid.git
synced 2023-03-04 19:17:16 +00:00
improved sql parser.
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user