From b7e4de250171e98feaeef21b788dd1fd85ff86bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B8=A9=E5=B0=91?= Date: Tue, 28 Feb 2012 18:37:05 +0800 Subject: [PATCH] bug fixed for oracle sql parser --- .../druid/sql/ast/expr/SQLUnaryOperator.java | 2 +- .../sql/ast/statement/SQLAssignItem.java | 53 +++ .../sql/ast/statement/SQLSetStatement.java | 59 +--- .../oracle/ast/expr/OracleAggregateExpr.java | 11 +- .../oracle/ast/expr/OracleDatetimeExpr.java | 48 +++ .../ast/stmt/OracleAlterSessionStatement.java | 31 ++ .../ast/stmt/OracleMethodInvokeStatement.java | 37 ++ .../ast/stmt/OracleTruncateStatement.java | 18 + .../oracle/parser/OracleExprParser.java | 26 ++ .../dialect/oracle/parser/OracleLexer.java | 5 + .../oracle/parser/OracleSelectParser.java | 48 ++- .../oracle/parser/OracleStatementParser.java | 62 +++- .../visitor/OracleASTVIsitorAdapter.java | 81 +++-- .../oracle/visitor/OracleASTVisitor.java | 15 + .../oracle/visitor/OracleOutputVisitor.java | 50 +++ .../visitor/OracleSchemaStatVisitor.java | 67 +++- .../alibaba/druid/sql/parser/Keywords.java | 4 + .../com/alibaba/druid/sql/parser/Lexer.java | 7 +- .../druid/sql/parser/SQLExprParser.java | 46 ++- .../alibaba/druid/sql/parser/SQLParser.java | 7 +- .../druid/sql/parser/SQLSelectParser.java | 6 + .../druid/sql/parser/SQLStatementParser.java | 32 +- .../com/alibaba/druid/sql/parser/Token.java | 6 + .../sql/visitor/SQLASTOutputVisitor.java | 3 +- .../druid/sql/visitor/SQLASTVisitor.java | 5 +- .../sql/visitor/SQLASTVisitorAdapter.java | 5 +- .../druid/sql/visitor/SchemaStatVisitor.java | 8 +- .../sql/oracle/OracleAlterSessionTest.java | 41 +++ .../bvt/sql/oracle/OracleInsertTest4.java | 83 +++++ .../bvt/sql/oracle/OracleSelectTest12.java | 49 +++ .../bvt/sql/oracle/OracleSelectTest13.java | 46 +++ .../bvt/sql/oracle/OracleSelectTest14.java | 45 +++ .../bvt/sql/oracle/OracleSelectTest15.java | 44 +++ .../bvt/sql/oracle/OracleSelectTest16.java | 44 +++ .../com/alibaba/druid/sql/TestTransform.java | 325 +++++++++++++++--- 35 files changed, 1221 insertions(+), 198 deletions(-) create mode 100644 src/main/java/com/alibaba/druid/sql/ast/statement/SQLAssignItem.java create mode 100644 src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleDatetimeExpr.java create mode 100644 src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleAlterSessionStatement.java create mode 100644 src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleMethodInvokeStatement.java create mode 100644 src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleTruncateStatement.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleAlterSessionTest.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleInsertTest4.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleSelectTest12.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleSelectTest13.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleSelectTest14.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleSelectTest15.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleSelectTest16.java diff --git a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLUnaryOperator.java b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLUnaryOperator.java index 4a99173590..00c2e2750c 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLUnaryOperator.java +++ b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLUnaryOperator.java @@ -16,7 +16,7 @@ package com.alibaba.druid.sql.ast.expr; public enum SQLUnaryOperator { - Plus("+"), Negative("-"), Not("!"), Compl("~"), Prior("PRIOR"), ConnectByRoot("CONNECT BY"); + Plus("+"), Negative("-"), Not("!"), Compl("~"), Prior("PRIOR"), ConnectByRoot("CONNECT BY"), NOT("NOT"); public final String name; diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAssignItem.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAssignItem.java new file mode 100644 index 0000000000..3b6227b34c --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAssignItem.java @@ -0,0 +1,53 @@ +package com.alibaba.druid.sql.ast.statement; + +import com.alibaba.druid.sql.ast.SQLExpr; +import com.alibaba.druid.sql.ast.SQLObjectImpl; +import com.alibaba.druid.sql.visitor.SQLASTVisitor; + +public class SQLAssignItem extends SQLObjectImpl { + + private static final long serialVersionUID = 1L; + + private SQLExpr target; + private SQLExpr value; + + public SQLAssignItem(){ + } + + public SQLAssignItem(SQLExpr target, SQLExpr value){ + this.target = target; + this.value = value; + } + + public SQLExpr getTarget() { + return target; + } + + public void setTarget(SQLExpr target) { + this.target = target; + } + + public SQLExpr getValue() { + return value; + } + + public void setValue(SQLExpr value) { + this.value = value; + } + + public void output(StringBuffer buf) { + target.output(buf); + buf.append(" = "); + value.output(buf); + } + + @Override + protected void accept0(SQLASTVisitor visitor) { + if (visitor.visit(this)) { + acceptChild(visitor, this.target); + acceptChild(visitor, this.value); + } + visitor.endVisit(this); + } + +} \ No newline at end of file diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSetStatement.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSetStatement.java index 3b11c60b4b..d285ccccff 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSetStatement.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSetStatement.java @@ -19,7 +19,6 @@ import java.util.ArrayList; import java.util.List; import com.alibaba.druid.sql.ast.SQLExpr; -import com.alibaba.druid.sql.ast.SQLObjectImpl; import com.alibaba.druid.sql.ast.SQLStatementImpl; import com.alibaba.druid.sql.visitor.SQLASTVisitor; @@ -27,20 +26,20 @@ public class SQLSetStatement extends SQLStatementImpl { private static final long serialVersionUID = 1L; - private List items = new ArrayList(); + private List items = new ArrayList(); public SQLSetStatement(){ } public SQLSetStatement(SQLExpr target, SQLExpr value) { - this.items.add(new Item(target, value)); + this.items.add(new SQLAssignItem(target, value)); } - public List getItems() { + public List getItems() { return items; } - public void setItems(List items) { + public void setItems(List items) { this.items = items; } @@ -60,56 +59,8 @@ public class SQLSetStatement extends SQLStatementImpl { buf.append(", "); } - Item item = items.get(i); + SQLAssignItem item = items.get(i); item.output(buf); } } - - public static class Item extends SQLObjectImpl { - - private static final long serialVersionUID = 1L; - - private SQLExpr target; - private SQLExpr value; - - public Item(){ - } - - public Item(SQLExpr target, SQLExpr value){ - this.target = target; - this.value = value; - } - - public SQLExpr getTarget() { - return target; - } - - public void setTarget(SQLExpr target) { - this.target = target; - } - - public SQLExpr getValue() { - return value; - } - - public void setValue(SQLExpr value) { - this.value = value; - } - - public void output(StringBuffer buf) { - target.output(buf); - buf.append(" = "); - value.output(buf); - } - - @Override - protected void accept0(SQLASTVisitor visitor) { - if (visitor.visit(this)) { - acceptChild(visitor, this.target); - acceptChild(visitor, this.value); - } - visitor.endVisit(this); - } - - } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleAggregateExpr.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleAggregateExpr.java index 69d73af737..77a2125b46 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleAggregateExpr.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleAggregateExpr.java @@ -74,7 +74,16 @@ public class OracleAggregateExpr extends SQLAggregateExpr implements Serializabl @Override protected void accept0(SQLASTVisitor visitor) { - this.accept0((OracleASTVisitor) visitor); + if (visitor instanceof OracleASTVisitor) { + this.accept0((OracleASTVisitor) visitor); + } else { + if (visitor.visit(this)) { + acceptChild(visitor, this.methodName); + acceptChild(visitor, this.arguments); + acceptChild(visitor, this.over); + } + visitor.endVisit(this); + } } public void accept0(OracleASTVisitor visitor) { diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleDatetimeExpr.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleDatetimeExpr.java new file mode 100644 index 0000000000..68e6c9f917 --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleDatetimeExpr.java @@ -0,0 +1,48 @@ +package com.alibaba.druid.sql.dialect.oracle.ast.expr; + +import com.alibaba.druid.sql.ast.SQLExpr; +import com.alibaba.druid.sql.dialect.oracle.ast.OracleSQLObjectImpl; +import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor; + +public class OracleDatetimeExpr extends OracleSQLObjectImpl implements SQLExpr { + + private static final long serialVersionUID = 1L; + + private SQLExpr expr; + private SQLExpr timeZone; + + public OracleDatetimeExpr(){ + + } + + public OracleDatetimeExpr(SQLExpr expr, SQLExpr timeZone){ + this.expr = expr; + this.timeZone = timeZone; + } + + @Override + public void accept0(OracleASTVisitor visitor) { + if (visitor.visit(this)) { + acceptChild(visitor, expr); + acceptChild(visitor, timeZone); + } + visitor.endVisit(this); + } + + public SQLExpr getExpr() { + return expr; + } + + public void setExpr(SQLExpr expr) { + this.expr = expr; + } + + public SQLExpr getTimeZone() { + return timeZone; + } + + public void setTimeZone(SQLExpr timeZone) { + this.timeZone = timeZone; + } + +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleAlterSessionStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleAlterSessionStatement.java new file mode 100644 index 0000000000..608f979fbb --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleAlterSessionStatement.java @@ -0,0 +1,31 @@ +package com.alibaba.druid.sql.dialect.oracle.ast.stmt; + +import java.util.ArrayList; +import java.util.List; + +import com.alibaba.druid.sql.ast.statement.SQLAssignItem; +import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor; + +public class OracleAlterSessionStatement extends OracleStatementImpl { + + private static final long serialVersionUID = 1L; + + private List items = new ArrayList(); + + @Override + public void accept0(OracleASTVisitor visitor) { + if (visitor.visit(this)) { + acceptChild(visitor, items); + } + visitor.endVisit(this); + } + + public List getItems() { + return items; + } + + public void setItems(List items) { + this.items = items; + } + +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleMethodInvokeStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleMethodInvokeStatement.java new file mode 100644 index 0000000000..2f6a549afe --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleMethodInvokeStatement.java @@ -0,0 +1,37 @@ +package com.alibaba.druid.sql.dialect.oracle.ast.stmt; + +import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr; +import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor; + +public class OracleMethodInvokeStatement extends OracleStatementImpl { + + private static final long serialVersionUID = 1L; + + private SQLMethodInvokeExpr expr; + + public OracleMethodInvokeStatement(){ + + } + + public OracleMethodInvokeStatement(SQLMethodInvokeExpr expr){ + this.expr = expr; + } + + @Override + public void accept0(OracleASTVisitor visitor) { + if (visitor.visit(this)) { + acceptChild(visitor, expr); + } + visitor.endVisit(this); + + } + + public SQLMethodInvokeExpr getExpr() { + return expr; + } + + public void setExpr(SQLMethodInvokeExpr expr) { + this.expr = expr; + } + +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleTruncateStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleTruncateStatement.java new file mode 100644 index 0000000000..7a319ee4f8 --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleTruncateStatement.java @@ -0,0 +1,18 @@ +package com.alibaba.druid.sql.dialect.oracle.ast.stmt; + +import com.alibaba.druid.sql.ast.statement.SQLTruncateStatement; +import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor; +import com.alibaba.druid.sql.visitor.SQLASTVisitor; + +public class OracleTruncateStatement extends SQLTruncateStatement implements OracleStatement { + + private static final long serialVersionUID = 1L; + + @Override + protected void accept0(SQLASTVisitor visitor) { + this.accept0((OracleASTVisitor) visitor); + } + + public void accept0(OracleASTVisitor visitor) { + } +} 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 6852f2ad9f..91e262aa4d 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 @@ -29,6 +29,8 @@ import com.alibaba.druid.sql.ast.expr.SQLIntegerExpr; import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr; import com.alibaba.druid.sql.ast.expr.SQLNumberExpr; import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr; +import com.alibaba.druid.sql.ast.expr.SQLUnaryExpr; +import com.alibaba.druid.sql.ast.expr.SQLUnaryOperator; import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr; import com.alibaba.druid.sql.dialect.oracle.ast.OracleHint; import com.alibaba.druid.sql.dialect.oracle.ast.OracleOrderBy; @@ -40,6 +42,7 @@ import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleBinaryFloatExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleCursorExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleDateExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleDateTimeUnit; +import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleDatetimeExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleDbLinkExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleExtractExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleIntervalExpr; @@ -90,6 +93,11 @@ public class OracleExprParser extends SQLExprParser { SQLExpr sqlExpr = null; switch (tok) { + case PRIOR: + lexer.nextToken(); + sqlExpr = expr(); + sqlExpr = new SQLUnaryExpr(SQLUnaryOperator.Prior, sqlExpr); + return primaryRest(sqlExpr); case COLON: lexer.nextToken(); if (lexer.token() == Token.LITERAL_INT) { @@ -204,6 +212,10 @@ public class OracleExprParser extends SQLExprParser { sqlExpr = new OracleBinaryDoubleExpr(Double.parseDouble(lexer.numberString()) * -1); lexer.nextToken(); break; + case IDENTIFIER: + sqlExpr = expr(); + sqlExpr = new SQLUnaryExpr(SQLUnaryOperator.Negative, sqlExpr); + break; default: throw new ParserException("TODO"); } @@ -286,6 +298,20 @@ public class OracleExprParser extends SQLExprParser { expr = interval; } + if (lexer.token() == Token.AT) { + lexer.nextToken(); + if (lexer.token() == Token.LOCAL) { + lexer.nextToken(); + expr = new OracleDatetimeExpr(expr, new SQLIdentifierExpr("LOCAL")); + } else { + accept(Token.TIME); + accept(Token.ZONE); + + SQLExpr timeZone = primary(); + expr = new OracleDatetimeExpr(expr, timeZone); + } + } + SQLExpr restExpr = super.primaryRest(expr); if (restExpr != expr && restExpr instanceof SQLMethodInvokeExpr) { diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleLexer.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleLexer.java index 5561030682..0b3ea8dd7c 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleLexer.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleLexer.java @@ -120,6 +120,11 @@ public class OracleLexer extends Lexer { map.put("MODE", Token.MODE); map.put("WAIT", Token.WAIT); map.put("NOWAIT", Token.NOWAIT); + map.put("SESSION", Token.SESSION); + map.put("AT", Token.AT); + map.put("LOCAL", Token.LOCAL); + map.put("TIME", Token.TIME); + map.put("ZONE", Token.ZONE); DEFAULT_ORACLE_KEYWORDS = new Keywords(map); } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleSelectParser.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleSelectParser.java index 128a4bfca0..7f806dbdc8 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleSelectParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleSelectParser.java @@ -572,9 +572,49 @@ public class OracleSelectParser extends SQLSelectParser { groupBy.setHaving(this.createExprParser().expr()); } + queryBlock.setGroupBy(groupBy); + } else if (lexer.token() == (Token.HAVING)) { + lexer.nextToken(); + + SQLSelectGroupByClause groupBy = new SQLSelectGroupByClause(); + groupBy.setHaving(this.createExprParser().expr()); + + if (lexer.token() == (Token.GROUP)) { + lexer.nextToken(); + accept(Token.BY); + + for (;;) { + if (identifierEquals("GROUPING")) { + GroupingSetExpr groupingSet = new GroupingSetExpr(); + lexer.nextToken(); + acceptIdentifier("SETS"); + accept(Token.LPAREN); + createExprParser().exprList(groupingSet.getParameters()); + accept(Token.RPAREN); + groupBy.getItems().add(groupingSet); + } else { + groupBy.getItems().add(this.createExprParser().expr()); + } + + if (!(lexer.token() == (Token.COMMA))) { + break; + } + + lexer.nextToken(); + } + } + queryBlock.setGroupBy(groupBy); } } + + protected String as() throws ParserException { + if (lexer.token() == Token.CONNECT) { + return null; + } + + return super.as(); + } private void parseHierachical(OracleSelectQueryBlock queryBlock) { OracleSelectHierachicalQueryClause hierachical = null; @@ -814,7 +854,7 @@ public class OracleSelectParser extends SQLSelectParser { if (lexer.token() == Token.LEFT) { lexer.nextToken(); - if (identifierEquals("OUTER")) { + if (lexer.token() == Token.OUTER) { lexer.nextToken(); } accept(Token.JOIN); @@ -823,16 +863,16 @@ public class OracleSelectParser extends SQLSelectParser { if (lexer.token() == Token.RIGHT) { lexer.nextToken(); - if (identifierEquals("OUTER")) { + if (lexer.token() == Token.OUTER) { lexer.nextToken(); } accept(Token.JOIN); joinType = OracleSelectJoin.JoinType.RIGHT_OUTER_JOIN; } - if (identifierEquals("FULL")) { + if (lexer.token() == Token.FULL) { lexer.nextToken(); - if (identifierEquals("OUTER")) { + if (lexer.token() == Token.OUTER) { lexer.nextToken(); } accept(Token.JOIN); 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 cca3126751..4f8b6a2522 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 @@ -22,6 +22,7 @@ import com.alibaba.druid.sql.ast.SQLExpr; import com.alibaba.druid.sql.ast.SQLStatement; import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr; import com.alibaba.druid.sql.ast.expr.SQLBinaryOperator; +import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr; import com.alibaba.druid.sql.ast.statement.SQLInsertInto; import com.alibaba.druid.sql.ast.statement.SQLSelect; import com.alibaba.druid.sql.ast.statement.SQLSelectStatement; @@ -31,14 +32,16 @@ import com.alibaba.druid.sql.ast.statement.SQLUpdateSetItem; import com.alibaba.druid.sql.dialect.oracle.ast.OracleHint; import com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleErrorLoggingClause; import com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleReturningClause; +import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleAlterSessionStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleBlockStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleInsertStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleLockTableStatement; +import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleLockTableStatement.LockMode; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMergeStatement; +import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMethodInvokeStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMultiInsertStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OraclePLSQLCommitStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleStatement; -import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleLockTableStatement.LockMode; import com.alibaba.druid.sql.parser.Lexer; import com.alibaba.druid.sql.parser.ParserException; import com.alibaba.druid.sql.parser.SQLStatementParser; @@ -60,7 +63,7 @@ public class OracleStatementParser extends SQLStatementParser { protected OracleExprParser createExprParser() { return new OracleExprParser(lexer); } - + protected void parseInsert0_hinits(SQLInsertInto insertStatement) { if (insertStatement instanceof OracleInsertStatement) { OracleInsertStatement stmt = (OracleInsertStatement) insertStatement; @@ -119,7 +122,8 @@ public class OracleStatementParser extends SQLStatementParser { } if (lexer.token() == Token.ALTER) { - throw new ParserException("TODO"); + statementList.add(parserAlter()); + continue; } if (lexer.token() == Token.WITH) { @@ -146,6 +150,11 @@ public class OracleStatementParser extends SQLStatementParser { statementList.add(this.parseLock()); continue; } + + if (lexer.token() == Token.TRUNCATE) { + statementList.add(this.parseTruncate()); + continue; + } if (lexer.token() == Token.VARIANT) { SQLExpr variant = this.exprParser.primary(); @@ -164,10 +173,42 @@ public class OracleStatementParser extends SQLStatementParser { statementList.add(stmt); continue; } + + if (lexer.token() == Token.IDENTIFIER) { + SQLExpr expr = exprParser.expr(); + if (expr instanceof SQLMethodInvokeExpr) { + OracleMethodInvokeStatement stmt = new OracleMethodInvokeStatement((SQLMethodInvokeExpr) expr); + statementList.add(stmt); + continue; + } else { + throw new ParserException("expr : " + expr); + } + } throw new ParserException("TODO : " + lexer.token() + " " + lexer.stringVal()); } } + + public SQLStatement parseTruncate() { + return super.parseTruncate(); + } + + public OracleStatement parserAlter() { + accept(Token.ALTER); + if (lexer.token() == Token.SESSION) { + lexer.nextToken(); + + OracleAlterSessionStatement stmt = new OracleAlterSessionStatement(); + if (lexer.token() == Token.SET) { + lexer.nextToken(); + parseAssignItems(stmt.getItems()); + } else { + throw new ParserException("TODO : " + lexer.token() + " " + lexer.stringVal()); + } + return stmt; + } + throw new ParserException("TODO : " + lexer.token() + " " + lexer.stringVal()); + } public OracleLockTableStatement parseLock() { accept(Token.LOCK); @@ -185,7 +226,7 @@ public class OracleStatementParser extends SQLStatementParser { lexer.nextToken(); } accept(Token.MODE); - + if (lexer.token() == Token.NOWAIT) { lexer.nextToken(); } else if (lexer.token() == Token.WAIT) { @@ -313,9 +354,14 @@ public class OracleStatementParser extends SQLStatementParser { public OracleStatement parseInsert() { accept(Token.INSERT); + List hints = new ArrayList(); + + this.createExprParser().parseHints(hints); + if (lexer.token() == Token.INTO) { OracleInsertStatement stmt = new OracleInsertStatement(); - + stmt.setHints(hints); + parseInsert0(stmt); stmt.setReturning(parseReturningClause()); @@ -324,10 +370,12 @@ public class OracleStatementParser extends SQLStatementParser { return stmt; } - return parseMultiInsert(); + OracleMultiInsertStatement stmt = parseMultiInsert(); + stmt.setHints(hints); + return stmt; } - public OracleStatement parseMultiInsert() { + public OracleMultiInsertStatement parseMultiInsert() { OracleMultiInsertStatement stmt = new OracleMultiInsertStatement(); if (lexer.token() == Token.ALL) { 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 e303105fde..466d9e71c6 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 @@ -30,12 +30,14 @@ import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleBinaryDoubleExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleBinaryFloatExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleCursorExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleDateExpr; +import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleDatetimeExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleDbLinkExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleExtractExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleIntervalExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleIsSetExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleOuterExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleTimestampExpr; +import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleAlterSessionStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleBlockStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleConstraintState; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleDeleteStatement; @@ -44,6 +46,7 @@ import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleLockTableStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMergeStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMergeStatement.MergeInsertClause; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMergeStatement.MergeUpdateClause; +import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMethodInvokeStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMultiInsertStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMultiInsertStatement.ConditionalInsertClause; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMultiInsertStatement.ConditionalInsertClauseItem; @@ -700,85 +703,85 @@ public class OracleASTVIsitorAdapter extends SQLASTVisitorAdapter implements Ora public void endVisit(OracleErrorLoggingClause x) { } - + @Override public boolean visit(OracleReturningClause x) { return true; } - + @Override public void endVisit(OracleReturningClause x) { - + } - + @Override public boolean visit(OracleInsertStatement x) { return true; } - + @Override public void endVisit(OracleInsertStatement x) { - + } - + @Override public boolean visit(InsertIntoClause x) { return true; } - + @Override public void endVisit(InsertIntoClause x) { - + } - + @Override public boolean visit(OracleMultiInsertStatement x) { return true; } - + @Override public void endVisit(OracleMultiInsertStatement x) { - + } - + @Override public boolean visit(ConditionalInsertClause x) { return true; } - + @Override public void endVisit(ConditionalInsertClause x) { - + } - + @Override public boolean visit(ConditionalInsertClauseItem x) { return true; } - + @Override public void endVisit(ConditionalInsertClauseItem x) { - + } - + @Override public boolean visit(OracleSelectQueryBlock x) { return true; } - + @Override public void endVisit(OracleSelectQueryBlock x) { - + } - + @Override public boolean visit(OracleBlockStatement x) { return true; } - + @Override public void endVisit(OracleBlockStatement x) { - + } @Override @@ -788,6 +791,36 @@ public class OracleASTVIsitorAdapter extends SQLASTVisitorAdapter implements Ora @Override public void endVisit(OracleLockTableStatement x) { + + } + + @Override + public boolean visit(OracleAlterSessionStatement x) { + return true; + } + + @Override + public void endVisit(OracleAlterSessionStatement x) { + + } + + @Override + public boolean visit(OracleMethodInvokeStatement x) { + return true; + } + + @Override + public void endVisit(OracleMethodInvokeStatement x) { + + } + + @Override + public boolean visit(OracleDatetimeExpr x) { + return true; + } + + @Override + public void endVisit(OracleDatetimeExpr x) { } 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 b587dc5bcb..5251dd8576 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 @@ -36,18 +36,21 @@ import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleBinaryDoubleExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleBinaryFloatExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleCursorExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleDateExpr; +import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleDatetimeExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleDbLinkExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleExtractExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleIntervalExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleIsSetExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleOuterExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleTimestampExpr; +import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleAlterSessionStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleBlockStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleConstraintState; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleDeleteStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleInsertStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleLockTableStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMergeStatement; +import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMethodInvokeStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMultiInsertStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMultiInsertStatement.ConditionalInsertClause; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMultiInsertStatement.ConditionalInsertClauseItem; @@ -345,4 +348,16 @@ public interface OracleASTVisitor extends SQLASTVisitor { boolean visit(OracleLockTableStatement x); void endVisit(OracleLockTableStatement x); + + boolean visit(OracleAlterSessionStatement x); + + void endVisit(OracleAlterSessionStatement x); + + boolean visit(OracleMethodInvokeStatement x); + + void endVisit(OracleMethodInvokeStatement x); + + boolean visit(OracleDatetimeExpr x); + + void endVisit(OracleDatetimeExpr 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 1e84973ee3..697395a5cb 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 @@ -24,6 +24,7 @@ import com.alibaba.druid.sql.ast.SQLObject; import com.alibaba.druid.sql.ast.SQLSetQuantifier; import com.alibaba.druid.sql.ast.SQLStatement; import com.alibaba.druid.sql.ast.expr.SQLAllColumnExpr; +import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; import com.alibaba.druid.sql.ast.expr.SQLLiteralExpr; import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr; import com.alibaba.druid.sql.ast.expr.SQLObjectCreateExpr; @@ -62,12 +63,14 @@ import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleBinaryDoubleExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleBinaryFloatExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleCursorExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleDateExpr; +import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleDatetimeExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleDbLinkExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleExtractExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleIntervalExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleIsSetExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleOuterExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleTimestampExpr; +import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleAlterSessionStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleBlockStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleConstraintState; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleDeleteStatement; @@ -76,6 +79,7 @@ import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleLockTableStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMergeStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMergeStatement.MergeInsertClause; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMergeStatement.MergeUpdateClause; +import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMethodInvokeStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMultiInsertStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMultiInsertStatement.ConditionalInsertClause; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMultiInsertStatement.ConditionalInsertClauseItem; @@ -1669,4 +1673,50 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS public void endVisit(OracleLockTableStatement x) { } + + @Override + public boolean visit(OracleAlterSessionStatement x) { + print("ALTER SESSION SET "); + printAndAccept(x.getItems(), ", "); + return false; + } + + @Override + public void endVisit(OracleAlterSessionStatement x) { + + } + + @Override + public boolean visit(OracleMethodInvokeStatement x) { + x.getExpr().accept(this); + return false; + } + + @Override + public void endVisit(OracleMethodInvokeStatement x) { + + } + + @Override + public boolean visit(OracleDatetimeExpr x) { + x.getExpr().accept(this); + SQLExpr timeZone = x.getTimeZone(); + + if (timeZone instanceof SQLIdentifierExpr) { + if (((SQLIdentifierExpr) timeZone).getName().equalsIgnoreCase("LOCAL")) { + print(" AT LOCAL"); + return false; + } + } + + print(" AT TIME ZONE "); + timeZone.accept(this); + + return false; + } + + @Override + public void endVisit(OracleDatetimeExpr 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 9610f5f830..dde9148e35 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 @@ -45,12 +45,14 @@ import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleBinaryDoubleExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleBinaryFloatExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleCursorExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleDateExpr; +import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleDatetimeExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleDbLinkExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleExtractExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleIntervalExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleIsSetExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleOuterExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleTimestampExpr; +import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleAlterSessionStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleBlockStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleConstraintState; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleDeleteStatement; @@ -59,6 +61,7 @@ import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleLockTableStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMergeStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMergeStatement.MergeInsertClause; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMergeStatement.MergeUpdateClause; +import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMethodInvokeStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMultiInsertStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMultiInsertStatement.ConditionalInsertClause; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMultiInsertStatement.ConditionalInsertClauseItem; @@ -95,28 +98,28 @@ public class OracleSchemaStatVisitor extends SchemaStatVisitor implements Oracle if (expr instanceof OracleOuterExpr) { expr = ((OracleOuterExpr) expr).getExpr(); } - + return super.getColumn(expr); } - + public boolean visit(OracleSelectTableReference x) { SQLExpr expr = x.getExpr(); - + if (expr instanceof SQLMethodInvokeExpr) { SQLMethodInvokeExpr methodInvoke = (SQLMethodInvokeExpr) expr; if ("TABLE".equalsIgnoreCase(methodInvoke.getMethodName()) && methodInvoke.getParameters().size() == 1) { expr = methodInvoke.getParameters().get(0); } } - + Map aliasMap = aliasLocal.get(); - + if (expr instanceof SQLName) { String ident; if (expr instanceof SQLPropertyExpr) { String owner = ((SQLPropertyExpr) expr).getOwner().toString(); String name = ((SQLPropertyExpr) expr).getName(); - + if (aliasMap.containsKey(owner)) { owner = aliasMap.get(owner); } @@ -124,11 +127,11 @@ public class OracleSchemaStatVisitor extends SchemaStatVisitor implements Oracle } else { ident = expr.toString(); } - + if (subQueryMap.containsKey(ident)) { return false; } - + if ("DUAL".equalsIgnoreCase(ident)) { return false; } @@ -254,7 +257,7 @@ public class OracleSchemaStatVisitor extends SchemaStatVisitor implements Oracle if (x.getWhere() != null) { x.getWhere().setParent(x); } - + return visit((SQLSelectQueryBlock) x); } @@ -269,7 +272,7 @@ public class OracleSchemaStatVisitor extends SchemaStatVisitor implements Oracle return super.visit(x); } - + public boolean visit(SQLMethodInvokeExpr x) { accept(x.getParameters()); return false; @@ -287,7 +290,7 @@ public class OracleSchemaStatVisitor extends SchemaStatVisitor implements Oracle if ("+".equalsIgnoreCase(x.getName())) { return false; } - + if ("LEVEL".equals(x.getName())) { return false; } @@ -530,7 +533,7 @@ public class OracleSchemaStatVisitor extends SchemaStatVisitor implements Oracle if (x.getCondition() != null) { x.getCondition().accept(this); } - + for (SQLExpr item : x.getUsing()) { if (item instanceof SQLIdentifierExpr) { String columnName = ((SQLIdentifierExpr) item).getName(); @@ -543,17 +546,17 @@ public class OracleSchemaStatVisitor extends SchemaStatVisitor implements Oracle relationship.setOperator("USING"); relationships.add(relationship); } - + if (leftTable != null) { columns.add(new Column(leftTable, columnName)); } - + if (rightTable != null) { columns.add(new Column(rightTable, columnName)); } } } - + return false; } @@ -1090,7 +1093,6 @@ public class OracleSchemaStatVisitor extends SchemaStatVisitor implements Oracle @Override public void endVisit(ConditionalInsertClauseItem x) { - } @Override @@ -1100,8 +1102,29 @@ public class OracleSchemaStatVisitor extends SchemaStatVisitor implements Oracle @Override public void endVisit(OracleBlockStatement x) { + + } + + @Override + public boolean visit(OracleAlterSessionStatement x) { + return false; + } + + @Override + public void endVisit(OracleAlterSessionStatement x) { + + } + + @Override + public boolean visit(OracleMethodInvokeStatement x) { + return false; + } + + @Override + public void endVisit(OracleMethodInvokeStatement x) { } + @Override public boolean visit(OracleLockTableStatement x) { String tableName = x.getTable().toString(); @@ -1109,9 +1132,19 @@ public class OracleSchemaStatVisitor extends SchemaStatVisitor implements Oracle this.tableStats.put(new TableStat.Name(tableName), stat); return false; } - + @Override public void endVisit(OracleLockTableStatement x) { + + } + + @Override + public boolean visit(OracleDatetimeExpr x) { + return true; + } + + @Override + public void endVisit(OracleDatetimeExpr x) { } } diff --git a/src/main/java/com/alibaba/druid/sql/parser/Keywords.java b/src/main/java/com/alibaba/druid/sql/parser/Keywords.java index 1f8975d830..cd9548aff7 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/Keywords.java +++ b/src/main/java/com/alibaba/druid/sql/parser/Keywords.java @@ -101,6 +101,10 @@ public class Keywords { map.put("DEFAULT", Token.DEFAULT); DEFAULT_KEYWORDS = new Keywords(map); } + + public boolean containsValue(Token token) { + return this.keywords.containsValue(token); + } public Keywords(Map keywords){ this.keywords = keywords; diff --git a/src/main/java/com/alibaba/druid/sql/parser/Lexer.java b/src/main/java/com/alibaba/druid/sql/parser/Lexer.java index 3b4f098b46..df4a27bb42 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/Lexer.java +++ b/src/main/java/com/alibaba/druid/sql/parser/Lexer.java @@ -19,7 +19,6 @@ import static com.alibaba.druid.sql.parser.CharTypes.isFirstIdentifierChar; import static com.alibaba.druid.sql.parser.CharTypes.isIdentifierChar; import static com.alibaba.druid.sql.parser.CharTypes.isWhitespace; import static com.alibaba.druid.sql.parser.LayoutCharacters.EOI; -import static com.alibaba.druid.sql.parser.Token.COLON; import static com.alibaba.druid.sql.parser.Token.COLONEQ; import static com.alibaba.druid.sql.parser.Token.COMMA; import static com.alibaba.druid.sql.parser.Token.EOF; @@ -91,6 +90,10 @@ public class Lexer { Token token; } + public Keywords getKeywods() { + return keywods; + } + public void mark() { SavePoint savePoint = new SavePoint(); savePoint.bp = bp; @@ -144,7 +147,7 @@ public class Lexer { protected final void scanChar() { ch = buf[++bp]; } - + protected void unscan() { ch = buf[--bp]; } 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 99d2e2ff80..9341d813a1 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java @@ -201,6 +201,14 @@ public class SQLExprParser extends SQLParser { case USER: case PASSWORD: case DUAL: + case REFERENCE: + case KEY: + case DISTINCT: + case YEAR: + case MONTH: + case TIME: + case ZONE: + case LOG: sqlExpr = new SQLIdentifierExpr(lexer.stringVal()); lexer.nextToken(); break; @@ -250,9 +258,10 @@ public class SQLExprParser extends SQLParser { sqlExpr = new SQLExistsExpr(createSelectParser().select(), true); accept(Token.RPAREN); } else if (lexer.token() == Token.LPAREN) { - lexer.token(); + lexer.nextToken(); - sqlExpr = new SQLNotExpr(expr()); + SQLExpr notTarget = expr(); + sqlExpr = new SQLNotExpr(notTarget); accept(Token.RPAREN); return primaryRest(sqlExpr); @@ -393,13 +402,6 @@ public class SQLExprParser extends SQLParser { sqlExpr = someExpr; break; - case KEY: - case DISTINCT: - case YEAR: - case MONTH: - lexer.nextToken(); - sqlExpr = new SQLIdentifierExpr(tok.name()); - break; case ALL: lexer.nextToken(); SQLAllExpr allExpr = new SQLAllExpr(); @@ -476,14 +478,14 @@ public class SQLExprParser extends SQLParser { } else { String name; - if (lexer.token() == Token.KEY) { - name = "KEY"; - lexer.nextToken(); - } else if (lexer.token() != Token.IDENTIFIER && lexer.token() != Token.USER && lexer.token() != Token.PASSWORD) { - throw new ParserException("error : " + lexer.stringVal()); - } else { + if (lexer.token() == Token.IDENTIFIER || lexer.token() == Token.LITERAL_CHARS || lexer.token() == Token.LITERAL_ALIAS) { name = lexer.stringVal(); lexer.nextToken(); + } else if (lexer.getKeywods().containsValue(lexer.token())) { + name = lexer.stringVal(); + lexer.nextToken(); + } else { + throw new ParserException("error : " + lexer.stringVal()); } if (lexer.token() == Token.LPAREN) { @@ -569,6 +571,12 @@ public class SQLExprParser extends SQLParser { if (lexer.token() == Token.DOT) { lexer.nextToken(); + + if (lexer.token() == Token.KEY) { + name = new SQLPropertyExpr(name, "KEY"); + lexer.nextToken(); + return name; + } if (lexer.token() != Token.LITERAL_ALIAS && lexer.token() != Token.IDENTIFIER) { throw new ParserException("error, " + lexer.token()); @@ -914,9 +922,9 @@ public class SQLExprParser extends SQLParser { expr = notRationalRest(expr); } else if (lexer.token() == (Token.BETWEEN)) { lexer.nextToken(); - SQLExpr beginExpr = primary(); + SQLExpr beginExpr = bitOr(); accept(Token.AND); - SQLExpr endExpr = primary(); + SQLExpr endExpr = bitOr(); expr = new SQLBetweenExpr(expr, beginExpr, endExpr); } else if (lexer.token() == (Token.IS)) { lexer.nextToken(); @@ -975,9 +983,9 @@ public class SQLExprParser extends SQLParser { return expr; } else if (lexer.token() == (Token.BETWEEN)) { lexer.nextToken(); - SQLExpr beginExpr = primary(); + SQLExpr beginExpr = bitOr(); accept(Token.AND); - SQLExpr endExpr = primary(); + SQLExpr endExpr = bitOr(); expr = new SQLBetweenExpr(expr, true, beginExpr, endExpr); diff --git a/src/main/java/com/alibaba/druid/sql/parser/SQLParser.java b/src/main/java/com/alibaba/druid/sql/parser/SQLParser.java index 234df9d221..9d1b4be687 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLParser.java @@ -65,7 +65,7 @@ public class SQLParser { return alias; } - if (lexer.token() == Token.YEAR || lexer.token() == Token.DAY) { + if (lexer.token() == Token.YEAR || lexer.token() == Token.DAY || lexer.token() == Token.KEY || lexer.token() == Token.CASE) { alias = lexer.token.name(); lexer.nextToken(); return alias; @@ -92,7 +92,7 @@ public class SQLParser { } else if (lexer.token() == Token.LITERAL_CHARS) { alias = "'" + lexer.stringVal() + "'"; lexer.nextToken(); - } else if (lexer.token() == Token.YEAR || lexer.token() == Token.DAY) { + } else if (lexer.token() == Token.YEAR || lexer.token() == Token.DAY || lexer.token() == Token.CASE) { alias = lexer.token.name(); lexer.nextToken(); } @@ -114,7 +114,8 @@ public class SQLParser { lexer.nextToken(); } else { setErrorEndPos(lexer.pos()); - throw new SQLParseException("syntax error, expect " + token + ", actual " + lexer.token() + " " + lexer.stringVal()); + throw new SQLParseException("syntax error, expect " + token + ", actual " + lexer.token() + " " + + lexer.stringVal()); } } diff --git a/src/main/java/com/alibaba/druid/sql/parser/SQLSelectParser.java b/src/main/java/com/alibaba/druid/sql/parser/SQLSelectParser.java index 014a178d02..e48d34a8ee 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLSelectParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLSelectParser.java @@ -167,6 +167,12 @@ public class SQLSelectParser extends SQLParser { groupBy.setHaving(expr()); } + queryBlock.setGroupBy(groupBy); + } else if (lexer.token() == (Token.HAVING)) { + lexer.nextToken(); + + SQLSelectGroupByClause groupBy = new SQLSelectGroupByClause(); + groupBy.setHaving(this.createExprParser().expr()); queryBlock.setGroupBy(groupBy); } } 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 0fd7ad4ca6..ea6b7d98ef 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java @@ -22,6 +22,7 @@ import com.alibaba.druid.sql.ast.SQLExpr; import com.alibaba.druid.sql.ast.SQLName; import com.alibaba.druid.sql.ast.SQLStatement; import com.alibaba.druid.sql.ast.expr.SQLQueryExpr; +import com.alibaba.druid.sql.ast.statement.SQLAssignItem; import com.alibaba.druid.sql.ast.statement.SQLCallStatement; import com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement; import com.alibaba.druid.sql.ast.statement.SQLCreateViewStatement; @@ -32,6 +33,7 @@ import com.alibaba.druid.sql.ast.statement.SQLInsertStatement; import com.alibaba.druid.sql.ast.statement.SQLSelectStatement; import com.alibaba.druid.sql.ast.statement.SQLSetStatement; import com.alibaba.druid.sql.ast.statement.SQLTableSource; +import com.alibaba.druid.sql.ast.statement.SQLTruncateStatement; import com.alibaba.druid.sql.ast.statement.SQLUpdateSetItem; import com.alibaba.druid.sql.ast.statement.SQLUpdateStatement; @@ -157,7 +159,23 @@ public class SQLStatementParser extends SQLParser { } public SQLStatement parseTruncate() { - throw new ParserException("TODO " + lexer.token()); + accept(Token.TRUNCATE); + accept(Token.TABLE); + SQLTruncateStatement stmt = new SQLTruncateStatement(); + + for (;;) { + SQLName name = this.exprParser.name(); + stmt.getTableNames().add(name); + + if (lexer.token() == Token.COMMA) { + lexer.nextToken(); + continue; + } + + break; + } + + return stmt; } public SQLStatement parseInsert() { @@ -236,13 +254,19 @@ public class SQLStatementParser extends SQLParser { accept(Token.SET); SQLSetStatement stmt = new SQLSetStatement(); + parseAssignItems(stmt.getItems()); + + return stmt; + } + + public void parseAssignItems(List items) { for (;;) { - SQLSetStatement.Item item = new SQLSetStatement.Item(); + SQLAssignItem item = new SQLAssignItem(); item.setTarget(exprParser.primary()); accept(Token.EQ); item.setValue(exprParser.expr()); - stmt.getItems().add(item); + items.add(item); if (lexer.token() == Token.COMMA) { lexer.nextToken(); @@ -251,8 +275,6 @@ public class SQLStatementParser extends SQLParser { break; } } - - return stmt; } public SQLStatement parseCreate() throws ParserException { diff --git a/src/main/java/com/alibaba/druid/sql/parser/Token.java b/src/main/java/com/alibaba/druid/sql/parser/Token.java index 7e224d24b3..13256b5729 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/Token.java +++ b/src/main/java/com/alibaba/druid/sql/parser/Token.java @@ -155,6 +155,12 @@ public enum Token { EXCLUSIVE("EXCLUSIVE"), MODE("MODE"), WAIT("WAIT"), + ADVISE("ADVISE"), + SESSION("SESSION"), + AT("AT"), + LOCAL("LOCAL"), + TIME("TIME"), + ZONE("ZONE"), // transact-sql TOP("TOP"), 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 a1f4596448..9552454a25 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java @@ -53,6 +53,7 @@ import com.alibaba.druid.sql.ast.expr.SQLQueryExpr; import com.alibaba.druid.sql.ast.expr.SQLSomeExpr; import com.alibaba.druid.sql.ast.expr.SQLUnaryExpr; import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr; +import com.alibaba.druid.sql.ast.statement.SQLAssignItem; import com.alibaba.druid.sql.ast.statement.NotNullConstraint; import com.alibaba.druid.sql.ast.statement.SQLCallStatement; import com.alibaba.druid.sql.ast.statement.SQLColumnConstraint; @@ -746,7 +747,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter { } @Override - public boolean visit(SQLSetStatement.Item x) { + public boolean visit(SQLAssignItem x) { x.getTarget().accept(this); print(" = "); x.getValue().accept(this); 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 31fcd89a19..69a17a2792 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitor.java @@ -50,6 +50,7 @@ import com.alibaba.druid.sql.ast.expr.SQLQueryExpr; import com.alibaba.druid.sql.ast.expr.SQLSomeExpr; import com.alibaba.druid.sql.ast.expr.SQLUnaryExpr; import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr; +import com.alibaba.druid.sql.ast.statement.SQLAssignItem; import com.alibaba.druid.sql.ast.statement.NotNullConstraint; import com.alibaba.druid.sql.ast.statement.SQLCallStatement; import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition; @@ -281,9 +282,9 @@ public interface SQLASTVisitor { boolean visit(SQLSetStatement x); - void endVisit(SQLSetStatement.Item x); + void endVisit(SQLAssignItem x); - boolean visit(SQLSetStatement.Item x); + boolean visit(SQLAssignItem x); void endVisit(SQLCallStatement 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 865c35a0d9..86dfc3005b 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitorAdapter.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitorAdapter.java @@ -50,6 +50,7 @@ import com.alibaba.druid.sql.ast.expr.SQLQueryExpr; import com.alibaba.druid.sql.ast.expr.SQLSomeExpr; import com.alibaba.druid.sql.ast.expr.SQLUnaryExpr; import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr; +import com.alibaba.druid.sql.ast.statement.SQLAssignItem; import com.alibaba.druid.sql.ast.statement.NotNullConstraint; import com.alibaba.druid.sql.ast.statement.SQLCallStatement; import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition; @@ -443,12 +444,12 @@ public class SQLASTVisitorAdapter implements SQLASTVisitor { } @Override - public void endVisit(SQLSetStatement.Item x) { + public void endVisit(SQLAssignItem x) { } @Override - public boolean visit(SQLSetStatement.Item x) { + public boolean visit(SQLAssignItem x) { return true; } 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 94690c0247..b704ab865e 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SchemaStatVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SchemaStatVisitor.java @@ -20,6 +20,7 @@ import com.alibaba.druid.sql.ast.expr.SQLInSubQueryExpr; import com.alibaba.druid.sql.ast.expr.SQLIntegerExpr; import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr; import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr; +import com.alibaba.druid.sql.ast.statement.SQLCallStatement; import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition; import com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement; import com.alibaba.druid.sql.ast.statement.SQLDeleteStatement; @@ -677,7 +678,7 @@ public class SchemaStatVisitor extends SQLASTVisitorAdapter { setMode(x, Mode.Delete); - String ident = ((SQLIdentifierExpr) x.getTableName()).getName(); + String ident = x.getTableName().toString(); currentTableLocal.set(ident); TableStat stat = tableStats.get(ident); @@ -753,4 +754,9 @@ public class SchemaStatVisitor extends SQLASTVisitorAdapter { return false; } + + @Override + public boolean visit(SQLCallStatement x) { + return false; + } } diff --git a/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleAlterSessionTest.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleAlterSessionTest.java new file mode 100644 index 0000000000..851d403e5b --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleAlterSessionTest.java @@ -0,0 +1,41 @@ +package com.alibaba.druid.bvt.sql.oracle; + +import java.util.List; + +import junit.framework.Assert; + +import com.alibaba.druid.sql.OracleTest; +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; + +public class OracleAlterSessionTest extends OracleTest { + + public void test_0() throws Exception { + String sql = "alter session set current_schema=retl"; + + OracleStatementParser parser = new OracleStatementParser(sql); + List statementList = parser.parseStatementList(); + SQLStatement statemen = statementList.get(0); + System.out.println(output(statementList)); + + Assert.assertEquals(1, statementList.size()); + + OracleSchemaStatVisitor visitor = new OracleSchemaStatVisitor(); + statemen.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()); + +// Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("employees@remote"))); + + Assert.assertEquals(0, visitor.getTables().size()); + Assert.assertEquals(0, visitor.getColumns().size()); + +// Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("bonuses", "employee_id"))); + } + +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleInsertTest4.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleInsertTest4.java new file mode 100644 index 0000000000..b2f178d0a2 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleInsertTest4.java @@ -0,0 +1,83 @@ +package com.alibaba.druid.bvt.sql.oracle; + +import java.util.List; + +import junit.framework.Assert; + +import com.alibaba.druid.sql.OracleTest; +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; + +public class OracleInsertTest4 extends OracleTest { + + public void test_0() throws Exception { + String sql = "insert into \"OPS$ADMIN\".\"ORASTAT\"" + + // + " select /*+ rule */ :5 statid, 'C' type, :6 version, bitand(h.spare2,7) flags, " + + // + "ot.name c1, null c2, null c3, c.name c4, u.name c5, " + + // + " h.distcnt n1, h.density n2, h.spare1 n3, h.sample_size n4, h.null_cnt n5, " + + // + " h.minimum n6, h.maximum n7, h.avgcln n8, " + + // + " decode(h.cache_cnt,0,null,1) n9, hg.bucket n10, hg.endpoint n11, " + + // + " null n12, h.timestamp# d1, h.lowval r1, h.hival r2, hg.epvalue ch1 " + + // + " from sys.user$ u, sys.obj$ ot, sys.col$ c, sys.hist_head$ h, histgrm$ hg " + + // + " where :3 is null and u.name = :1 and ot.owner# = u.user# and " + + // + " ot.name = :2 and ot.type# = 2 and c.obj# = ot.obj# and " + + // + " (:4 is null or c.name = :4) and h.obj# = ot.obj# and h.intcol# = c.intcol# and " + + // + " hg.obj#(+) = h.obj# and hg.intcol#(+) = h.intcol# union all select :5 statid, " + + // + "'C' type, :6 version, bitand(h.spare2,7) flags, ot.name c1, op.subname c2, null c3, c.name c4, u.name c5, " + + // + " h.distcnt n1, h.density n2, h.spare1 n3, h.sample_size n4, h.null_cnt n5, " + + // + " h.minimum n6, h.maximum n7, h.avgcln n8, " + + // + " decode(h.cache_cnt,0,null,1) n9, hg.bucket n10, hg.endpoint n11, null n12, h.timestamp# d1, " + + " h.lowval r1, h.hival r2, hg.epvalue ch1 from sys.user$ u, sys.obj$ ot, sys.col$ c, sys.tabpart$ tp, sys.obj$ op, " + + " sys.hist_head$ h, histgrm$ hg where u.name = :1 and ot.owner# = u.user# and " + + " ot.name = :2 and ot.type# = 2 and c.obj# = ot.obj# and (:4 is null or c.name = :4) and " + + " tp.bo# = ot.obj# and tp.obj# = op.obj# and ((:3 is null and :vc_cascade_parts is not null) " + + " or op.subname = :3) and h.obj# = op.obj# and h.intcol# = c.intcol# and " + + " hg.obj#(+) = h.obj# and hg.intcol#(+) = h.intcol# " + + "" + + " union all select :5 statid, 'C' type, :6 version, bitand(h.spare2,7) flags, " + + " op.name c1, op.subname c2, null c3, c.name c4, u.name c5, h.distcnt n1, h.density n2, h.spare1 n3, h.sample_size n4, h.null_cnt n5, h.minimum n6, h.maximum n7, h.avgcln n8, decode(h.cache_cnt,0,null,1) n9, hg.bucket n10, hg.endpoint n11, null n12, h.timestamp# d1, h.lowval r1, h.hival r2, hg.epvalue ch1 from sys.user$ u, sys.col$ c, sys.tabcompart$ tp, sys.obj$ op, sys.hist_head$ h, histgrm$ hg where u.name = :1 and op.owner# = u.user# and op.name = :2 and op.type# = 19 and ((:3 is null and :vc_cascade_parts is not null) or op.subname = :3) and tp.obj# = op.obj# and c.obj# = tp.bo# and (:4 is null or c.name = :4) and h.obj# = op.obj# and h.intcol# = c.intcol# and hg.obj#(+) = h.obj# and hg.intcol#(+) = h.intcol# union all select :5 statid, 'C' type, :6 version, bitand(h.spare2,7) flags, op.name c1, op.subname c2, os.subname c3, c.name c4, u.name c5, h.distcnt n1, h.density n2, h.spare1 n3, h.sample_size n4, h.null_cnt n5, h.minimum n6, h.maximum n7, h.avgcln n8, decode(h.cache_cnt,0,null,1) n9, hg.bucket n10, hg.endpoint n11, null n12, h.timestamp# d1, h.lowval r1, h.hival r2, hg.epvalue ch1 from sys.user$ u, sys.col$ c, sys.tabcompart$ tp, sys.obj$ op, sys.tabsubpart$ ts, sys.obj$ os, sys.hist_head$ h, histgrm$ hg where u.name = :1 and op.owner# = u.user# and op.name = :2 and op.type# = 19 and tp.obj# = op.obj# and c.obj# = tp.bo# and (:4 is null or c.name = :4) and ts.pobj# = tp.obj# and ts.obj# = os.obj# and ((:3 is null and :vc_cascade_parts is not null) or (op.subname = :3 and (:vc_cascade_parts is not null -- cascade to subpart or os.subname is null)) -- matches partition itself or os.subname = :3) and -- matches subpartition h.obj# = os.obj# and h.intcol# = c.intcol# and hg.obj#(+) = h.obj# and hg.intcol#(+) = h.intcol# order by c5,c1,c2,c3,c4,n10"; + + OracleStatementParser parser = new OracleStatementParser(sql); + List statementList = parser.parseStatementList(); + SQLStatement statemen = statementList.get(0); + System.out.println(output(statementList)); + + Assert.assertEquals(1, statementList.size()); + + OracleSchemaStatVisitor visitor = new OracleSchemaStatVisitor(); + statemen.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()); + + Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("raises"))); + Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("employees"))); + + Assert.assertEquals(2, visitor.getTables().size()); + Assert.assertEquals(3, visitor.getColumns().size()); + + Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("employees", "employee_id"))); + Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("employees", "salary"))); + Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("employees", "commission_pct"))); + } + +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleSelectTest12.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleSelectTest12.java new file mode 100644 index 0000000000..a8fa2328fa --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleSelectTest12.java @@ -0,0 +1,49 @@ +package com.alibaba.druid.bvt.sql.oracle; + +import java.util.List; + +import junit.framework.Assert; + +import com.alibaba.druid.sql.OracleTest; +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; + +public class OracleSelectTest12 extends OracleTest { + + public void test_0() throws Exception { + String sql = "select /*+ use_nl(b c) ordered */ count(*) " + // + " from (" + // + " select distinct parent_id parentId from BUSINESS_ORDER a1 " + // + " where SELLER_SEQ in ( ?) " + // + " and not (order_from = 'safepay' and status in ('buyer_create', 'closed')) " + // + " ) b, business_order c where ID = b.parentId"; // + + OracleStatementParser parser = new OracleStatementParser(sql); + List statementList = parser.parseStatementList(); + SQLStatement statemen = statementList.get(0); + System.out.println(output(statementList)); + + Assert.assertEquals(1, statementList.size()); + + OracleSchemaStatVisitor visitor = new OracleSchemaStatVisitor(); + statemen.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(1, visitor.getTables().size()); + + Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("BUSINESS_ORDER"))); + + Assert.assertEquals(3, visitor.getColumns().size()); + + Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("pivot_table", "*"))); + Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("pivot_table", "YEAR"))); + Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("pivot_table", "order_mode"))); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleSelectTest13.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleSelectTest13.java new file mode 100644 index 0000000000..1eca45b2fb --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleSelectTest13.java @@ -0,0 +1,46 @@ +package com.alibaba.druid.bvt.sql.oracle; + +import java.util.List; + +import junit.framework.Assert; + +import com.alibaba.druid.sql.OracleTest; +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; + +public class OracleSelectTest13 extends OracleTest { + + public void test_0() throws Exception { + String sql = "select id, table_id, event_type, pk_data, transaction_id, ignore_node_cluster_id, gmt_create " + + " from retl_data_search" + + " where id>=50001 and id<52001 and GMT_CREATE between sysdate-2 and sysdate order by id"; // + + OracleStatementParser parser = new OracleStatementParser(sql); + List statementList = parser.parseStatementList(); + SQLStatement statemen = statementList.get(0); + System.out.println(output(statementList)); + + Assert.assertEquals(1, statementList.size()); + + OracleSchemaStatVisitor visitor = new OracleSchemaStatVisitor(); + statemen.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(1, visitor.getTables().size()); + + Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("BUSINESS_ORDER"))); + + Assert.assertEquals(3, visitor.getColumns().size()); + + Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("pivot_table", "*"))); + Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("pivot_table", "YEAR"))); + Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("pivot_table", "order_mode"))); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleSelectTest14.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleSelectTest14.java new file mode 100644 index 0000000000..ef778774e9 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleSelectTest14.java @@ -0,0 +1,45 @@ +package com.alibaba.druid.bvt.sql.oracle; + +import java.util.List; + +import junit.framework.Assert; + +import com.alibaba.druid.sql.OracleTest; +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; + +public class OracleSelectTest14 extends OracleTest { + + public void test_0() throws Exception { + String sql = "select /* EXEC_FROM_DBMS_XPLAN */ case when upper(sql_text) like '%DBMS_XPLAN%' then 0 else 1 end case, SQL_ID, child_number" + + " from v$sql where SQL_ID ='90jx354zd6jx5' and child_number =0"; // + + OracleStatementParser parser = new OracleStatementParser(sql); + List statementList = parser.parseStatementList(); + SQLStatement statemen = statementList.get(0); + System.out.println(output(statementList)); + + Assert.assertEquals(1, statementList.size()); + + OracleSchemaStatVisitor visitor = new OracleSchemaStatVisitor(); + statemen.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(1, visitor.getTables().size()); + + Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("BUSINESS_ORDER"))); + + Assert.assertEquals(3, visitor.getColumns().size()); + + Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("pivot_table", "*"))); + Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("pivot_table", "YEAR"))); + Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("pivot_table", "order_mode"))); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleSelectTest15.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleSelectTest15.java new file mode 100644 index 0000000000..4e8bec9064 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleSelectTest15.java @@ -0,0 +1,44 @@ +package com.alibaba.druid.bvt.sql.oracle; + +import java.util.List; + +import junit.framework.Assert; + +import com.alibaba.druid.sql.OracleTest; +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; + +public class OracleSelectTest15 extends OracleTest { + + public void test_0() throws Exception { + String sql = "SELECT CURRENT_TIMESTAMP(6) AT TIME ZONE 'PST' FROM \"DUAL\" \"A1\""; // + + OracleStatementParser parser = new OracleStatementParser(sql); + List statementList = parser.parseStatementList(); + SQLStatement statemen = statementList.get(0); + System.out.println(output(statementList)); + + Assert.assertEquals(1, statementList.size()); + + OracleSchemaStatVisitor visitor = new OracleSchemaStatVisitor(); + statemen.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(1, visitor.getTables().size()); + + Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("\"DUAL\""))); + + Assert.assertEquals(0, visitor.getColumns().size()); + +// Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("pivot_table", "*"))); +// Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("pivot_table", "YEAR"))); +// Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("pivot_table", "order_mode"))); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleSelectTest16.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleSelectTest16.java new file mode 100644 index 0000000000..613227d6ab --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleSelectTest16.java @@ -0,0 +1,44 @@ +package com.alibaba.druid.bvt.sql.oracle; + +import java.util.List; + +import junit.framework.Assert; + +import com.alibaba.druid.sql.OracleTest; +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; + +public class OracleSelectTest16 extends OracleTest { + + public void test_0() throws Exception { + String sql = "select privilege#,level from sysauth$ connect by grantee#=prior privilege# and privilege#>0 start with grantee#=:1 and privilege#>0"; // + + OracleStatementParser parser = new OracleStatementParser(sql); + List statementList = parser.parseStatementList(); + SQLStatement statemen = statementList.get(0); + System.out.println(output(statementList)); + + Assert.assertEquals(1, statementList.size()); + + OracleSchemaStatVisitor visitor = new OracleSchemaStatVisitor(); + statemen.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(1, visitor.getTables().size()); + + Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("\"DUAL\""))); + + Assert.assertEquals(0, visitor.getColumns().size()); + +// Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("pivot_table", "*"))); +// Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("pivot_table", "YEAR"))); +// Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("pivot_table", "order_mode"))); + } +} diff --git a/src/test/java/com/alibaba/druid/sql/TestTransform.java b/src/test/java/com/alibaba/druid/sql/TestTransform.java index 3f904fd3d1..1c97adf4cf 100644 --- a/src/test/java/com/alibaba/druid/sql/TestTransform.java +++ b/src/test/java/com/alibaba/druid/sql/TestTransform.java @@ -5,9 +5,13 @@ import java.sql.Date; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.Statement; +import java.util.ArrayList; import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; import junit.framework.Assert; +import oracle.jdbc.OracleStatement; import com.alibaba.druid.pool.DruidDataSource; import com.alibaba.druid.sql.ast.SQLStatement; @@ -22,6 +26,8 @@ public class TestTransform extends OracleTest { private String password; private DruidDataSource dataSource; + private ExecutorService executor = Executors.newFixedThreadPool(10); + public void setUp() throws Exception { jdbcUrl = "jdbc:oracle:thin:@10.20.149.18:1521:emdb"; user = "wardon"; @@ -32,26 +38,104 @@ public class TestTransform extends OracleTest { dataSource.setUrl(jdbcUrl); dataSource.setUsername(user); dataSource.setPassword(password); + dataSource.setMaxActive(50); + dataSource.setPoolPreparedStatements(true); + dataSource.setMaxOpenPreparedStatements(100); } - public void test_transform() throws Exception { + public void f_test_createIndex() throws Exception { + String sql = "CREATE INDEX i_db_day_sql_fulltext on db_day_sql_fulltext (sql_id)"; + Connection conn = dataSource.getConnection(); + + Statement stmt = conn.createStatement(); + + stmt.execute(sql); + + conn.close(); + } + + private int updateCount = 0; + + public void updateRecord(String sqlId, String result) throws Exception { + Connection conn = dataSource.getConnection(); + + PreparedStatement stmt = conn.prepareStatement("UPDATE db_day_sql_fulltext SET SQL_PARSE_RESULT = ? WHERE sql_id = ?"); + + stmt.setString(1, result); + stmt.setString(2, sqlId); + + int updateCount = stmt.executeUpdate(); + if (updateCount != 1) { + throw new Exception(); + } + + stmt.close(); + + conn.close(); + + System.out.println((this.updateCount++) + " : " + sqlId); + } + + public void f_test_transform() throws Exception { + + Connection conn = dataSource.getConnection(); + + int count = 0; + { + String sql = "SELECT COUNT(*) FROM db_day_sql_fulltext WHERE SQL_PARSE_RESULT IS NULL"; + Statement stmt = conn.createStatement(); + + ResultSet rs = stmt.executeQuery(sql); + rs.next(); + count = rs.getInt(1); + rs.close(); + stmt.close(); + } + System.out.println("COUNT : " + count); + String sql = "SELECT SNAP_DATE, DBNAME, SQL_ID, PIECE, SQL_TEXT" + // " , COMMAND_TYPE, LAST_SNAP_DATE, DB_PK, SQL_PARSE_RESULT " + // " FROM db_day_sql_fulltext " + // + " WHERE SQL_PARSE_RESULT IS NULL" + // " ORDER BY sql_id, piece"; - Connection conn = dataSource.getConnection(); - + Statement stmt = conn.createStatement(); + + OracleStatement oracleStmt = stmt.unwrap(OracleStatement.class); + oracleStmt.setRowPrefetch(100); + ResultSet rs = stmt.executeQuery(sql); Record r = null; - + + int i = 0; while (rs.next()) { r = new Record(); - + + i++; + Date d1 = rs.getDate(1); String s2 = rs.getString(2); String sqlId = rs.getString(3); - + + if (sqlId.equals("018vcjmqxuguv")) { + continue; + } + if (sqlId.equals("0d69js78vuh8j")) { + continue; + } + if (sqlId.equals("0khp9aykj08vq")) { + continue; + } + if (sqlId.equals("0ns0zv7qaxzus")) { + continue; + } + if (sqlId.equals("0tg8ryp81gq1w")) { + continue; + } + if (sqlId.equals("0tvydgpa3jmkv")) { + continue; + } + r.setSnapshotDate(d1); r.setDbName(s2); r.setSqlId(sqlId); @@ -61,82 +145,170 @@ public class TestTransform extends OracleTest { r.setCommandType(rs.getInt(6)); r.setLastSnapshotDate(rs.getDate(7)); r.setDbPk(rs.getLong(8)); - - System.out.println(r.getSqlText()); + + // System.out.println(i + "(" + r.getDbName() + "/" + r.getSqlId() + ") : " + r.getSqlText()); schemaStat(r); } rs.close(); stmt.close(); - + conn.close(); } - - public void schemaStat(Record r) { + + public void schemaStat(final Record r) throws Exception { + executor.submit(new Runnable() { + + public void run() { + try { + schemaStatInternal(r); + } catch (Exception e) { + // e.printStackTrace(); + } + } + }); + } + + public void schemaStatInternal(Record r) throws Exception { String sql = r.getSqlText(); - + if (sql.startsWith("/* MV_REFRESH (INS) */")) { return; } if (sql.startsWith("/* MV_REFRESH (DEL) */")) { return; } - + if (sql.startsWith("grant") || sql.startsWith("GRANT")) { + return; + } + if (sql.startsWith("SELECT /*+ Q1630000 NO_EXPAND ROWID(A1) */ A1.\"PRODUCT_ID\",A1.\"SUMMARY\"")) { + return; + } + if (sql.startsWith("declare") || sql.startsWith("DECLARE")) { + return; + } + if (sql.startsWith("alter table")) { + return; + } + if (sql.startsWith("SELECT /* OPT_DYN_SAMP */")) { + return; + } + if (sql.startsWith("COMMENT")) { + return; + } + if (sql.startsWith("create index")) { + return; + } + if (sql.startsWith("alter index")) { + return; + } + if (sql.startsWith("create table")) { + return; + } + if (sql.startsWith("CREATE")) { + return; + } + if (sql.startsWith("explain plan")) { + return; + } + if (sql.startsWith("ALTER TABLE")) { + return; + } + if (r.getSqlId().equals("09x7ytfdk63sp")) { + return; + } + OracleStatementParser parser = new OracleStatementParser(sql); List statementList = parser.parseStatementList(); SQLStatement statemen = statementList.get(0); Assert.assertEquals(1, statementList.size()); - System.out.println(output(statementList)); + // System.out.println(output(statementList)); OracleSchemaStatVisitor visitor = new OracleSchemaStatVisitor(); statemen.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(); - System.out.println(); - System.out.println(); + + StringBuffer buf = new StringBuffer(); + buf.append("Tables : " + visitor.getTables().toString()); + buf.append("\nColumns : " + visitor.getColumns().toString()); + buf.append("\nCoditions : " + visitor.getConditions().toString()); + buf.append("\nrelationships " + visitor.getRelationships().toString()); + + // System.out.println(buf.toString()); + + // System.out.println(); + // System.out.println(); + // System.out.println(); + + updateRecord(r.getSqlId(), buf.toString()); } - + public void clearResult() throws Exception { Connection conn = dataSource.getConnection(); Statement stmt = conn.createStatement(); - + stmt.execute("DELETE FROM db_day_sql_fulltext"); stmt.close(); conn.close(); } - public void f_test_migrate() throws Exception { + public void test_migrate() throws Exception { + Connection conn = dataSource.getConnection(); + + int count = 0; + { + String sql = "SELECT COUNT(*) FROM db_day_sqltext"; + Statement stmt = conn.createStatement(); + + ResultSet rs = stmt.executeQuery(sql); + rs.next(); + count = rs.getInt(1); + rs.close(); + stmt.close(); + } + System.out.println("COUNT : " + count); + clearResult(); - + String sql = "SELECT SNAP_DATE, DBNAME, SQL_ID, PIECE, SQL_TEXT" + // " , COMMAND_TYPE, LAST_SNAP_DATE, DB_PK, SQL_PARSE_RESULT " + // " FROM db_day_sqltext " + // - " WHERE db_pk = 40 and snap_date = trunc(sysdate) " + // - " ORDER BY sql_id, piece"; - Connection conn = dataSource.getConnection(); + // " WHERE db_pk = 40 and snap_date = trunc(sysdate) " + // + " ORDER BY db_pk, sql_id, piece"; Statement stmt = conn.createStatement(); + OracleStatement oracleStmt = stmt.unwrap(OracleStatement.class); + oracleStmt.setRowPrefetch(1000); ResultSet rs = stmt.executeQuery(sql); + + List list = new ArrayList(); Record r = null; String lastSqlId = null; + int i = 0; + int j = 0; while (rs.next()) { + j++; Date d1 = rs.getDate(1); String s2 = rs.getString(2); String sqlId = rs.getString(3); if (lastSqlId == null || !lastSqlId.equals(sqlId)) { if (r != null) { - System.out.println(r.getSqlText()); + System.out.println((i++) + "/" + j + " : " + r.getSqlId()); System.out.println(); - insert(r); + try { + setInfo(r); + } catch (Exception e) { + e.printStackTrace(); + } + + list.add(r); + if (list.size() > 100) { + insert(list); + list.clear(); + } } r = new Record(); @@ -152,19 +324,46 @@ public class TestTransform extends OracleTest { } else { String part = rs.getString(5); if (part != null) { - r.setSqlText(r.getSqlText() + part); + r.appendSqlText(part); } } lastSqlId = sqlId; } + + insert(list); rs.close(); stmt.close(); conn.close(); } - public void insert(Record r) throws Exception { + public void setInfo(Record r) { + OracleStatementParser parser = new OracleStatementParser(r.getSqlText()); + List statementList = parser.parseStatementList(); + SQLStatement statemen = statementList.get(0); + + Assert.assertEquals(1, statementList.size()); + // System.out.println(output(statementList)); + + OracleSchemaStatVisitor visitor = new OracleSchemaStatVisitor(); + statemen.accept(visitor); + + StringBuffer buf = new StringBuffer(); + buf.append("Tables : " + visitor.getTables().toString()); + buf.append("\nColumns : " + visitor.getColumns().toString()); + buf.append("\nCoditions : " + visitor.getConditions().toString()); + buf.append("\nrelationships " + visitor.getRelationships().toString()); + + r.setResult(buf.toString()); + + } + + public void insert(List list) throws Exception { + if (list.size() == 0) { + return; + } + String sql = "INSERT INTO db_day_sql_fulltext " + // "(SNAP_DATE, DBNAME, SQL_ID, PIECE, SQL_TEXT" + // ", COMMAND_TYPE, LAST_SNAP_DATE, DB_PK, SQL_PARSE_RESULT)" + // @@ -173,18 +372,21 @@ public class TestTransform extends OracleTest { PreparedStatement stmt = conn.prepareStatement(sql); - stmt.setDate(1, r.getSnapshotDate()); - stmt.setString(2, r.getDbName()); - stmt.setString(3, r.getSqlId()); - stmt.setInt(4, r.getPiece()); - stmt.setString(5, r.getSqlText()); + for (Record r : list) { + stmt.setDate(1, r.getSnapshotDate()); + stmt.setString(2, r.getDbName()); + stmt.setString(3, r.getSqlId()); + stmt.setInt(4, r.getPiece()); + stmt.setString(5, r.getSqlText()); - stmt.setInt(6, r.getCommandType()); - stmt.setDate(7, r.getLastSnapshotDate()); - stmt.setLong(8, r.getDbPk()); - stmt.setString(9, r.getSqlText()); - - stmt.execute(); + stmt.setInt(6, r.getCommandType()); + stmt.setDate(7, r.getLastSnapshotDate()); + stmt.setLong(8, r.getDbPk()); + stmt.setString(9, r.getResult()); + + stmt.addBatch(); + } + stmt.executeBatch(); stmt.close(); @@ -193,14 +395,23 @@ public class TestTransform extends OracleTest { public static class Record { - private Date snapshotDate; - private String dbName; - private String sqlId; - private String sqlText; - private Integer piece; - private Integer commandType; - private Date lastSnapshotDate; - private Long dbPk; + private Date snapshotDate; + private String dbName; + private String sqlId; + private StringBuffer sqlText = new StringBuffer(); + private Integer piece; + private Integer commandType; + private Date lastSnapshotDate; + private Long dbPk; + private String result; + + public String getResult() { + return result; + } + + public void setResult(String result) { + this.result = result; + } public Date getSnapshotDate() { return snapshotDate; @@ -227,11 +438,15 @@ public class TestTransform extends OracleTest { } public String getSqlText() { - return sqlText; + return sqlText.toString(); } public void setSqlText(String sqlText) { - this.sqlText = sqlText; + this.sqlText = new StringBuffer(sqlText); + } + + public void appendSqlText(String sqlText) { + this.sqlText.append(sqlText); } public Integer getPiece() {