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 627fa5401a..1ca47a5f46 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/SQLParameter.java +++ b/src/main/java/com/alibaba/druid/sql/ast/SQLParameter.java @@ -24,6 +24,7 @@ public class SQLParameter extends SQLObjectImpl { private SQLExpr defaultValue; private ParameterType paramType; private boolean noCopy = false; + private boolean constant = false; public SQLExpr getDefaultValue() { return defaultValue; @@ -81,4 +82,12 @@ public class SQLParameter extends SQLObjectImpl { public void setNoCopy(boolean noCopy) { this.noCopy = noCopy; } + + public boolean isConstant() { + return constant; + } + + public void setConstant(boolean constant) { + this.constant = constant; + } } 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 88f01d8f70..45e222cec0 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 @@ -46,11 +46,14 @@ public class SQLBlockStatement extends SQLStatementImpl { this.labelName = labelName; } + public SQLStatement exception; + @Override public void accept0(SQLASTVisitor visitor) { if (visitor.visit(this)) { acceptChild(visitor, parameters); acceptChild(visitor, statementList); + acceptChild(visitor, exception); } visitor.endVisit(this); } @@ -63,4 +66,11 @@ public class SQLBlockStatement extends SQLStatementImpl { this.parameters = parameters; } + public SQLStatement getException() { + return exception; + } + + public void setException(SQLStatement exception) { + this.exception = exception; + } } diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateProcedureStatement.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateProcedureStatement.java index 6a9cac2369..af92bdc02f 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateProcedureStatement.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateProcedureStatement.java @@ -37,6 +37,8 @@ public class SQLCreateProcedureStatement extends SQLStatementImpl { // for oracle private String javaCallSpec; + private SQLName authid; + @Override public void accept0(SQLASTVisitor visitor) { if (visitor.visit(this)) { @@ -75,6 +77,17 @@ public class SQLCreateProcedureStatement extends SQLStatementImpl { 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; } 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 281c5e72a6..c2affb46d6 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 @@ -3194,6 +3194,7 @@ public class MySqlStatementParser extends SQLStatementParser { * CREATE OR REPALCE PROCEDURE SP_NAME(parameter_list) BEGIN block_statement END */ SQLCreateProcedureStatement stmt = new SQLCreateProcedureStatement(); + stmt.setDbType(dbType); if (lexer.token() != Token.PROCEDURE) { if (identifierEquals("DEFINER")) { 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 c70eac70eb..9fc8972330 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 @@ -42,7 +42,7 @@ public class OracleExceptionStatement extends OracleStatementImpl implements Ora public static class Item extends OracleSQLObjectImpl { private SQLExpr when; - private SQLStatement statement; + private List statements = new ArrayList(); public SQLExpr getWhen() { return when; @@ -52,22 +52,22 @@ public class OracleExceptionStatement extends OracleStatementImpl implements Ora this.when = when; } - public SQLStatement getStatement() { - return statement; + public List getStatements() { + return statements; } public void setStatement(SQLStatement statement) { if (statement != null) { statement.setParent(this); + this.statements.add(statement); } - this.statement = statement; } @Override public void accept0(OracleASTVisitor visitor) { if (visitor.visit(this)) { acceptChild(visitor, when); - acceptChild(visitor, statement); + acceptChild(visitor, statements); } visitor.endVisit(this); } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleExprParser.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleExprParser.java index b06efd5c3a..a013b38e6e 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleExprParser.java @@ -158,30 +158,30 @@ public class OracleExprParser extends SQLExprParser { } public SQLDataType parseDataType() { - + if (lexer.token() == Token.CONSTRAINT || lexer.token() == Token.COMMA) { return null; } - + if (lexer.token() == Token.DEFAULT || lexer.token() == Token.NOT || lexer.token() == Token.NULL) { return null; } - + if (lexer.token() == Token.INTERVAL) { lexer.nextToken(); if (identifierEquals("YEAR")) { lexer.nextToken(); OracleDataTypeIntervalYear interval = new OracleDataTypeIntervalYear(); - + if (lexer.token() == Token.LPAREN) { lexer.nextToken(); interval.addArgument(this.expr()); accept(Token.RPAREN); } - + accept(Token.TO); acceptIdentifier("MONTH"); - + return interval; } else { acceptIdentifier("DAY"); @@ -191,22 +191,25 @@ public class OracleExprParser extends SQLExprParser { interval.addArgument(this.expr()); accept(Token.RPAREN); } - + accept(Token.TO); acceptIdentifier("SECOND"); - + if (lexer.token() == Token.LPAREN) { lexer.nextToken(); interval.getFractionalSeconds().add(this.expr()); accept(Token.RPAREN); } - + return interval; } } - + String typeName; - if (identifierEquals("LONG")) { + if (lexer.token() == Token.EXCEPTION) { + typeName = "EXCEPTION"; + lexer.nextToken(); + } else if (identifierEquals("LONG")) { lexer.nextToken(); acceptIdentifier("RAW"); typeName = "LONG RAW"; 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 d3ffe551e6..452a1d1828 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 @@ -62,7 +62,7 @@ public class OracleStatementParser extends SQLStatementParser { } } - public void parseStatementList(List statementList, int max, SQLStatement parent) { + public void parseStatementList(List statementList, int max, SQLObject parent) { for (;;) { if (max != -1) { if (statementList.size() >= max) { @@ -176,7 +176,12 @@ public class OracleStatementParser extends SQLStatementParser { } if (lexer.token() == Token.EXCEPTION) { - statementList.add(this.parseException()); + OracleExceptionStatement stmt = this.parseException(); + if (parent instanceof SQLBlockStatement) { + ((SQLBlockStatement) parent).setException(stmt); + } else { + statementList.add(stmt); + } continue; } @@ -215,13 +220,15 @@ public class OracleStatementParser extends SQLStatementParser { if (identifierEquals("ROLLBACK")) { SQLRollbackStatement stmt = parseRollback(); - + stmt.setParent(parent); statementList.add(stmt); continue; } if (lexer.token() == Token.EXPLAIN) { - statementList.add(this.parseExplain()); + OracleExplainStatement stmt = this.parseExplain(); + stmt.setParent(parent); + statementList.add(stmt); continue; } @@ -240,6 +247,7 @@ public class OracleStatementParser extends SQLStatementParser { SQLExpr expr = exprParser.expr(); OracleExprStatement stmt = new OracleExprStatement(expr); + stmt.setParent(parent); statementList.add(stmt); continue; } @@ -477,7 +485,13 @@ public class OracleStatementParser extends SQLStatementParser { continue; } - if (lexer.token() == Token.ELSIF && parent instanceof SQLIfStatement) { + if (lexer.token() == Token.ELSIF + && parent instanceof SQLIfStatement) { + break; + } + + if (lexer.token() == Token.WHEN + && parent instanceof OracleExceptionStatement.Item) { break; } @@ -1111,6 +1125,7 @@ public class OracleStatementParser extends SQLStatementParser { public SQLBlockStatement parseBlock() { SQLBlockStatement block = new SQLBlockStatement(); + block.setDbType(JdbcConstants.ORACLE); if (lexer.token() == Token.DECLARE) { lexer.nextToken(); @@ -1125,7 +1140,7 @@ public class OracleStatementParser extends SQLStatementParser { accept(Token.BEGIN); - parseStatementList(block.getStatementList()); + parseStatementList(block.getStatementList(), -1, block); accept(Token.END); @@ -1214,6 +1229,11 @@ public class OracleStatementParser extends SQLStatementParser { parameter.setNoCopy(true); } + if (identifierEquals("CONSTANT")) { + lexer.nextToken(); + parameter.setConstant(true); + } + dataType = this.exprParser.parseDataType(); if (lexer.token() == Token.COLONEQ) { @@ -1340,11 +1360,15 @@ public class OracleStatementParser extends SQLStatementParser { OracleExceptionStatement.Item item = new OracleExceptionStatement.Item(); item.setWhen(this.exprParser.expr()); accept(Token.THEN); - SQLStatement thenStmt = this.parseStatement(); - item.setStatement(thenStmt); + + this.parseStatementList(item.getStatements(), -1, item); stmt.addItem(item); + if (lexer.token() == Token.SEMI) { + lexer.nextToken(); + } + if (lexer.token() != Token.WHEN) { break; } @@ -1671,6 +1695,7 @@ public class OracleStatementParser extends SQLStatementParser { public SQLCreateProcedureStatement parseCreateProcedure() { SQLCreateProcedureStatement stmt = new SQLCreateProcedureStatement(); + stmt.setDbType(dbType); if (lexer.token() == Token.CREATE) { lexer.nextToken(); @@ -1694,6 +1719,18 @@ public class OracleStatementParser extends SQLStatementParser { accept(Token.RPAREN); } + 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.IS) { lexer.nextToken(); } else { 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 667d1da8de..feac56e072 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 @@ -104,30 +104,29 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS return; } + SQLObject parent = x.getParent(); + if ((!isPrintPostSemi()) // - && (!(x.getParent() instanceof SQLBlockStatement))) { + && (!(parent instanceof SQLBlockStatement)) + && (!(parent instanceof OracleForStatement))) { return; } if (x instanceof OraclePLSQLCommitStatement || x instanceof OracleLabelStatement - || x instanceof OracleExceptionStatement.Item) { + || x instanceof OracleExceptionStatement.Item + || x instanceof OracleExceptionStatement) { return; } - SQLObject parent = x.getParent(); - if (parent instanceof SQLCreateProcedureStatement) { + + if (parent instanceof SQLCreateProcedureStatement + || parent instanceof OracleExceptionStatement.Item + || parent instanceof OracleForStatement) { return; } if (isPrettyFormat()) { - if (parent instanceof OracleForStatement) { - OracleForStatement forStatement = (OracleForStatement) parent; - if (forStatement.isAll()) { - return; - } - } - if (parent != null) { print(';'); } else { @@ -1367,6 +1366,9 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS public boolean visit(SQLBlockStatement x) { if (x.getParameters().size() != 0) { incrementIndent(); + if (x.getParent() instanceof SQLCreateProcedureStatement) { + printIndent(); + } if (!(x.getParent() instanceof SQLCreateProcedureStatement)) { print0(ucase ? "DECLARE" : "declare"); println(); @@ -1396,6 +1398,13 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS stmt.accept(this); } decrementIndent(); + + SQLStatement exception = x.getException(); + if (exception != null) { + println(); + exception.accept(this); + } + println(); print0(ucase ? "END" : "end"); return false; @@ -1497,9 +1506,23 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS public boolean visit(com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleExceptionStatement.Item x) { print0(ucase ? "WHEN " : "when "); x.getWhen().accept(this); - print0(ucase ? " THEN " : " then "); + print0(ucase ? " THEN" : " then"); + incrementIndent(); - x.getStatement().accept(this); + if (x.getStatements().size() > 1) { + println(); + } else { + print(' '); + } + + for (int i = 0, size = x.getStatements().size(); i < size; ++i) { + if (i != 0 && size > 1) { + println(); + } + SQLStatement stmt = x.getStatements().get(i); + stmt.accept(this); + print(";"); + } decrementIndent(); return false; @@ -1509,8 +1532,10 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS public boolean visit(OracleExceptionStatement x) { print0(ucase ? "EXCEPTION" : "exception"); incrementIndent(); - for (OracleExceptionStatement.Item item : x.getItems()) { + List items = x.getItems(); + for (int i = 0, size = items.size(); i < size; ++i) { println(); + OracleExceptionStatement.Item item = items.get(i); item.accept(this); } decrementIndent(); @@ -2590,6 +2615,12 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS print(')'); } + SQLName authid = x.getAuthid(); + if (authid != null) { + print(ucase ? " AUTHID " : " authid "); + authid.accept(this); + } + SQLStatement block = x.getBlock(); if (!create) { @@ -2599,8 +2630,8 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS println(); if (block instanceof SQLBlockStatement) { SQLBlockStatement blockStatement = (SQLBlockStatement) block; - if (blockStatement.getParameters().size() > 0) { - println("AS"); + if (blockStatement.getParameters().size() > 0 || authid != null) { + println(ucase ? "AS" : "as"); } } } 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 55fb7d6133..8a730245e1 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java @@ -84,7 +84,7 @@ public class SQLStatementParser extends SQLParser { parseStatementList(statementList, max, null); } - public void parseStatementList(List statementList, int max, SQLStatement parent) { + public void parseStatementList(List statementList, int max, SQLObject parent) { for (;;) { if (max != -1) { if (statementList.size() >= max) { 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 62e2a6cb5e..bf6dfa029c 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java @@ -3390,6 +3390,10 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet print0(ucase ? "NOCOPY " : "nocopy "); } + if (x.isConstant()) { + print0(ucase ? "CONSTANT " : "constant "); + } + if (printType) { print0(ucase ? "IS " : "is "); } diff --git a/src/test/java/com/alibaba/druid/bvt/sql/oracle/pl/Oracle_pl_0.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/pl/Oracle_pl_0.java index 0687d2a678..7481aa4a14 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/oracle/pl/Oracle_pl_0.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/pl/Oracle_pl_0.java @@ -67,7 +67,7 @@ public class Oracle_pl_0 extends OracleTest { "\temployee_id NUMBER\n" + ")\n" + "AS\n" + - "tot_emps NUMBER;\n" + + "\ttot_emps NUMBER;\n" + "BEGIN\n" + "\tDELETE FROM employees\n" + "\tWHERE employees.employee_id = remove_emp.employee_id;\n" + @@ -80,8 +80,8 @@ public class Oracle_pl_0 extends OracleTest { assertEquals("create procedure remove_emp (\n" + "\temployee_id NUMBER\n" + ")\n" + - "AS\n" + - "tot_emps NUMBER;\n" + + "as\n" + + "\ttot_emps NUMBER;\n" + "begin\n" + "\tdelete from employees\n" + "\twhere employees.employee_id = remove_emp.employee_id;\n" + diff --git a/src/test/java/com/alibaba/druid/bvt/sql/oracle/pl/Oracle_pl_case_1.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/pl/Oracle_pl_case_1.java index 803d226b10..03e0d2a29a 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/oracle/pl/Oracle_pl_case_1.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/pl/Oracle_pl_case_1.java @@ -84,8 +84,8 @@ public class Oracle_pl_case_1 extends OracleTest { "\t\tWHEN grade = 'F' THEN DBMS_OUTPUT.PUT_LINE('Poor');\n" + "\t\tELSE ;\n" + "\tEND CASE;\n" + - "\tEXCEPTION\n" + - "\t\tWHEN CASE_NOT_FOUND THEN DBMS_OUTPUT.PUT_LINE('No such grade');\n" + + "EXCEPTION\n" + + "\tWHEN CASE_NOT_FOUND THEN DBMS_OUTPUT.PUT_LINE('No such grade');\n" + "END", // output); } @@ -103,8 +103,8 @@ public class Oracle_pl_case_1 extends OracleTest { "\t\twhen grade = 'F' then DBMS_OUTPUT.PUT_LINE('Poor');\n" + "\t\telse ;\n" + "\tend case;\n" + - "\texception\n" + - "\t\twhen CASE_NOT_FOUND then DBMS_OUTPUT.PUT_LINE('No such grade');\n" + + "exception\n" + + "\twhen CASE_NOT_FOUND then DBMS_OUTPUT.PUT_LINE('No such grade');\n" + "end", // output); } diff --git a/src/test/java/com/alibaba/druid/bvt/sql/oracle/pl/Oracle_pl_exception_0.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/pl/Oracle_pl_exception_0.java new file mode 100644 index 0000000000..10a5d08478 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/pl/Oracle_pl_exception_0.java @@ -0,0 +1,147 @@ +/* + * 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.pl; + +import com.alibaba.druid.sql.OracleTest; +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 Oracle_pl_exception_0 extends OracleTest { + + public void test_0() throws Exception { + String sql = "CREATE OR REPLACE PROCEDURE select_item (\n" + + " t_column VARCHAR2,\n" + + " t_name VARCHAR2\n" + + ") AUTHID DEFINER\n" + + "IS\n" + + " temp VARCHAR2(30);\n" + + "BEGIN\n" + + " temp := t_column; -- For error message if next SELECT fails\n" + + " \n" + + " -- Fails if table t_name does not have column t_column:\n" + + " \n" + + " SELECT COLUMN_NAME INTO temp\n" + + " FROM USER_TAB_COLS \n" + + " WHERE TABLE_NAME = UPPER(t_name)\n" + + " AND COLUMN_NAME = UPPER(t_column);\n" + + " \n" + + " temp := t_name; -- For error message if next SELECT fails\n" + + " \n" + + " -- Fails if there is no table named t_name:\n" + + " \n" + + " SELECT OBJECT_NAME INTO temp\n" + + " FROM USER_OBJECTS\n" + + " WHERE OBJECT_NAME = UPPER(t_name)\n" + + " AND OBJECT_TYPE = 'TABLE';\n" + + " \n" + + "EXCEPTION\n" + + " WHEN NO_DATA_FOUND THEN\n" + + " DBMS_OUTPUT.PUT_LINE ('No Data found for SELECT on ' || temp);\n" + + " WHEN OTHERS THEN\n" + + " DBMS_OUTPUT.PUT_LINE ('Unexpected error');\n" + + " RAISE;\n" + + "END;"; // + + List statementList = SQLUtils.parseStatements(sql, JdbcConstants.ORACLE); + assertEquals(1, statementList.size()); + + SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.ORACLE); + for (SQLStatement statement : statementList) { + statement.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()); + + assertEquals(2, visitor.getTables().size()); + +// Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("employees"))); +// Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("emp_name"))); + +// Assert.assertEquals(7, visitor.getColumns().size()); +// Assert.assertEquals(3, visitor.getConditions().size()); +// Assert.assertEquals(1, visitor.getRelationships().size()); + + // Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("employees", "salary"))); + + { + String output = SQLUtils.toSQLString(statementList, JdbcConstants.ORACLE); + System.out.println(output); + assertEquals("CREATE OR REPLACE PROCEDURE select_item (\n" + + "\tt_column VARCHAR2, \n" + + "\tt_name VARCHAR2\n" + + ") AUTHID DEFINER\n" + + "AS\n" + + "\ttemp VARCHAR2(30);\n" + + "BEGIN\n" + + "\ttemp := t_column;\n" + + "\tSELECT COLUMN_NAME\n" + + "\tINTO temp\n" + + "\tFROM USER_TAB_COLS\n" + + "\tWHERE TABLE_NAME = UPPER(t_name)\n" + + "\t\tAND COLUMN_NAME = UPPER(t_column);\n" + + "\ttemp := t_name;\n" + + "\tSELECT OBJECT_NAME\n" + + "\tINTO temp\n" + + "\tFROM USER_OBJECTS\n" + + "\tWHERE OBJECT_NAME = UPPER(t_name)\n" + + "\t\tAND OBJECT_TYPE = 'TABLE';\n" + + "EXCEPTION\n" + + "\tWHEN NO_DATA_FOUND THEN DBMS_OUTPUT.PUT_LINE('No Data found for SELECT on ' || temp);\n" + + "\tWHEN OTHERS THEN\n" + + "\t\tDBMS_OUTPUT.PUT_LINE('Unexpected error');\n" + + "\t\tRAISE;\n" + + "END", // + output); + } + { + String output = SQLUtils.toSQLString(statementList, JdbcConstants.ORACLE, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION); + assertEquals("create or replace procedure select_item (\n" + + "\tt_column VARCHAR2, \n" + + "\tt_name VARCHAR2\n" + + ") authid DEFINER\n" + + "as\n" + + "\ttemp VARCHAR2(30);\n" + + "begin\n" + + "\ttemp := t_column;\n" + + "\tselect COLUMN_NAME\n" + + "\tinto temp\n" + + "\tfrom USER_TAB_COLS\n" + + "\twhere TABLE_NAME = UPPER(t_name)\n" + + "\t\tand COLUMN_NAME = UPPER(t_column);\n" + + "\ttemp := t_name;\n" + + "\tselect OBJECT_NAME\n" + + "\tinto temp\n" + + "\tfrom USER_OBJECTS\n" + + "\twhere OBJECT_NAME = UPPER(t_name)\n" + + "\t\tand OBJECT_TYPE = 'TABLE';\n" + + "exception\n" + + "\twhen NO_DATA_FOUND then DBMS_OUTPUT.PUT_LINE('No Data found for SELECT on ' || temp);\n" + + "\twhen OTHERS then\n" + + "\t\tDBMS_OUTPUT.PUT_LINE('Unexpected error');\n" + + "\t\traise;\n" + + "end", // + output); + } + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/oracle/pl/Oracle_pl_exception_1.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/pl/Oracle_pl_exception_1.java new file mode 100644 index 0000000000..fce6c1dfec --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/pl/Oracle_pl_exception_1.java @@ -0,0 +1,120 @@ +/* + * 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.pl; + +import com.alibaba.druid.sql.OracleTest; +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 Oracle_pl_exception_1 extends OracleTest { + + public void test_0() throws Exception { + String sql = "CREATE OR REPLACE PROCEDURE loc_var AUTHID DEFINER IS\n" + + " stmt_no POSITIVE;\n" + + " name_ VARCHAR2(100);\n" + + "BEGIN\n" + + " stmt_no := 1;\n" + + "\n" + + " SELECT table_name INTO name_\n" + + " FROM user_tables\n" + + " WHERE table_name LIKE 'ABC%';\n" + + "\n" + + " stmt_no := 2;\n" + + "\n" + + " SELECT table_name INTO name_\n" + + " FROM user_tables\n" + + " WHERE table_name LIKE 'XYZ%';\n" + + "EXCEPTION\n" + + " WHEN NO_DATA_FOUND THEN\n" + + " DBMS_OUTPUT.PUT_LINE ('Table name not found in query ' || stmt_no);\n" + + "END;"; // + + List statementList = SQLUtils.parseStatements(sql, JdbcConstants.ORACLE); + assertEquals(1, statementList.size()); + + SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.ORACLE); + for (SQLStatement statement : statementList) { + statement.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()); + + assertEquals(1, visitor.getTables().size()); + +// Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("employees"))); +// Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("emp_name"))); + +// Assert.assertEquals(7, visitor.getColumns().size()); +// Assert.assertEquals(3, visitor.getConditions().size()); +// Assert.assertEquals(1, visitor.getRelationships().size()); + + // Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("employees", "salary"))); + + { + String output = SQLUtils.toSQLString(statementList, JdbcConstants.ORACLE); + System.out.println(output); + assertEquals("CREATE OR REPLACE PROCEDURE loc_var AUTHID DEFINER\n" + + "AS\n" + + "\tstmt_no POSITIVE;\n" + + "\tname_ VARCHAR2(100);\n" + + "BEGIN\n" + + "\tstmt_no := 1;\n" + + "\tSELECT table_name\n" + + "\tINTO name_\n" + + "\tFROM user_tables\n" + + "\tWHERE table_name LIKE 'ABC%';\n" + + "\tstmt_no := 2;\n" + + "\tSELECT table_name\n" + + "\tINTO name_\n" + + "\tFROM user_tables\n" + + "\tWHERE table_name LIKE 'XYZ%';\n" + + "EXCEPTION\n" + + "\tWHEN NO_DATA_FOUND THEN DBMS_OUTPUT.PUT_LINE('Table name not found in query ' || stmt_no);\n" + + "END", // + output); + } + { + String output = SQLUtils.toSQLString(statementList, JdbcConstants.ORACLE, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION); + assertEquals("create or replace procedure loc_var authid DEFINER\n" + + "as\n" + + "\tstmt_no POSITIVE;\n" + + "\tname_ VARCHAR2(100);\n" + + "begin\n" + + "\tstmt_no := 1;\n" + + "\tselect table_name\n" + + "\tinto name_\n" + + "\tfrom user_tables\n" + + "\twhere table_name like 'ABC%';\n" + + "\tstmt_no := 2;\n" + + "\tselect table_name\n" + + "\tinto name_\n" + + "\tfrom user_tables\n" + + "\twhere table_name like 'XYZ%';\n" + + "exception\n" + + "\twhen NO_DATA_FOUND then DBMS_OUTPUT.PUT_LINE('Table name not found in query ' || stmt_no);\n" + + "end", // + output); + } + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/oracle/pl/Oracle_pl_exception_2.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/pl/Oracle_pl_exception_2.java new file mode 100644 index 0000000000..3f07d4358b --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/pl/Oracle_pl_exception_2.java @@ -0,0 +1,101 @@ +/* + * 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.pl; + +import com.alibaba.druid.sql.OracleTest; +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 Oracle_pl_exception_2 extends OracleTest { + + public void test_0() throws Exception { + String sql = "DECLARE\n" + + " stock_price NUMBER := 9.73;\n" + + " net_earnings NUMBER := 0;\n" + + " pe_ratio NUMBER;\n" + + "BEGIN\n" + + " pe_ratio := stock_price / net_earnings; -- raises ZERO_DIVIDE exception\n" + + " DBMS_OUTPUT.PUT_LINE('Price/earnings ratio = ' || pe_ratio);\n" + + "EXCEPTION\n" + + " WHEN ZERO_DIVIDE THEN\n" + + " DBMS_OUTPUT.PUT_LINE('Company had zero earnings.');\n" + + " pe_ratio := NULL;\n" + + "END;"; // + + List statementList = SQLUtils.parseStatements(sql, JdbcConstants.ORACLE); + assertEquals(1, statementList.size()); + + SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.ORACLE); + for (SQLStatement statement : statementList) { + statement.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()); + + assertEquals(0, visitor.getTables().size()); + +// Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("employees"))); +// Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("emp_name"))); + +// Assert.assertEquals(7, visitor.getColumns().size()); +// Assert.assertEquals(3, visitor.getConditions().size()); +// Assert.assertEquals(1, visitor.getRelationships().size()); + + // Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("employees", "salary"))); + + { + String output = SQLUtils.toSQLString(statementList, JdbcConstants.ORACLE); + System.out.println(output); + assertEquals("DECLARE\n" + + "\tstock_price NUMBER := 9.73;\n" + + "\tnet_earnings NUMBER := 0;\n" + + "\tpe_ratio NUMBER;\n" + + "BEGIN\n" + + "\tpe_ratio := stock_price / net_earnings;\n" + + "\tDBMS_OUTPUT.PUT_LINE('Price/earnings ratio = ' || pe_ratio);\n" + + "EXCEPTION\n" + + "\tWHEN ZERO_DIVIDE THEN\n" + + "\t\tDBMS_OUTPUT.PUT_LINE('Company had zero earnings.');\n" + + "\t\tpe_ratio := NULL;\n" + + "END", // + output); + } + { + String output = SQLUtils.toSQLString(statementList, JdbcConstants.ORACLE, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION); + assertEquals("declare\n" + + "\tstock_price NUMBER := 9.73;\n" + + "\tnet_earnings NUMBER := 0;\n" + + "\tpe_ratio NUMBER;\n" + + "begin\n" + + "\tpe_ratio := stock_price / net_earnings;\n" + + "\tDBMS_OUTPUT.PUT_LINE('Price/earnings ratio = ' || pe_ratio);\n" + + "exception\n" + + "\twhen ZERO_DIVIDE then\n" + + "\t\tDBMS_OUTPUT.PUT_LINE('Company had zero earnings.');\n" + + "\t\tpe_ratio := null;\n" + + "end", // + output); + } + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/oracle/pl/Oracle_pl_exception_3.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/pl/Oracle_pl_exception_3.java new file mode 100644 index 0000000000..e7556a67f4 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/pl/Oracle_pl_exception_3.java @@ -0,0 +1,137 @@ +/* + * 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.pl; + +import com.alibaba.druid.sql.OracleTest; +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 Oracle_pl_exception_3 extends OracleTest { + + public void test_0() throws Exception { + String sql = "DECLARE\n" + + " salary_too_high EXCEPTION;\n" + + " current_salary NUMBER := 20000;\n" + + " max_salary NUMBER := 10000;\n" + + " erroneous_salary NUMBER;\n" + + "BEGIN\n" + + "\n" + + " BEGIN\n" + + " IF current_salary > max_salary THEN\n" + + " RAISE salary_too_high; -- raise exception\n" + + " END IF;\n" + + " EXCEPTION\n" + + " WHEN salary_too_high THEN -- start handling exception\n" + + " erroneous_salary := current_salary;\n" + + " DBMS_OUTPUT.PUT_LINE('Salary ' || erroneous_salary ||' is out of range.');\n" + + " DBMS_OUTPUT.PUT_LINE ('Maximum salary is ' || max_salary || '.');\n" + + " RAISE; -- reraise current exception (exception name is optional)\n" + + " END;\n" + + "\n" + + "EXCEPTION\n" + + " WHEN salary_too_high THEN -- finish handling exception\n" + + " current_salary := max_salary;\n" + + "\n" + + " DBMS_OUTPUT.PUT_LINE (\n" + + " 'Revising salary from ' || erroneous_salary ||\n" + + " ' to ' || current_salary || '.'\n" + + " );\n" + + "END;"; // + + List statementList = SQLUtils.parseStatements(sql, JdbcConstants.ORACLE); + assertEquals(1, statementList.size()); + + SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.ORACLE); + for (SQLStatement statement : statementList) { + statement.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()); + + assertEquals(0, visitor.getTables().size()); + +// Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("employees"))); +// Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("emp_name"))); + +// Assert.assertEquals(7, visitor.getColumns().size()); +// Assert.assertEquals(3, visitor.getConditions().size()); +// Assert.assertEquals(1, visitor.getRelationships().size()); + + // Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("employees", "salary"))); + + { + String output = SQLUtils.toSQLString(statementList, JdbcConstants.ORACLE); + System.out.println(output); + assertEquals("DECLARE\n" + + "\tsalary_too_high EXCEPTION;\n" + + "\tcurrent_salary NUMBER := 20000;\n" + + "\tmax_salary NUMBER := 10000;\n" + + "\terroneous_salary NUMBER;\n" + + "BEGIN\n" + + "\tBEGIN\n" + + "\t\tIF current_salary > max_salary THEN\n" + + "\t\t\tRAISE salary_too_high;\n" + + "\t\tEND IF;\n" + + "\tEXCEPTION\n" + + "\t\tWHEN salary_too_high THEN\n" + + "\t\t\terroneous_salary := current_salary;\n" + + "\t\t\tDBMS_OUTPUT.PUT_LINE('Salary ' || erroneous_salary || ' is out of range.');\n" + + "\t\t\tDBMS_OUTPUT.PUT_LINE('Maximum salary is ' || max_salary || '.');\n" + + "\t\t\tRAISE;\n" + + "\tEND;\n" + + "EXCEPTION\n" + + "\tWHEN salary_too_high THEN\n" + + "\t\tcurrent_salary := max_salary;\n" + + "\t\tDBMS_OUTPUT.PUT_LINE('Revising salary from ' || erroneous_salary || ' to ' || current_salary || '.');\n" + + "END", // + output); + } + { + String output = SQLUtils.toSQLString(statementList, JdbcConstants.ORACLE, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION); + assertEquals("declare\n" + + "\tsalary_too_high EXCEPTION;\n" + + "\tcurrent_salary NUMBER := 20000;\n" + + "\tmax_salary NUMBER := 10000;\n" + + "\terroneous_salary NUMBER;\n" + + "begin\n" + + "\tbegin\n" + + "\t\tif current_salary > max_salary then\n" + + "\t\t\traise salary_too_high;\n" + + "\t\tend if;\n" + + "\texception\n" + + "\t\twhen salary_too_high then\n" + + "\t\t\terroneous_salary := current_salary;\n" + + "\t\t\tDBMS_OUTPUT.PUT_LINE('Salary ' || erroneous_salary || ' is out of range.');\n" + + "\t\t\tDBMS_OUTPUT.PUT_LINE('Maximum salary is ' || max_salary || '.');\n" + + "\t\t\traise;\n" + + "\tend;\n" + + "exception\n" + + "\twhen salary_too_high then\n" + + "\t\tcurrent_salary := max_salary;\n" + + "\t\tDBMS_OUTPUT.PUT_LINE('Revising salary from ' || erroneous_salary || ' to ' || current_salary || '.');\n" + + "end", // + output); + } + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/oracle/pl/Oracle_pl_exception_4.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/pl/Oracle_pl_exception_4.java new file mode 100644 index 0000000000..42aac5444d --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/pl/Oracle_pl_exception_4.java @@ -0,0 +1,117 @@ +/* + * 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.pl; + +import com.alibaba.druid.sql.OracleTest; +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 Oracle_pl_exception_4 extends OracleTest { + + public void test_0() throws Exception { + String sql = "CREATE OR REPLACE PROCEDURE p AUTHID DEFINER AS\n" + + "BEGIN\n" + + "\n" + + " DECLARE\n" + + " past_due EXCEPTION;\n" + + " due_date DATE := trunc(SYSDATE) - 1;\n" + + " todays_date DATE := trunc(SYSDATE);\n" + + " BEGIN\n" + + " IF due_date < todays_date THEN\n" + + " RAISE past_due;\n" + + " END IF;\n" + + " END;\n" + + "\n" + + "EXCEPTION\n" + + " WHEN OTHERS THEN\n" + + " ROLLBACK;\n" + + " RAISE;\n" + + "END;"; // + + List statementList = SQLUtils.parseStatements(sql, JdbcConstants.ORACLE); + assertEquals(1, statementList.size()); + + SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.ORACLE); + for (SQLStatement statement : statementList) { + statement.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()); + + assertEquals(0, visitor.getTables().size()); + +// Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("employees"))); +// Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("emp_name"))); + +// Assert.assertEquals(7, visitor.getColumns().size()); +// Assert.assertEquals(3, visitor.getConditions().size()); +// Assert.assertEquals(1, visitor.getRelationships().size()); + + // Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("employees", "salary"))); + + { + String output = SQLUtils.toSQLString(statementList, JdbcConstants.ORACLE); + System.out.println(output); + assertEquals("CREATE OR REPLACE PROCEDURE p AUTHID DEFINER\n" + + "AS\n" + + "BEGIN\n" + + "\tDECLARE\n" + + "\t\tpast_due EXCEPTION;\n" + + "\t\tdue_date DATE := trunc(SYSDATE) - 1;\n" + + "\t\ttodays_date DATE := trunc(SYSDATE);\n" + + "\tBEGIN\n" + + "\t\tIF due_date < todays_date THEN\n" + + "\t\t\tRAISE past_due;\n" + + "\t\tEND IF;\n" + + "\tEND;\n" + + "EXCEPTION\n" + + "\tWHEN OTHERS THEN\n" + + "\t\tROLLBACK;\n" + + "\t\tRAISE;\n" + + "END", // + output); + } + { + String output = SQLUtils.toSQLString(statementList, JdbcConstants.ORACLE, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION); + assertEquals("create or replace procedure p authid DEFINER\n" + + "as\n" + + "begin\n" + + "\tdeclare\n" + + "\t\tpast_due EXCEPTION;\n" + + "\t\tdue_date DATE := trunc(sysdate) - 1;\n" + + "\t\ttodays_date DATE := trunc(sysdate);\n" + + "\tbegin\n" + + "\t\tif due_date < todays_date then\n" + + "\t\t\traise past_due;\n" + + "\t\tend if;\n" + + "\tend;\n" + + "exception\n" + + "\twhen OTHERS then\n" + + "\t\trollback;\n" + + "\t\traise;\n" + + "end", // + output); + } + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/oracle/pl/Oracle_pl_exception_5.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/pl/Oracle_pl_exception_5.java new file mode 100644 index 0000000000..9b00131cbb --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/pl/Oracle_pl_exception_5.java @@ -0,0 +1,100 @@ +/* + * 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.pl; + +import com.alibaba.druid.sql.OracleTest; +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 Oracle_pl_exception_5 extends OracleTest { + + public void test_0() throws Exception { + String sql = "BEGIN\n" + + "\n" + + " DECLARE\n" + + " past_due EXCEPTION;\n" + + " due_date DATE := trunc(SYSDATE) - 1;\n" + + " todays_date DATE := trunc(SYSDATE);\n" + + " BEGIN\n" + + " IF due_date < todays_date THEN\n" + + " RAISE past_due;\n" + + " END IF;\n" + + " END;\n" + + "\n" + + "END;"; // + + List statementList = SQLUtils.parseStatements(sql, JdbcConstants.ORACLE); + assertEquals(1, statementList.size()); + + SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.ORACLE); + for (SQLStatement statement : statementList) { + statement.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()); + + assertEquals(0, visitor.getTables().size()); + +// Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("employees"))); +// Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("emp_name"))); + +// Assert.assertEquals(7, visitor.getColumns().size()); +// Assert.assertEquals(3, visitor.getConditions().size()); +// Assert.assertEquals(1, visitor.getRelationships().size()); + + // Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("employees", "salary"))); + + { + String output = SQLUtils.toSQLString(statementList, JdbcConstants.ORACLE); + System.out.println(output); + assertEquals("BEGIN\n" + + "\tDECLARE\n" + + "\t\tpast_due EXCEPTION;\n" + + "\t\tdue_date DATE := trunc(SYSDATE) - 1;\n" + + "\t\ttodays_date DATE := trunc(SYSDATE);\n" + + "\tBEGIN\n" + + "\t\tIF due_date < todays_date THEN\n" + + "\t\t\tRAISE past_due;\n" + + "\t\tEND IF;\n" + + "\tEND;\n" + + "END", // + output); + } + { + String output = SQLUtils.toSQLString(statementList, JdbcConstants.ORACLE, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION); + assertEquals("begin\n" + + "\tdeclare\n" + + "\t\tpast_due EXCEPTION;\n" + + "\t\tdue_date DATE := trunc(sysdate) - 1;\n" + + "\t\ttodays_date DATE := trunc(sysdate);\n" + + "\tbegin\n" + + "\t\tif due_date < todays_date then\n" + + "\t\t\traise past_due;\n" + + "\t\tend if;\n" + + "\tend;\n" + + "end", // + output); + } + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/oracle/pl/Oracle_pl_exception_6.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/pl/Oracle_pl_exception_6.java new file mode 100644 index 0000000000..b062587008 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/pl/Oracle_pl_exception_6.java @@ -0,0 +1,87 @@ +/* + * 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.pl; + +import com.alibaba.druid.sql.OracleTest; +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 Oracle_pl_exception_6 extends OracleTest { + + public void test_0() throws Exception { + String sql = "DECLARE\n" + + " credit_limit CONSTANT NUMBER(3) := 5000; -- Maximum value is 999\n" + + "BEGIN\n" + + " NULL;\n" + + "EXCEPTION\n" + + " WHEN VALUE_ERROR THEN\n" + + " DBMS_OUTPUT.PUT_LINE('Exception raised in declaration.');\n" + + "END;"; // + + List statementList = SQLUtils.parseStatements(sql, JdbcConstants.ORACLE); + assertEquals(1, statementList.size()); + + SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.ORACLE); + for (SQLStatement statement : statementList) { + statement.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()); + + assertEquals(0, visitor.getTables().size()); + +// Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("employees"))); +// Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("emp_name"))); + +// Assert.assertEquals(7, visitor.getColumns().size()); +// Assert.assertEquals(3, visitor.getConditions().size()); +// Assert.assertEquals(1, visitor.getRelationships().size()); + + // Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("employees", "salary"))); + + { + String output = SQLUtils.toSQLString(statementList, JdbcConstants.ORACLE); + System.out.println(output); + assertEquals("DECLARE\n" + + "\tcredit_limit CONSTANT NUMBER(3) := 5000;\n" + + "BEGIN\n" + + "\tNULL;\n" + + "EXCEPTION\n" + + "\tWHEN VALUE_ERROR THEN DBMS_OUTPUT.PUT_LINE('Exception raised in declaration.');\n" + + "END", // + output); + } + { + String output = SQLUtils.toSQLString(statementList, JdbcConstants.ORACLE, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION); + assertEquals("declare\n" + + "\tcredit_limit constant NUMBER(3) := 5000;\n" + + "begin\n" + + "\tnull;\n" + + "exception\n" + + "\twhen VALUE_ERROR then DBMS_OUTPUT.PUT_LINE('Exception raised in declaration.');\n" + + "end", // + output); + } + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/oracle/pl/Oracle_pl_exception_7.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/pl/Oracle_pl_exception_7.java new file mode 100644 index 0000000000..ad2279a8cb --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/pl/Oracle_pl_exception_7.java @@ -0,0 +1,95 @@ +/* + * 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.pl; + +import com.alibaba.druid.sql.OracleTest; +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 Oracle_pl_exception_7 extends OracleTest { + + public void test_0() throws Exception { + String sql = "BEGIN\n" + + " \n" + + " DECLARE\n" + + " credit_limit CONSTANT NUMBER(3) := 5000;\n" + + " BEGIN\n" + + " NULL;\n" + + " END;\n" + + " \n" + + "EXCEPTION\n" + + " WHEN VALUE_ERROR THEN\n" + + " DBMS_OUTPUT.PUT_LINE('Exception raised in declaration.');\n" + + "END;"; // + + List statementList = SQLUtils.parseStatements(sql, JdbcConstants.ORACLE); + assertEquals(1, statementList.size()); + + SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.ORACLE); + for (SQLStatement statement : statementList) { + statement.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()); + + assertEquals(0, visitor.getTables().size()); + +// Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("employees"))); +// Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("emp_name"))); + +// Assert.assertEquals(7, visitor.getColumns().size()); +// Assert.assertEquals(3, visitor.getConditions().size()); +// Assert.assertEquals(1, visitor.getRelationships().size()); + + // Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("employees", "salary"))); + + { + String output = SQLUtils.toSQLString(statementList, JdbcConstants.ORACLE); + System.out.println(output); + assertEquals("BEGIN\n" + + "\tDECLARE\n" + + "\t\tcredit_limit CONSTANT NUMBER(3) := 5000;\n" + + "\tBEGIN\n" + + "\t\tNULL;\n" + + "\tEND;\n" + + "EXCEPTION\n" + + "\tWHEN VALUE_ERROR THEN DBMS_OUTPUT.PUT_LINE('Exception raised in declaration.');\n" + + "END", // + output); + } + { + String output = SQLUtils.toSQLString(statementList, JdbcConstants.ORACLE, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION); + assertEquals("begin\n" + + "\tdeclare\n" + + "\t\tcredit_limit constant NUMBER(3) := 5000;\n" + + "\tbegin\n" + + "\t\tnull;\n" + + "\tend;\n" + + "exception\n" + + "\twhen VALUE_ERROR then DBMS_OUTPUT.PUT_LINE('Exception raised in declaration.');\n" + + "end", // + output); + } + } +} 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 new file mode 100644 index 0000000000..ea6555f78e --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/pl/Oracle_pl_exception_8.java @@ -0,0 +1,198 @@ +/* + * 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.pl; + +import com.alibaba.druid.sql.OracleTest; +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 Oracle_pl_exception_8 extends OracleTest { + + public void test_0() throws Exception { + String sql = "DROP TABLE results;\n" + + "CREATE TABLE results (\n" + + " res_name VARCHAR(20),\n" + + " res_answer VARCHAR2(3)\n" + + ");\n" + + " \n" + + "CREATE UNIQUE INDEX res_name_ix ON results (res_name);\n" + + "INSERT INTO results (res_name, res_answer) VALUES ('SMYTHE', 'YES');\n" + + "INSERT INTO results (res_name, res_answer) VALUES ('JONES', 'NO');\n" + + " \n" + + "DECLARE\n" + + " name VARCHAR2(20) := 'SMYTHE';\n" + + " answer VARCHAR2(3) := 'NO';\n" + + " suffix NUMBER := 1;\n" + + "BEGIN\n" + + " FOR i IN 1..5 LOOP -- Try transaction at most 5 times.\n" + + " \n" + + " DBMS_OUTPUT.PUT('Try #' || i);\n" + + " \n" + + " BEGIN -- sub-block begins\n" + + " \n" + + " SAVEPOINT start_transaction;\n" + + " \n" + + " -- transaction begins\n" + + " \n" + + " DELETE FROM results WHERE res_answer = 'NO';\n" + + " \n" + + " INSERT INTO results (res_name, res_answer) VALUES (name, answer);\n" + + " \n" + + " -- Nonunique name raises DUP_VAL_ON_INDEX.\n" + + " \n" + + " -- If transaction succeeded:\n" + + " \n" + + " COMMIT;\n" + + " DBMS_OUTPUT.PUT_LINE(' succeeded.');\n" + + " EXIT;\n" + + " \n" + + " EXCEPTION\n" + + " WHEN DUP_VAL_ON_INDEX THEN\n" + + " DBMS_OUTPUT.PUT_LINE(' failed; trying again.');\n" + + " ROLLBACK TO start_transaction; -- Undo changes.\n" + + " suffix := suffix + 1; -- Try to fix problem.\n" + + " name := name || TO_CHAR(suffix);\n" + + " END; -- sub-block ends\n" + + " \n" + + " END LOOP;\n" + + "END;"; // + + List statementList = SQLUtils.parseStatements(sql, JdbcConstants.ORACLE); + assertEquals(6, statementList.size()); + + SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.ORACLE); + for (SQLStatement statement : statementList) { + statement.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()); + + assertEquals(1, visitor.getTables().size()); + +// Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("employees"))); +// Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("emp_name"))); + +// Assert.assertEquals(7, visitor.getColumns().size()); +// Assert.assertEquals(3, visitor.getConditions().size()); +// Assert.assertEquals(1, visitor.getRelationships().size()); + + // Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("employees", "salary"))); + + { + String output = SQLUtils.toSQLString(statementList, JdbcConstants.ORACLE); + System.out.println(output); + assertEquals("DROP TABLE results;\n" + + "\n" + + "CREATE TABLE results (\n" + + "\tres_name VARCHAR(20),\n" + + "\tres_answer VARCHAR2(3)\n" + + ");\n" + + "\n" + + "CREATE UNIQUE INDEX res_name_ix ON results(res_name);\n" + + "\n" + + "INSERT INTO results (res_name, res_answer)\n" + + "VALUES ('SMYTHE', 'YES');\n" + + "\n" + + "INSERT INTO results (res_name, res_answer)\n" + + "VALUES ('JONES', 'NO');\n" + + "\n" + + "DECLARE\n" + + "\tname VARCHAR2(20) := 'SMYTHE';\n" + + "\tanswer VARCHAR2(3) := 'NO';\n" + + "\tsuffix NUMBER := 1;\n" + + "BEGIN\n" + + "\tFOR i IN 1..5\n" + + "\tLOOP\n" + + "\t\tDBMS_OUTPUT.PUT('Try #' || i);\n" + + "\t\tBEGIN\n" + + "\t\t\tROLLBACK;\n" + + "\t\t\tstart_transaction;\n" + + "\t\t\tDELETE FROM results\n" + + "\t\t\tWHERE res_answer = 'NO';\n" + + "\t\t\tINSERT INTO results (res_name, res_answer)\n" + + "\t\t\tVALUES (name, answer);\n" + + "\t\t\tCOMMIT;\n" + + "\t\t\tDBMS_OUTPUT.PUT_LINE(' succeeded.');\n" + + "\t\t\tEXIT;\n" + + "\t\tEXCEPTION\n" + + "\t\t\tWHEN DUP_VAL_ON_INDEX THEN\n" + + "\t\t\t\tDBMS_OUTPUT.PUT_LINE(' failed; trying again.');\n" + + "\t\t\t\tROLLBACK TO start_transaction;\n" + + "\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); + } + { + String output = SQLUtils.toSQLString(statementList, JdbcConstants.ORACLE, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION); + assertEquals("drop table results;\n" + + "\n" + + "create table results (\n" + + "\tres_name VARCHAR(20),\n" + + "\tres_answer VARCHAR2(3)\n" + + ");\n" + + "\n" + + "create UNIQUE index res_name_ix on results(res_name);\n" + + "\n" + + "insert into results (res_name, res_answer)\n" + + "values ('SMYTHE', 'YES');\n" + + "\n" + + "insert into results (res_name, res_answer)\n" + + "values ('JONES', 'NO');\n" + + "\n" + + "declare\n" + + "\tname VARCHAR2(20) := 'SMYTHE';\n" + + "\tanswer VARCHAR2(3) := 'NO';\n" + + "\tsuffix NUMBER := 1;\n" + + "begin\n" + + "\tfor i in 1..5\n" + + "\tloop\n" + + "\t\tDBMS_OUTPUT.PUT('Try #' || i);\n" + + "\t\tbegin\n" + + "\t\t\trollback;\n" + + "\t\t\tstart_transaction;\n" + + "\t\t\tdelete from results\n" + + "\t\t\twhere res_answer = 'NO';\n" + + "\t\t\tinsert into results (res_name, res_answer)\n" + + "\t\t\tvalues (name, answer);\n" + + "\t\t\tcommit;\n" + + "\t\t\tDBMS_OUTPUT.PUT_LINE(' succeeded.');\n" + + "\t\t\texit;\n" + + "\t\texception\n" + + "\t\t\twhen DUP_VAL_ON_INDEX then\n" + + "\t\t\t\tDBMS_OUTPUT.PUT_LINE(' failed; trying again.');\n" + + "\t\t\t\trollback to start_transaction;\n" + + "\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); + } + } +}