diff --git a/src/main/java/com/alibaba/druid/sql/SQLUtils.java b/src/main/java/com/alibaba/druid/sql/SQLUtils.java index 621bd3600a..bd3e54d408 100644 --- a/src/main/java/com/alibaba/druid/sql/SQLUtils.java +++ b/src/main/java/com/alibaba/druid/sql/SQLUtils.java @@ -857,7 +857,7 @@ public class SQLUtils { List parameters = x.getParameters(); SQLCaseExpr caseExpr = new SQLCaseExpr(); - + caseExpr.setParent(x.getParent()); caseExpr.setValueExpr(parameters.get(0)); for (int i = 1; i + 1 < parameters.size(); i += 2) { diff --git a/src/main/java/com/alibaba/druid/sql/ast/SQLHint.java b/src/main/java/com/alibaba/druid/sql/ast/SQLHint.java index 788d9f382b..0191d19b1d 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/SQLHint.java +++ b/src/main/java/com/alibaba/druid/sql/ast/SQLHint.java @@ -17,5 +17,5 @@ package com.alibaba.druid.sql.ast; public interface SQLHint extends SQLObject { - + SQLHint clone(); } diff --git a/src/main/java/com/alibaba/druid/sql/ast/SQLParameter.java b/src/main/java/com/alibaba/druid/sql/ast/SQLParameter.java index 6bd1d0c9ae..d649c427c3 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/SQLParameter.java +++ b/src/main/java/com/alibaba/druid/sql/ast/SQLParameter.java @@ -117,4 +117,29 @@ public class SQLParameter extends SQLObjectImpl { } this.cursorName = cursorName; } + + public SQLParameter clone() { + SQLParameter x = new SQLParameter(); + if (name != null) { + x.setName(name.clone()); + } + if (dataType != null) { + x.setDataType(dataType.clone()); + } + if (defaultValue != null) { + x.setDefaultValue(defaultValue.clone()); + } + x.paramType = paramType; + x.noCopy = noCopy; + x.constant = constant; + if (cursorName != null) { + x.setCursorName(cursorName.clone()); + } + for (SQLParameter p : cursorParameters) { + SQLParameter p2 = p.clone(); + p2.setParent(x); + x.cursorParameters.add(p2); + } + return x; + } } diff --git a/src/main/java/com/alibaba/druid/sql/ast/SQLStatement.java b/src/main/java/com/alibaba/druid/sql/ast/SQLStatement.java index 59a45c9434..0ea8d338cf 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/SQLStatement.java +++ b/src/main/java/com/alibaba/druid/sql/ast/SQLStatement.java @@ -21,4 +21,6 @@ public interface SQLStatement extends SQLObject { boolean isAfterSemi(); void setAfterSemi(boolean afterSemi); + + SQLStatement clone(); } diff --git a/src/main/java/com/alibaba/druid/sql/ast/SQLStatementImpl.java b/src/main/java/com/alibaba/druid/sql/ast/SQLStatementImpl.java index e5dfeda95b..fcf311968a 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/SQLStatementImpl.java +++ b/src/main/java/com/alibaba/druid/sql/ast/SQLStatementImpl.java @@ -56,4 +56,8 @@ public abstract class SQLStatementImpl extends SQLObjectImpl implements SQLState public void setAfterSemi(boolean afterSemi) { this.afterSemi = afterSemi; } + + public SQLStatement clone() { + throw new UnsupportedOperationException(this.getClass().getName()); + } } diff --git a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLBinaryExpr.java b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLBinaryExpr.java index 0c10b308dd..8aa6fecab0 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLBinaryExpr.java +++ b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLBinaryExpr.java @@ -59,6 +59,10 @@ public class SQLBinaryExpr extends SQLExprImpl implements SQLLiteralExpr { return result; } + public SQLBinaryExpr clone() { + return new SQLBinaryExpr(value); + } + @Override public boolean equals(Object obj) { if (this == obj) { diff --git a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLBooleanExpr.java b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLBooleanExpr.java index 69043fd9a0..09b95b9f9c 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLBooleanExpr.java +++ b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLBooleanExpr.java @@ -83,4 +83,8 @@ public class SQLBooleanExpr extends SQLExprImpl implements SQLExpr, SQLLiteralEx public SQLDataType computeDataType() { return DEFAULT_DATA_TYPE; } + + public SQLBooleanExpr clone() { + return new SQLBooleanExpr(value); + } } diff --git a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLDateExpr.java b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLDateExpr.java index ca58cf2332..fe73df2db7 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLDateExpr.java +++ b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLDateExpr.java @@ -31,6 +31,10 @@ public class SQLDateExpr extends SQLExprImpl implements SQLLiteralExpr { } + public SQLDateExpr(String literal) { + this.literal = literal; + } + public String getLiteral() { return literal; } @@ -75,4 +79,7 @@ public class SQLDateExpr extends SQLExprImpl implements SQLLiteralExpr { return true; } + public SQLDateExpr clone() { + return new SQLDateExpr(literal); + } } diff --git a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLDefaultExpr.java b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLDefaultExpr.java index 2243240aed..7ac062a2d7 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLDefaultExpr.java +++ b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLDefaultExpr.java @@ -39,4 +39,8 @@ public class SQLDefaultExpr extends SQLExprImpl implements SQLLiteralExpr { public String toString() { return "DEFAULT"; } + + public SQLDefaultExpr clone() { + return new SQLDefaultExpr(); + } } diff --git a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLHexExpr.java b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLHexExpr.java index ba79b3682d..2e839f259c 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLHexExpr.java +++ b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLHexExpr.java @@ -80,4 +80,8 @@ public class SQLHexExpr extends SQLExprImpl implements SQLLiteralExpr { public byte[] toBytes() { return HexBin.decode(this.hex); } + + public SQLHexExpr clone () { + return new SQLHexExpr(hex); + } } diff --git a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLInListExpr.java b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLInListExpr.java index 9ae3b4cad2..c59a0a7b57 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLInListExpr.java +++ b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLInListExpr.java @@ -44,6 +44,20 @@ public class SQLInListExpr extends SQLExprImpl implements Serializable { this.not = not; } + public SQLInListExpr clone() { + SQLInListExpr x = new SQLInListExpr(); + x.not = not; + if (expr != null) { + x.setExpr(expr.clone()); + } + for (SQLExpr e : targetList) { + SQLExpr e2 = e.clone(); + e2.setParent(x); + x.targetList.add(e2); + } + return x; + } + public boolean isNot() { return this.not; } diff --git a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLInSubQueryExpr.java b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLInSubQueryExpr.java index f4c3f00b78..c9143658e5 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLInSubQueryExpr.java +++ b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLInSubQueryExpr.java @@ -35,6 +35,18 @@ public class SQLInSubQueryExpr extends SQLExprImpl implements Serializable { } + public SQLInSubQueryExpr clone() { + SQLInSubQueryExpr x = new SQLInSubQueryExpr(); + x.not = not; + if (expr != null) { + x.setExpr(expr.clone()); + } + if (subQuery != null) { + x.setSubQuery(subQuery.clone()); + } + return x; + } + public boolean isNot() { return not; } diff --git a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLListExpr.java b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLListExpr.java index c599a121c8..a27c6387ce 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLListExpr.java +++ b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLListExpr.java @@ -75,4 +75,14 @@ public class SQLListExpr extends SQLExprImpl { return true; } + public SQLListExpr clone() { + SQLListExpr x = new SQLListExpr(); + for (SQLExpr item : items) { + SQLExpr item2 = item.clone(); + item2.setParent(x); + x.items.add(item2); + } + return x; + } + } diff --git a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLLiteralExpr.java b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLLiteralExpr.java index 1edcc55390..675879985b 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLLiteralExpr.java +++ b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLLiteralExpr.java @@ -18,5 +18,5 @@ package com.alibaba.druid.sql.ast.expr; import com.alibaba.druid.sql.ast.SQLExpr; public interface SQLLiteralExpr extends SQLExpr { - + SQLLiteralExpr clone(); } diff --git a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLNumericLiteralExpr.java b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLNumericLiteralExpr.java index efda599279..126ccc8e05 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLNumericLiteralExpr.java +++ b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLNumericLiteralExpr.java @@ -26,4 +26,6 @@ public abstract class SQLNumericLiteralExpr extends SQLExprImpl implements SQLLi public abstract Number getNumber(); public abstract void setNumber(Number number); + + public abstract SQLNumericLiteralExpr clone(); } diff --git a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLTextLiteralExpr.java b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLTextLiteralExpr.java index b4dff0cb3d..232c38807b 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLTextLiteralExpr.java +++ b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLTextLiteralExpr.java @@ -67,4 +67,6 @@ public abstract class SQLTextLiteralExpr extends SQLExprImpl implements SQLLiter } return true; } + + public abstract SQLTextLiteralExpr clone(); } diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLBlockStatement.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLBlockStatement.java index 9a55bae9d0..495805c697 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLBlockStatement.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLBlockStatement.java @@ -32,6 +32,8 @@ public class SQLBlockStatement extends SQLStatementImpl { private List statementList = new ArrayList(); + public SQLStatement exception; + public List getStatementList() { return statementList; } @@ -48,8 +50,6 @@ public class SQLBlockStatement extends SQLStatementImpl { this.labelName = labelName; } - public SQLStatement exception; - @Override public void accept0(SQLASTVisitor visitor) { if (visitor.visit(this)) { @@ -86,4 +86,28 @@ public class SQLBlockStatement extends SQLStatementImpl { public void setEndLabel(String endLabel) { this.endLabel = endLabel; } + + public SQLBlockStatement clone() { + SQLBlockStatement x = new SQLBlockStatement(); + x.labelName = labelName; + x.endLabel = endLabel; + + for (SQLParameter p : parameters) { + SQLParameter p2 = p.clone(); + p2.setParent(x); + x.parameters.add(p2); + } + + for (SQLStatement stmt : statementList) { + SQLStatement stmt2 = stmt.clone(); + stmt2.setParent(x); + x.statementList.add(stmt2); + } + + if (exception != null) { + x.setException(exception.clone()); + } + + return x; + } } diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCommitStatement.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCommitStatement.java index a0058f2d19..7e8093a03b 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCommitStatement.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCommitStatement.java @@ -35,6 +35,24 @@ public class SQLCommitStatement extends SQLStatementImpl { private SQLExpr transactionName; private SQLExpr delayedDurability; + public SQLCommitStatement clone() { + SQLCommitStatement x = new SQLCommitStatement(); + x.write = write; + x.wait = wait; + x.immediate = immediate; + x.work = work; + x.chain = chain; + x.release = release; + + if(transactionName != null) { + x.setTransactionName(transactionName.clone()); + } + if (delayedDurability != null) { + x.setDelayedDurability(delayedDurability.clone()); + } + return x; + } + public void accept0(SQLASTVisitor visitor) { if (visitor.visit(this)) { acceptChild(visitor, transactionName); diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateFunctionStatement.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateFunctionStatement.java index 797aba9770..f66dccc7d2 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateFunctionStatement.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateFunctionStatement.java @@ -25,7 +25,7 @@ import java.util.List; /** * Created by wenshao on 23/05/2017. */ -public class SQLCreateFunctionStatement extends SQLStatementImpl { +public class SQLCreateFunctionStatement extends SQLStatementImpl implements SQLDDLStatement { private SQLName definer; private boolean create = true; @@ -47,6 +47,38 @@ public class SQLCreateFunctionStatement extends SQLStatementImpl { private boolean deterministic = false; + public SQLCreateFunctionStatement clone() { + SQLCreateFunctionStatement x = new SQLCreateFunctionStatement(); + + if (definer != null) { + x.setDefiner(definer.clone()); + } + x.create = create; + x.orReplace = orReplace; + if (name != null) { + x.setName(name.clone()); + } + if (block != null) { + x.setBlock(block.clone()); + } + for (SQLParameter p : parameters) { + SQLParameter p2 = p.clone(); + p2.setParent(x); + x.parameters.add(p2); + } + x.javaCallSpec = javaCallSpec; + if (authid != null) { + x.setAuthid(authid.clone()); + } + if (returnDataType != null) { + x.setReturnDataType(returnDataType.clone()); + } + x.comment = comment; + x.deterministic = deterministic; + + return x; + } + @Override public void accept0(SQLASTVisitor visitor) { if (visitor.visit(this)) { diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateIndexStatement.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateIndexStatement.java index 4b7f1f573b..039f2cfcf1 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateIndexStatement.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateIndexStatement.java @@ -135,4 +135,23 @@ public class SQLCreateIndexStatement extends SQLStatementImpl implements SQLDDLS return null; } + + + public SQLCreateIndexStatement clone() { + SQLCreateIndexStatement x = new SQLCreateIndexStatement(); + if (name != null) { + x.setName(name.clone()); + } + if (table != null) { + x.setTable(table.clone()); + } + for (SQLSelectOrderByItem item : items) { + SQLSelectOrderByItem item2 = item.clone(); + item2.setParent(x); + x.items.add(item2); + } + x.type = type; + x.using = using; + return x; + } } diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateSequenceStatement.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateSequenceStatement.java index 976f5a7fb2..98aff4ea26 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateSequenceStatement.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateSequenceStatement.java @@ -26,7 +26,7 @@ import com.alibaba.druid.sql.visitor.SQLASTVisitor; /** * Created by wenshao on 16/9/14. */ -public class SQLCreateSequenceStatement extends SQLStatementImpl { +public class SQLCreateSequenceStatement extends SQLStatementImpl implements SQLDDLStatement { private SQLName name; private SQLExpr startWith; diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateViewStatement.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateViewStatement.java index 90d522bc36..1ca627b411 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateViewStatement.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateViewStatement.java @@ -280,4 +280,40 @@ public class SQLCreateViewStatement extends SQLStatementImpl implements SQLDDLSt } } } + + + public SQLCreateViewStatement clone() { + SQLCreateViewStatement x = new SQLCreateViewStatement(); + + x.orReplace = orReplace; + x.force = force; + if (subQuery != null) { + x.setSubQuery(subQuery.clone()); + } + x.ifNotExists = ifNotExists; + + x.algorithm = algorithm; + if (definer != null) { + x.setDefiner(definer.clone()); + } + x.sqlSecurity = sqlSecurity; + if (tableSource != null) { + x.setTableSource(tableSource.clone()); + } + for (SQLTableElement column : columns) { + SQLTableElement column2 = column.clone(); + column2.setParent(x); + x.columns.add(column2); + } + x.withCheckOption = withCheckOption; + x.withCascaded = withCascaded; + x.withLocal = withLocal; + x.withReadOnly = withReadOnly; + + if (comment != null) { + x.setComment(comment.clone()); + } + + return x; + } } diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLErrorLoggingClause.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLErrorLoggingClause.java index 1b714e272c..576c2a6797 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLErrorLoggingClause.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLErrorLoggingClause.java @@ -60,4 +60,18 @@ public class SQLErrorLoggingClause extends SQLObjectImpl { this.limit = limit; } + public SQLErrorLoggingClause clone() { + SQLErrorLoggingClause x = new SQLErrorLoggingClause(); + if (into != null) { + x.setInto(into.clone()); + } + if (simpleExpression != null) { + x.setSimpleExpression(simpleExpression.clone()); + } + if (limit != null) { + x.setLimit(limit.clone()); + } + return x; + } + } diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLExprHint.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLExprHint.java index 8a443fbd22..ea4dcbc657 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLExprHint.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLExprHint.java @@ -52,4 +52,11 @@ public class SQLExprHint extends SQLObjectImpl implements SQLHint { visitor.endVisit(this); } + public SQLExprHint clone() { + SQLExprHint x = new SQLExprHint(); + if (expr != null) { + x.setExpr(expr.clone()); + } + return x; + } } diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLExprTableSource.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLExprTableSource.java index fbc6d57a41..183d3a4c37 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLExprTableSource.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLExprTableSource.java @@ -223,4 +223,20 @@ public class SQLExprTableSource extends SQLTableSourceImpl { } return null; } + + public SQLTableSource findTableSourceWithColumn(String columnName) { + if (schemaObject == null) { + return null; + } + + SQLStatement stmt = schemaObject.getStatement(); + if (stmt instanceof SQLCreateTableStatement) { + SQLCreateTableStatement createTableStmt = (SQLCreateTableStatement) stmt; + if (createTableStmt.findColumn(columnName) != null) { + return this; + } + } + + return null; + } } diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLIfStatement.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLIfStatement.java index b05bebd739..002c783fb3 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLIfStatement.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLIfStatement.java @@ -31,6 +31,26 @@ public class SQLIfStatement extends SQLStatementImpl { private List elseIfList = new ArrayList(); private Else elseItem; + public SQLIfStatement clone() { + SQLIfStatement x = new SQLIfStatement(); + + for (SQLStatement stmt : statements) { + SQLStatement stmt2 = stmt.clone(); + stmt2.setParent(x); + x.statements.add(stmt2); + } + for (ElseIf o : elseIfList) { + ElseIf o2 = o.clone(); + o2.setParent(x); + x.elseIfList.add(o2); + } + if (elseItem != null) { + x.setElseItem(elseItem.clone()); + } + + return x; + } + @Override public void accept0(SQLASTVisitor visitor) { if (visitor.visit(this)) { @@ -111,6 +131,21 @@ public class SQLIfStatement extends SQLStatementImpl { } this.condition = condition; } + + public ElseIf clone() { + ElseIf x = new ElseIf(); + + if (condition != null) { + x.setCondition(condition.clone()); + } + for (SQLStatement stmt : statements) { + SQLStatement stmt2 = stmt.clone(); + stmt2.setParent(x); + x.statements.add(stmt2); + } + + return x; + } } public static class Else extends SQLObjectImpl { @@ -133,5 +168,14 @@ public class SQLIfStatement extends SQLStatementImpl { this.statements = statements; } + public Else clone() { + Else x = new Else(); + for (SQLStatement stmt : statements) { + SQLStatement stmt2 = stmt.clone(); + stmt2.setParent(x); + x.statements.add(stmt2); + } + return x; + } } } 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 3f18a7178d..c1e43ea598 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 @@ -36,6 +36,27 @@ public abstract class SQLInsertInto extends SQLObjectImpl { } + public void cloneTo(SQLInsertInto x) { + if (tableSource != null) { + x.setTableSource(tableSource.clone()); + } + for (SQLExpr column : columns) { + SQLExpr column2 = column.clone(); + column2.setParent(x); + x.columns.add(column2); + } + if (query != null) { + x.setQuery(query.clone()); + } + for (ValuesClause v : valuesList) { + ValuesClause v2 = v.clone(); + v2.setParent(x); + x.valuesList.add(v2); + } + } + + public abstract SQLInsertInto clone(); + public String getAlias() { return tableSource.getAlias(); } diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLInsertStatement.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLInsertStatement.java index be57bc8ed6..3f4b9aab74 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLInsertStatement.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLInsertStatement.java @@ -34,6 +34,19 @@ public class SQLInsertStatement extends SQLInsertInto implements SQLStatement { } + public void cloneTo(SQLInsertStatement x) { + super.cloneTo(x); + x.dbType = dbType; + x.upsert = upsert; + x.afterSemi = afterSemi; + } + + public SQLInsertStatement clone() { + SQLInsertStatement x = new SQLInsertStatement(); + cloneTo(x); + return x; + } + @Override protected void accept0(SQLASTVisitor visitor) { if (visitor.visit(this)) { @@ -62,6 +75,14 @@ public class SQLInsertStatement extends SQLInsertInto implements SQLStatement { this(new ArrayList()); } + public ValuesClause clone() { + ValuesClause x = new ValuesClause(new ArrayList(this.values.size())); + for (SQLExpr v : values) { + x.addValue(v); + } + return x; + } + public ValuesClause(List values){ this.values = values; for (int i = 0; i < values.size(); ++i) { diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLJoinTableSource.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLJoinTableSource.java index f322011060..a6ed35dea0 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLJoinTableSource.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLJoinTableSource.java @@ -285,6 +285,10 @@ public class SQLJoinTableSource extends SQLTableSourceImpl implements SQLReplace if (right instanceof SQLJoinTableSource) { SQLJoinTableSource rightJoin = (SQLJoinTableSource) right; + if (rightJoin.joinType != JoinType.COMMA && rightJoin.joinType != JoinType.INNER_JOIN) { + return; + } + SQLTableSource a = left; SQLTableSource b = rightJoin.getLeft(); SQLTableSource c = rightJoin.getRight(); @@ -384,4 +388,20 @@ public class SQLJoinTableSource extends SQLTableSourceImpl implements SQLReplace return null; } + @Override + public SQLTableSource findTableSourceWithColumn(String columnName) { + if (left != null) { + SQLTableSource tableSource = left.findTableSourceWithColumn(columnName); + if (tableSource != null) { + return tableSource; + } + } + + if (right != null) { + return right.findTableSourceWithColumn(columnName); + } + + return null; + } + } diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLReturnStatement.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLReturnStatement.java index 80534fc8d0..ad9438b5f9 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLReturnStatement.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLReturnStatement.java @@ -49,4 +49,12 @@ public class SQLReturnStatement extends SQLStatementImpl { } visitor.endVisit(this); } + + public SQLReturnStatement clone() { + SQLReturnStatement x = new SQLReturnStatement(); + if (expr != null) { + x.setExpr(expr.clone()); + } + return x; + } } diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectGroupByClause.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectGroupByClause.java index f2b78f27de..5debd1403a 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectGroupByClause.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectGroupByClause.java @@ -83,6 +83,17 @@ public class SQLSelectGroupByClause extends SQLObjectImpl { } public SQLSelectGroupByClause clone() { - throw new UnsupportedOperationException(); + SQLSelectGroupByClause x = new SQLSelectGroupByClause(); + for (SQLExpr item : items) { + SQLExpr item2 = item.clone(); + item2.setParent(x); + x.items.add(item2); + } + if (having != null) { + x.setHaving(having.clone()); + } + x.withRollUp = withRollUp; + x.withCube = withCube; + return x; } } diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectItem.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectItem.java index 98852e98f7..b1cd78eedb 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectItem.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectItem.java @@ -62,10 +62,10 @@ public class SQLSelectItem extends SQLObjectImpl implements SQLReplaceable { } public void setExpr(SQLExpr expr) { - this.expr = expr; if (expr != null) { expr.setParent(this); } + this.expr = expr; } public String computeAlias() { @@ -151,7 +151,7 @@ public class SQLSelectItem extends SQLObjectImpl implements SQLReplaceable { SQLSelectItem x = new SQLSelectItem(); x.alias = alias; if (expr != null) { - x.expr = expr.clone(); + x.setExpr(expr.clone()); } x.connectByRoot = connectByRoot; return x; 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 09ef7849b9..6021a1dc61 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 @@ -438,6 +438,13 @@ public class SQLSelectQueryBlock extends SQLObjectImpl implements SQLSelectQuery return findTableSource(from, alias); } + public SQLTableSource findTableSourceWithColumn(String column) { + if (from == null) { + return null; + } + return from.findTableSourceWithColumn(column); + } + private static SQLTableSource findTableSource(SQLTableSource from, String alias) { if (from == null || alias == null) { return null; @@ -489,6 +496,14 @@ public class SQLSelectQueryBlock extends SQLObjectImpl implements SQLSelectQuery return null; } + public SQLColumnDefinition findColumn(String columnName) { + if (from == null) { + return null; + } + + return from.findColumn(columnName); + } + public void addCondition(SQLExpr expr) { if (expr == null) { return; diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectStatement.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectStatement.java index f385340363..448684da55 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectStatement.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectStatement.java @@ -73,4 +73,19 @@ public class SQLSelectStatement extends SQLStatementImpl { public void setHeadHints(List headHints) { this.headHints = headHints; } + + public SQLSelectStatement clone() { + SQLSelectStatement x = new SQLSelectStatement(); + if (select != null) { + x.setSelect(select.clone()); + } + if (headHints != null) { + for (SQLCommentHint h : headHints) { + SQLCommentHint h2 = h.clone(); + h2.setParent(x); + x.headHints.add(h2); + } + } + return x; + } } diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSetStatement.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSetStatement.java index 831bda7028..ed0a0f12c5 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSetStatement.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSetStatement.java @@ -91,4 +91,21 @@ public class SQLSetStatement extends SQLStatementImpl { item.output(buf); } } + + public SQLSetStatement clone() { + SQLSetStatement x = new SQLSetStatement(); + for (SQLAssignItem item : items) { + SQLAssignItem item2 = item.clone(); + item2.setParent(x); + x.items.add(item2); + } + if (hints != null) { + for (SQLCommentHint hint : hints) { + SQLCommentHint h2 = hint.clone(); + h2.setParent(x); + x.hints.add(h2); + } + } + return x; + } } diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLTableSource.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLTableSource.java index 47a37f4aa7..66899efe65 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLTableSource.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLTableSource.java @@ -38,4 +38,5 @@ public interface SQLTableSource extends SQLObject { void setFlashback(SQLExpr flashback); SQLColumnDefinition findColumn(String columnName); + SQLTableSource findTableSourceWithColumn(String columnName); } diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLTableSourceImpl.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLTableSourceImpl.java index bb3cc9aa71..616c15c398 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLTableSourceImpl.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLTableSourceImpl.java @@ -98,4 +98,8 @@ public abstract class SQLTableSourceImpl extends SQLObjectImpl implements SQLTab public SQLColumnDefinition findColumn(String columnName) { return null; } + + public SQLTableSource findTableSourceWithColumn(String columnName) { + return null; + } } diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLWhileStatement.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLWhileStatement.java index 3d73271a74..04eb7bd762 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLWhileStatement.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLWhileStatement.java @@ -68,4 +68,19 @@ public class SQLWhileStatement extends SQLStatementImpl { public void setCondition(SQLExpr condition) { this.condition = condition; } + + public SQLWhileStatement clone() { + SQLWhileStatement x = new SQLWhileStatement(); + + if (condition != null) { + x.setCondition(condition.clone()); + } + for (SQLStatement stmt : statements) { + SQLStatement stmt2 = stmt.clone(); + stmt2.setParent(x); + x.statements.add(stmt2); + } + x.labelName = labelName; + return x; + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/MySqlForceIndexHint.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/MySqlForceIndexHint.java index 87f8be0cac..7fe55df921 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/MySqlForceIndexHint.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/MySqlForceIndexHint.java @@ -27,4 +27,9 @@ public class MySqlForceIndexHint extends MySqlIndexHintImpl { visitor.endVisit(this); } + public MySqlForceIndexHint clone() { + MySqlForceIndexHint x = new MySqlForceIndexHint(); + cloneTo(x); + return x; + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/MySqlIgnoreIndexHint.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/MySqlIgnoreIndexHint.java index 382669181b..6e77afbce5 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/MySqlIgnoreIndexHint.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/MySqlIgnoreIndexHint.java @@ -27,4 +27,9 @@ public class MySqlIgnoreIndexHint extends MySqlIndexHintImpl { visitor.endVisit(this); } + public MySqlIgnoreIndexHint clone() { + MySqlIgnoreIndexHint x = new MySqlIgnoreIndexHint(); + cloneTo(x); + return x; + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/MySqlIndexHintImpl.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/MySqlIndexHintImpl.java index 89b873a617..c277928525 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/MySqlIndexHintImpl.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/MySqlIndexHintImpl.java @@ -46,4 +46,14 @@ public abstract class MySqlIndexHintImpl extends MySqlObjectImpl implements MySq this.indexList = indexList; } + public abstract MySqlIndexHintImpl clone(); + + public void cloneTo(MySqlIndexHintImpl x) { + x.option = option; + for (SQLName name : indexList) { + SQLName name2 = name.clone(); + name2.setParent(x); + x.indexList.add(name2); + } + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/MySqlUseIndexHint.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/MySqlUseIndexHint.java index 4e05f13473..f1144ef033 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/MySqlUseIndexHint.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/MySqlUseIndexHint.java @@ -27,4 +27,9 @@ public class MySqlUseIndexHint extends MySqlIndexHintImpl { visitor.endVisit(this); } + public MySqlUseIndexHint clone() { + MySqlUseIndexHint x = new MySqlUseIndexHint(); + cloneTo(x); + return x; + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlInsertStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlInsertStatement.java index e2eaecde36..cffbc3ef5b 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlInsertStatement.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlInsertStatement.java @@ -34,6 +34,21 @@ public class MySqlInsertStatement extends SQLInsertStatement { private final List duplicateKeyUpdate = new ArrayList(); + public void cloneTo(MySqlInsertStatement x) { + super.cloneTo(x); + x.lowPriority = lowPriority; + x.delayed = delayed; + x.highPriority = highPriority; + x.ignore = ignore; + x.rollbackOnFail = rollbackOnFail; + + for (SQLExpr e : duplicateKeyUpdate) { + SQLExpr e2 = e.clone(); + e2.setParent(x); + x.duplicateKeyUpdate.add(e2); + } + } + public List getDuplicateKeyUpdate() { return duplicateKeyUpdate; } @@ -102,4 +117,10 @@ public class MySqlInsertStatement extends SQLInsertStatement { visitor.endVisit(this); } + + public SQLInsertStatement clone() { + MySqlInsertStatement x = new MySqlInsertStatement(); + cloneTo(x); + return x; + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/transform/NameResolveVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/transform/NameResolveVisitor.java index 27f9775038..ae633540be 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/transform/NameResolveVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/transform/NameResolveVisitor.java @@ -69,4 +69,32 @@ public class NameResolveVisitor extends OracleASTVisitorAdapter { } return true; } + + public boolean visit(SQLPropertyExpr x) { + String ownerName = x.getOwnernName(); + if (ownerName == null) { + return super.visit(x); + } + + for (SQLObject parent = x.getParent(); parent != null; parent = parent.getParent()) { + if (parent instanceof SQLSelectQueryBlock) { + SQLSelectQueryBlock queryBlock = (SQLSelectQueryBlock) parent; + SQLTableSource tableSource = queryBlock.findTableSource(ownerName); + if (tableSource == null) { + continue; + } + + String alias = tableSource.getAlias(); + if (tableSource != null + && ownerName.equalsIgnoreCase(alias) + && !ownerName.equals(alias)) { + x.setOwner(alias); + } + + break; + } + } + + return super.visit(x); + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/OracleSQLObjectImpl.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/OracleSQLObjectImpl.java index b1aa9e9d9c..2f1f1e9a93 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/OracleSQLObjectImpl.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/OracleSQLObjectImpl.java @@ -35,7 +35,7 @@ public abstract class OracleSQLObjectImpl extends SQLObjectImpl implements Oracl public abstract void accept0(OracleASTVisitor visitor); public OracleSQLObject clone() { - throw new UnsupportedOperationException(); + throw new UnsupportedOperationException(this.getClass().getName()); } public SQLDataType computeDataType() { diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/clause/OracleReturningClause.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/clause/OracleReturningClause.java index 5acd1d5fc5..c093ca106a 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/clause/OracleReturningClause.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/clause/OracleReturningClause.java @@ -58,4 +58,21 @@ public class OracleReturningClause extends OracleSQLObjectImpl { visitor.endVisit(this); } + public OracleReturningClause clone() { + OracleReturningClause x = new OracleReturningClause(); + + for (SQLExpr item : items) { + SQLExpr item2 = item.clone(); + item2.setParent(x); + x.items.add(item2); + } + + for (SQLExpr v : values) { + SQLExpr v2 = v.clone(); + v2.setParent(x); + x.values.add(v2); + } + + return x; + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/clause/OracleStorageClause.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/clause/OracleStorageClause.java index 030897e458..f437f51f27 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/clause/OracleStorageClause.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/clause/OracleStorageClause.java @@ -34,6 +34,43 @@ public class OracleStorageClause extends OracleSQLObjectImpl { private FlashCacheType flashCache; private FlashCacheType cellFlashCache; + public OracleStorageClause clone() { + OracleStorageClause x = new OracleStorageClause(); + if (initial != null) { + x.setInitial(initial.clone()); + } + if (next != null) { + x.setNext(next.clone()); + } + if (minExtents != null) { + x.setMinExtents(minExtents.clone()); + } + if (maxExtents != null) { + x.setMinExtents(maxExtents.clone()); + } + if (maxSize != null) { + x.setMaxSize(maxSize.clone()); + } + if (pctIncrease != null) { + x.setPctIncrease(pctIncrease.clone()); + } + if (freeLists != null) { + x.setFreeLists(freeLists.clone()); + } + if (freeListGroups != null) { + x.setFreeListGroups(freeListGroups.clone()); + } + if (bufferPool != null) { + x.setBufferPool(bufferPool.clone()); + } + if (objno != null) { + x.setObjno(objno.clone()); + } + x.flashCache = flashCache; + x.cellFlashCache = cellFlashCache; + return x; + } + @Override public void accept0(OracleASTVisitor visitor) { if (visitor.visit(this)) { diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleBinaryDoubleExpr.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleBinaryDoubleExpr.java index 0e1b998139..b11e73290d 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleBinaryDoubleExpr.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleBinaryDoubleExpr.java @@ -95,4 +95,7 @@ public class OracleBinaryDoubleExpr extends SQLNumericLiteralExpr implements Ora this.setValue(number.doubleValue()); } + public OracleBinaryDoubleExpr clone() { + return new OracleBinaryDoubleExpr(value); + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleBinaryFloatExpr.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleBinaryFloatExpr.java index c9c8fba5b9..fb8fbb0e9f 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleBinaryFloatExpr.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleBinaryFloatExpr.java @@ -32,6 +32,10 @@ public class OracleBinaryFloatExpr extends SQLNumericLiteralExpr implements Orac this.value = value; } + public OracleBinaryFloatExpr clone() { + return new OracleBinaryFloatExpr(value); + } + @Override public Number getNumber() { return value; diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleIntervalExpr.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleIntervalExpr.java index 67218324b7..71658a5eff 100755 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleIntervalExpr.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleIntervalExpr.java @@ -34,6 +34,19 @@ public class OracleIntervalExpr extends SQLExprImpl implements SQLLiteralExpr, O } + public OracleIntervalExpr clone() { + OracleIntervalExpr x = new OracleIntervalExpr(); + if (value != null) { + x.setValue(value.clone()); + } + x.type = type; + x.precision = precision; + x.factionalSecondsPrecision = factionalSecondsPrecision; + x.toType = toType; + x.toFactionalSecondsPrecision = toFactionalSecondsPrecision; + return x; + } + public SQLExpr getValue() { return this.value; } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleCheck.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleCheck.java index b1d9b4f822..a8ff9288a8 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleCheck.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleCheck.java @@ -84,4 +84,21 @@ public class OracleCheck extends SQLCheck implements OracleConstraint, OracleSQL this.using = using; } + public void cloneTo(OracleCheck x) { + super.cloneTo(x); + if (using != null) { + x.setUsing(using.clone()); + } + if (exceptionsInto != null) { + x.setExceptionsInto(exceptionsInto.clone()); + } + x.initially = initially; + x.deferrable = deferrable; + } + + public OracleCheck clone() { + OracleCheck x = new OracleCheck(); + cloneTo(x); + return x; + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleConstraint.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleConstraint.java index ef4bb9a814..7daa3b2b31 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleConstraint.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleConstraint.java @@ -48,4 +48,6 @@ public interface OracleConstraint extends OracleSQLObject, SQLConstraint, SQLTab public static enum Initially { DEFERRED, IMMEDIATE } + + OracleConstraint clone(); } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleExceptionStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleExceptionStatement.java index 9fc8972330..9847ec51b8 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleExceptionStatement.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleExceptionStatement.java @@ -72,6 +72,18 @@ public class OracleExceptionStatement extends OracleStatementImpl implements Ora visitor.endVisit(this); } + public Item clone() { + Item x = new Item(); + if (when != null) { + x.setWhen(when.clone()); + } + for (SQLStatement stmt : statements) { + SQLStatement stmt2 = stmt.clone(); + stmt2.setParent(x); + x.statements.add(stmt2); + } + return x; + } } @Override @@ -81,4 +93,14 @@ public class OracleExceptionStatement extends OracleStatementImpl implements Ora } visitor.endVisit(this); } + + public OracleExceptionStatement clone() { + OracleExceptionStatement x = new OracleExceptionStatement(); + for (Item item : items) { + Item item2 = item.clone(); + item2.setParent(x); + x.items.add(item2); + } + return x; + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleForStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleForStatement.java index 984b768e7e..53c2a18dfe 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleForStatement.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleForStatement.java @@ -86,4 +86,24 @@ public class OracleForStatement extends OracleStatementImpl { } this.endLabel = endLabel; } + + public OracleForStatement clone() { + OracleForStatement x = new OracleForStatement(); + if (index != null) { + x.setIndex(index.clone()); + } + if (range != null) { + x.setRange(range.clone()); + } + for (SQLStatement stmt : statements) { + SQLStatement stmt2 = stmt.clone(); + stmt2.setParent(x); + x.statements.add(stmt2); + } + x.all = all; + if (endLabel != null) { + x.setEndLabel(endLabel.clone()); + } + return x; + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleForeignKey.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleForeignKey.java index ea2d2d4de4..b63bb006dd 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleForeignKey.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleForeignKey.java @@ -86,4 +86,21 @@ public class OracleForeignKey extends SQLForeignKeyImpl implements OracleConstra this.using = using; } + public void cloneTo(OracleForeignKey x) { + super.cloneTo(x); + if (using != null) { + x.setUsing(using.clone()); + } + if (exceptionsInto != null) { + x.setExceptionsInto(exceptionsInto.clone()); + } + x.initially = initially; + x.deferrable = deferrable; + } + + public OracleForeignKey clone() { + OracleForeignKey x = new OracleForeignKey(); + cloneTo(x); + return x; + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleInsertStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleInsertStatement.java index b36e780847..149cf14ba8 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleInsertStatement.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleInsertStatement.java @@ -28,9 +28,24 @@ import com.alibaba.druid.sql.visitor.SQLASTVisitor; public class OracleInsertStatement extends SQLInsertStatement implements OracleStatement { - private OracleReturningClause returning; + private OracleReturningClause returning; private SQLErrorLoggingClause errorLogging; - private List hints = new ArrayList(); + private List hints = new ArrayList(); + + public void cloneTo(OracleInsertStatement x) { + super.cloneTo(x); + if (returning != null) { + x.setReturning(returning.clone()); + } + if (errorLogging != null) { + x.setErrorLogging(errorLogging.clone()); + } + for (SQLHint hint : hints) { + SQLHint h2 = hint.clone(); + h2.setParent(x); + x.hints.add(h2); + } + } public List getHints() { return hints; @@ -77,4 +92,10 @@ public class OracleInsertStatement extends SQLInsertStatement implements OracleS public void output(StringBuffer buf) { new OracleOutputVisitor(buf).visit(this); } + + public OracleInsertStatement clone() { + OracleInsertStatement x = new OracleInsertStatement(); + cloneTo(x); + return x; + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleMultiInsertStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleMultiInsertStatement.java index aa23298ee7..5d08aefa06 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleMultiInsertStatement.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleMultiInsertStatement.java @@ -198,5 +198,21 @@ public class OracleMultiInsertStatement extends OracleStatementImpl { visitor.endVisit(this); } + + public void cloneTo(InsertIntoClause x) { + super.cloneTo(x); + if (returning != null) { + x.setReturning(returning.clone()); + } + if (errorLogging != null) { + x.setErrorLogging(errorLogging.clone()); + } + } + + public InsertIntoClause clone() { + InsertIntoClause x = new InsertIntoClause(); + cloneTo(x); + return x; + } } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleSelectRestriction.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleSelectRestriction.java index 024fe0eb2b..a616f5d78a 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleSelectRestriction.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleSelectRestriction.java @@ -47,6 +47,14 @@ public abstract class OracleSelectRestriction extends OracleSQLObjectImpl { visitor.endVisit(this); } + + public CheckOption clone() { + CheckOption x = new CheckOption(); + if (constraint != null) { + x.setConstraint(constraint.clone()); + } + return x; + } } public static class ReadOnly extends OracleSelectRestriction { @@ -60,5 +68,12 @@ public abstract class OracleSelectRestriction extends OracleSQLObjectImpl { visitor.endVisit(this); } + + public ReadOnly clone() { + ReadOnly x = new ReadOnly(); + return x; + } } + + } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleUnique.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleUnique.java index 5909636178..02b7c4de80 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleUnique.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleUnique.java @@ -83,4 +83,22 @@ public class OracleUnique extends SQLUnique implements OracleConstraint, OracleS this.initially = initially; } + public void cloneTo(OracleUnique x) { + super.cloneTo(x); + if (using != null) { + x.setUsing(using.clone()); + } + if (exceptionsInto != null) { + x.setExceptionsInto(exceptionsInto.clone()); + } + x.initially = initially; + x.deferrable = deferrable; + } + + public OracleUnique clone() { + OracleUnique x = new OracleUnique(); + cloneTo(x); + return x; + } + } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/PGWithClause.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/PGWithClause.java index 8aa79c05c6..e6e5e6215f 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/PGWithClause.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/PGWithClause.java @@ -48,4 +48,15 @@ public class PGWithClause extends PGSQLObjectImpl { } visitor.endVisit(this); } + + public PGWithClause clone() { + PGWithClause x = new PGWithClause(); + x.recursive = recursive; + for (PGWithQuery w : withQuery) { + PGWithQuery w2 = w.clone(); + w2.setParent(x); + x.withQuery.add(w2); + } + return x; + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/PGWithQuery.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/PGWithQuery.java index b1770c1d02..149a03be85 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/PGWithQuery.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/PGWithQuery.java @@ -64,4 +64,22 @@ public class PGWithQuery extends PGSQLObjectImpl { } visitor.endVisit(this); } + + public PGWithQuery clone() { + PGWithQuery x = new PGWithQuery(); + + if (name != null) { + x.setName(name.clone()); + } + for (SQLExpr c : columns) { + SQLExpr c2 = c.clone(); + c2.setParent(x); + x.columns.add(c); + } + if (query != null) { + x.setQuery(query.clone()); + } + + return x; + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/expr/PGIntervalExpr.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/expr/PGIntervalExpr.java index 812dd75113..8fa46f540e 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/expr/PGIntervalExpr.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/expr/PGIntervalExpr.java @@ -65,4 +65,12 @@ public class PGIntervalExpr extends SQLExprImpl implements SQLLiteralExpr,PGExpr protected void accept0(SQLASTVisitor visitor) { this.accept0((PGASTVisitor) visitor); } + + public PGIntervalExpr clone() { + PGIntervalExpr x = new PGIntervalExpr(); + if (value != null) { + x.setValue(value.clone()); + } + return x; + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGInsertStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGInsertStatement.java index fa8c2036dd..ee5d540f8f 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGInsertStatement.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGInsertStatement.java @@ -31,6 +31,22 @@ public class PGInsertStatement extends SQLInsertStatement implements PGSQLStatem private SQLExpr returning; private boolean defaultValues = false; + public void cloneTo(PGInsertStatement x) { + super.cloneTo(x); + if (with != null) { + x.setWith(with.clone()); + } + for (ValuesClause v : valuesList) { + ValuesClause v2 = v.clone(); + v2.setParent(x); + x.valuesList.add(v2); + } + if (returning != null) { + x.setReturning(returning.clone()); + } + x.defaultValues = defaultValues; + } + public SQLExpr getReturning() { return returning; } @@ -96,4 +112,10 @@ public class PGInsertStatement extends SQLInsertStatement implements PGSQLStatem visitor.endVisit(this); } + + public PGInsertStatement clone() { + PGInsertStatement x = new PGInsertStatement(); + cloneTo(x); + return x; + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/SQLServerOutput.java b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/SQLServerOutput.java index ef560d774e..607b09ecc4 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/SQLServerOutput.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/SQLServerOutput.java @@ -58,4 +58,21 @@ public class SQLServerOutput extends SQLServerObjectImpl { return selectList; } + public SQLServerOutput clone() { + SQLServerOutput x = new SQLServerOutput(); + if (into != null) { + x.setInto(into.clone()); + } + for (SQLExpr c : columns) { + SQLExpr c2 = c.clone(); + c2.setParent(x); + x.columns.add(c2); + } + for (SQLSelectItem item : selectList) { + SQLSelectItem item2 = item.clone(); + item2.setParent(x); + x.selectList.add(item2); + } + return x; + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/SQLServerTop.java b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/SQLServerTop.java index 64780753d5..91fdcab95a 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/SQLServerTop.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/SQLServerTop.java @@ -65,4 +65,13 @@ public class SQLServerTop extends SQLServerObjectImpl { visitor.endVisit(this); } + public SQLServerTop clone() { + SQLServerTop x = new SQLServerTop(); + if (expr != null) { + x.setExpr(expr.clone()); + } + x.percent = percent; + x.withTies = withTies; + return x; + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/stmt/SQLServerInsertStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/stmt/SQLServerInsertStatement.java index dedf3addd0..4717df19fa 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/stmt/SQLServerInsertStatement.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/stmt/SQLServerInsertStatement.java @@ -33,6 +33,17 @@ public class SQLServerInsertStatement extends SQLInsertStatement implements SQLS private SQLServerOutput output; + public void cloneTo(SQLServerInsertStatement x) { + super.cloneTo(x); + x.defaultValues = defaultValues; + if (top != null) { + x.setTop(top.clone()); + } + if (output != null) { + x.setOutput(output.clone()); + } + } + @Override protected void accept0(SQLASTVisitor visitor) { this.accept0((SQLServerASTVisitor) visitor); @@ -76,4 +87,9 @@ public class SQLServerInsertStatement extends SQLInsertStatement implements SQLS this.top = top; } + public SQLServerInsertStatement clone() { + SQLServerInsertStatement x = new SQLServerInsertStatement(); + cloneTo(x); + return x; + } } diff --git a/src/main/java/com/alibaba/druid/sql/repository/SchemaRepository.java b/src/main/java/com/alibaba/druid/sql/repository/SchemaRepository.java index eff7133a9a..79faca4628 100644 --- a/src/main/java/com/alibaba/druid/sql/repository/SchemaRepository.java +++ b/src/main/java/com/alibaba/druid/sql/repository/SchemaRepository.java @@ -17,10 +17,7 @@ package com.alibaba.druid.sql.repository; import com.alibaba.druid.DruidRuntimeException; import com.alibaba.druid.sql.SQLUtils; -import com.alibaba.druid.sql.ast.SQLDataType; -import com.alibaba.druid.sql.ast.SQLExpr; -import com.alibaba.druid.sql.ast.SQLName; -import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.ast.*; import com.alibaba.druid.sql.ast.expr.SQLAggregateExpr; import com.alibaba.druid.sql.ast.expr.SQLAllColumnExpr; import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; @@ -32,7 +29,11 @@ import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlShowColumnsStateme import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlShowCreateTableStatement; import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor; import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitorAdapter; +import com.alibaba.druid.sql.dialect.odps.ast.OdpsSelectQueryBlock; +import com.alibaba.druid.sql.dialect.odps.visitor.OdpsASTVisitorAdapter; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleCreateTableStatement; +import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectQueryBlock; +import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectTableReference; import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitorAdapter; import com.alibaba.druid.sql.visitor.SQLASTVisitor; import com.alibaba.druid.sql.visitor.SQLASTVisitorAdapter; @@ -50,6 +51,7 @@ public class SchemaRepository { private Schema defaultSchema; protected String dbType; protected SQLASTVisitor consoleVisitor; + protected SQLASTVisitor resolveVisitor; public SchemaRepository() { @@ -60,8 +62,10 @@ public class SchemaRepository { if (JdbcConstants.MYSQL.equals(dbType)) { consoleVisitor = new MySqlConsoleSchemaVisitor(); + resolveVisitor = new MySqlResolveVisitor(); } else if (JdbcConstants.ORACLE.equals(dbType)) { consoleVisitor = new OracleConsoleSchemaVisitor(); + resolveVisitor = new OracleResolveVisitor(); } else { consoleVisitor = new DefaultConsoleSchemaVisitor(); } @@ -113,8 +117,15 @@ public class SchemaRepository { return getDefaultSchema(); } - String normalizedName = SQLUtils.normalize(name) - .toLowerCase(); + name = SQLUtils.normalize(name); + String normalizedName = name.toLowerCase(); + + if (getDefaultSchema() != null && defaultSchema.getName() == null) { + defaultSchema.setName(name); + schemas.put(normalizedName, defaultSchema); + return defaultSchema; + } + Schema schema = schemas.get(normalizedName); if (schema == null) { schema = new Schema(this, name); @@ -228,6 +239,16 @@ public class SchemaRepository { return getDefaultSchema().getViewCount(); } + public String resolve(String input) { + List stmtList = SQLUtils.parseStatements(input, dbType); + + for (SQLStatement stmt : stmtList) { + stmt.accept(resolveVisitor); + } + + return SQLUtils.toSQLString(stmtList, dbType); + } + public String console(String input) { try { StringBuffer buf = new StringBuffer(); @@ -300,85 +321,148 @@ public class SchemaRepository { return null; } - public SQLASTVisitor createResolveVisitor() { - if (JdbcConstants.MYSQL.equals(dbType)) { - return new MySqlResolveVisitor(); - } - - throw new DruidRuntimeException("dbType not support : " + dbType); - } - public class MySqlResolveVisitor extends MySqlASTVisitorAdapter { public boolean visit(SQLExprTableSource x) { - if (x.getSchemaObject() != null) { - return false; - } - - SQLExpr expr = x.getExpr(); - if (expr instanceof SQLName) { - SchemaObject table = findTable((SQLName) expr); - if (table != null) { - x.setSchemaObject(table); - } - } + resolve(this, x); return false; } public boolean visit(MySqlSelectQueryBlock x) { - SQLTableSource from = x.getFrom(); - from.accept(this); + x.getFrom().accept(this); - List selectList = x.getSelectList(); + resolve(this, x); + return super.visit(x); + } + } - List columns = new ArrayList(); - for (int i = selectList.size() - 1; i >= 0; i--) { - SQLSelectItem selectItem = selectList.get(i); - SQLExpr expr = selectItem.getExpr(); - if (expr instanceof SQLAllColumnExpr) { - extractColumns(from, columns); - } else if (expr instanceof SQLPropertyExpr) { - SQLPropertyExpr propertyExpr = (SQLPropertyExpr) expr; - String ownerName = propertyExpr.getOwnernName(); - if (propertyExpr.getName().equals("*")) { - SQLTableSource tableSource = x.findTableSource(ownerName); - extractColumns(tableSource, columns); - } + public class OracleResolveVisitor extends OracleASTVisitorAdapter { + public boolean visit(OracleSelectTableReference x) { + resolve(this, x); + return false; + } - SQLColumnDefinition column = propertyExpr.getResolvedColumn(); - if (column != null) { - continue; - } - SQLTableSource tableSource = x.findTableSource(propertyExpr.getOwnernName()); - if (tableSource != null) { - column = tableSource.findColumn(propertyExpr.getName()); - if (column != null) { - propertyExpr.setResolvedColumn(column); - } - } - } else if (expr instanceof SQLIdentifierExpr) { - SQLIdentifierExpr identExpr = (SQLIdentifierExpr) expr; - SQLColumnDefinition column = identExpr.getResolvedColumn(); - if (column != null) { - continue; - } - column = from.findColumn(identExpr.getName()); - if (column != null) { - identExpr.setResolvedColumn(column); - } + public boolean visit(SQLExprTableSource x) { + resolve(this, x); + return false; + } + + public boolean visit(OracleSelectQueryBlock x) { + x.getFrom().accept(this); + + resolve(this, x); + return super.visit(x); + } + + public boolean visit(SQLIdentifierExpr x) { + resolve(this, x); + return true; + } + } + + public class OdpsResolveVisitor extends OdpsASTVisitorAdapter { + + public boolean visit(SQLExprTableSource x) { + resolve(this, x); + return false; + } + + public boolean visit(OdpsSelectQueryBlock x) { + resolve(this, x); + return super.visit(x); + } + } + + private void resolve(SQLASTVisitor visitor, SQLIdentifierExpr x) { + SQLSelectQueryBlock queryBlock = null; + for (SQLObject parent = x.getParent(); parent != null; parent = parent.getParent()) { + if (parent instanceof SQLTableSource) { + return; + } + if (parent instanceof SQLSelectQueryBlock) { + queryBlock = (SQLSelectQueryBlock) parent; + break; + } + } + + if (queryBlock == null) { + return; + } + + String ident = x.getName(); + SQLTableSource tableSource = queryBlock.findTableSourceWithColumn(ident); + if (tableSource != null) { + String alias = tableSource.computeAlias(); + SQLPropertyExpr propertyExpr = new SQLPropertyExpr(alias, ident); + SQLUtils.replaceInParent(x, propertyExpr); + } + } + + private void resolve(SQLASTVisitor visitor, SQLExprTableSource x) { + if (x.getSchemaObject() != null) { + return; + } + + SQLExpr expr = x.getExpr(); + if (expr instanceof SQLName) { + SchemaObject table = findTable((SQLName) expr); + if (table != null) { + x.setSchemaObject(table); + } + } + } + + private void resolve(SQLASTVisitor visitor, SQLSelectQueryBlock x) { + SQLTableSource from = x.getFrom(); + from.accept(visitor); + + List selectList = x.getSelectList(); + + List columns = new ArrayList(); + for (int i = selectList.size() - 1; i >= 0; i--) { + SQLSelectItem selectItem = selectList.get(i); + SQLExpr expr = selectItem.getExpr(); + if (expr instanceof SQLAllColumnExpr) { + extractColumns(from, columns); + } else if (expr instanceof SQLPropertyExpr) { + SQLPropertyExpr propertyExpr = (SQLPropertyExpr) expr; + String ownerName = propertyExpr.getOwnernName(); + if (propertyExpr.getName().equals("*")) { + SQLTableSource tableSource = x.findTableSource(ownerName); + extractColumns(tableSource, columns); } - if (columns.size() > 0) { - for (SQLSelectItem column : columns) { - column.setParent(x); + SQLColumnDefinition column = propertyExpr.getResolvedColumn(); + if (column != null) { + continue; + } + SQLTableSource tableSource = x.findTableSource(propertyExpr.getOwnernName()); + if (tableSource != null) { + column = tableSource.findColumn(propertyExpr.getName()); + if (column != null) { + propertyExpr.setResolvedColumn(column); } - - selectList.remove(i); - selectList.addAll(i, columns); + } + } else if (expr instanceof SQLIdentifierExpr) { + SQLIdentifierExpr identExpr = (SQLIdentifierExpr) expr; + SQLColumnDefinition column = identExpr.getResolvedColumn(); + if (column != null) { + continue; + } + column = from.findColumn(identExpr.getName()); + if (column != null) { + identExpr.setResolvedColumn(column); } } - - return super.visit(x); + + if (columns.size() > 0) { + for (SQLSelectItem column : columns) { + column.setParent(x); + } + + selectList.remove(i); + selectList.addAll(i, columns); + } } } @@ -412,10 +496,6 @@ public class SchemaRepository { return null; } - public class OracleResolveVisitor extends OracleASTVisitorAdapter { - - } - public class MySqlConsoleSchemaVisitor extends MySqlASTVisitorAdapter { public boolean visit(SQLDropSequenceStatement x) { acceptDropSequence(x); @@ -461,6 +541,13 @@ public class SchemaRepository { acceptAlterTable(x); return false; } + + + public boolean visit(SQLUseStatement x) { + String schema = x.getDatabase().getSimpleName(); + setDefaultSchema(schema); + return false; + } } public class OracleConsoleSchemaVisitor extends OracleASTVisitorAdapter { @@ -508,6 +595,12 @@ public class SchemaRepository { acceptAlterTable(x); return false; } + + public boolean visit(SQLUseStatement x) { + String schema = x.getDatabase().getSimpleName(); + setDefaultSchema(schema); + return false; + } } public class DefaultConsoleSchemaVisitor extends SQLASTVisitorAdapter { @@ -575,7 +668,7 @@ public class SchemaRepository { SQLSelect select = x.getSelect(); if (select != null) { - select.accept(createResolveVisitor()); + select.accept(resolveVisitor); SQLSelectQueryBlock queryBlock = select.getFirstQueryBlock(); if (queryBlock != null) { @@ -601,7 +694,7 @@ public class SchemaRepository { return false; } - table = new SchemaObjectImpl(name, SchemaObjectType.Table, x); + table = new SchemaObjectImpl(name, SchemaObjectType.Table, x.clone()); String name_lower = SQLUtils.normalize(name).toLowerCase(); schema.objects.put(name_lower, table); return true; @@ -632,7 +725,7 @@ public class SchemaRepository { return false; } - SchemaObject object = new SchemaObjectImpl(name, SchemaObjectType.View, x); + SchemaObject object = new SchemaObjectImpl(name, SchemaObjectType.View, x.clone()); String name_lower = SQLUtils.normalize(name).toLowerCase(); schema.objects.put(name_lower, object); return true; @@ -644,7 +737,7 @@ public class SchemaRepository { Schema schema = findSchema(schemaName, true); String name = x.getName().getSimpleName(); - SchemaObject object = new SchemaObjectImpl(name, SchemaObjectType.Index); + SchemaObject object = new SchemaObjectImpl(name, SchemaObjectType.Index, x.clone()); String name_lower = SQLUtils.normalize(name).toLowerCase(); schema.objects.put(name_lower, object); @@ -656,7 +749,7 @@ public class SchemaRepository { Schema schema = findSchema(schemaName, true); String name = x.getName().getSimpleName(); - SchemaObject object = new SchemaObjectImpl(name, SchemaObjectType.Function); + SchemaObject object = new SchemaObjectImpl(name, SchemaObjectType.Function, x.clone()); String name_lower = SQLUtils.normalize(name).toLowerCase(); schema.functions.put(name_lower, object); diff --git a/src/main/java/com/alibaba/druid/util/JdbcUtils.java b/src/main/java/com/alibaba/druid/util/JdbcUtils.java index ea1999264f..e2abba5403 100644 --- a/src/main/java/com/alibaba/druid/util/JdbcUtils.java +++ b/src/main/java/com/alibaba/druid/util/JdbcUtils.java @@ -25,15 +25,8 @@ import java.io.Closeable; import java.io.InputStream; import java.io.PrintStream; import java.net.URL; -import java.sql.Connection; +import java.sql.*; import java.sql.Date; -import java.sql.Driver; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.ResultSetMetaData; -import java.sql.SQLException; -import java.sql.Statement; -import java.sql.Types; import java.util.*; /** @@ -117,6 +110,30 @@ public final class JdbcUtils implements JdbcConstants { } } + public static void close(Blob x) { + if (x == null) { + return; + } + + try { + x.free(); + } catch (Exception e) { + LOG.debug("close error", e); + } + } + + public static void close(Clob x) { + if (x == null) { + return; + } + + try { + x.free(); + } catch (Exception e) { + LOG.debug("close error", e); + } + } + public static void printResultSet(ResultSet rs) throws SQLException { printResultSet(rs, System.out); } diff --git a/src/main/java/com/alibaba/druid/util/Utils.java b/src/main/java/com/alibaba/druid/util/Utils.java index e5a733977d..ed72592d30 100644 --- a/src/main/java/com/alibaba/druid/util/Utils.java +++ b/src/main/java/com/alibaba/druid/util/Utils.java @@ -200,7 +200,7 @@ public class Utils { if (className == null) { return null; } - + try { return Class.forName(className); } catch (ClassNotFoundException e) { @@ -236,7 +236,7 @@ public class Utils { /** * murmur hash 2.0, The murmur hash is a relatively fast hash function from http://murmurhash.googlepages.com/ for * platforms with efficient multiplication. - * + * * @author Viliam Holub */ public static long murmurhash2_64(final byte[] data, int length, int seed) { @@ -250,13 +250,13 @@ public class Utils { for (int i = 0; i < length8; i++) { final int i8 = i * 8; long k = ((long) data[i8 + 0] & 0xff) // - + (((long) data[i8 + 1] & 0xff) << 8) // - + (((long) data[i8 + 2] & 0xff) << 16)// - + (((long) data[i8 + 3] & 0xff) << 24) // - + (((long) data[i8 + 4] & 0xff) << 32)// - + (((long) data[i8 + 5] & 0xff) << 40)// - + (((long) data[i8 + 6] & 0xff) << 48) // - + (((long) data[i8 + 7] & 0xff) << 56); + + (((long) data[i8 + 1] & 0xff) << 8) // + + (((long) data[i8 + 2] & 0xff) << 16)// + + (((long) data[i8 + 3] & 0xff) << 24) // + + (((long) data[i8 + 4] & 0xff) << 32)// + + (((long) data[i8 + 5] & 0xff) << 40)// + + (((long) data[i8 + 6] & 0xff) << 48) // + + (((long) data[i8 + 7] & 0xff) << 56); k *= m; k ^= k >>> r; diff --git a/src/test/java/com/alibaba/druid/bvt/sql/repository/OracleJoinResolveTest.java b/src/test/java/com/alibaba/druid/bvt/sql/repository/OracleJoinResolveTest.java new file mode 100644 index 0000000000..35371beb10 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/repository/OracleJoinResolveTest.java @@ -0,0 +1,23 @@ +package com.alibaba.druid.bvt.sql.repository; + +import com.alibaba.druid.sql.repository.SchemaRepository; +import com.alibaba.druid.util.JdbcConstants; +import junit.framework.TestCase; + +/** + * Created by wenshao on 03/08/2017. + */ +public class OracleJoinResolveTest extends TestCase { + protected SchemaRepository repository = new SchemaRepository(JdbcConstants.ORACLE); + + public void test_for_issue() throws Exception { + repository.console("create table t_user (uid number(20, 0), gid number(20, 0), uname varchar2(20))"); + repository.console("create table t_group (id number(20, 0), name varchar2(20))"); + + assertEquals("SELECT a.uid, a.gid, a.uname\n" + + "FROM t_user a\n" + + "\tINNER JOIN t_group b\n" + + "WHERE a.uid = b.id" + , repository.resolve("select a.* from t_user a inner join t_group b where a.uid = id")); + } +}