From 81a70bed083d0656f59c1a28db6975d8a9c8b57a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B8=A9=E5=B0=91?= Date: Tue, 28 Feb 2012 04:51:12 +0800 Subject: [PATCH] bug fixed for oracle sql parser --- .../sql/ast/statement/SQLExprTableSource.java | 2 +- .../sql/ast/statement/SQLJoinTableSource.java | 2 +- .../sql/ast/statement/SQLSetStatement.java | 4 + .../ast/statement/SQLSubqueryTableSource.java | 2 +- .../sql/ast/statement/SQLTableSource.java | 40 +-- .../sql/ast/statement/SQLTableSourceImpl.java | 42 +++ .../mysql/visitor/MySqlSchemaStatVisitor.java | 9 +- .../oracle/ast/stmt/OracleBlockStatement.java | 31 ++ .../ast/stmt/OracleInsertStatement.java | 15 +- .../ast/stmt/OracleLockTableStatement.java | 60 ++++ .../oracle/ast/stmt/OracleSelectJoin.java | 11 + .../stmt/OracleSelectSubqueryTableSource.java | 17 +- .../ast/stmt/OracleSelectTableSource.java | 10 +- .../oracle/parser/OracleDeleteParser.java | 3 + .../oracle/parser/OracleExprParser.java | 19 ++ .../dialect/oracle/parser/OracleLexer.java | 10 +- .../oracle/parser/OracleSelectParser.java | 65 +++-- .../oracle/parser/OracleStatementParser.java | 107 ++++++- .../visitor/OracleASTVIsitorAdapter.java | 22 ++ .../oracle/visitor/OracleASTVisitor.java | 10 + .../oracle/visitor/OracleOutputVisitor.java | 72 ++++- .../visitor/OracleSchemaStatVisitor.java | 33 ++- .../visitor/PGSchemaStatVisitor.java | 8 +- .../alibaba/druid/sql/parser/CharTypes.java | 1 + .../com/alibaba/druid/sql/parser/Lexer.java | 8 +- .../druid/sql/parser/SQLExprParser.java | 6 +- .../alibaba/druid/sql/parser/SQLParser.java | 2 +- .../druid/sql/parser/SQLStatementParser.java | 10 +- .../com/alibaba/druid/sql/parser/Token.java | 4 + .../druid/sql/visitor/SchemaStatVisitor.java | 60 ++-- .../bvt/sql/oracle/OracleLockTableTest1.java | 41 +++ .../bvt/sql/oracle/OracleLockTableTest2.java | 41 +++ .../bvt/sql/oracle/OracleSelectTest11.java | 63 ++++ .../com/alibaba/druid/sql/TestTransform.java | 272 ++++++++++++++++++ 34 files changed, 962 insertions(+), 140 deletions(-) create mode 100644 src/main/java/com/alibaba/druid/sql/ast/statement/SQLTableSourceImpl.java create mode 100644 src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleBlockStatement.java create mode 100644 src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleLockTableStatement.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleLockTableTest1.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleLockTableTest2.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleSelectTest11.java create mode 100644 src/test/java/com/alibaba/druid/sql/TestTransform.java diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLExprTableSource.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLExprTableSource.java index 77ba5ca4b9..6f7ad00423 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLExprTableSource.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLExprTableSource.java @@ -18,7 +18,7 @@ package com.alibaba.druid.sql.ast.statement; import com.alibaba.druid.sql.ast.SQLExpr; import com.alibaba.druid.sql.visitor.SQLASTVisitor; -public class SQLExprTableSource extends SQLTableSource { +public class SQLExprTableSource extends SQLTableSourceImpl { private static final long serialVersionUID = 1L; diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLJoinTableSource.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLJoinTableSource.java index 7ac1bb968c..8560db412b 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLJoinTableSource.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLJoinTableSource.java @@ -18,7 +18,7 @@ package com.alibaba.druid.sql.ast.statement; import com.alibaba.druid.sql.ast.SQLExpr; import com.alibaba.druid.sql.visitor.SQLASTVisitor; -public class SQLJoinTableSource extends SQLTableSource { +public class SQLJoinTableSource extends SQLTableSourceImpl { private static final long serialVersionUID = 1L; 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 82833eaee5..3b11c60b4b 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 @@ -31,6 +31,10 @@ public class SQLSetStatement extends SQLStatementImpl { public SQLSetStatement(){ } + + public SQLSetStatement(SQLExpr target, SQLExpr value) { + this.items.add(new Item(target, value)); + } public List getItems() { return items; diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSubqueryTableSource.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSubqueryTableSource.java index a8800371f7..cb374f2730 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSubqueryTableSource.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSubqueryTableSource.java @@ -17,7 +17,7 @@ package com.alibaba.druid.sql.ast.statement; import com.alibaba.druid.sql.visitor.SQLASTVisitor; -public class SQLSubqueryTableSource extends SQLTableSource { +public class SQLSubqueryTableSource extends SQLTableSourceImpl { private static final long serialVersionUID = 1L; diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLTableSource.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLTableSource.java index 90dcf1d84d..b90dbc2b7e 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLTableSource.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLTableSource.java @@ -1,42 +1,10 @@ -/* - * Copyright 1999-2011 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.sql.ast.statement; -import com.alibaba.druid.sql.ast.SQLObjectImpl; +import com.alibaba.druid.sql.ast.SQLObject; -public abstract class SQLTableSource extends SQLObjectImpl { +public interface SQLTableSource extends SQLObject { - private static final long serialVersionUID = 1L; + String getAlias(); - protected String alias; - - public SQLTableSource(){ - - } - - public SQLTableSource(String alias){ - - this.alias = alias; - } - - public String getAlias() { - return this.alias; - } - - public void setAlias(String alias) { - this.alias = alias; - } + void setAlias(String alias); } diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLTableSourceImpl.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLTableSourceImpl.java new file mode 100644 index 0000000000..a83b30a325 --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLTableSourceImpl.java @@ -0,0 +1,42 @@ +/* + * Copyright 1999-2011 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.sql.ast.statement; + +import com.alibaba.druid.sql.ast.SQLObjectImpl; + +public abstract class SQLTableSourceImpl extends SQLObjectImpl implements SQLTableSource { + + private static final long serialVersionUID = 1L; + + protected String alias; + + public SQLTableSourceImpl(){ + + } + + public SQLTableSourceImpl(String alias){ + + this.alias = alias; + } + + public String getAlias() { + return this.alias; + } + + public void setAlias(String alias) { + this.alias = alias; + } +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlSchemaStatVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlSchemaStatVisitor.java index 3548137860..14989ec287 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlSchemaStatVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlSchemaStatVisitor.java @@ -54,8 +54,7 @@ public class MySqlSchemaStatVisitor extends SchemaStatVisitor implements MySqlAS public boolean visit(MySqlDeleteStatement x) { aliasLocal.set(new HashMap()); - x.putAttribute("_original_use_mode", modeLocal.get()); - modeLocal.set(Mode.Delete); + setMode(x, Mode.Delete); aliasLocal.set(new HashMap()); @@ -89,14 +88,12 @@ public class MySqlSchemaStatVisitor extends SchemaStatVisitor implements MySqlAS @Override public void endVisit(MySqlInsertStatement x) { - Mode originalMode = (Mode) x.getAttribute("_original_use_mode"); - modeLocal.set(originalMode); + setModeOrigin(x); } @Override public boolean visit(MySqlInsertStatement x) { - x.putAttribute("_original_use_mode", modeLocal.get()); - modeLocal.set(Mode.Insert); + setMode(x, Mode.Insert); aliasLocal.set(new HashMap()); diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleBlockStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleBlockStatement.java new file mode 100644 index 0000000000..4d1db86fa1 --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleBlockStatement.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.SQLStatement; +import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor; + +public class OracleBlockStatement extends OracleStatementImpl { + + private static final long serialVersionUID = 1L; + + private List statementList = new ArrayList(); + + public List getStatementList() { + return statementList; + } + + public void setStatementList(List statementList) { + this.statementList = statementList; + } + + @Override + public void accept0(OracleASTVisitor visitor) { + if (visitor.visit(this)) { + acceptChild(visitor, statementList); + } + visitor.endVisit(this); + } + +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleInsertStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleInsertStatement.java index 7561197aec..6b5fb5e9fc 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleInsertStatement.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleInsertStatement.java @@ -1,6 +1,10 @@ package com.alibaba.druid.sql.dialect.oracle.ast.stmt; +import java.util.ArrayList; +import java.util.List; + import com.alibaba.druid.sql.ast.statement.SQLInsertStatement; +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.visitor.OracleASTVisitor; @@ -10,8 +14,17 @@ public class OracleInsertStatement extends SQLInsertStatement implements OracleS private static final long serialVersionUID = 1L; - private OracleReturningClause returning; + private OracleReturningClause returning; private OracleErrorLoggingClause errorLogging; + private List hints = new ArrayList(); + + public List getHints() { + return hints; + } + + public void setHints(List hints) { + this.hints = hints; + } public OracleReturningClause getReturning() { return returning; diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleLockTableStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleLockTableStatement.java new file mode 100644 index 0000000000..ad6b8bd7c9 --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleLockTableStatement.java @@ -0,0 +1,60 @@ +package com.alibaba.druid.sql.dialect.oracle.ast.stmt; + +import com.alibaba.druid.sql.ast.SQLExpr; +import com.alibaba.druid.sql.ast.SQLName; +import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor; + +public class OracleLockTableStatement extends OracleStatementImpl { + + private static final long serialVersionUID = 1L; + + private SQLName table; + private LockMode lockMode; + private boolean noWait = false; + private SQLExpr wait; + + public boolean isNoWait() { + return noWait; + } + + public void setNoWait(boolean noWait) { + this.noWait = noWait; + } + + public SQLExpr getWait() { + return wait; + } + + public void setWait(SQLExpr wait) { + this.wait = wait; + } + + public SQLName getTable() { + return table; + } + + public void setTable(SQLName table) { + this.table = table; + } + + public LockMode getLockMode() { + return lockMode; + } + + public void setLockMode(LockMode lockMode) { + this.lockMode = lockMode; + } + + @Override + public void accept0(OracleASTVisitor visitor) { + if (visitor.visit(this)) { + acceptChild(visitor, table); + acceptChild(visitor, wait); + } + visitor.endVisit(this); + } + + public static enum LockMode { + EXCLUSIVE, SHARE + } +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleSelectJoin.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleSelectJoin.java index c615570b95..c822f85411 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleSelectJoin.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleSelectJoin.java @@ -20,6 +20,7 @@ import java.util.List; import com.alibaba.druid.sql.ast.SQLExpr; import com.alibaba.druid.sql.ast.statement.SQLJoinTableSource; +import com.alibaba.druid.sql.dialect.oracle.ast.clause.FlashbackQueryClause; import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor; import com.alibaba.druid.sql.visitor.SQLASTVisitor; @@ -29,6 +30,7 @@ public class OracleSelectJoin extends SQLJoinTableSource implements OracleSelect private final List using = new ArrayList(); protected OracleSelectPivotBase pivot; + protected FlashbackQueryClause flashback; public OracleSelectJoin(String alias){ super(alias); @@ -38,6 +40,14 @@ public class OracleSelectJoin extends SQLJoinTableSource implements OracleSelect } + public FlashbackQueryClause getFlashback() { + return flashback; + } + + public void setFlashback(FlashbackQueryClause flashback) { + this.flashback = flashback; + } + public OracleSelectPivotBase getPivot() { return pivot; } @@ -57,6 +67,7 @@ public class OracleSelectJoin extends SQLJoinTableSource implements OracleSelect acceptChild(visitor, this.right); acceptChild(visitor, this.condition); acceptChild(visitor, this.using); + acceptChild(visitor, this.flashback); } visitor.endVisit(this); diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleSelectSubqueryTableSource.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleSelectSubqueryTableSource.java index 79accd0857..c13c05a3b8 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleSelectSubqueryTableSource.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleSelectSubqueryTableSource.java @@ -17,6 +17,7 @@ package com.alibaba.druid.sql.dialect.oracle.ast.stmt; import com.alibaba.druid.sql.ast.statement.SQLSelect; import com.alibaba.druid.sql.ast.statement.SQLSubqueryTableSource; +import com.alibaba.druid.sql.dialect.oracle.ast.clause.FlashbackQueryClause; import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor; import com.alibaba.druid.sql.visitor.SQLASTVisitor; @@ -26,10 +27,20 @@ public class OracleSelectSubqueryTableSource extends SQLSubqueryTableSource impl protected OracleSelectPivotBase pivot; + protected FlashbackQueryClause flashback; + public OracleSelectSubqueryTableSource(){ } + public FlashbackQueryClause getFlashback() { + return flashback; + } + + public void setFlashback(FlashbackQueryClause flashback) { + this.flashback = flashback; + } + public OracleSelectSubqueryTableSource(String alias){ super(alias); } @@ -58,13 +69,9 @@ public class OracleSelectSubqueryTableSource extends SQLSubqueryTableSource impl protected void accept0(OracleASTVisitor visitor) { if (visitor.visit(this)) { acceptChild(visitor, this.select); + acceptChild(visitor, this.flashback); } visitor.endVisit(this); } - public void output(StringBuffer buf) { - buf.append("("); - this.select.output(buf); - buf.append(")"); - } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleSelectTableSource.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleSelectTableSource.java index a614ee1efd..c0ad9b7dd0 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleSelectTableSource.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleSelectTableSource.java @@ -15,14 +15,16 @@ */ package com.alibaba.druid.sql.dialect.oracle.ast.stmt; -public interface OracleSelectTableSource { +import com.alibaba.druid.sql.ast.statement.SQLTableSource; +import com.alibaba.druid.sql.dialect.oracle.ast.clause.FlashbackQueryClause; - String getAlias(); - - void setAlias(String alias); +public interface OracleSelectTableSource extends SQLTableSource { OracleSelectPivotBase getPivot(); void setPivot(OracleSelectPivotBase pivot); + FlashbackQueryClause getFlashback(); + + void setFlashback(FlashbackQueryClause flashback); } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleDeleteParser.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleDeleteParser.java index f6eb0b3522..aef4a0fe47 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleDeleteParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleDeleteParser.java @@ -26,11 +26,14 @@ public class OracleDeleteParser extends SQLStatementParser { public OracleDeleteParser(String sql){ super(sql); + this.exprParser = new OracleExprParser(lexer); } public OracleDeleteParser(Lexer lexer){ super(lexer); + this.exprParser = new OracleExprParser(lexer); } + public OracleDeleteStatement parseDelete() throws ParserException { accept(Token.DELETE); 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 511eac757f..6852f2ad9f 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 @@ -19,6 +19,7 @@ import java.math.BigInteger; import java.util.List; import com.alibaba.druid.sql.ast.SQLExpr; +import com.alibaba.druid.sql.ast.SQLName; import com.alibaba.druid.sql.ast.SQLOrderingSpecification; import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr; import com.alibaba.druid.sql.ast.expr.SQLBinaryOperator; @@ -599,4 +600,22 @@ public class OracleExprParser extends SQLExprParser { lexer.nextToken(); } } + + public SQLName name() throws ParserException { + SQLName name = super.name(); + + if (lexer.token() == Token.MONKEYS_AT) { + lexer.nextToken(); + if (lexer.token() != Token.IDENTIFIER) { + throw new ParserException("syntax error, expect identifier, but " + lexer.token()); + } + OracleDbLinkExpr dbLink = new OracleDbLinkExpr(); + dbLink.setExpr(name); + dbLink.setDbLink(lexer.stringVal()); + lexer.nextToken(); + return dbLink; + } + + return name; + } } 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 8240194685..5561030682 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 @@ -113,6 +113,13 @@ public class OracleLexer extends Lexer { map.put("UNLIMITED", Token.UNLIMITED); map.put("RETURNING", Token.RETURNING); map.put("LIMIT", Token.LIMIT); + map.put("OF", Token.OF); + map.put("BEGIN", Token.BEGIN); + map.put("SHARE", Token.SHARE); + map.put("EXCLUSIVE", Token.EXCLUSIVE); + map.put("MODE", Token.MODE); + map.put("WAIT", Token.WAIT); + map.put("NOWAIT", Token.NOWAIT); DEFAULT_ORACLE_KEYWORDS = new Keywords(map); } @@ -164,7 +171,7 @@ public class OracleLexer extends Lexer { if (tok != null) { token = tok; } else { - token = Token.IDENTIFIER; + token = Token.VARIANT; } } @@ -323,4 +330,5 @@ public class OracleLexer extends Lexer { token = Token.LITERAL_INT; } } + } 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 3820bbbb08..128a4bfca0 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 @@ -28,6 +28,7 @@ import com.alibaba.druid.sql.ast.statement.SQLTableSource; import com.alibaba.druid.sql.ast.statement.SQLUnionOperator; import com.alibaba.druid.sql.ast.statement.SQLUnionQuery; import com.alibaba.druid.sql.dialect.oracle.ast.clause.CycleClause; +import com.alibaba.druid.sql.dialect.oracle.ast.clause.FlashbackQueryClause; import com.alibaba.druid.sql.dialect.oracle.ast.clause.FlashbackQueryClause.AsOfFlashbackQueryClause; import com.alibaba.druid.sql.dialect.oracle.ast.clause.FlashbackQueryClause.VersionsFlashbackQueryClause; import com.alibaba.druid.sql.dialect.oracle.ast.clause.GroupingSetExpr; @@ -246,6 +247,8 @@ public class OracleSelectParser extends SQLSelectParser { lexer.nextToken(); } + this.createExprParser().parseHints(queryBlock.getHints()); + parseSelectList(queryBlock); parseFrom(queryBlock); @@ -666,6 +669,10 @@ public class OracleSelectParser extends SQLSelectParser { private void parseTableSourceQueryTableExpr(OracleSelectTableReference tableReference) { tableReference.setExpr(this.createExprParser().expr()); + { + FlashbackQueryClause clause = flashback(); + tableReference.setFlashback(clause); + } if (identifierEquals("SAMPLE")) { lexer.nextToken(); @@ -733,27 +740,7 @@ public class OracleSelectParser extends SQLSelectParser { tableReference.setPartition(partition); } - if (lexer.token() == Token.AS) { - lexer.nextToken(); - - if (identifierEquals("OF")) { - lexer.nextToken(); - - AsOfFlashbackQueryClause clause = new AsOfFlashbackQueryClause(); - if (identifierEquals("SCN")) { - clause.setType(AsOfFlashbackQueryClause.Type.SCN); - lexer.nextToken(); - } else { - accept(Token.TIMESTAMP); - clause.setType(AsOfFlashbackQueryClause.Type.TIMESTAMP); - } - clause.setExpr(createExprParser().primary()); - - tableReference.setFlashback(clause); - } else { - throw new SQLParseException("TODO"); - } - } else if (identifierEquals("VERSIONS")) { + if (identifierEquals("VERSIONS")) { lexer.nextToken(); if (lexer.token() == Token.BETWEEN) { @@ -784,8 +771,40 @@ public class OracleSelectParser extends SQLSelectParser { } - protected SQLTableSource parseTableSourceRest(SQLTableSource tableSource) { - if ((tableSource.getAlias() == null) || (tableSource.getAlias().length() == 0)) { + private FlashbackQueryClause flashback() { + if (lexer.token() == Token.AS) { + lexer.nextToken(); + } + + if (lexer.token() == Token.OF) { + lexer.nextToken(); + + AsOfFlashbackQueryClause clause = new AsOfFlashbackQueryClause(); + if (identifierEquals("SCN")) { + clause.setType(AsOfFlashbackQueryClause.Type.SCN); + lexer.nextToken(); + } else { + accept(Token.TIMESTAMP); + clause.setType(AsOfFlashbackQueryClause.Type.TIMESTAMP); + } + clause.setExpr(createExprParser().primary()); + + return clause; + } + + return null; + } + + protected SQLTableSource parseTableSourceRest(OracleSelectTableSource tableSource) { + if (lexer.token() == Token.AS) { + lexer.nextToken(); + + if (lexer.token() == Token.OF) { + tableSource.setFlashback(flashback()); + } + + tableSource.setAlias(as()); + } else if ((tableSource.getAlias() == null) || (tableSource.getAlias().length() == 0)) { if (lexer.token() != Token.LEFT && lexer.token() != Token.RIGHT && lexer.token() != Token.FULL) { tableSource.setAlias(as()); } 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 7854597ecf..15287b38b4 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 @@ -15,21 +15,30 @@ */ package com.alibaba.druid.sql.dialect.oracle.parser; +import java.util.ArrayList; import java.util.List; import com.alibaba.druid.sql.ast.SQLExpr; import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr; +import com.alibaba.druid.sql.ast.expr.SQLBinaryOperator; +import com.alibaba.druid.sql.ast.statement.SQLInsertInto; import com.alibaba.druid.sql.ast.statement.SQLSelect; 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.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.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.OracleMergeStatement; 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; @@ -40,22 +49,37 @@ public class OracleStatementParser extends SQLStatementParser { public OracleStatementParser(String sql){ super(new OracleLexer(sql)); this.lexer.nextToken(); + this.exprParser = createExprParser(); } public OracleStatementParser(Lexer lexer){ super(lexer); + this.exprParser = createExprParser(); } protected OracleExprParser createExprParser() { return new OracleExprParser(lexer); } + protected void parseInsert0_hinits(SQLInsertInto insertStatement) { + if (insertStatement instanceof OracleInsertStatement) { + OracleInsertStatement stmt = (OracleInsertStatement) insertStatement; + this.createExprParser().parseHints(stmt.getHints()); + } else { + List hints = new ArrayList(); + this.createExprParser().parseHints(hints); + } + } + @Override public void parseStatementList(List statementList) throws ParserException { for (;;) { if (lexer.token() == Token.EOF) { return; } + if (lexer.token() == Token.END) { + return; + } if (lexer.token() == (Token.SEMI)) { lexer.nextToken(); @@ -75,18 +99,6 @@ public class OracleStatementParser extends SQLStatementParser { if (lexer.token() == (Token.CREATE)) { lexer.nextToken(); - // if ((this.tokenList.lookup(1).equals(Token.ViewToken)) || - // (this.tokenList.lookup(3).equals(Token.ViewToken)) - // || (this.tokenList.lookup(4).equals(Token.ViewToken)) || - // (this.tokenList.lookup(5).equals(Token.ViewToken))) { - // statementList.add(parseCreateView()); - // } - // - // if ((this.tokenList.lookup(1).equals(Token.TableToken)) || - // (this.tokenList.lookup(3).equals(Token.TableToken))) { - // statementList.add(parseOracleCreateTable()); - // } - throw new ParserException("TODO"); } @@ -125,10 +137,75 @@ public class OracleStatementParser extends SQLStatementParser { continue; } + if (lexer.token() == Token.BEGIN) { + statementList.add(this.parseBegin()); + continue; + } + + if (lexer.token() == Token.LOCK) { + statementList.add(this.parseLock()); + continue; + } + + if (lexer.token() == Token.VARIANT) { + SQLExpr variant = this.exprParser.primary(); + if (variant instanceof SQLBinaryOpExpr) { + SQLBinaryOpExpr binaryOpExpr = (SQLBinaryOpExpr) variant; + if (binaryOpExpr.getOperator() == SQLBinaryOperator.Assignment) { + SQLSetStatement stmt = new SQLSetStatement(binaryOpExpr.getLeft(), binaryOpExpr.getRight()); + statementList.add(stmt); + continue; + } + } + accept(Token.COLONEQ); + SQLExpr value = this.exprParser.expr(); + + SQLSetStatement stmt = new SQLSetStatement(variant, value); + statementList.add(stmt); + continue; + } + throw new ParserException("TODO : " + lexer.token() + " " + lexer.stringVal()); } } + public OracleLockTableStatement parseLock() { + accept(Token.LOCK); + accept(Token.TABLE); + + OracleLockTableStatement stmt = new OracleLockTableStatement(); + stmt.setTable(this.exprParser.name()); + + accept(Token.IN); + if (lexer.token() == Token.SHARE) { + stmt.setLockMode(LockMode.SHARE); + lexer.nextToken(); + } else if (lexer.token() == Token.EXCLUSIVE) { + stmt.setLockMode(LockMode.EXCLUSIVE); + lexer.nextToken(); + } + accept(Token.MODE); + + if (lexer.token() == Token.NOWAIT) { + lexer.nextToken(); + } else if (lexer.token() == Token.WAIT) { + lexer.nextToken(); + stmt.setWait(exprParser.expr()); + } + return stmt; + } + + public OracleStatement parseBegin() { + accept(Token.BEGIN); + OracleBlockStatement block = new OracleBlockStatement(); + + parseStatementList(block.getStatementList()); + + accept(Token.END); + + return block; + } + public OracleMergeStatement parseMerge() throws ParserException { accept(Token.MERGE); @@ -285,13 +362,13 @@ public class OracleStatementParser extends SQLStatementParser { OracleMultiInsertStatement.InsertIntoClause insertInto = new OracleMultiInsertStatement.InsertIntoClause(); parseInsert0(insertInto); item.setThen(insertInto); - + clause.getItems().add(item); } - + if (lexer.token() == Token.ELSE) { lexer.nextToken(); - + OracleMultiInsertStatement.InsertIntoClause insertInto = new OracleMultiInsertStatement.InsertIntoClause(); parseInsert0(insertInto, false); clause.setElseItem(insertInto); 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 89a64d4827..e303105fde 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 @@ -36,9 +36,11 @@ 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.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.OracleMergeStatement.MergeInsertClause; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMergeStatement.MergeUpdateClause; @@ -768,5 +770,25 @@ public class OracleASTVIsitorAdapter extends SQLASTVisitorAdapter implements Ora public void endVisit(OracleSelectQueryBlock x) { } + + @Override + public boolean visit(OracleBlockStatement x) { + return true; + } + + @Override + public void endVisit(OracleBlockStatement x) { + + } + + @Override + public boolean visit(OracleLockTableStatement x) { + return true; + } + + @Override + public void endVisit(OracleLockTableStatement 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 d9389bec95..b587dc5bcb 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 @@ -42,9 +42,11 @@ 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.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.OracleMultiInsertStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMultiInsertStatement.ConditionalInsertClause; @@ -335,4 +337,12 @@ public interface OracleASTVisitor extends SQLASTVisitor { boolean visit(OracleSelectQueryBlock x); void endVisit(OracleSelectQueryBlock x); + + boolean visit(OracleBlockStatement x); + + void endVisit(OracleBlockStatement x); + + boolean visit(OracleLockTableStatement x); + + void endVisit(OracleLockTableStatement 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 0acc53cb1b..1e84973ee3 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 @@ -68,9 +68,11 @@ 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.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.OracleMergeStatement.MergeInsertClause; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMergeStatement.MergeUpdateClause; @@ -107,13 +109,17 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS super(appender); } - public void postVisit(SQLObject astNode) { - if (astNode instanceof SQLStatement) { - if (astNode instanceof OraclePLSQLCommitStatement) { + public void postVisit(SQLObject x) { + if (x instanceof SQLStatement) { + if (x instanceof OraclePLSQLCommitStatement) { return; } - println(";"); + if (x.getParent() instanceof SQLStatement) { + print(";"); + } else { + println(";"); + } } } @@ -376,6 +382,12 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS printAndAccept(x.getUsing(), ", "); print(")"); } + + if (x.getFlashback() != null) { + println(); + x.getFlashback().accept(this); + } + return false; } @@ -513,7 +525,7 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS println(); decrementIndent(); print(")"); - + if (x.getPivot() != null) { incrementIndent(); @@ -522,6 +534,11 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS decrementIndent(); } + + if (x.getFlashback() != null) { + println(); + x.getFlashback().accept(this); + } if ((x.getAlias() != null) && (x.getAlias().length() != 0)) { print(" "); @@ -1607,4 +1624,49 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS public void endVisit(OracleSelectQueryBlock x) { } + + @Override + public boolean visit(OracleBlockStatement x) { + print("BEGIN"); + incrementIndent(); + println(); + for (int i = 0, size = x.getStatementList().size(); i < size; ++i) { + if (i != 0) { + println(); + } + SQLStatement stmt = x.getStatementList().get(i); + stmt.setParent(x); + stmt.accept(this); + } + decrementIndent(); + println(); + print("END"); + return false; + } + + @Override + public void endVisit(OracleBlockStatement x) { + + } + + @Override + public boolean visit(OracleLockTableStatement x) { + print("LOCK TABLE "); + x.getTable().accept(this); + print(" IN "); + print(x.getLockMode().name()); + print(" MODE "); + if (x.isNoWait()) { + print("NOWAIT"); + } else if (x.getWait() != null){ + print("WAIT "); + x.getWait().accept(this); + } + return false; + } + + @Override + public void endVisit(OracleLockTableStatement 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 b44e62abf5..9610f5f830 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 @@ -51,9 +51,11 @@ 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.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.OracleMergeStatement.MergeInsertClause; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMergeStatement.MergeUpdateClause; @@ -138,7 +140,7 @@ public class OracleSchemaStatVisitor extends SchemaStatVisitor implements Oracle x.putAttribute(ATTR_TABLE, ident); } - Mode mode = modeLocal.get(); + Mode mode = getMode(); switch (mode) { case Delete: stat.incrementDeleteCount(); @@ -895,8 +897,7 @@ public class OracleSchemaStatVisitor extends SchemaStatVisitor implements Oracle public boolean visit(OracleMergeStatement x) { aliasLocal.set(new HashMap()); - x.putAttribute("_original_use_mode", modeLocal.get()); - modeLocal.set(Mode.Merge); + setMode(x, Mode.Merge); String originalTable = currentTableLocal.get(); @@ -1029,8 +1030,8 @@ public class OracleSchemaStatVisitor extends SchemaStatVisitor implements Oracle @Override public boolean visit(OracleMultiInsertStatement x) { - x.putAttribute("_original_use_mode", modeLocal.get()); - modeLocal.set(Mode.Insert); + x.putAttribute("_original_use_mode", getMode()); + setMode(x, Mode.Insert); aliasLocal.set(new HashMap()); @@ -1090,5 +1091,27 @@ public class OracleSchemaStatVisitor extends SchemaStatVisitor implements Oracle public void endVisit(ConditionalInsertClauseItem x) { + } + + @Override + public boolean visit(OracleBlockStatement x) { + return true; + } + + @Override + public void endVisit(OracleBlockStatement x) { + + } + @Override + public boolean visit(OracleLockTableStatement x) { + String tableName = x.getTable().toString(); + TableStat stat = new TableStat(); + this.tableStats.put(new TableStat.Name(tableName), stat); + return false; + } + + @Override + public void endVisit(OracleLockTableStatement x) { + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGSchemaStatVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGSchemaStatVisitor.java index 82542c7ca6..7456501d09 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGSchemaStatVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGSchemaStatVisitor.java @@ -147,8 +147,8 @@ public class PGSchemaStatVisitor extends SchemaStatVisitor implements PGASTVisit } } - x.putAttribute("_original_use_mode", modeLocal.get()); - modeLocal.set(Mode.Delete); + x.putAttribute("_original_use_mode", getMode()); + setMode(x, Mode.Delete); String ident = ((SQLIdentifierExpr) x.getTableName()).getName(); currentTableLocal.set(ident); @@ -191,8 +191,8 @@ public class PGSchemaStatVisitor extends SchemaStatVisitor implements PGASTVisit x.getWith().accept(this); } - x.putAttribute("_original_use_mode", modeLocal.get()); - modeLocal.set(Mode.Insert); + x.putAttribute("_original_use_mode", getMode()); + setMode(x, Mode.Insert); String originalTable = currentTableLocal.get(); diff --git a/src/main/java/com/alibaba/druid/sql/parser/CharTypes.java b/src/main/java/com/alibaba/druid/sql/parser/CharTypes.java index 8c84b24b7c..2023d2bee5 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/CharTypes.java +++ b/src/main/java/com/alibaba/druid/sql/parser/CharTypes.java @@ -70,6 +70,7 @@ public class CharTypes { // identifierFlags['`'] = true; identifierFlags['_'] = true; identifierFlags['$'] = true; + identifierFlags['#'] = true; } public static boolean isIdentifierChar(char c) { 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 2a9aa53051..3b4f098b46 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/Lexer.java +++ b/src/main/java/com/alibaba/druid/sql/parser/Lexer.java @@ -252,7 +252,13 @@ public class Lexer { scanChar(); token = COLONEQ; } else { - token = COLON; + if (isDigit(ch)) { + unscan(); + scanVariable(); + } else { + unscan(); + scanVariable(); + } } return; case '.': 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 24329a1aa8..99d2e2ff80 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java @@ -552,7 +552,7 @@ public class SQLExprParser extends SQLParser { } } - public final SQLName name() throws ParserException { + public SQLName name() throws ParserException { String identName; if (lexer.token() == Token.LITERAL_ALIAS) { identName = '"' + lexer.stringVal() + '"'; @@ -570,8 +570,8 @@ public class SQLExprParser extends SQLParser { if (lexer.token() == Token.DOT) { lexer.nextToken(); - if (lexer.token() != Token.IDENTIFIER) { - throw new ParserException("error"); + if (lexer.token() != Token.LITERAL_ALIAS && lexer.token() != Token.IDENTIFIER) { + throw new ParserException("error, " + lexer.token()); } name = new SQLPropertyExpr(name, lexer.stringVal()); 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 4ba52cb485..234df9d221 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLParser.java @@ -114,7 +114,7 @@ public class SQLParser { lexer.nextToken(); } else { setErrorEndPos(lexer.pos()); - throw new SQLParseException("syntax error, expect " + token + ", actual " + lexer.token()); + throw new SQLParseException("syntax error, expect " + token + ", actual " + lexer.token() + " " + lexer.stringVal()); } } 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 eeb4fb76f4..0fd7ad4ca6 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java @@ -37,7 +37,7 @@ import com.alibaba.druid.sql.ast.statement.SQLUpdateStatement; public class SQLStatementParser extends SQLParser { - protected final SQLExprParser exprParser; + protected SQLExprParser exprParser; public SQLStatementParser(String sql){ super(sql); @@ -173,12 +173,18 @@ public class SQLStatementParser extends SQLParser { parseInsert0(insertStatement, true); } + protected void parseInsert0_hinits(SQLInsertInto insertStatement) { + + } + protected void parseInsert0(SQLInsertInto insertStatement, boolean acceptSubQuery) { accept(Token.INTO); SQLName tableName = this.exprParser.name(); insertStatement.setTableName(tableName); - + + parseInsert0_hinits(insertStatement); + if (lexer.token() == Token.IDENTIFIER) { insertStatement.setAlias(lexer.stringVal()); lexer.nextToken(); 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 413807a546..7e224d24b3 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/Token.java +++ b/src/main/java/com/alibaba/druid/sql/parser/Token.java @@ -151,6 +151,10 @@ public enum Token { ERRORS("ERRORS"), REJECT("REJECT"), UNLIMITED("UNLIMITED"), + BEGIN("BEGIN"), + EXCLUSIVE("EXCLUSIVE"), + MODE("MODE"), + WAIT("WAIT"), // transact-sql TOP("TOP"), 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 20cf450a29..94690c0247 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SchemaStatVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SchemaStatVisitor.java @@ -52,14 +52,31 @@ public class SchemaStatVisitor extends SQLASTVisitorAdapter { protected final Set orderByColumns = new LinkedHashSet(); protected final Set groupByColumns = new LinkedHashSet(); - protected final Map subQueryMap = new LinkedHashMap(); + protected final Map subQueryMap = new LinkedHashMap(); protected final static ThreadLocal> aliasLocal = new ThreadLocal>(); protected final static ThreadLocal currentTableLocal = new ThreadLocal(); - protected final static ThreadLocal modeLocal = new ThreadLocal(); public final static String ATTR_TABLE = "_table_"; public final static String ATTR_COLUMN = "_column_"; + private Mode mode; + + protected Mode getMode() { + return mode; + } + + protected void setModeOrigin(SQLObject x) { + Mode originalMode = (Mode) x.getAttribute("_original_use_mode"); + mode = originalMode; + } + + protected Mode setMode(SQLObject x, Mode mode) { + Mode oldMode = this.mode; + x.putAttribute("_original_use_mode", oldMode); + this.mode = mode; + return oldMode; + } + public class OrderByStatVisitor extends SQLASTVisitorAdapter { private final SQLOrderBy orderBy; @@ -94,7 +111,7 @@ public class SchemaStatVisitor extends SQLASTVisitorAdapter { if (subQueryMap.containsKey(owner)) { return false; } - + owner = aliasWrap(owner); if (owner != null) { @@ -258,8 +275,7 @@ public class SchemaStatVisitor extends SQLASTVisitorAdapter { @Override public boolean visit(SQLTruncateStatement x) { - x.putAttribute("_original_use_mode", modeLocal.get()); - modeLocal.set(Mode.Insert); + setMode(x, Mode.Insert); aliasLocal.set(new HashMap()); @@ -288,8 +304,7 @@ public class SchemaStatVisitor extends SQLASTVisitorAdapter { @Override public boolean visit(SQLDropTableStatement x) { - x.putAttribute("_original_use_mode", modeLocal.get()); - modeLocal.set(Mode.Insert); + setMode(x, Mode.Insert); aliasLocal.set(new HashMap()); @@ -318,8 +333,7 @@ public class SchemaStatVisitor extends SQLASTVisitorAdapter { @Override public boolean visit(SQLInsertStatement x) { - x.putAttribute("_original_use_mode", modeLocal.get()); - modeLocal.set(Mode.Insert); + setMode(x, Mode.Insert); aliasLocal.set(new HashMap()); @@ -365,15 +379,13 @@ public class SchemaStatVisitor extends SQLASTVisitorAdapter { } public boolean visit(SQLSelectQueryBlock x) { - + setMode(x, Mode.Select); + if (x.getFrom() instanceof SQLSubqueryTableSource) { x.getFrom().accept(this); return false; } - x.putAttribute("_original_use_mode", modeLocal.get()); - modeLocal.set(Mode.Select); - String originalTable = currentTableLocal.get(); if (x.getFrom() instanceof SQLExprTableSource) { @@ -404,8 +416,7 @@ public class SchemaStatVisitor extends SQLASTVisitorAdapter { x.putAttribute("table", currentTableLocal.get()); currentTableLocal.set(originalTable); - Mode originalMode = (Mode) x.getAttribute("_original_use_mode"); - modeLocal.set(originalMode); + setModeOrigin(x); } public boolean visit(SQLJoinTableSource x) { @@ -415,13 +426,13 @@ public class SchemaStatVisitor extends SQLASTVisitorAdapter { public boolean visit(SQLPropertyExpr x) { if (x.getOwner() instanceof SQLIdentifierExpr) { String owner = ((SQLIdentifierExpr) x.getOwner()).getName(); - + if (subQueryMap.containsKey(owner)) { return false; } - + owner = aliasWrap(owner); - + if (owner != null) { Column column = new Column(owner, x.getName()); columns.add(column); @@ -430,13 +441,13 @@ public class SchemaStatVisitor extends SQLASTVisitorAdapter { } return false; } - + protected String aliasWrap(String name) { Map aliasMap = aliasLocal.get(); if (aliasMap.containsKey(name)) { return aliasMap.get(name); } - + return name; } @@ -503,7 +514,7 @@ public class SchemaStatVisitor extends SQLASTVisitorAdapter { public boolean visit(SQLAllColumnExpr x) { String currentTable = currentTableLocal.get(); - + if (subQueryMap.containsKey(currentTable)) { return false; } @@ -557,7 +568,7 @@ public class SchemaStatVisitor extends SQLASTVisitorAdapter { public boolean visit(SQLExprTableSource x) { if (isSimpleExprTableSource(x)) { String ident = x.getExpr().toString(); - + if (subQueryMap.containsKey(ident)) { return false; } @@ -571,7 +582,7 @@ public class SchemaStatVisitor extends SQLASTVisitorAdapter { x.putAttribute(ATTR_TABLE, ident); } - Mode mode = modeLocal.get(); + Mode mode = getMode(); switch (mode) { case Delete: stat.incrementDeleteCount(); @@ -664,8 +675,7 @@ public class SchemaStatVisitor extends SQLASTVisitorAdapter { public boolean visit(SQLDeleteStatement x) { aliasLocal.set(new HashMap()); - x.putAttribute("_original_use_mode", modeLocal.get()); - modeLocal.set(Mode.Delete); + setMode(x, Mode.Delete); String ident = ((SQLIdentifierExpr) x.getTableName()).getName(); currentTableLocal.set(ident); diff --git a/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleLockTableTest1.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleLockTableTest1.java new file mode 100644 index 0000000000..29c2a83091 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleLockTableTest1.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 OracleLockTableTest1 extends OracleTest { + + public void test_0() throws Exception { + String sql = "LOCK TABLE employees IN EXCLUSIVE MODE NOWAIT; "; + + 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"))); + + Assert.assertEquals(1, 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/OracleLockTableTest2.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleLockTableTest2.java new file mode 100644 index 0000000000..8e45b44fe0 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleLockTableTest2.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 OracleLockTableTest2 extends OracleTest { + + public void test_0() throws Exception { + String sql = "LOCK TABLE employees@remote IN SHARE MODE"; + + 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(1, 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/OracleSelectTest11.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleSelectTest11.java new file mode 100644 index 0000000000..a48c227dbe --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleSelectTest11.java @@ -0,0 +1,63 @@ +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 OracleSelectTest11 extends OracleTest { + + public void test_0() throws Exception { + String sql = "SELECT ID, GMT_CREATE, GMT_MODIFIED, COMPANY_ID, MEMBER_ID" + // + " , MEMBER_SEQ, FILE_NAME, DISPLAY_NAME, DISPLAY_NAME_UTF8, FILE_SIZE" + // + " , STATUS, WIDTH, HEIGHT, REFERENCE_COUNT, HASH_CODE" + // + " , GROUP_ID" + // + " FROM (SELECT *" + // + " FROM (SELECT row_.*, rownum AS rownum_" + // + " FROM (SELECT rowid AS rid" + // + " FROM IMAGE_REPOSITORY" + // + " WHERE COMPANY_ID = :1 AND STATUS = 'enable' " + // + " AND MEMBER_SEQ = :2 AND GMT_MODIFIED >= to_date(:3, 'yyyy-mm-dd hh24:mi:ss') " + // + " AND GMT_MODIFIED < to_date(:4, 'yyyy-mm-dd hh24:mi:ss')" + // + " ORDER BY \"FILE_SIZE\" DESC, \"ID\" DESC" + // // + " ) row_" + // + " WHERE rownum <= :5" + // + " )" + // + " WHERE rownum_ >= :6" + // + " ) a, IMAGE_REPOSITORY b " + // + " WHERE a.rid = b.rowid;"; // + +// sql = "select ID, GMT_CREATE, GMT_MODIFIED, COMPANY_ID, MEMBER_ID, MEMBER_SEQ, FILE_NAME, DISPLAY_NAME, DISPLAY_NAME_UTF8, FILE_SIZE, STATUS, WIDTH, HEIGHT, REFERENCE_COUNT, HASH_CODE, GROUP_ID from ( select * from (select row_.*, rownum rownum_ from ( select rowid rid from IMAGE_REPOSITORY where COMPANY_ID = :1 and STATUS = 'enable' and MEMBER_SEQ = :2 and GMT_MODIFIED >= to_date(:3 , 'yyyy-mm-dd hh24:mi:ss') and GMT_MODIFIED < to_date(:4 , 'yyyy-mm-dd hh24:mi:ss') order by \"FILE_SIZE\" desc , \"ID\" desc )row_ where rownum <= :5 ) where rownum_ >= :6 ) a , IMAGE_REPOSITORY b where a.rid = b.rowid "; + + 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("pivot_table"))); + + 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/sql/TestTransform.java b/src/test/java/com/alibaba/druid/sql/TestTransform.java new file mode 100644 index 0000000000..e8e63ff2d0 --- /dev/null +++ b/src/test/java/com/alibaba/druid/sql/TestTransform.java @@ -0,0 +1,272 @@ +package com.alibaba.druid.sql; + +import java.sql.Connection; +import java.sql.Date; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.Statement; +import java.util.List; + +import junit.framework.Assert; + +import com.alibaba.druid.pool.DruidDataSource; +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.fastjson.JSON; + +public class TestTransform extends OracleTest { + + private String jdbcUrl; + private String user; + private String password; + private DruidDataSource dataSource; + + public void setUp() throws Exception { + jdbcUrl = "jdbc:oracle:thin:@10.20.149.18:1521:emdb"; + user = "wardon"; + password = "wardon"; + + dataSource = new DruidDataSource(); + dataSource.setInitialSize(1); + dataSource.setUrl(jdbcUrl); + dataSource.setUsername(user); + dataSource.setPassword(password); + } + + public void test_transform() throws Exception { + 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 " + // + " ORDER BY sql_id, piece"; + Connection conn = dataSource.getConnection(); + + Statement stmt = conn.createStatement(); + ResultSet rs = stmt.executeQuery(sql); + Record r = null; + + while (rs.next()) { + r = new Record(); + + Date d1 = rs.getDate(1); + String s2 = rs.getString(2); + String sqlId = rs.getString(3); + + r.setSnapshotDate(d1); + r.setDbName(s2); + r.setSqlId(sqlId); + r.setPiece(rs.getInt(4)); + r.setSqlText(rs.getString(5)); + + r.setCommandType(rs.getInt(6)); + r.setLastSnapshotDate(rs.getDate(7)); + r.setDbPk(rs.getLong(8)); + + System.out.println(r.getSqlText()); + schemaStat(r); + } + rs.close(); + stmt.close(); + + conn.close(); + } + + public void schemaStat(Record r) { + String sql = r.getSqlText(); + + if (sql.startsWith("/* MV_REFRESH (INS) */")) { + return; + } + if (sql.startsWith("/* MV_REFRESH (DEL) */")) { + 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)); + + 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(); + } + + 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 { + 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(); + + Statement stmt = conn.createStatement(); + ResultSet rs = stmt.executeQuery(sql); + Record r = null; + + String lastSqlId = null; + while (rs.next()) { + 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(); + + insert(r); + } + + r = new Record(); + r.setSnapshotDate(d1); + r.setDbName(s2); + r.setSqlId(sqlId); + r.setPiece(rs.getInt(4)); + r.setSqlText(rs.getString(5)); + + r.setCommandType(rs.getInt(6)); + r.setLastSnapshotDate(rs.getDate(7)); + r.setDbPk(rs.getLong(8)); + } else { + String part = rs.getString(5); + if (part != null) { + r.setSqlText(r.getSqlText() + part); + } + } + lastSqlId = sqlId; + } + rs.close(); + stmt.close(); + + conn.close(); + } + + public void insert(Record r) throws Exception { + 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)" + // + " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"; + Connection conn = dataSource.getConnection(); + + 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()); + + stmt.setInt(6, r.getCommandType()); + stmt.setDate(7, r.getLastSnapshotDate()); + stmt.setLong(8, r.getDbPk()); + stmt.setString(9, r.getSqlText()); + + stmt.execute(); + + stmt.close(); + + conn.close(); + } + + 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; + + public Date getSnapshotDate() { + return snapshotDate; + } + + public void setSnapshotDate(Date snapshotDate) { + this.snapshotDate = snapshotDate; + } + + public String getDbName() { + return dbName; + } + + public void setDbName(String dbName) { + this.dbName = dbName; + } + + public String getSqlId() { + return sqlId; + } + + public void setSqlId(String sqlId) { + this.sqlId = sqlId; + } + + public String getSqlText() { + return sqlText; + } + + public void setSqlText(String sqlText) { + this.sqlText = sqlText; + } + + public Integer getPiece() { + return piece; + } + + public void setPiece(Integer piece) { + this.piece = piece; + } + + public Integer getCommandType() { + return commandType; + } + + public void setCommandType(Integer commandType) { + this.commandType = commandType; + } + + public Date getLastSnapshotDate() { + return lastSnapshotDate; + } + + public void setLastSnapshotDate(Date lastSnapshotDate) { + this.lastSnapshotDate = lastSnapshotDate; + } + + public Long getDbPk() { + return dbPk; + } + + public void setDbPk(Long dbPk) { + this.dbPk = dbPk; + } + + public String toString() { + return JSON.toJSONString(this); + } + } +}