From 465b7b34b994044eddc2976324690789e3ce3b36 Mon Sep 17 00:00:00 2001 From: wenshao Date: Tue, 23 May 2017 15:58:39 +0800 Subject: [PATCH] improved sql parser. --- .../alibaba/druid/sql/ast/SQLParameter.java | 21 ++ .../statement/SQLCreateFunctionStatement.java | 119 +++++++ .../statement/SQLDeclareStatement.java} | 9 +- .../statement/SQLWhileStatement.java} | 9 +- .../clause/MySqlDeclareHandlerStatement.java | 10 +- .../mysql/ast/clause/MySqlStatementType.java | 7 +- .../mysql/parser/MySqlStatementParser.java | 68 ++-- .../mysql/visitor/MySqlASTVisitor.java | 8 - .../mysql/visitor/MySqlASTVisitorAdapter.java | 11 - .../mysql/visitor/MySqlOutputVisitor.java | 104 +++--- .../mysql/visitor/MySqlSchemaStatVisitor.java | 15 - .../stmt/OracleCreatePackageStatement.java | 66 ++++ .../oracle/parser/OracleStatementParser.java | 337 +++++++++++++++--- .../oracle/visitor/OracleASTVisitor.java | 4 + .../visitor/OracleASTVisitorAdapter.java | 10 + .../oracle/visitor/OracleOutputVisitor.java | 131 ++++++- .../visitor/OracleSchemaStatVisitor.java | 10 + .../parser/SQLServerStatementParser.java | 4 +- .../visitor/SQLServerASTVisitor.java | 5 - .../visitor/SQLServerASTVisitorAdapter.java | 29 +- .../visitor/SQLServerOutputVisitor.java | 13 - .../visitor/SQLServerSchemaStatVisitor.java | 19 - .../druid/sql/parser/SQLExprParser.java | 3 +- .../druid/sql/parser/SQLStatementParser.java | 11 +- .../sql/visitor/SQLASTOutputVisitor.java | 39 +- .../druid/sql/visitor/SQLASTVisitor.java | 17 + .../sql/visitor/SQLASTVisitorAdapter.java | 33 ++ .../druid/sql/visitor/SchemaStatVisitor.java | 23 +- .../druid/bvt/sql/cobar/DALParserTest.java | 8 +- .../bvt/sql/mysql/START_TRANSACTION_Test.java | 2 +- .../create/MySqlCreateProcedureTest11.java | 79 ++++ ...MySqlParameterizedOutputVisitorTest_6.java | 6 +- .../create/OracleCreatePackageTest0.java | 231 ++++++++++++ .../sql/oracle/pl/Oracle_pl_exception_8.java | 2 - .../bvt/sql/oracle/pl/Oracle_pl_for_2.java | 2 - 35 files changed, 1205 insertions(+), 260 deletions(-) create mode 100644 src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateFunctionStatement.java rename src/main/java/com/alibaba/druid/sql/{dialect/sqlserver/ast/stmt/SQLServerDeclareStatement.java => ast/statement/SQLDeclareStatement.java} (83%) rename src/main/java/com/alibaba/druid/sql/{dialect/mysql/ast/clause/MySqlWhileStatement.java => ast/statement/SQLWhileStatement.java} (87%) create mode 100644 src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleCreatePackageStatement.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateProcedureTest11.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/oracle/create/OracleCreatePackageTest0.java 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 1ca47a5f46..f3582eabd8 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/SQLParameter.java +++ b/src/main/java/com/alibaba/druid/sql/ast/SQLParameter.java @@ -17,6 +17,9 @@ package com.alibaba.druid.sql.ast; import com.alibaba.druid.sql.visitor.SQLASTVisitor; +import java.util.ArrayList; +import java.util.List; + public class SQLParameter extends SQLObjectImpl { private SQLExpr name; @@ -26,6 +29,9 @@ public class SQLParameter extends SQLObjectImpl { private boolean noCopy = false; private boolean constant = false; + private SQLName cursorName; + private final List cursorParameters = new ArrayList(); + public SQLExpr getDefaultValue() { return defaultValue; } @@ -90,4 +96,19 @@ public class SQLParameter extends SQLObjectImpl { public void setConstant(boolean constant) { this.constant = constant; } + + public List getCursorParameters() { + return cursorParameters; + } + + public SQLName getCursorName() { + return cursorName; + } + + public void setCursorName(SQLName cursorName) { + if (cursorName != null) { + cursorName.setParent(this); + } + this.cursorName = cursorName; + } } 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 new file mode 100644 index 0000000000..e1206f072a --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateFunctionStatement.java @@ -0,0 +1,119 @@ +package com.alibaba.druid.sql.ast.statement; + +import com.alibaba.druid.sql.ast.*; +import com.alibaba.druid.sql.visitor.SQLASTVisitor; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by wenshao on 23/05/2017. + */ +public class SQLCreateFunctionStatement extends SQLStatementImpl { + private SQLName definer; + + private boolean create = true; + private boolean orReplace; + private SQLName name; + private SQLStatement block; + private List parameters = new ArrayList(); + + // for oracle + private String javaCallSpec; + + private SQLName authid; + + SQLDataType returnDataType; + + @Override + public void accept0(SQLASTVisitor visitor) { + if (visitor.visit(this)) { + acceptChild(visitor, definer); + acceptChild(visitor, name); + acceptChild(visitor, parameters); + acceptChild(visitor, block); + } + visitor.endVisit(this); + } + + public List getParameters() { + return parameters; + } + + public void setParameters(List parameters) { + this.parameters = parameters; + } + + public SQLName getName() { + return name; + } + + public void setName(SQLName name) { + this.name = name; + } + + public SQLStatement getBlock() { + return block; + } + + public void setBlock(SQLStatement block) { + if (block != null) { + block.setParent(this); + } + this.block = block; + } + + public SQLName getAuthid() { + return authid; + } + + public void setAuthid(SQLName authid) { + if (authid != null) { + authid.setParent(this); + } + this.authid = authid; + } + + public boolean isOrReplace() { + return orReplace; + } + + public void setOrReplace(boolean orReplace) { + this.orReplace = orReplace; + } + + public SQLName getDefiner() { + return definer; + } + + public void setDefiner(SQLName definer) { + this.definer = definer; + } + + public boolean isCreate() { + return create; + } + + public void setCreate(boolean create) { + this.create = create; + } + + public String getJavaCallSpec() { + return javaCallSpec; + } + + public void setJavaCallSpec(String javaCallSpec) { + this.javaCallSpec = javaCallSpec; + } + + public SQLDataType getReturnDataType() { + return returnDataType; + } + + public void setReturnDataType(SQLDataType returnDataType) { + if (returnDataType != null) { + returnDataType.setParent(this); + } + this.returnDataType = returnDataType; + } +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/stmt/SQLServerDeclareStatement.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLDeclareStatement.java similarity index 83% rename from src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/stmt/SQLServerDeclareStatement.java rename to src/main/java/com/alibaba/druid/sql/ast/statement/SQLDeclareStatement.java index 8fe52c0a1c..734e78e87c 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/stmt/SQLServerDeclareStatement.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLDeclareStatement.java @@ -13,24 +13,27 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.alibaba.druid.sql.dialect.sqlserver.ast.stmt; +package com.alibaba.druid.sql.ast.statement; import java.util.ArrayList; import java.util.List; import com.alibaba.druid.sql.ast.SQLDeclareItem; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.ast.SQLStatementImpl; import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerObjectImpl; import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerStatement; import com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerASTVisitor; +import com.alibaba.druid.sql.visitor.SQLASTVisitor; -public class SQLServerDeclareStatement extends SQLServerObjectImpl implements SQLServerStatement { +public class SQLDeclareStatement extends SQLStatementImpl { protected List items = new ArrayList(); private String dbType; @Override - public void accept0(SQLServerASTVisitor visitor) { + public void accept0(SQLASTVisitor visitor) { if (visitor.visit(this)) { this.acceptChild(visitor, items); } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/clause/MySqlWhileStatement.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLWhileStatement.java similarity index 87% rename from src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/clause/MySqlWhileStatement.java rename to src/main/java/com/alibaba/druid/sql/ast/statement/SQLWhileStatement.java index 0a9b68db09..3d73271a74 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/clause/MySqlWhileStatement.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLWhileStatement.java @@ -13,21 +13,23 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.alibaba.druid.sql.dialect.mysql.ast.clause; +package com.alibaba.druid.sql.ast.statement; import java.util.ArrayList; import java.util.List; import com.alibaba.druid.sql.ast.SQLExpr; import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.ast.SQLStatementImpl; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlStatementImpl; import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor; +import com.alibaba.druid.sql.visitor.SQLASTVisitor; /** * * @author zz [455910092@qq.com] */ -public class MySqlWhileStatement extends MySqlStatementImpl { +public class SQLWhileStatement extends SQLStatementImpl { //while expr private SQLExpr condition; @@ -44,8 +46,7 @@ public class MySqlWhileStatement extends MySqlStatementImpl { this.labelName = labelName; } - @Override - public void accept0(MySqlASTVisitor visitor) { + public void accept0(SQLASTVisitor visitor) { if (visitor.visit(this)) { acceptChild(visitor, condition); acceptChild(visitor, statements); diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/clause/MySqlDeclareHandlerStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/clause/MySqlDeclareHandlerStatement.java index 2048e4efbd..d987abf8b9 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/clause/MySqlDeclareHandlerStatement.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/clause/MySqlDeclareHandlerStatement.java @@ -67,12 +67,10 @@ public class MySqlDeclareHandlerStatement extends MySqlStatementImpl{ @Override public void accept0(MySqlASTVisitor visitor) { - // TODO Auto-generated method stub - if (visitor.visit(this)) { - acceptChild(visitor, spStatement); - } - visitor.endVisit(this); - + if (visitor.visit(this)) { + acceptChild(visitor, spStatement); + } + visitor.endVisit(this); } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/clause/MySqlStatementType.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/clause/MySqlStatementType.java index ba86f5ce48..46e9a84dcc 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/clause/MySqlStatementType.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/clause/MySqlStatementType.java @@ -16,10 +16,7 @@ package com.alibaba.druid.sql.dialect.mysql.ast.clause; import com.alibaba.druid.sql.ast.SQLStatement; -import com.alibaba.druid.sql.ast.statement.SQLBlockStatement; -import com.alibaba.druid.sql.ast.statement.SQLIfStatement; -import com.alibaba.druid.sql.ast.statement.SQLLoopStatement; -import com.alibaba.druid.sql.ast.statement.SQLSelectStatement; +import com.alibaba.druid.sql.ast.statement.*; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlDeleteStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlInsertStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlUpdateStatement; @@ -38,7 +35,7 @@ public enum MySqlStatementType { //delete statement DELETE(MySqlDeleteStatement.class.getName()), //while statement - WHILE(MySqlWhileStatement.class.getName()), + WHILE(SQLWhileStatement.class.getName()), //begin-end IF(SQLIfStatement.class.getName()), //begin-end diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java index 110d5d02f4..a731a7a8e6 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java @@ -93,14 +93,12 @@ import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlCursorDeclareStatemen import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlDeclareConditionStatement; import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlDeclareHandlerStatement; import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlDeclareStatement; -import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlExplainType; -import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlFormatName; import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlHandlerType; import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlIterateStatement; import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlLeaveStatement; import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlRepeatStatement; import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlSelectIntoStatement; -import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlWhileStatement; +import com.alibaba.druid.sql.ast.statement.SQLWhileStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.CobarShowStatus; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlAlterTableAlterColumn; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlAlterTableChangeColumn; @@ -3450,26 +3448,8 @@ public class MySqlStatementParser extends SQLStatementParser { // declare statement if (lexer.token() == Token.DECLARE) { - char markChar = lexer.current(); - int markBp = lexer.bp(); - lexer.nextToken(); - lexer.nextToken(); - if (lexer.token() == Token.CURSOR)// cursor declare statement - { - lexer.reset(markBp, markChar, Token.DECLARE); - statementList.add(this.parseCursorDeclare()); - } else if (identifierEquals("HANDLER")) { - //DECLARE异常处理程序 [add by zhujun 2016-04-16] - lexer.reset(markBp, markChar, Token.DECLARE); - statementList.add(this.parseDeclareHandler()); - } else if (lexer.token() == Token.CONDITION) { - //DECLARE异常 [add by zhujun 2016-04-17] - lexer.reset(markBp, markChar, Token.DECLARE); - statementList.add(this.parseDeclareCondition()); - } else { - lexer.reset(markBp, markChar, Token.DECLARE); - statementList.add(this.parseDeclare()); - } + SQLStatement stmt = this.parseDeclare(); + statementList.add(stmt); continue; } @@ -3590,9 +3570,9 @@ public class MySqlStatementParser extends SQLStatementParser { * * @return MySqlWhileStatement */ - public MySqlWhileStatement parseWhile() { + public SQLWhileStatement parseWhile() { accept(Token.WHILE); - MySqlWhileStatement stmt = new MySqlWhileStatement(); + SQLWhileStatement stmt = new SQLWhileStatement(); stmt.setCondition(this.exprParser.expr()); @@ -3615,10 +3595,10 @@ public class MySqlStatementParser extends SQLStatementParser { * * @return MySqlWhileStatement */ - public MySqlWhileStatement parseWhile(String label) { + public SQLWhileStatement parseWhile(String label) { accept(Token.WHILE); - MySqlWhileStatement stmt = new MySqlWhileStatement(); + SQLWhileStatement stmt = new SQLWhileStatement(); stmt.setLabelName(label); @@ -3706,7 +3686,33 @@ public class MySqlStatementParser extends SQLStatementParser { /** * parse declare statement */ - public MySqlDeclareStatement parseDeclare() { + public SQLStatement parseDeclare() { + char markChar = lexer.current(); + int markBp = lexer.bp(); + + lexer.nextToken(); + + if (lexer.token() == Token.CONTINUE) { + lexer.reset(markBp, markChar, Token.DECLARE); + return this.parseDeclareHandler(); + } + + lexer.nextToken(); + if (lexer.token() == Token.CURSOR) { + lexer.reset(markBp, markChar, Token.DECLARE); + return this.parseCursorDeclare(); + } else if (identifierEquals("HANDLER")) { + //DECLARE异常处理程序 [add by zhujun 2016-04-16] + lexer.reset(markBp, markChar, Token.DECLARE); + return this.parseDeclareHandler(); + } else if (lexer.token() == Token.CONDITION) { + //DECLARE异常 [add by zhujun 2016-04-17] + lexer.reset(markBp, markChar, Token.DECLARE); + return this.parseDeclareCondition(); + } else { + lexer.reset(markBp, markChar, Token.DECLARE); + } + MySqlDeclareStatement stmt = new MySqlDeclareStatement(); accept(Token.DECLARE); // lexer.nextToken(); @@ -3777,7 +3783,9 @@ public class MySqlStatementParser extends SQLStatementParser { parseProcedureStatementList(loopStmt.getStatements()); accept(Token.END); accept(Token.LOOP); - acceptIdentifier(label); + if (lexer.token() != Token.SEMI) { + acceptIdentifier(label); + } accept(Token.SEMI); return loopStmt; } @@ -3967,7 +3975,7 @@ public class MySqlStatementParser extends SQLStatementParser { if (tokenName.equalsIgnoreCase("NOT")) {//for 'NOT FOUND' lexer.nextToken(); - acceptIdentifier("HANDLE"); + acceptIdentifier("FOUND"); condition.setType(ConditionType.SYSTEM); condition.setValue("NOT FOUND"); diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitor.java index 3fd4fcfaf4..7bb9dddc69 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitor.java @@ -32,7 +32,6 @@ import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlIterateStatement; import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlLeaveStatement; import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlRepeatStatement; import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlSelectIntoStatement; -import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlWhileStatement; import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlCharExpr; import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlExtractExpr; import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlIntervalExpr; @@ -525,13 +524,6 @@ public interface MySqlASTVisitor extends SQLASTVisitor { void endVisit(MySqlOrderingExpr x); - /** - * support procedure - */ - boolean visit(MySqlWhileStatement x); - - void endVisit(MySqlWhileStatement x); - boolean visit(MySqlCaseStatement x); void endVisit(MySqlCaseStatement x); diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitorAdapter.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitorAdapter.java index 05bb60e546..d9e5578a4a 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitorAdapter.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitorAdapter.java @@ -32,7 +32,6 @@ import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlIterateStatement; import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlLeaveStatement; import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlRepeatStatement; import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlSelectIntoStatement; -import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlWhileStatement; import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlCharExpr; import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlExtractExpr; import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlIntervalExpr; @@ -1138,16 +1137,6 @@ public class MySqlASTVisitorAdapter extends SQLASTVisitorAdapter implements MySq } - @Override - public boolean visit(MySqlWhileStatement x) { - return true; - } - - @Override - public void endVisit(MySqlWhileStatement x) { - - } - @Override public boolean visit(MySqlCaseStatement x) { return true; diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java index f93ed72cd6..0551d8074d 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java @@ -23,7 +23,6 @@ import com.alibaba.druid.sql.ast.SQLOrderBy; import com.alibaba.druid.sql.ast.SQLParameter; import com.alibaba.druid.sql.ast.SQLSetQuantifier; import com.alibaba.druid.sql.ast.SQLStatement; -import com.alibaba.druid.sql.ast.SQLSubPartitionBy; import com.alibaba.druid.sql.ast.expr.SQLAggregateExpr; import com.alibaba.druid.sql.ast.expr.SQLCharExpr; import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr; @@ -44,12 +43,10 @@ import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlCursorDeclareStatemen import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlDeclareConditionStatement; import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlDeclareHandlerStatement; import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlDeclareStatement; -import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlExplainType; import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlIterateStatement; import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlLeaveStatement; import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlRepeatStatement; import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlSelectIntoStatement; -import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlWhileStatement; import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlCharExpr; import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlExtractExpr; import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlIntervalExpr; @@ -690,21 +687,21 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV if (x.isGlobal()) { print0("@@global."); } else { - if ((!varName.startsWith("@")) // / - && (!varName.equals("?")) // - && (!varName.startsWith("#")) // - && (!varName.startsWith("$")) // - && (!varName.startsWith(":"))) { - - boolean subPartitionOption = false; - if (x.getParent() != null) { - subPartitionOption = x.getParent().getParent() instanceof SQLSubPartitionBy; - } - - if (!subPartitionOption) { - print0("@@"); - } - } +// if ((!varName.startsWith("@")) // / +// && (!varName.equals("?")) // +// && (!varName.startsWith("#")) // +// && (!varName.startsWith("$")) // +// && (!varName.startsWith(":"))) { +// +// boolean subPartitionOption = false; +// if (x.getParent() != null) { +// subPartitionOption = x.getParent().getParent() instanceof SQLSubPartitionBy; +// } +// +// if (!subPartitionOption) { +// print0("@@"); +// } +// } } for (int i = 0; i < x.getName().length(); ++i) { @@ -3154,6 +3151,28 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV print0(x.getLabelName()); print0(": "); } + if (x.getParameters().size() != 0) { + incrementIndent(); + if (x.getParent() instanceof SQLCreateProcedureStatement) { + printIndent(); + } + if (!(x.getParent() instanceof SQLCreateProcedureStatement)) { + print0(ucase ? "DECLARE" : "declare"); + println(); + } + + for (int i = 0, size = x.getParameters().size(); i < size; ++i) { + if (i != 0) { + println(); + } + SQLParameter param = x.getParameters().get(i); + param.accept(this); + print(';'); + } + + decrementIndent(); + println(); + } print0(ucase ? "BEGIN" : "begin"); incrementIndent(); println(); @@ -3215,41 +3234,12 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV return false; } - @Override - public boolean visit(MySqlWhileStatement x) { - if (x.getLabelName() != null && !x.getLabelName().equals("")) { - print0(x.getLabelName()); - print0(": "); - } - print0(ucase ? "WHILE " : "while "); - x.getCondition().accept(this); - print0(ucase ? " DO" : " do"); - println(); - for (int i = 0, size = x.getStatements().size(); i < size; ++i) { - SQLStatement item = x.getStatements().get(i); - item.setParent(x); - item.accept(this); - if (i != size - 1) { - println(); - } - } - println(); - print0(ucase ? "END WHILE" : "end while"); - if (x.getLabelName() != null && !x.getLabelName().equals("")) print(' '); - print0(x.getLabelName()); - return false; - } - - @Override - public void endVisit(MySqlWhileStatement x) { - - } - @Override public boolean visit(SQLIfStatement x) { print0(ucase ? "IF " : "if "); x.getCondition().accept(this); print0(ucase ? " THEN" : " then"); + incrementIndent(); println(); for (int i = 0, size = x.getStatements().size(); i < size; ++i) { SQLStatement item = x.getStatements().get(i); @@ -3259,6 +3249,7 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV println(); } } + decrementIndent(); println(); for (SQLIfStatement.ElseIf iterable_element : x.getElseIfList()) { iterable_element.accept(this); @@ -3275,6 +3266,7 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV print0(ucase ? "ELSE IF " : "else if "); x.getCondition().accept(this); print0(ucase ? " THEN" : " then"); + incrementIndent(); println(); for (int i = 0, size = x.getStatements().size(); i < size; ++i) { SQLStatement item = x.getStatements().get(i); @@ -3284,6 +3276,7 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV println(); } } + decrementIndent(); println(); return false; } @@ -3379,6 +3372,7 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV } print0(ucase ? "LOOP " : "loop "); + incrementIndent(); println(); for (int i = 0, size = x.getStatements().size(); i < size; ++i) { SQLStatement item = x.getStatements().get(i); @@ -3388,6 +3382,7 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV println(); } } + decrementIndent(); println(); print0(ucase ? "END LOOP" : "end loop"); if (x.getLabelName() != null && !x.getLabelName().equals("")) { @@ -3463,8 +3458,11 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV public boolean visit(MySqlCursorDeclareStatement x) { print0(ucase ? "DECLARE " : "declare "); print0(x.getCursorName()); - print0(ucase ? " CURSOR FOR " : " cursor for "); + print0(ucase ? " CURSOR FOR" : " cursor for"); + incrementIndent(); + println(); x.getSelect().accept(this); + decrementIndent(); return false; } @@ -3563,9 +3561,10 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV @Override public boolean visit(MySqlDeclareHandlerStatement x) { + String handleType = x.getHandleType().name(); print0(ucase ? "DECLARE " : "declare "); - print0(ucase ? x.getHandleType().toString().toUpperCase() : x.getHandleType().toString().toLowerCase()); + print0(ucase ? handleType : handleType.toLowerCase()); print0(ucase ? " HANDLER FOR " : " handler for "); for (int i = 0; i < x.getConditionValues().size(); i++) { ConditionValue cv = x.getConditionValues().get(i); @@ -3585,8 +3584,11 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV } } + incrementIndent(); println(); - return true; + x.getSpStatement().accept(this); + decrementIndent(); + return false; } @Override diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlSchemaStatVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlSchemaStatVisitor.java index db608d40da..f2504b876b 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlSchemaStatVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlSchemaStatVisitor.java @@ -47,7 +47,6 @@ import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlIterateStatement; import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlLeaveStatement; import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlRepeatStatement; import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlSelectIntoStatement; -import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlWhileStatement; import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlCharExpr; import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlExtractExpr; import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlIntervalExpr; @@ -1310,20 +1309,6 @@ public class MySqlSchemaStatVisitor extends SchemaStatVisitor implements MySqlAS } - /** - * support procedure - */ - @Override - public boolean visit(MySqlWhileStatement x) { - accept(x.getStatements()); - return false; - } - - @Override - public void endVisit(MySqlWhileStatement x) { - - } - @Override public boolean visit(MySqlCaseStatement x) { accept(x.getWhenList()); diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleCreatePackageStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleCreatePackageStatement.java new file mode 100644 index 0000000000..e1397361bf --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleCreatePackageStatement.java @@ -0,0 +1,66 @@ +package com.alibaba.druid.sql.dialect.oracle.ast.stmt; + +import com.alibaba.druid.sql.ast.SQLName; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor; +import com.alibaba.druid.util.JdbcConstants; +import org.apache.ibatis.jdbc.SQL; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by wenshao on 23/05/2017. + */ +public class OracleCreatePackageStatement extends OracleStatementImpl { + private boolean orReplace; + private SQLName name; + + private boolean body; + + private final List statements = new ArrayList(); + + public OracleCreatePackageStatement() { + super.setDbType(JdbcConstants.ORACLE); + } + + @Override + public void accept0(OracleASTVisitor visitor) { + if (visitor.visit(this)) { + acceptChild(visitor, name); + acceptChild(visitor, statements); + } + visitor.endVisit(this); + } + + public boolean isOrReplace() { + return orReplace; + } + + public void setOrReplace(boolean orReplace) { + this.orReplace = orReplace; + } + + public boolean isBody() { + return body; + } + + public void setBody(boolean body) { + this.body = body; + } + + public SQLName getName() { + return name; + } + + public void setName(SQLName name) { + if (name != null) { + name.setParent(this); + } + this.name = name; + } + + public List getStatements() { + return statements; + } +} 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 1065348e4d..9911261bd8 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 @@ -21,6 +21,7 @@ import java.util.List; import com.alibaba.druid.sql.ast.*; import com.alibaba.druid.sql.ast.expr.*; import com.alibaba.druid.sql.ast.statement.*; +import com.alibaba.druid.sql.ast.statement.SQLWhileStatement; import com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleReturningClause; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.*; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleAlterTableSplitPartition.NestedTablePartitionSpec; @@ -86,39 +87,53 @@ public class OracleStatementParser extends SQLStatementParser { } if (lexer.token() == (Token.SELECT)) { - SQLSelectStatement stmt = new SQLSelectStatement(new OracleSelectParser(this.exprParser).select(), JdbcConstants.ORACLE); + SQLStatement stmt = new SQLSelectStatement(new OracleSelectParser(this.exprParser).select(), JdbcConstants.ORACLE); + stmt.setParent(parent); statementList.add(stmt); continue; } if (lexer.token() == (Token.UPDATE)) { - statementList.add(parseUpdateStatement()); + SQLStatement stmt = parseUpdateStatement(); + stmt.setParent(parent); + statementList.add(stmt); continue; } if (lexer.token() == (Token.CREATE)) { - statementList.add(parseCreate()); + SQLStatement stmt = parseCreate(); + stmt.setParent(parent); + statementList.add(stmt); continue; } if (lexer.token() == Token.INSERT) { - statementList.add(parseInsert()); + SQLStatement stmt = parseInsert(); + stmt.setParent(parent); + statementList.add(stmt); continue; } if (lexer.token() == (Token.DELETE)) { - statementList.add(parseDeleteStatement()); + SQLStatement stmt = parseDeleteStatement(); + stmt.setParent(parent); + statementList.add(stmt); continue; } if (lexer.token() == (Token.SLASH)) { lexer.nextToken(); - statementList.add(new OraclePLSQLCommitStatement()); + + SQLStatement stmt = new OraclePLSQLCommitStatement(); + stmt.setParent(parent); + statementList.add(stmt); continue; } if (lexer.token() == Token.ALTER) { - statementList.add(parserAlter()); + SQLStatement stmt = parserAlter(); + stmt.setParent(parent); + statementList.add(stmt); continue; } @@ -128,32 +143,38 @@ public class OracleStatementParser extends SQLStatementParser { } if (lexer.token() == Token.LBRACE || identifierEquals("CALL")) { - statementList.add(this.parseCall()); + SQLStatement stmt = parseCall(); + stmt.setParent(parent); + statementList.add(stmt); continue; } if (lexer.token() == Token.MERGE) { - statementList.add(this.parseMerge()); + SQLStatement stmt = parseMerge(); + stmt.setParent(parent); + statementList.add(stmt); continue; } - if (lexer.token() == Token.BEGIN) { - statementList.add(this.parseBlock()); - continue; - } - - if (lexer.token() == Token.DECLARE) { - statementList.add(this.parseBlock()); + if (lexer.token() == Token.BEGIN + || lexer.token() == Token.DECLARE) { + SQLStatement stmt = parseBlock(); + stmt.setParent(parent); + statementList.add(stmt); continue; } if (lexer.token() == Token.LOCK) { - statementList.add(this.parseLock()); + SQLStatement stmt = parseLock(); + stmt.setParent(parent); + statementList.add(stmt); continue; } if (lexer.token() == Token.TRUNCATE) { - statementList.add(this.parseTruncate()); + SQLStatement stmt = parseTruncate(); + stmt.setParent(parent); + statementList.add(stmt); continue; } @@ -163,6 +184,7 @@ public class OracleStatementParser extends SQLStatementParser { SQLBinaryOpExpr binaryOpExpr = (SQLBinaryOpExpr) variant; if (binaryOpExpr.getOperator() == SQLBinaryOperator.Assignment) { SQLSetStatement stmt = new SQLSetStatement(binaryOpExpr.getLeft(), binaryOpExpr.getRight(), getDbType()); + stmt.setParent(parent); statementList.add(stmt); continue; } @@ -171,12 +193,14 @@ public class OracleStatementParser extends SQLStatementParser { SQLExpr value = this.exprParser.expr(); SQLSetStatement stmt = new SQLSetStatement(variant, value, getDbType()); + stmt.setParent(parent); statementList.add(stmt); continue; } if (lexer.token() == Token.EXCEPTION) { OracleExceptionStatement stmt = this.parseException(); + stmt.setParent(parent); if (parent instanceof SQLBlockStatement) { ((SQLBlockStatement) parent).setException(stmt); } else { @@ -192,6 +216,7 @@ public class OracleStatementParser extends SQLStatementParser { lexer.nextToken(); stmt.setWhen(this.exprParser.expr()); } + stmt.setParent(parent); statementList.add(stmt); continue; } @@ -208,12 +233,14 @@ public class OracleStatementParser extends SQLStatementParser { lexer.nextToken(); stmt.setWhen(this.exprParser.expr()); } + stmt.setParent(parent); statementList.add(stmt); continue; } if (lexer.token() == Token.FETCH || identifierEquals("FETCH")) { SQLStatement stmt = parseFetch(); + stmt.setParent(parent); statementList.add(stmt); continue; } @@ -259,7 +286,10 @@ public class OracleStatementParser extends SQLStatementParser { if (lexer.token() == Token.SELECT) { lexer.reset(bp, ch, Token.LPAREN); - statementList.add(this.parseSelect()); + + SQLStatement stmt = parseSelect(); + stmt.setParent(parent); + statementList.add(stmt); continue; } else { throw new ParserException("TODO : " + lexer.info()); @@ -267,7 +297,9 @@ public class OracleStatementParser extends SQLStatementParser { } if (lexer.token() == Token.SET) { - statementList.add(this.parseSet()); + SQLStatement stmt = parseSet(); + stmt.setParent(parent); + statementList.add(stmt); continue; } @@ -287,6 +319,7 @@ public class OracleStatementParser extends SQLStatementParser { } if (lexer.token() == Token.FOR) { OracleForStatement forStatement = this.parseFor(); + forStatement.setParent(parent); if (lexer.token() == Token.IDENTIFIER) { String strVal = lexer.stringVal(); int stmtListSize = statementList.size(); @@ -304,11 +337,15 @@ public class OracleStatementParser extends SQLStatementParser { continue; } if (lexer.token() == Token.LOOP) { - statementList.add(this.parseLoop()); + SQLStatement stmt = parseLoop(); + stmt.setParent(parent); + statementList.add(stmt); continue; } if (lexer.token() == Token.IF) { - statementList.add(this.parseIf()); + SQLStatement stmt = parseIf(); + stmt.setParent(parent); + statementList.add(stmt); continue; } @@ -316,6 +353,7 @@ public class OracleStatementParser extends SQLStatementParser { lexer.nextToken(); SQLName label = this.exprParser.name(); OracleGotoStatement stmt = new OracleGotoStatement(label); + stmt.setParent(parent); statementList.add(stmt); continue; } @@ -327,6 +365,7 @@ public class OracleStatementParser extends SQLStatementParser { lexer.nextToken(); } OracleCommitStatement stmt = new OracleCommitStatement(); + stmt.setParent(parent); if (identifierEquals("WRITE")) { stmt.setWrite(true); @@ -363,6 +402,7 @@ public class OracleStatementParser extends SQLStatementParser { lexer.nextToken(); OracleSavePointStatement stmt = new OracleSavePointStatement(); + stmt.setParent(parent); if (lexer.token() == Token.TO) { lexer.nextToken(); @@ -378,6 +418,7 @@ public class OracleStatementParser extends SQLStatementParser { SQLName label = this.exprParser.name(); OracleLabelStatement stmt = new OracleLabelStatement(label); accept(Token.GTGT); + stmt.setParent(parent); statementList.add(stmt); continue; } @@ -387,6 +428,7 @@ public class OracleStatementParser extends SQLStatementParser { if (lexer.token() == Token.TABLE) { SQLDropTableStatement stmt = parseDropTable(false); + stmt.setParent(parent); statementList.add(stmt); continue; } @@ -417,36 +459,42 @@ public class OracleStatementParser extends SQLStatementParser { if (lexer.token() == Token.INDEX) { SQLStatement stmt = parseDropIndex(); + stmt.setParent(parent); statementList.add(stmt); continue; } if (lexer.token() == Token.VIEW) { SQLStatement stmt = parseDropView(false); + stmt.setParent(parent); statementList.add(stmt); continue; } if (lexer.token() == Token.SEQUENCE) { SQLDropSequenceStatement stmt = parseDropSequece(false); + stmt.setParent(parent); statementList.add(stmt); continue; } if (lexer.token() == Token.TRIGGER) { SQLDropTriggerStatement stmt = parseDropTrigger(false); + stmt.setParent(parent); statementList.add(stmt); continue; } if (lexer.token() == Token.USER) { SQLDropUserStatement stmt = parseDropUser(); + stmt.setParent(parent); statementList.add(stmt); continue; } if (lexer.token() == Token.PROCEDURE) { SQLDropProcedureStatement stmt = parseDropProcedure(false); + stmt.setParent(parent); statementList.add(stmt); continue; } @@ -457,30 +505,35 @@ public class OracleStatementParser extends SQLStatementParser { if (lexer.token() == Token.NULL) { lexer.nextToken(); OracleExprStatement stmt = new OracleExprStatement(new SQLNullExpr()); + stmt.setParent(parent); statementList.add(stmt); continue; } if (lexer.token() == Token.OPEN) { SQLStatement stmt = this.parseOpen(); + stmt.setParent(parent); statementList.add(stmt); continue; } if (lexer.token() == Token.CLOSE) { SQLStatement stmt = this.parseClose(); + stmt.setParent(parent); statementList.add(stmt); continue; } if (lexer.token() == Token.CASE) { SQLStatement stmt = this.parseCase(); + stmt.setParent(parent); statementList.add(stmt); continue; } if (lexer.token() == Token.PROCEDURE) { SQLStatement stmt = this.parseCreateProcedure(); + stmt.setParent(parent); statementList.add(stmt); continue; } @@ -495,10 +548,126 @@ public class OracleStatementParser extends SQLStatementParser { break; } + if (lexer.token() == Token.FUNCTION) { + SQLStatement stmt = this.parseFunction(); + stmt.setParent(parent); + statementList.add(stmt); + continue; + } + + if (lexer.token() == Token.WHILE) { + SQLStatement stmt = this.parseWhile(); + stmt.setParent(parent); + statementList.add(stmt); + continue; + } + throw new ParserException("TODO : " + lexer.info()); } } + public SQLStatement parseWhile() { + accept(Token.WHILE); + + SQLWhileStatement stmt = new SQLWhileStatement(); + stmt.setDbType(dbType); + + stmt.setCondition(this.exprParser.expr()); + + accept(Token.LOOP); + + this.parseStatementList(stmt.getStatements(), -1, stmt); + accept(Token.END); + accept(Token.LOOP); + accept(Token.SEMI); + + return stmt; + } + + public SQLStatement parseFunction() { + SQLCreateFunctionStatement stmt = new SQLCreateFunctionStatement(); + stmt.setDbType(dbType); + + if (lexer.token() == Token.CREATE) { + lexer.nextToken(); + if (lexer.token() == Token.OR) { + lexer.nextToken(); + accept(Token.REPLACE); + stmt.setOrReplace(true); + } + } else { + stmt.setCreate(false); + } + + accept(Token.FUNCTION); + + SQLName procedureName = this.exprParser.name(); + stmt.setName(procedureName); + + if (lexer.token() == Token.LPAREN) { + lexer.nextToken(); + parserParameters(stmt.getParameters(), stmt); + accept(Token.RPAREN); + } + + acceptIdentifier("RETURN"); + SQLDataType returnDataType = this.exprParser.parseDataType(); + stmt.setReturnDataType(returnDataType); + + if (identifierEquals("AUTHID")) { + lexer.nextToken(); + String strVal = lexer.stringVal(); + if (identifierEquals("CURRENT_USER")) { + lexer.nextToken(); + } else { + acceptIdentifier("DEFINER"); + } + SQLName authid = new SQLIdentifierExpr(strVal); + stmt.setAuthid(authid); + } + + if (lexer.token() == Token.SEMI) { + lexer.nextToken(); + return stmt; + } + + if (lexer.token() == Token.IS) { + lexer.nextToken(); + } else { + accept(Token.AS); + } + + if (identifierEquals("LANGUAGE")) { + lexer.nextToken(); + if (identifierEquals("JAVA")) { + lexer.nextToken(); + acceptIdentifier("NAME"); + String javaCallSpec = lexer.stringVal(); + accept(Token.LITERAL_CHARS); + stmt.setJavaCallSpec(javaCallSpec); + } else { + throw new ParserException("TODO : " + lexer.info()); + } + return stmt; + } + + SQLBlockStatement block = this.parseBlock(); + + stmt.setBlock(block); + + if (identifierEquals(procedureName.getSimpleName())) { + lexer.nextToken(); + } + + // return stmt; + + if (identifierEquals(procedureName.getSimpleName())) { + lexer.nextToken(); + } + + return stmt; + } + public SQLStatement parseRaise() { lexer.nextToken(); OracleRaiseStatement stmt = new OracleRaiseStatement(); @@ -551,6 +720,7 @@ public class OracleStatementParser extends SQLStatementParser { accept(Token.IF); SQLIfStatement stmt = new SQLIfStatement(); + stmt.setDbType(dbType); stmt.setCondition(this.exprParser.expr()); @@ -571,30 +741,20 @@ public class OracleStatementParser extends SQLStatementParser { stmt.getElseIfList().add(elseIf); } - while (lexer.token() == Token.ELSE) { + if (lexer.token() == Token.ELSE) { lexer.nextToken(); - if (lexer.token() == Token.IF) { - lexer.nextToken(); - - SQLIfStatement.ElseIf elseIf = new SQLIfStatement.ElseIf(); - - elseIf.setCondition(this.exprParser.expr()); - - accept(Token.THEN); - this.parseStatementList(elseIf.getStatements()); - - stmt.getElseIfList().add(elseIf); - } else { - SQLIfStatement.Else elseItem = new SQLIfStatement.Else(); - this.parseStatementList(elseItem.getStatements()); - stmt.setElseItem(elseItem); - break; - } + SQLIfStatement.Else elseItem = new SQLIfStatement.Else(); + this.parseStatementList(elseItem.getStatements(), -1, elseItem); + stmt.setElseItem(elseItem); } accept(Token.END); accept(Token.IF); +// if (lexer.token() == Token.SEMI) { +// lexer.nextToken(); +// } + accept(Token.SEMI); return stmt; } @@ -1156,15 +1316,21 @@ public class OracleStatementParser extends SQLStatementParser { if (lexer.token() == Token.CURSOR) { lexer.nextToken(); - name = this.exprParser.name(); - - accept(Token.IS); - SQLSelect select = this.createSQLSelectParser().select(); - dataType = new SQLDataTypeImpl(); dataType.setName("CURSOR"); + name = this.exprParser.name(); + + if (lexer.token() == Token.LPAREN) { + lexer.nextToken(); + this.parserParameters(parameter.getCursorParameters(), parameter); + accept(Token.RPAREN); + } + + accept(Token.IS); + SQLSelect select = this.createSQLSelectParser().select(); parameter.setDefaultValue(new SQLQueryExpr(select)); + } else if (lexer.token() == Token.PROCEDURE) { break; } else if (identifierEquals("TYPE")) { @@ -1731,6 +1897,11 @@ public class OracleStatementParser extends SQLStatementParser { stmt.setAuthid(authid); } + if (lexer.token() == Token.SEMI) { + lexer.nextToken(); + return stmt; + } + if (lexer.token() == Token.IS) { lexer.nextToken(); } else { @@ -1765,4 +1936,80 @@ public class OracleStatementParser extends SQLStatementParser { public SQLUpdateStatement parseUpdateStatement() { return new OracleUpdateParser(this.lexer).parseUpdateStatement(); } + + public SQLStatement parseCreatePackage() { + accept(Token.CREATE); + + boolean repalce = false; + if (lexer.token() == Token.OR) { + lexer.nextToken(); + accept(Token.REPLACE); + repalce = true; + } + + acceptIdentifier("PACKAGE"); + + OracleCreatePackageStatement stmt = new OracleCreatePackageStatement(); + stmt.setOrReplace(repalce); + + if (identifierEquals("BODY")) { + lexer.nextToken(); + stmt.setBody(true); + } + + SQLName pkgName = this.exprParser.name(); + stmt.setName(pkgName); + + if (lexer.token() == Token.IS) { + lexer.nextToken(); + } else { + accept(Token.AS); + } + + // this.parseStatementList(stmt.getStatements(), -1, stmt); + for (;;) { + if (lexer.token() == Token.IDENTIFIER) { + + SQLDeclareStatement varDecl = new SQLDeclareStatement(); + varDecl.setDbType(dbType); + varDecl.setParent(stmt); + + SQLDeclareItem varItem = new SQLDeclareItem(); + + SQLName name = this.exprParser.name(); + varItem.setName(name); + + varItem.setDataType(this.exprParser.parseDataType()); + varItem.setParent(varDecl); + + varDecl.getItems().add(varItem); + + stmt.getStatements().add(varDecl); + accept(Token.SEMI); + } else if (lexer.token() == Token.FUNCTION) { + SQLStatement function = this.parseFunction(); + function.setParent(stmt); + stmt.getStatements().add(function); + accept(Token.SEMI); + } else if (lexer.token() == Token.PROCEDURE) { + SQLStatement proc = this.parseCreateProcedure(); + proc.setParent(stmt); + stmt.getStatements().add(proc); + accept(Token.SEMI); + } else if (lexer.token() == Token.END) { + break; + } else { + throw new ParserException("TODO : " + lexer.info()); + } + } + + accept(Token.END); + + if (identifierEquals(pkgName.getSimpleName())) { + lexer.nextToken(); + } + + accept(Token.SEMI); + return stmt; + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVisitor.java index 31d97a1d3a..b16ef4c57d 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVisitor.java @@ -460,4 +460,8 @@ public interface OracleASTVisitor extends SQLASTVisitor { boolean visit(OracleCreateTableStatement.OIDIndex x); void endVisit(OracleCreateTableStatement.OIDIndex x); + + boolean visit(OracleCreatePackageStatement x); + + void endVisit(OracleCreatePackageStatement x); } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVisitorAdapter.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVisitorAdapter.java index fe8733d86b..01fcf55b48 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVisitorAdapter.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVisitorAdapter.java @@ -1109,4 +1109,14 @@ public class OracleASTVisitorAdapter extends SQLASTVisitorAdapter implements Ora public void endVisit(OracleCreateTableStatement.OIDIndex x) { } + + @Override + public boolean visit(OracleCreatePackageStatement x) { + return true; + } + + @Override + public void endVisit(OracleCreatePackageStatement x) { + + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleOutputVisitor.java index 3ee3248e47..d3da005ad8 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleOutputVisitor.java @@ -116,14 +116,16 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS if (x instanceof OraclePLSQLCommitStatement || x instanceof OracleLabelStatement || x instanceof OracleExceptionStatement.Item - || x instanceof OracleExceptionStatement) { + || x instanceof OracleExceptionStatement + || x instanceof OracleCreatePackageStatement) { return; } if (parent instanceof SQLCreateProcedureStatement || parent instanceof OracleExceptionStatement.Item - || parent instanceof OracleForStatement) { + || parent instanceof OracleForStatement + || parent instanceof SQLCreateFunctionStatement) { return; } @@ -1358,9 +1360,14 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS if (x.getParameters().size() != 0) { incrementIndent(); if (x.getParent() instanceof SQLCreateProcedureStatement) { - printIndent(); + SQLCreateProcedureStatement procedureStatement = (SQLCreateProcedureStatement) x.getParent(); + if (procedureStatement.isCreate()) { + printIndent(); + } } - if (!(x.getParent() instanceof SQLCreateProcedureStatement)) { + if (!(x.getParent() instanceof SQLCreateProcedureStatement + || x.getParent() instanceof SQLCreateFunctionStatement) + ) { print0(ucase ? "DECLARE" : "declare"); println(); } @@ -2590,6 +2597,77 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS SQLStatement block = x.getBlock(); + if (!create) { + println(); + print("IS"); + println(); + } else { + println(); + if (block instanceof SQLBlockStatement) { + SQLBlockStatement blockStatement = (SQLBlockStatement) block; + if (blockStatement.getParameters().size() > 0 || authid != null) { + println(ucase ? "AS" : "as"); + } + } + } + + String javaCallSpec = x.getJavaCallSpec(); + if (javaCallSpec != null) { + print0(ucase ? "LANGUAGE JAVA NAME '" : "language java name '"); + print0(javaCallSpec); + print('\''); + return false; + } + + block.accept(this); + return false; + } + + @Override + public boolean visit(SQLCreateFunctionStatement x) { + boolean create = x.isCreate(); + if (!create) { + print0(ucase ? "FUNCTION " : "function "); + } else if (x.isOrReplace()) { + print0(ucase ? "CREATE OR REPLACE FUNCTION " : "create or replace function "); + } else { + print0(ucase ? "CREATE FUNCTION " : "create function "); + } + x.getName().accept(this); + + int paramSize = x.getParameters().size(); + + if (paramSize > 0) { + print0(" ("); + incrementIndent(); + println(); + + for (int i = 0; i < paramSize; ++i) { + if (i != 0) { + print0(", "); + println(); + } + SQLParameter param = x.getParameters().get(i); + param.accept(this); + } + + decrementIndent(); + println(); + print(')'); + } + + println(); + print(ucase ? "RETURN " : "return "); + x.getReturnDataType().accept(this); + + SQLName authid = x.getAuthid(); + if (authid != null) { + print(ucase ? " AUTHID " : " authid "); + authid.accept(this); + } + + SQLStatement block = x.getBlock(); + if (!create) { println(); println("IS"); @@ -3125,4 +3203,49 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS public void endVisit(OracleCreateTableStatement.OIDIndex x) { } + + @Override + public boolean visit(OracleCreatePackageStatement x) { + if (x.isOrReplace()) { + print0(ucase ? "CREATE OR REPLACE PACKAGE " : "create or replace procedure "); + } else { + print0(ucase ? "CREATE PACKAGE " : "create procedure "); + } + + if (x.isBody()) { + print0(ucase ? "BODY " : "body "); + } + + x.getName().accept(this); + + if (x.isBody()) { + println(); + print0(ucase ? "BEGIN" : "begin"); + } + + incrementIndent(); + + for (int i = 0, size = x.getStatements().size(); i < size; ++i) { + println(); + SQLStatement item = x.getStatements().get(i); + item.setParent(x); + item.accept(this); + } + + decrementIndent(); + + if (x.isBody()) { + println(); + print0(ucase ? "END " : "end "); + x.getName().accept(this); + print(';'); + } + + return false; + } + + @Override + public void endVisit(OracleCreatePackageStatement x) { + + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleSchemaStatVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleSchemaStatVisitor.java index 7dc6e55652..4ca8ac2c61 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleSchemaStatVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleSchemaStatVisitor.java @@ -1447,4 +1447,14 @@ public class OracleSchemaStatVisitor extends SchemaStatVisitor implements Oracle public void endVisit(OracleCreateTableStatement.OIDIndex x) { } + + @Override + public boolean visit(OracleCreatePackageStatement x) { + return true; + } + + @Override + public void endVisit(OracleCreatePackageStatement x) { + + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerStatementParser.java b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerStatementParser.java index a2cb7a9705..4ce3fc2526 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerStatementParser.java @@ -29,7 +29,7 @@ import com.alibaba.druid.sql.ast.statement.*; import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerOutput; import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerTop; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerCommitStatement; -import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerDeclareStatement; +import com.alibaba.druid.sql.ast.statement.SQLDeclareStatement; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerExecStatement; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerExecStatement.SQLServerParameter; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerInsertStatement; @@ -155,7 +155,7 @@ public class SQLServerStatementParser extends SQLStatementParser { public SQLStatement parseDeclare() { this.accept(Token.DECLARE); - SQLServerDeclareStatement declareStatement = new SQLServerDeclareStatement(); + SQLDeclareStatement declareStatement = new SQLDeclareStatement(); for (;;) { SQLDeclareItem item = new SQLDeclareItem(); diff --git a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerASTVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerASTVisitor.java index ae0211cda6..ea15382749 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerASTVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerASTVisitor.java @@ -21,7 +21,6 @@ import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerSelectQueryBlock; import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerTop; import com.alibaba.druid.sql.dialect.sqlserver.ast.expr.SQLServerObjectReferenceExpr; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerCommitStatement; -import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerDeclareStatement; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerExecStatement; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerExecStatement.SQLServerParameter; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerInsertStatement; @@ -70,10 +69,6 @@ public interface SQLServerASTVisitor extends SQLASTVisitor { void endVisit(SQLServerOutput x); - boolean visit(SQLServerDeclareStatement x); - - void endVisit(SQLServerDeclareStatement x); - boolean visit(SQLServerSelect x); void endVisit(SQLServerSelect x); diff --git a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerASTVisitorAdapter.java b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerASTVisitorAdapter.java index fb0c4d475f..bbf099cf92 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerASTVisitorAdapter.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerASTVisitorAdapter.java @@ -21,7 +21,6 @@ import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerSelectQueryBlock; import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerTop; import com.alibaba.druid.sql.dialect.sqlserver.ast.expr.SQLServerObjectReferenceExpr; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerCommitStatement; -import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerDeclareStatement; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerExecStatement; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerExecStatement.SQLServerParameter; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerInsertStatement; @@ -124,16 +123,6 @@ public class SQLServerASTVisitorAdapter extends SQLASTVisitorAdapter implements } - @Override - public boolean visit(SQLServerDeclareStatement x) { - return true; - } - - @Override - public void endVisit(SQLServerDeclareStatement x) { - - } - @Override public boolean visit(SQLServerSelect x) { return true; @@ -174,16 +163,14 @@ public class SQLServerASTVisitorAdapter extends SQLASTVisitorAdapter implements } - @Override - public boolean visit(SQLServerParameter x) { - // TODO Auto-generated method stub - return false; - } + @Override + public boolean visit(SQLServerParameter x) { + return true; + } - @Override - public void endVisit(SQLServerParameter x) { - // TODO Auto-generated method stub - - } + @Override + public void endVisit(SQLServerParameter x) { + + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerOutputVisitor.java index cbb3864856..00325cd300 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerOutputVisitor.java @@ -25,7 +25,6 @@ import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerSelectQueryBlock; import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerTop; import com.alibaba.druid.sql.dialect.sqlserver.ast.expr.SQLServerObjectReferenceExpr; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerCommitStatement; -import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerDeclareStatement; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerExecStatement; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerExecStatement.SQLServerParameter; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerInsertStatement; @@ -385,18 +384,6 @@ public class SQLServerOutputVisitor extends SQLASTOutputVisitor implements SQLSe } - @Override - public boolean visit(SQLServerDeclareStatement x) { - print0(ucase ? "DECLARE " : "declare "); - this.printAndAccept(x.getItems(), ", "); - return false; - } - - @Override - public void endVisit(SQLServerDeclareStatement x) { - - } - @Override public boolean visit(SQLBlockStatement x) { print0(ucase ? "BEGIN" : "begin"); diff --git a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerSchemaStatVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerSchemaStatVisitor.java index 07d50c80f1..d864f1ac19 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerSchemaStatVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerSchemaStatVisitor.java @@ -17,8 +17,6 @@ package com.alibaba.druid.sql.dialect.sqlserver.visitor; import java.util.Map; -import com.alibaba.druid.sql.ast.SQLDeclareItem; -import com.alibaba.druid.sql.ast.SQLExpr; import com.alibaba.druid.sql.ast.statement.SQLInsertStatement; import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock; import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerOutput; @@ -27,7 +25,6 @@ import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerSelectQueryBlock; import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerTop; import com.alibaba.druid.sql.dialect.sqlserver.ast.expr.SQLServerObjectReferenceExpr; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerCommitStatement; -import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerDeclareStatement; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerExecStatement; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerExecStatement.SQLServerParameter; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerInsertStatement; @@ -153,22 +150,6 @@ public class SQLServerSchemaStatVisitor extends SchemaStatVisitor implements SQL } - @Override - public boolean visit(SQLServerDeclareStatement x) { - for (SQLDeclareItem item : x.getItems()) { - item.setParent(x); - - SQLExpr name = item.getName(); - this.variants.put(name.toString(), name); - } - return true; - } - - @Override - public void endVisit(SQLServerDeclareStatement x) { - - } - @Override public boolean visit(SQLServerSelect x) { return super.visit(x); diff --git a/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java b/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java index d91c0288d6..21c888731b 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java @@ -620,7 +620,7 @@ public class SQLExprParser extends SQLParser { sqlExpr = new SQLBooleanExpr(false); break; default: - throw new ParserException("ERROR. token : " + tok + ", pos : " + lexer.pos()); + throw new ParserException("ERROR" + lexer.info()); } SQLExpr expr = primaryRest(sqlExpr); @@ -2253,6 +2253,7 @@ public class SQLExprParser extends SQLParser { } } else if (lexer.token() == Token.DO || lexer.token() == Token.JOIN) { expr = this.name(); + expr = this.exprRest(expr); } else { expr = expr(); } diff --git a/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java b/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java index b346991237..fd3a7e4405 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java @@ -392,7 +392,7 @@ public class SQLStatementParser extends SQLParser { if (lexer.token() == Token.TO) { lexer.nextToken(); - if (identifierEquals("SAVEPOINT")) { + if (identifierEquals("SAVEPOINT") || lexer.token() == Token.SAVEPOINT) { lexer.nextToken(); } @@ -1650,6 +1650,10 @@ public class SQLStatementParser extends SQLParser { } } + public SQLStatement parseCreatePackage() { + throw new ParserException("TODO " + lexer.info()); + } + public SQLStatement parseCreate() { char markChar = lexer.current(); int markBp = lexer.bp(); @@ -1696,6 +1700,11 @@ public class SQLStatementParser extends SQLParser { return parseCreateView(); } + if (identifierEquals("PACKAGE")) { + lexer.reset(markBp, markChar, Token.CREATE); + return parseCreatePackage(); + } + // lexer.reset(mark_bp, mark_ch, Token.CREATE); throw new ParserException("TODO " + lexer.token() + " " + lexer.stringVal()); } else if (token == Token.DATABASE) { 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 f79a74c233..4a5f9ffac2 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java @@ -33,8 +33,10 @@ import com.alibaba.druid.sql.ast.statement.SQLInsertStatement.ValuesClause; import com.alibaba.druid.sql.ast.statement.SQLJoinTableSource.JoinType; import com.alibaba.druid.sql.ast.statement.SQLMergeStatement.MergeInsertClause; import com.alibaba.druid.sql.ast.statement.SQLMergeStatement.MergeUpdateClause; +import com.alibaba.druid.sql.ast.statement.SQLWhileStatement; import com.alibaba.druid.sql.dialect.oracle.ast.OracleSegmentAttributes; -import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectQueryBlock; +import com.alibaba.druid.sql.ast.statement.SQLDeclareStatement; +import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleCreatePackageStatement; import com.alibaba.druid.util.JdbcConstants; public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements ParameterizedVisitor, PrintableVisitor { @@ -4204,4 +4206,39 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet x.getStorage().accept(this); } } + + @Override + public boolean visit(SQLWhileStatement x) { + if (x.getLabelName() != null && !x.getLabelName().equals("")) { + print0(x.getLabelName()); + print0(": "); + } + print0(ucase ? "WHILE " : "while "); + x.getCondition().accept(this); + print0(ucase ? " DO" : " do"); + println(); + for (int i = 0, size = x.getStatements().size(); i < size; ++i) { + SQLStatement item = x.getStatements().get(i); + item.setParent(x); + item.accept(this); + if (i != size - 1) { + println(); + } + } + println(); + print0(ucase ? "END WHILE" : "end while"); + if (x.getLabelName() != null && !x.getLabelName().equals("")) print(' '); + print0(x.getLabelName()); + return false; + } + + @Override + public boolean visit(SQLDeclareStatement x) { + boolean printDeclare = !(x.getParent() instanceof OracleCreatePackageStatement); + if (printDeclare) { + print0(ucase ? "DECLARE " : "declare "); + } + this.printAndAccept(x.getItems(), ", "); + return false; + } } diff --git a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitor.java b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitor.java index f8b8f444ff..c98c4bc63f 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitor.java @@ -18,6 +18,8 @@ package com.alibaba.druid.sql.visitor; import com.alibaba.druid.sql.ast.*; import com.alibaba.druid.sql.ast.expr.*; import com.alibaba.druid.sql.ast.statement.*; +import com.alibaba.druid.sql.ast.statement.SQLWhileStatement; +import com.alibaba.druid.sql.ast.statement.SQLDeclareStatement; public interface SQLASTVisitor { @@ -564,6 +566,10 @@ public interface SQLASTVisitor { boolean visit(SQLCreateProcedureStatement x); void endVisit(SQLCreateProcedureStatement x); + + boolean visit(SQLCreateFunctionStatement x); + + void endVisit(SQLCreateFunctionStatement x); boolean visit(SQLBlockStatement x); @@ -696,4 +702,15 @@ public interface SQLASTVisitor { void endVisit(SQLDescribeStatement x); boolean visit(SQLDescribeStatement x); + + /** + * support procedure + */ + boolean visit(SQLWhileStatement x); + + void endVisit(SQLWhileStatement x); + + boolean visit(SQLDeclareStatement x); + + void endVisit(SQLDeclareStatement x); } diff --git a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitorAdapter.java b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitorAdapter.java index b868f45362..c4d1e423b8 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitorAdapter.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitorAdapter.java @@ -21,6 +21,8 @@ import com.alibaba.druid.sql.ast.statement.*; import com.alibaba.druid.sql.ast.statement.SQLInsertStatement.ValuesClause; import com.alibaba.druid.sql.ast.statement.SQLMergeStatement.MergeInsertClause; import com.alibaba.druid.sql.ast.statement.SQLMergeStatement.MergeUpdateClause; +import com.alibaba.druid.sql.ast.statement.SQLWhileStatement; +import com.alibaba.druid.sql.ast.statement.SQLDeclareStatement; public class SQLASTVisitorAdapter implements SQLASTVisitor { @@ -1252,6 +1254,16 @@ public class SQLASTVisitorAdapter implements SQLASTVisitor { } + @Override + public boolean visit(SQLCreateFunctionStatement x) { + return true; + } + + @Override + public void endVisit(SQLCreateFunctionStatement x) { + + } + @Override public boolean visit(SQLBlockStatement x) { return true; @@ -1588,4 +1600,25 @@ public class SQLASTVisitorAdapter implements SQLASTVisitor { public boolean visit(SQLDescribeStatement x) { return true; } + + @Override + public boolean visit(SQLWhileStatement x) { + return true; + } + + @Override + public void endVisit(SQLWhileStatement x) { + + } + + + @Override + public boolean visit(SQLDeclareStatement x) { + return true; + } + + @Override + public void endVisit(SQLDeclareStatement x) { + + } } diff --git a/src/main/java/com/alibaba/druid/sql/visitor/SchemaStatVisitor.java b/src/main/java/com/alibaba/druid/sql/visitor/SchemaStatVisitor.java index 4782a0fe84..fa8b31f772 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SchemaStatVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SchemaStatVisitor.java @@ -53,11 +53,11 @@ import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr; import com.alibaba.druid.sql.ast.expr.SQLSequenceExpr; import com.alibaba.druid.sql.ast.statement.*; import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlExpr; -import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlExplainStatement; import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitorAdapter; import com.alibaba.druid.sql.dialect.odps.ast.OdpsValuesTableSource; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleExpr; import com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitorAdapter; +import com.alibaba.druid.sql.ast.statement.SQLDeclareStatement; import com.alibaba.druid.stat.TableStat; import com.alibaba.druid.stat.TableStat.Column; import com.alibaba.druid.stat.TableStat.Condition; @@ -1734,6 +1734,14 @@ public class SchemaStatVisitor extends SQLASTVisitorAdapter { accept(x.getBlock()); return false; } + + @Override + public boolean visit(SQLCreateFunctionStatement x) { + String name = x.getName().toString(); + this.variants.put(name, x); + accept(x.getBlock()); + return false; + } @Override public boolean visit(SQLBlockStatement x) { @@ -1977,6 +1985,15 @@ public class SchemaStatVisitor extends SQLASTVisitorAdapter { return false; } - // - // + + @Override + public boolean visit(SQLDeclareStatement x) { + for (SQLDeclareItem item : x.getItems()) { + item.setParent(x); + + SQLExpr name = item.getName(); + this.variants.put(name.toString(), name); + } + return true; + } } diff --git a/src/test/java/com/alibaba/druid/bvt/sql/cobar/DALParserTest.java b/src/test/java/com/alibaba/druid/bvt/sql/cobar/DALParserTest.java index b0eb1d82f0..01310a6aa3 100755 --- a/src/test/java/com/alibaba/druid/bvt/sql/cobar/DALParserTest.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/cobar/DALParserTest.java @@ -103,7 +103,7 @@ public class DALParserTest extends TestCase { SQLSetStatement set = (SQLSetStatement) parser.parseStatementList().get(0); parser.match(Token.EOF); String output = SQLUtils.toMySqlString(set); - Assert.assertEquals("SET @@sysVar1 = ?", output); + Assert.assertEquals("SET sysVar1 = ?", output); } public void testSet_2() throws Exception { @@ -112,7 +112,7 @@ public class DALParserTest extends TestCase { SQLSetStatement set = (SQLSetStatement) parser.parseStatementList().get(0); parser.match(Token.EOF); String output = SQLUtils.toMySqlString(set); - Assert.assertEquals("SET @@`sysVar1` = ?, @@global.`var2` = 1", output); + Assert.assertEquals("SET `sysVar1` = ?, @@global.`var2` = 1", output); } public void testSet_3() throws Exception { @@ -130,7 +130,7 @@ public class DALParserTest extends TestCase { SQLSetStatement set = (SQLSetStatement) parser.parseStatementList().get(0); parser.match(Token.EOF); String output = SQLUtils.toMySqlString(set); - Assert.assertEquals("SET @@global.var1 = 1, @@var2 = 2", output); + Assert.assertEquals("SET @@global.var1 = 1, var2 = 2", output); } public void testSet_5() throws Exception { @@ -139,7 +139,7 @@ public class DALParserTest extends TestCase { SQLSetStatement set = (SQLSetStatement) parser.parseStatementList().get(0); parser.match(Token.EOF); String output = SQLUtils.toMySqlString(set); - Assert.assertEquals("SET @@global.var1 = 1, @@var2 = 2", output); + Assert.assertEquals("SET @@global.var1 = 1, var2 = 2", output); } public void testSetTxn_0() throws Exception { diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/START_TRANSACTION_Test.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/START_TRANSACTION_Test.java index e20a5904c2..f7c52c8219 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/mysql/START_TRANSACTION_Test.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/START_TRANSACTION_Test.java @@ -112,7 +112,7 @@ public class START_TRANSACTION_Test extends TestCase { String text = output(stmtList); - Assert.assertEquals("SET @@autocommit = 0;", text); + Assert.assertEquals("SET autocommit = 0;", text); } private String output(List stmtList) { diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateProcedureTest11.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateProcedureTest11.java new file mode 100644 index 0000000000..2da1968594 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateProcedureTest11.java @@ -0,0 +1,79 @@ +/* + * 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.bvt.sql.mysql.create; + +import com.alibaba.druid.sql.MysqlTest; +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.visitor.SchemaStatVisitor; +import com.alibaba.druid.util.JdbcConstants; + +import java.util.List; + +public class MySqlCreateProcedureTest11 extends MysqlTest { + + public void test_0() throws Exception { + String sql = "CREATE PROCEDURE curdemo()\n" + + "BEGIN\n" + + " DECLARE done INT DEFAULT FALSE;\n" + + " DECLARE a CHAR(16);\n" + + " DECLARE b, c INT;\n" + + " DECLARE cur1 CURSOR FOR SELECT id,data FROM test.t1;\n" + + " DECLARE cur2 CURSOR FOR SELECT i FROM test.t2;\n" + + " DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;\n" + + "\n" + + " OPEN cur1;\n" + + " OPEN cur2;\n" + + "\n" + + " read_loop: LOOP\n" + + " FETCH cur1 INTO a, b;\n" + + " FETCH cur2 INTO c;\n" + + " IF done THEN\n" + + " LEAVE read_loop;\n" + + " END IF;\n" + + " IF b < c THEN\n" + + " INSERT INTO test.t3 VALUES (a,b);\n" + + " ELSE\n" + + " INSERT INTO test.t3 VALUES (a,c);\n" + + " END IF;\n" + + " END LOOP;\n" + + "\n" + + " CLOSE cur1;\n" + + " CLOSE cur2;\n" + + "END;"; + + List statementList = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL); + SQLStatement stmt = statementList.get(0); +// print(statementList); +// assertEquals(1, statementList.size()); + + System.out.println(SQLUtils.toMySqlString(stmt)); + + SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.MYSQL); + stmt.accept(visitor); + +// System.out.println("Tables : " + visitor.getTables()); +// System.out.println("fields : " + visitor.getColumns()); +// System.out.println("coditions : " + visitor.getConditions()); +// System.out.println("orderBy : " + visitor.getOrderByColumns()); + + assertEquals(3, visitor.getTables().size()); + assertEquals(3, visitor.getColumns().size()); + assertEquals(2, visitor.getConditions().size()); + } + + +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/param/MySqlParameterizedOutputVisitorTest_6.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/param/MySqlParameterizedOutputVisitorTest_6.java index 11a838113e..e7bef630ff 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/mysql/param/MySqlParameterizedOutputVisitorTest_6.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/param/MySqlParameterizedOutputVisitorTest_6.java @@ -26,13 +26,13 @@ public class MySqlParameterizedOutputVisitorTest_6 extends TestCase { public void test_0() throws Exception { String sql = "SET autocommit=1"; - String paramSql = "SET @@autocommit = ?"; + String paramSql = "SET autocommit = ?"; Assert.assertEquals(ParameterizedOutputVisitorUtils.parameterize(sql, JdbcConstants.MYSQL), paramSql); } public void test_1() throws Exception { String sql = "SET GLOBAL sort_buffer_size=1000000, SESSION sort_buffer_size=1000000;"; - String paramSql = "SET @@global.sort_buffer_size = ?, @@sort_buffer_size = ?"; - Assert.assertEquals(ParameterizedOutputVisitorUtils.parameterize(sql, JdbcConstants.MYSQL), paramSql); + String paramSql = "SET @@global.sort_buffer_size = ?, sort_buffer_size = ?"; + Assert.assertEquals(paramSql, ParameterizedOutputVisitorUtils.parameterize(sql, JdbcConstants.MYSQL)); } } diff --git a/src/test/java/com/alibaba/druid/bvt/sql/oracle/create/OracleCreatePackageTest0.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/create/OracleCreatePackageTest0.java new file mode 100644 index 0000000000..7ead6bfb63 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/create/OracleCreatePackageTest0.java @@ -0,0 +1,231 @@ +/* + * 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.bvt.sql.oracle.create; + +import com.alibaba.druid.sql.OracleTest; +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.oracle.parser.OracleStatementParser; +import com.alibaba.druid.sql.dialect.oracle.visitor.OracleSchemaStatVisitor; +import com.alibaba.druid.stat.TableStat; +import com.alibaba.druid.util.JdbcConstants; +import org.junit.Assert; + +import java.util.List; + +public class OracleCreatePackageTest0 extends OracleTest { + + public void test_types() throws Exception { + String sql = // + " CREATE OR REPLACE PACKAGE BODY emp_mgmt AS \n" + + " tot_emps NUMBER; \n" + + " tot_depts NUMBER; \n" + + "FUNCTION hire \n" + + " (last_name VARCHAR2, job_id VARCHAR2, \n" + + " manager_id NUMBER, salary NUMBER, \n" + + " commission_pct NUMBER, department_id NUMBER) \n" + + " RETURN NUMBER IS new_empno NUMBER; \n" + + "BEGIN \n" + + " SELECT employees_seq.NEXTVAL \n" + + " INTO new_empno \n" + + " FROM DUAL; \n" + + " INSERT INTO employees \n" + + " VALUES (new_empno, 'First', 'Last','first.last@oracle.com', \n" + + " '(123)123-1234','18-JUN-02','IT_PROG',90000000,00, \n" + + " 100,110); \n" + + " tot_emps := tot_emps + 1; \n" + + " RETURN(new_empno); \n" + + "END; \n" + + "FUNCTION create_dept(department_id NUMBER, location_id NUMBER) \n" + + " RETURN NUMBER IS \n" + + " new_deptno NUMBER; \n" + + " BEGIN \n" + + " SELECT departments_seq.NEXTVAL \n" + + " INTO new_deptno \n" + + " FROM dual; \n" + + " INSERT INTO departments \n" + + " VALUES (new_deptno, 'department name', 100, 1700); \n" + + " tot_depts := tot_depts + 1; \n" + + " RETURN(new_deptno); \n" + + " END; \n" + + "PROCEDURE remove_emp (employee_id NUMBER) IS \n" + + " BEGIN \n" + + " DELETE FROM employees \n" + + " WHERE employees.employee_id = remove_emp.employee_id; \n" + + " tot_emps := tot_emps - 1; \n" + + " END; \n" + + "PROCEDURE remove_dept(department_id NUMBER) IS \n" + + " BEGIN \n" + + " DELETE FROM departments \n" + + " WHERE departments.department_id = remove_dept.department_id; \n" + + " tot_depts := tot_depts - 1; \n" + + " SELECT COUNT(*) INTO tot_emps FROM employees; \n" + + " END; \n" + + "PROCEDURE increase_sal(employee_id NUMBER, salary_incr NUMBER) IS \n" + + " curr_sal NUMBER; \n" + + " BEGIN \n" + + " SELECT salary INTO curr_sal FROM employees \n" + + " WHERE employees.employee_id = increase_sal.employee_id; \n" + + " IF curr_sal IS NULL \n" + + " THEN RAISE no_sal; \n" + + " ELSE \n" + + " UPDATE employees \n" + + " SET salary = salary + salary_incr \n" + + " WHERE employee_id = employee_id; \n" + + " END IF; \n" + + " END; \n" + + "PROCEDURE increase_comm(employee_id NUMBER, comm_incr NUMBER) IS \n" + + " curr_comm NUMBER; \n" + + " BEGIN \n" + + " SELECT commission_pct \n" + + " INTO curr_comm \n" + + " FROM employees \n" + + " WHERE employees.employee_id = increase_comm.employee_id; \n" + + " IF curr_comm IS NULL \n" + + " THEN RAISE no_comm; \n" + + " ELSE \n" + + " UPDATE employees \n" + + " SET commission_pct = commission_pct + comm_incr; \n" + + " END IF; \n" + + " END; \n" + + "END emp_mgmt; "; + + OracleStatementParser parser = new OracleStatementParser(sql); + List statementList = parser.parseStatementList(); + SQLStatement stmt = statementList.get(0); + print(statementList); + + Assert.assertEquals(1, statementList.size()); + + Assert.assertEquals("CREATE OR REPLACE PACKAGE BODY emp_mgmt\n" + + "BEGIN\n" + + "\ttot_emps NUMBER\n" + + "\ttot_depts NUMBER\n" + + "\tFUNCTION hire (\n" + + "\t\tlast_name VARCHAR2, \n" + + "\t\tjob_id VARCHAR2, \n" + + "\t\tmanager_id NUMBER, \n" + + "\t\tsalary NUMBER, \n" + + "\t\tcommission_pct NUMBER, \n" + + "\t\tdepartment_id NUMBER\n" + + "\t)\n" + + "\tRETURN NUMBER\n" + + "\tIS\n" + + "\tnew_empno NUMBER;\n" + + "\tBEGIN\n" + + "\t\tSELECT employees_seq.NEXTVAL\n" + + "\t\tINTO new_empno\n" + + "\t\tFROM DUAL;\n" + + "\t\tINSERT INTO employees\n" + + "\t\tVALUES (new_empno, 'First', 'Last', 'first.last@oracle.com', '(123)123-1234'\n" + + "\t\t\t, '18-JUN-02', 'IT_PROG', 90000000, 0, 100\n" + + "\t\t\t, 110);\n" + + "\t\ttot_emps := tot_emps + 1;\n" + + "\t\tRETURN(new_empno);\n" + + "\tEND\n" + + "\tFUNCTION create_dept (\n" + + "\t\tdepartment_id NUMBER, \n" + + "\t\tlocation_id NUMBER\n" + + "\t)\n" + + "\tRETURN NUMBER\n" + + "\tIS\n" + + "\tnew_deptno NUMBER;\n" + + "\tBEGIN\n" + + "\t\tSELECT departments_seq.NEXTVAL\n" + + "\t\tINTO new_deptno\n" + + "\t\tFROM dual;\n" + + "\t\tINSERT INTO departments\n" + + "\t\tVALUES (new_deptno, 'department name', 100, 1700);\n" + + "\t\ttot_depts := tot_depts + 1;\n" + + "\t\tRETURN(new_deptno);\n" + + "\tEND\n" + + "\tPROCEDURE remove_emp (\n" + + "\t\temployee_id NUMBER\n" + + "\t)\n" + + "\tIS\n" + + "\tBEGIN\n" + + "\t\tDELETE FROM employees\n" + + "\t\tWHERE employees.employee_id = remove_emp.employee_id;\n" + + "\t\ttot_emps := tot_emps - 1;\n" + + "\tEND\n" + + "\tPROCEDURE remove_dept (\n" + + "\t\tdepartment_id NUMBER\n" + + "\t)\n" + + "\tIS\n" + + "\tBEGIN\n" + + "\t\tDELETE FROM departments\n" + + "\t\tWHERE departments.department_id = remove_dept.department_id;\n" + + "\t\ttot_depts := tot_depts - 1;\n" + + "\t\tSELECT COUNT(*)\n" + + "\t\tINTO tot_emps\n" + + "\t\tFROM employees;\n" + + "\tEND\n" + + "\tPROCEDURE increase_sal (\n" + + "\t\temployee_id NUMBER, \n" + + "\t\tsalary_incr NUMBER\n" + + "\t)\n" + + "\tIS\n" + + "\tcurr_sal NUMBER;\n" + + "\tBEGIN\n" + + "\t\tSELECT salary\n" + + "\t\tINTO curr_sal\n" + + "\t\tFROM employees\n" + + "\t\tWHERE employees.employee_id = increase_sal.employee_id;\n" + + "\t\tIF curr_sal IS NULL THEN\n" + + "\t\t\tRAISE no_sal;\n" + + "\t\tELSE\n" + + "\t\t\tUPDATE employees\n" + + "\t\t\tSET salary = salary + salary_incr\n" + + "\t\t\tWHERE employee_id = employee_id;\n" + + "\t\tEND IF;\n" + + "\tEND\n" + + "\tPROCEDURE increase_comm (\n" + + "\t\temployee_id NUMBER, \n" + + "\t\tcomm_incr NUMBER\n" + + "\t)\n" + + "\tIS\n" + + "\tcurr_comm NUMBER;\n" + + "\tBEGIN\n" + + "\t\tSELECT commission_pct\n" + + "\t\tINTO curr_comm\n" + + "\t\tFROM employees\n" + + "\t\tWHERE employees.employee_id = increase_comm.employee_id;\n" + + "\t\tIF curr_comm IS NULL THEN\n" + + "\t\t\tRAISE no_comm;\n" + + "\t\tELSE\n" + + "\t\t\tUPDATE employees\n" + + "\t\t\tSET commission_pct = commission_pct + comm_incr;\n" + + "\t\tEND IF;\n" + + "\tEND\n" + + "END emp_mgmt;",// + SQLUtils.toSQLString(stmt, JdbcConstants.ORACLE)); + + OracleSchemaStatVisitor visitor = new OracleSchemaStatVisitor(); + stmt.accept(visitor); + + System.out.println("Tables : " + visitor.getTables()); + System.out.println("fields : " + visitor.getColumns()); + System.out.println("coditions : " + visitor.getConditions()); + System.out.println("relationships : " + visitor.getRelationships()); + System.out.println("orderBy : " + visitor.getOrderByColumns()); + + Assert.assertEquals(2, visitor.getTables().size()); + + Assert.assertEquals(11, visitor.getColumns().size()); + + Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("employees", "employee_id"))); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/oracle/pl/Oracle_pl_exception_8.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/pl/Oracle_pl_exception_8.java index ea6555f78e..b82154ff55 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/oracle/pl/Oracle_pl_exception_8.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/pl/Oracle_pl_exception_8.java @@ -142,7 +142,6 @@ public class Oracle_pl_exception_8 extends OracleTest { "\t\t\t\tsuffix := suffix + 1;\n" + "\t\t\t\tname := name || TO_CHAR(suffix);\n" + "\t\tEND;\n" + - "\t\t;\n" + "\tEND LOOP;\n" + "END;\n", // output); @@ -189,7 +188,6 @@ public class Oracle_pl_exception_8 extends OracleTest { "\t\t\t\tsuffix := suffix + 1;\n" + "\t\t\t\tname := name || TO_CHAR(suffix);\n" + "\t\tend;\n" + - "\t\t;\n" + "\tend loop;\n" + "end;\n", // output); diff --git a/src/test/java/com/alibaba/druid/bvt/sql/oracle/pl/Oracle_pl_for_2.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/pl/Oracle_pl_for_2.java index 6612c90b76..a185147e5a 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/oracle/pl/Oracle_pl_for_2.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/pl/Oracle_pl_for_2.java @@ -86,7 +86,6 @@ public class Oracle_pl_for_2 extends OracleTest { "\tLOOP\n" + "\t\tDELETE FROM employees_temp\n" + "\t\tWHERE department_id = depts(i);\n" + - "\t\t;\n" + "\tEND LOOP;\n" + "END;\n", // output); @@ -108,7 +107,6 @@ public class Oracle_pl_for_2 extends OracleTest { "\tloop\n" + "\t\tdelete from employees_temp\n" + "\t\twhere department_id = depts(i);\n" + - "\t\t;\n" + "\tend loop;\n" + "end;\n", // output);