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
@@ -24,6 +24,7 @@ import com.alibaba.druid.sql.ast.statement.*;
import com.alibaba.druid.sql.dialect.db2.visitor.DB2OutputVisitor;
import com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor;
import com.alibaba.druid.sql.dialect.h2.visitor.H2OutputVisitor;
import com.alibaba.druid.sql.dialect.h2.visitor.H2SchemaStatVisitor;
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlOutputVisitor;
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;
import com.alibaba.druid.sql.dialect.odps.visitor.OdpsOutputVisitor;
@@ -402,8 +403,7 @@ public class SQLUtils {
}
if (JdbcConstants.MYSQL.equals(dbType) || //
JdbcConstants.MARIADB.equals(dbType) || //
JdbcConstants.H2.equals(dbType)) {
JdbcConstants.MARIADB.equals(dbType)) {
return new MySqlSchemaStatVisitor();
}
@@ -423,6 +423,10 @@ public class SQLUtils {
return new OdpsSchemaStatVisitor();
}
if (JdbcConstants.H2.equals(dbType)) {
return new H2SchemaStatVisitor();
}
return new SchemaStatVisitor();
}
@@ -1,3 +1,18 @@
/*
* 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.ast.statement;
import com.alibaba.druid.sql.ast.SQLExpr;
@@ -25,36 +25,36 @@ import com.alibaba.druid.sql.visitor.SQLASTVisitor;
import com.alibaba.druid.util.FnvHash;
public class SQLSelectQueryBlock extends SQLObjectImpl implements SQLSelectQuery, SQLReplaceable {
private boolean bracket = false;
protected int distionOption;
protected final List<SQLSelectItem> selectList = new ArrayList<SQLSelectItem>();
private boolean bracket = false;
protected int distionOption;
protected final List<SQLSelectItem> selectList = new ArrayList<SQLSelectItem>();
protected SQLTableSource from;
protected SQLExprTableSource into;
protected SQLExpr where;
protected SQLTableSource from;
protected SQLExprTableSource into;
protected SQLExpr where;
// for oracle & oceanbase
protected SQLExpr startWith;
protected SQLExpr connectBy;
protected boolean prior = false;
protected boolean noCycle = false;
protected SQLOrderBy orderBySiblings;
protected SQLExpr startWith;
protected SQLExpr connectBy;
protected boolean prior = false;
protected boolean noCycle = false;
protected SQLOrderBy orderBySiblings;
protected SQLSelectGroupByClause groupBy;
protected SQLOrderBy orderBy;
protected boolean parenthesized = false;
protected boolean forUpdate = false;
protected boolean noWait = false;
protected SQLExpr waitTime;
protected SQLLimit limit;
protected SQLSelectGroupByClause groupBy;
protected SQLOrderBy orderBy;
protected boolean parenthesized = false;
protected boolean forUpdate = false;
protected boolean noWait = false;
protected SQLExpr waitTime;
protected SQLLimit limit;
// for oracle
protected List<SQLExpr> forUpdateOf;
protected List<SQLExpr> distributeBy;
protected List<SQLExpr> forUpdateOf;
protected List<SQLExpr> distributeBy;
protected List<SQLSelectOrderByItem> sortBy;
protected String cachedSelectList; // optimized for SelectListCache
public SQLSelectQueryBlock(){
}
@@ -397,6 +397,15 @@ public class SQLSelectQueryBlock extends SQLObjectImpl implements SQLSelectQuery
return forUpdateOf.size();
}
public void cloneSelectListTo(SQLSelectQueryBlock x) {
x.distionOption = distionOption;
for (SQLSelectItem item : this.selectList) {
SQLSelectItem item2 = item.clone();
item2.setParent(x);
x.selectList.add(item2);
}
}
public void cloneTo(SQLSelectQueryBlock x) {
x.distionOption = distionOption;
@@ -580,4 +589,12 @@ public class SQLSelectQueryBlock extends SQLObjectImpl implements SQLSelectQuery
setLimit(limit);
}
public String getCachedSelectList() {
return cachedSelectList;
}
public void setCachedSelectList(String cachedSelectList) {
this.cachedSelectList = cachedSelectList;
}
}
@@ -21,10 +21,7 @@ import com.alibaba.druid.sql.ast.SQLSetQuantifier;
import com.alibaba.druid.sql.ast.statement.SQLSelectQuery;
import com.alibaba.druid.sql.dialect.db2.ast.stmt.DB2SelectQueryBlock;
import com.alibaba.druid.sql.dialect.db2.ast.stmt.DB2SelectQueryBlock.Isolation;
import com.alibaba.druid.sql.parser.ParserException;
import com.alibaba.druid.sql.parser.SQLExprParser;
import com.alibaba.druid.sql.parser.SQLSelectParser;
import com.alibaba.druid.sql.parser.Token;
import com.alibaba.druid.sql.parser.*;
public class DB2SelectParser extends SQLSelectParser {
@@ -32,6 +29,10 @@ public class DB2SelectParser extends SQLSelectParser {
super(exprParser);
}
public DB2SelectParser(SQLExprParser exprParser, SQLSelectListCache selectListCache){
super(exprParser, selectListCache);
}
public DB2SelectParser(String sql){
this(new DB2ExprParser(sql));
}
@@ -39,7 +39,7 @@ public class DB2StatementParser extends SQLStatementParser {
}
public DB2SelectParser createSQLSelectParser() {
return new DB2SelectParser(this.exprParser);
return new DB2SelectParser(this.exprParser, selectListCache);
}
public boolean parseStatementListDialect(List<SQLStatement> statementList) {
@@ -1,33 +0,0 @@
package com.alibaba.druid.sql.dialect.h2.ast;
import com.alibaba.druid.sql.ast.SQLName;
import com.alibaba.druid.sql.ast.SQLStatementImpl;
import com.alibaba.druid.sql.ast.statement.SQLExprTableSource;
import java.util.ArrayList;
import java.util.List;
public class H2MergeStatement extends SQLStatementImpl {
private SQLExprTableSource table;
private final List<SQLName> keyColumns = new ArrayList<SQLName>();
public SQLExprTableSource getTable() {
return table;
}
public void setTable(SQLName table) {
this.setTable(new SQLExprTableSource(table));
}
public void setTable(SQLExprTableSource table) {
if (table != null) {
table.setParent(this);
}
this.table = table;
}
public List<SQLName> getKeyColumns() {
return keyColumns;
}
}
@@ -1,3 +1,18 @@
/*
* 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.dialect.h2.parser;
import com.alibaba.druid.sql.parser.Lexer;
@@ -1,3 +1,18 @@
/*
* 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.dialect.h2.parser;
import com.alibaba.druid.sql.parser.Keywords;
@@ -1,6 +1,22 @@
/*
* 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.dialect.h2.parser;
import com.alibaba.druid.sql.parser.SQLExprParser;
import com.alibaba.druid.sql.parser.SQLSelectListCache;
import com.alibaba.druid.sql.parser.SQLSelectParser;
public class H2SelectParser extends SQLSelectParser {
@@ -9,6 +25,10 @@ public class H2SelectParser extends SQLSelectParser {
super(exprParser);
}
public H2SelectParser(SQLExprParser exprParser, SQLSelectListCache selectListCache){
super(exprParser, selectListCache);
}
public H2SelectParser(String sql){
this(new H2ExprParser(sql));
}
@@ -1,3 +1,18 @@
/*
* 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.dialect.h2.parser;
import com.alibaba.druid.sql.ast.SQLName;
@@ -6,7 +21,6 @@ import com.alibaba.druid.sql.ast.expr.SQLQueryExpr;
import com.alibaba.druid.sql.ast.statement.SQLInsertStatement;
import com.alibaba.druid.sql.ast.statement.SQLReplaceStatement;
import com.alibaba.druid.sql.ast.statement.SQLSelect;
import com.alibaba.druid.sql.dialect.h2.ast.H2MergeStatement;
import com.alibaba.druid.sql.parser.*;
import com.alibaba.druid.util.FnvHash;
import com.alibaba.druid.util.JdbcConstants;
@@ -25,7 +39,7 @@ public class H2StatementParser extends SQLStatementParser {
}
public H2SelectParser createSQLSelectParser() {
return new H2SelectParser(this.exprParser);
return new H2SelectParser(this.exprParser, selectListCache);
}
public SQLStatement parseMerge() {
@@ -1,3 +1,18 @@
/*
* 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.dialect.h2.visitor;
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
@@ -1,3 +1,18 @@
/*
* 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.dialect.h2.visitor;
import com.alibaba.druid.sql.visitor.SQLASTVisitorAdapter;
@@ -1,3 +1,18 @@
/*
* 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.dialect.h2.visitor;
import com.alibaba.druid.sql.ast.expr.*;
@@ -1,3 +1,18 @@
/*
* 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.dialect.h2.visitor;
import com.alibaba.druid.sql.ast.SQLExpr;
@@ -1,6 +1,21 @@
/*
* 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.dialect.h2.visitor;
import com.alibaba.druid.sql.visitor.SchemaStatVisitor;
public class H2SchemaStatVisitor extends SchemaStatVisitor implements H2ASTVisitor {
}
}
@@ -20,6 +20,7 @@ import java.util.List;
import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.*;
import com.alibaba.druid.sql.ast.statement.SQLSelectItem;
import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;
import com.alibaba.druid.sql.dialect.mysql.ast.MySqlObject;
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;
@@ -28,21 +29,16 @@ import com.alibaba.druid.sql.visitor.SQLASTVisitor;
import oracle.sql.SQLUtil;
public class MySqlSelectQueryBlock extends SQLSelectQueryBlock implements MySqlObject {
private boolean hignPriority;
private boolean straightJoin;
private boolean smallResult;
private boolean bigResult;
private boolean bufferResult;
private Boolean cache;
private boolean calcFoundRows;
private SQLName procedureName;
private List<SQLExpr> procedureArgumentList;
private boolean lockInShareMode = false;
private boolean lockInShareMode;
private List<SQLCommentHint> hints;
public MySqlSelectQueryBlock(){
@@ -31,10 +31,7 @@ import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlOutFileExpr;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlUpdateStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlUpdateTableSource;
import com.alibaba.druid.sql.parser.ParserException;
import com.alibaba.druid.sql.parser.SQLExprParser;
import com.alibaba.druid.sql.parser.SQLSelectParser;
import com.alibaba.druid.sql.parser.Token;
import com.alibaba.druid.sql.parser.*;
import com.alibaba.druid.util.FnvHash;
import java.util.List;
@@ -48,6 +45,10 @@ public class MySqlSelectParser extends SQLSelectParser {
super(exprParser);
}
public MySqlSelectParser(SQLExprParser exprParser, SQLSelectListCache selectListCache){
super(exprParser, selectListCache);
}
public MySqlSelectParser(String sql){
this(new MySqlExprParser(sql));
}
@@ -93,6 +94,12 @@ public class MySqlSelectParser extends SQLSelectParser {
queryBlock.addBeforeComment(lexer.readAndResetComments());
}
if (lexer.token() == Token.SELECT) {
if (selectListCache != null) {
selectListCache.match(lexer, queryBlock);
}
}
if (lexer.token() == Token.SELECT) {
lexer.nextToken();
@@ -108,7 +108,7 @@ public class MySqlStatementParser extends SQLStatementParser {
}
public SQLStatement parseSelect() {
MySqlSelectParser selectParser = new MySqlSelectParser(this.exprParser);
MySqlSelectParser selectParser = createSQLSelectParser();
SQLSelect select = selectParser.select();
@@ -120,7 +120,7 @@ public class MySqlStatementParser extends SQLStatementParser {
}
public SQLUpdateStatement parseUpdateStatement() {
return new MySqlSelectParser(this.exprParser).parseUpdateStatment();
return new MySqlSelectParser(this.exprParser, selectListCache).parseUpdateStatment();
}
protected MySqlUpdateStatement createUpdateStatement() {
@@ -2262,8 +2262,8 @@ public class MySqlStatementParser extends SQLStatementParser {
return insertStatement;
}
public SQLSelectParser createSQLSelectParser() {
return new MySqlSelectParser(this.exprParser);
public MySqlSelectParser createSQLSelectParser() {
return new MySqlSelectParser(this.exprParser, selectListCache);
}
public SQLStatement parseSet() {
@@ -116,62 +116,68 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV
printlnComments(x.getBeforeCommentsDirect());
}
print0(ucase ? "SELECT " : "select ");
String cachedSelectList = x.getCachedSelectList();
for (int i = 0, size = x.getHintsSize(); i < size; ++i) {
SQLCommentHint hint = x.getHints().get(i);
hint.accept(this);
print(' ');
}
if (cachedSelectList != null) {
print0(cachedSelectList);
} else {
print0(ucase ? "SELECT " : "select ");
final int distionOption = x.getDistionOption();
if (SQLSetQuantifier.ALL == distionOption) {
print0(ucase ? "ALL " : "all ");
} else if (SQLSetQuantifier.DISTINCT == distionOption) {
print0(ucase ? "DISTINCT " : "distinct ");
} else if (SQLSetQuantifier.DISTINCTROW == distionOption) {
print0(ucase ? "DISTINCTROW " : "distinctrow ");
}
if (x.isHignPriority()) {
print0(ucase ? "HIGH_PRIORITY " : "high_priority ");
}
if (x.isStraightJoin()) {
print0(ucase ? "STRAIGHT_JOIN " : "straight_join ");
}
if (x.isSmallResult()) {
print0(ucase ? "SQL_SMALL_RESULT " : "sql_small_result ");
}
if (x.isBigResult()) {
print0(ucase ? "SQL_BIG_RESULT " : "sql_big_result ");
}
if (x.isBufferResult()) {
print0(ucase ? "SQL_BUFFER_RESULT " : "sql_buffer_result ");
}
if (x.getCache() != null) {
if (x.getCache().booleanValue()) {
print0(ucase ? "SQL_CACHE " : "sql_cache ");
} else {
print0(ucase ? "SQL_NO_CACHE " : "sql_no_cache ");
for (int i = 0, size = x.getHintsSize(); i < size; ++i) {
SQLCommentHint hint = x.getHints().get(i);
hint.accept(this);
print(' ');
}
}
if (x.isCalcFoundRows()) {
print0(ucase ? "SQL_CALC_FOUND_ROWS " : "sql_calc_found_rows ");
}
final int distionOption = x.getDistionOption();
if (SQLSetQuantifier.ALL == distionOption) {
print0(ucase ? "ALL " : "all ");
} else if (SQLSetQuantifier.DISTINCT == distionOption) {
print0(ucase ? "DISTINCT " : "distinct ");
} else if (SQLSetQuantifier.DISTINCTROW == distionOption) {
print0(ucase ? "DISTINCTROW " : "distinctrow ");
}
printSelectList(x.getSelectList());
if (x.isHignPriority()) {
print0(ucase ? "HIGH_PRIORITY " : "high_priority ");
}
SQLExprTableSource into = x.getInto();
if (into != null) {
println();
print0(ucase ? "INTO " : "into ");
printTableSource(into);
if (x.isStraightJoin()) {
print0(ucase ? "STRAIGHT_JOIN " : "straight_join ");
}
if (x.isSmallResult()) {
print0(ucase ? "SQL_SMALL_RESULT " : "sql_small_result ");
}
if (x.isBigResult()) {
print0(ucase ? "SQL_BIG_RESULT " : "sql_big_result ");
}
if (x.isBufferResult()) {
print0(ucase ? "SQL_BUFFER_RESULT " : "sql_buffer_result ");
}
if (x.getCache() != null) {
if (x.getCache().booleanValue()) {
print0(ucase ? "SQL_CACHE " : "sql_cache ");
} else {
print0(ucase ? "SQL_NO_CACHE " : "sql_no_cache ");
}
}
if (x.isCalcFoundRows()) {
print0(ucase ? "SQL_CALC_FOUND_ROWS " : "sql_calc_found_rows ");
}
printSelectList(x.getSelectList());
SQLExprTableSource into = x.getInto();
if (into != null) {
println();
print0(ucase ? "INTO " : "into ");
printTableSource(into);
}
}
SQLTableSource from = x.getFrom();
@@ -28,6 +28,7 @@ import com.alibaba.druid.sql.dialect.odps.ast.OdpsLateralViewTableSource;
import com.alibaba.druid.sql.dialect.odps.ast.OdpsSelectQueryBlock;
import com.alibaba.druid.sql.dialect.odps.ast.OdpsValuesTableSource;
import com.alibaba.druid.sql.parser.SQLExprParser;
import com.alibaba.druid.sql.parser.SQLSelectListCache;
import com.alibaba.druid.sql.parser.SQLSelectParser;
import com.alibaba.druid.sql.parser.Token;
@@ -37,6 +38,12 @@ public class OdpsSelectParser extends SQLSelectParser {
this.exprParser = exprParser;
}
public OdpsSelectParser(SQLExprParser exprParser, SQLSelectListCache selectListCache){
super(exprParser.getLexer());
this.exprParser = exprParser;
this.selectListCache = selectListCache;
}
@Override
public SQLSelectQuery query() {
if (lexer.token() == Token.LPAREN) {
@@ -266,7 +266,7 @@ public class OdpsStatementParser extends SQLStatementParser {
}
public SQLSelectParser createSQLSelectParser() {
return new OdpsSelectParser(this.exprParser);
return new OdpsSelectParser(this.exprParser, selectListCache);
}
public OdpsInsert parseOdpsInsert() {
@@ -47,10 +47,7 @@ import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectSubqueryTableSo
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectTableReference;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectTableSource;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectUnPivot;
import com.alibaba.druid.sql.parser.ParserException;
import com.alibaba.druid.sql.parser.SQLExprParser;
import com.alibaba.druid.sql.parser.SQLSelectParser;
import com.alibaba.druid.sql.parser.Token;
import com.alibaba.druid.sql.parser.*;
public class OracleSelectParser extends SQLSelectParser {
@@ -62,6 +59,10 @@ public class OracleSelectParser extends SQLSelectParser {
super(exprParser);
}
public OracleSelectParser(SQLExprParser exprParser, SQLSelectListCache selectListCache){
super(exprParser, selectListCache);
}
public SQLSelect select() {
SQLSelect select = new SQLSelect();
@@ -1692,7 +1692,7 @@ public class OracleStatementParser extends SQLStatementParser {
}
public OracleSelectParser createSQLSelectParser() {
return new OracleSelectParser(this.exprParser);
return new OracleSelectParser(this.exprParser, selectListCache);
}
public OracleStatement parseInsert() {
@@ -60,7 +60,7 @@ public class PGSQLStatementParser extends SQLStatementParser {
}
public PGSelectParser createSQLSelectParser() {
return new PGSelectParser(this.exprParser);
return new PGSelectParser(this.exprParser, selectListCache);
}
public SQLUpdateStatement parseUpdateStatement() {
@@ -30,10 +30,7 @@ import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGFunctionTableSource;
import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock;
import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock.IntoOption;
import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGValuesQuery;
import com.alibaba.druid.sql.parser.ParserException;
import com.alibaba.druid.sql.parser.SQLExprParser;
import com.alibaba.druid.sql.parser.SQLSelectParser;
import com.alibaba.druid.sql.parser.Token;
import com.alibaba.druid.sql.parser.*;
public class PGSelectParser extends SQLSelectParser {
@@ -41,6 +38,10 @@ public class PGSelectParser extends SQLSelectParser {
super(exprParser);
}
public PGSelectParser(SQLExprParser exprParser, SQLSelectListCache selectListCache){
super(exprParser, selectListCache);
}
public PGSelectParser(String sql){
this(new PGExprParser(sql));
}
@@ -20,10 +20,7 @@ import com.alibaba.druid.sql.ast.SQLSetQuantifier;
import com.alibaba.druid.sql.ast.statement.*;
import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerSelectQueryBlock;
import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerTop;
import com.alibaba.druid.sql.parser.ParserException;
import com.alibaba.druid.sql.parser.SQLExprParser;
import com.alibaba.druid.sql.parser.SQLSelectParser;
import com.alibaba.druid.sql.parser.Token;
import com.alibaba.druid.sql.parser.*;
public class SQLServerSelectParser extends SQLSelectParser {
@@ -35,6 +32,10 @@ public class SQLServerSelectParser extends SQLSelectParser {
super(exprParser);
}
public SQLServerSelectParser(SQLExprParser exprParser, SQLSelectListCache selectListCache){
super(exprParser, selectListCache);
}
public SQLSelect select() {
SQLSelect select = new SQLSelect();
@@ -51,7 +51,7 @@ public class SQLServerStatementParser extends SQLStatementParser {
}
public SQLSelectParser createSQLSelectParser() {
return new SQLServerSelectParser(this.exprParser);
return new SQLServerSelectParser(this.exprParser, selectListCache);
}
public SQLServerStatementParser(Lexer lexer){
@@ -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;
}
}