From c64c40e81de9415338067cfc9c1e075d210bf024 Mon Sep 17 00:00:00 2001 From: wenshao Date: Tue, 27 Jun 2017 11:28:15 +0800 Subject: [PATCH] improved sql parser. --- .../druid/sql/ast/expr/SQLCharExpr.java | 4 +++ .../druid/sql/ast/expr/SQLExistsExpr.java | 11 +++++++ .../druid/sql/ast/expr/SQLIdentifierExpr.java | 23 +++++++++++++++ .../sql/ast/statement/SQLInsertInto.java | 7 +++++ .../druid/sql/ast/statement/SQLSelect.java | 5 +++- .../sql/ast/statement/SQLSelectQuery.java | 1 + .../ast/statement/SQLSelectQueryBlock.java | 9 ++++++ .../sql/ast/statement/SQLUnionQuery.java | 29 +++++++++++++++++++ .../oracle/parser/OracleStatementParser.java | 3 +- .../postgresql/ast/stmt/PGValuesQuery.java | 13 +++++++++ .../sql/visitor/SQLASTOutputVisitor.java | 20 +++++++++---- 11 files changed, 118 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLCharExpr.java b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLCharExpr.java index 4936aa549c..55e2a7ef39 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLCharExpr.java +++ b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLCharExpr.java @@ -52,4 +52,8 @@ public class SQLCharExpr extends SQLTextLiteralExpr implements SQLValuableExpr{ public String toString() { return SQLUtils.toSQLString(this); } + + public SQLCharExpr clone() { + return new SQLCharExpr(this.text); + } } diff --git a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLExistsExpr.java b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLExistsExpr.java index 1657b57382..26d4d95746 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLExistsExpr.java +++ b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLExistsExpr.java @@ -100,4 +100,15 @@ public class SQLExistsExpr extends SQLExprImpl implements Serializable { } return true; } + + public SQLExistsExpr clone () { + SQLExistsExpr x = new SQLExistsExpr(); + + x.not = not; + if (subQuery != null) { + x.setSubQuery(subQuery.clone()); + } + + return x; + } } diff --git a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLIdentifierExpr.java b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLIdentifierExpr.java index f60089c051..8e7f9dc602 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLIdentifierExpr.java +++ b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLIdentifierExpr.java @@ -15,6 +15,7 @@ */ package com.alibaba.druid.sql.ast.expr; +import com.alibaba.druid.sql.SQLUtils; import com.alibaba.druid.sql.ast.SQLExprImpl; import com.alibaba.druid.sql.ast.SQLName; import com.alibaba.druid.sql.visitor.SQLASTVisitor; @@ -102,6 +103,28 @@ public class SQLIdentifierExpr extends SQLExprImpl implements SQLName { return true; } + public boolean equalsIgnoreCase(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof SQLIdentifierExpr)) { + return false; + } + SQLIdentifierExpr other = (SQLIdentifierExpr) obj; + if (name == null) { + if (other.name != null) { + return false; + } + + } else if (!SQLUtils.normalize(name).equalsIgnoreCase(SQLUtils.normalize(other.name))) { + return false; + } + return true; + } + public String toString() { return this.name; } diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLInsertInto.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLInsertInto.java index 2911e8132c..3f18a7178d 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLInsertInto.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLInsertInto.java @@ -71,7 +71,14 @@ public abstract class SQLInsertInto extends SQLObjectImpl { return query; } + public void setQuery(SQLSelectQuery query) { + this.setQuery(new SQLSelect(query)); + } + public void setQuery(SQLSelect query) { + if (query != null) { + query.setParent(this); + } this.query = query; } diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelect.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelect.java index da49f5a4d7..f2212d304a 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelect.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelect.java @@ -154,7 +154,10 @@ public class SQLSelect extends SQLObjectImpl { SQLSelect x = new SQLSelect(); x.withSubQuery = this.withSubQuery; - x.query = this.query; + if (query != null) { + x.setQuery(query.clone()); + } + if (orderBy != null) { x.setOrderBy(this.orderBy.clone()); } diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectQuery.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectQuery.java index 9ebca55ed1..c7bacc03b7 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectQuery.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectQuery.java @@ -21,4 +21,5 @@ public interface SQLSelectQuery extends SQLObject { boolean isBracket(); void setBracket(boolean bracket); + SQLSelectQuery clone(); } diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectQueryBlock.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectQueryBlock.java index 48aa96baea..1531b249d2 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectQueryBlock.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectQueryBlock.java @@ -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.expr.SQLBinaryOpExpr; import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; import com.alibaba.druid.sql.visitor.SQLASTVisitor; @@ -439,4 +440,12 @@ public class SQLSelectQueryBlock extends SQLObjectImpl implements SQLSelectQuery return null; } + + public void addCondition(SQLExpr expr) { + if (expr == null) { + return; + } + + this.setWhere(SQLBinaryOpExpr.and(where, expr)); + } } diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLUnionQuery.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLUnionQuery.java index de985fe116..d02fc000cd 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLUnionQuery.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLUnionQuery.java @@ -43,6 +43,12 @@ public class SQLUnionQuery extends SQLObjectImpl implements SQLSelectQuery { } + public SQLUnionQuery(SQLSelectQuery left, SQLUnionOperator operator, SQLSelectQuery right){ + this.setLeft(left); + this.operator = operator; + this.setRight(right); + } + public SQLSelectQuery getLeft() { return left; } @@ -106,4 +112,27 @@ public class SQLUnionQuery extends SQLObjectImpl implements SQLSelectQuery { public void setBracket(boolean bracket) { this.bracket = bracket; } + + public SQLUnionQuery clone() { + SQLUnionQuery x = new SQLUnionQuery(); + + x.bracket = bracket; + if (left != null) { + x.setLeft(left.clone()); + } + if (right != null) { + x.setRight(right.clone()); + } + x.operator = operator; + + if (orderBy != null) { + x.setOrderBy(orderBy.clone()); + } + + if (limit != null) { + x.setLimit(limit.clone()); + } + + return x; + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleStatementParser.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleStatementParser.java index 68ee820b96..8f8d05e802 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleStatementParser.java @@ -1703,7 +1703,8 @@ public class OracleStatementParser extends SQLStatementParser { while (lexer.token() == Token.INTO) { OracleMultiInsertStatement.InsertIntoClause clause = new OracleMultiInsertStatement.InsertIntoClause(); - parseInsert0(clause); + boolean acceptSubQuery = stmt.getEntries().size() == 0; + parseInsert0(clause, acceptSubQuery); clause.setReturning(parseReturningClause()); clause.setErrorLogging(parseErrorLoggingClause()); diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGValuesQuery.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGValuesQuery.java index d18195a582..09b60ec005 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGValuesQuery.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGValuesQuery.java @@ -49,4 +49,17 @@ public class PGValuesQuery extends PGSQLObjectImpl implements SQLSelectQuery { public void setBracket(boolean bracket) { this.bracket = bracket; } + + public PGValuesQuery clone() { + PGValuesQuery x = new PGValuesQuery(); + x.bracket = bracket; + + for (int i = 0; i < values.size(); ++i) { + SQLExpr value = values.get(i).clone(); + value.setParent(x); + x.values.add(value); + } + + return x; + } } diff --git a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java index ba9955fd1b..4a537adafe 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java @@ -707,9 +707,18 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet private boolean printName(SQLName x, String name) { boolean shardingSupport = this.shardingSupport && parameterized; + return printName(x, name, shardingSupport); + } + + private boolean printName(SQLName x, String name, boolean shardingSupport) { + if (shardingSupport) { SQLObject parent = x.getParent(); shardingSupport = parent instanceof SQLExprTableSource || parent instanceof SQLPropertyExpr; + + if (parent instanceof SQLPropertyExpr && parent.getParent() instanceof SQLExprTableSource) { + shardingSupport = false; + } } if (shardingSupport) { @@ -1133,11 +1142,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet if (mapTableName != null) { print0(mapTableName); } else { - if (owner instanceof SQLIdentifierExpr && x.getParent() instanceof SQLExprTableSource) { - print0(((SQLIdentifierExpr) owner).getName()); - } else { - owner.accept(this); - } + owner.accept(this); } print('.'); @@ -1321,6 +1326,11 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet printFetchFirst(x); } + if (x.isForUpdate()) { + println(); + print0(ucase ? "FOR UPDATE" : "for update"); + } + return false; }