From 3330643479be2fa58c1dea598d8c85f1019b62f4 Mon Sep 17 00:00:00 2001 From: wenshao Date: Sat, 9 Sep 2017 07:41:39 +0800 Subject: [PATCH] improved sql parser. --- .../alibaba/druid/filter/stat/StatFilter.java | 3 +- .../alibaba/druid/sql/SQLTransformUtils.java | 4 +- .../java/com/alibaba/druid/sql/SQLUtils.java | 4 +- .../alibaba/druid/sql/ast/SQLDataType.java | 3 + .../druid/sql/ast/SQLDataTypeImpl.java | 23 +- .../druid/sql/ast/expr/SQLIdentifierExpr.java | 8 + .../druid/sql/ast/expr/SQLPropertyExpr.java | 3 - .../statement/SQLForeignKeyConstraint.java | 1 + .../sql/ast/statement/SQLForeignKeyImpl.java | 38 ++- .../sql/dialect/db2/parser/DB2ExprParser.java | 6 +- .../mysql/parser/MySqlCreateTableParser.java | 7 +- .../dialect/mysql/parser/MySqlExprParser.java | 2 +- .../sql/dialect/mysql/parser/MySqlLexer.java | 9 +- .../mysql/parser/MySqlStatementParser.java | 4 +- .../mysql/visitor/MySqlOutputVisitor.java | 4 +- .../mysql/visitor/MySqlSchemaStatVisitor.java | 4 +- .../transform/FromSubqueryResolver.java | 2 + .../odps/parser/OdpsCreateTableParser.java | 2 +- .../odps/parser/OdpsStatementParser.java | 2 +- .../parser/OracleCreateTableParser.java | 11 +- .../oracle/parser/OracleExprParser.java | 21 +- .../oracle/parser/OracleSelectParser.java | 34 ++- .../oracle/parser/OracleStatementParser.java | 3 + .../expr/SQLServerObjectReferenceExpr.java | 13 +- .../com/alibaba/druid/sql/parser/Lexer.java | 115 ++++++-- .../sql/parser/SQLCreateTableParser.java | 6 +- .../druid/sql/parser/SQLExprParser.java | 128 ++++++--- .../alibaba/druid/sql/parser/SQLParser.java | 5 +- .../druid/sql/parser/SQLParserFeature.java | 4 +- .../druid/sql/parser/SQLParserUtils.java | 23 +- .../druid/sql/parser/SQLStatementParser.java | 5 +- .../alibaba/druid/sql/parser/SymbolTable.java | 2 - .../SchemaResolveVisitorFactory.java | 94 +++++++ .../ParameterizedOutputVisitorUtils.java | 11 +- .../sql/visitor/SQLASTOutputVisitor.java | 44 ++- .../java/com/alibaba/druid/util/FnvHash.java | 5 + .../sql/MySqlParameterizedBenchmark.java | 62 ++-- .../bvt/proxy/filter/StatFilterTest3.java | 20 +- .../bvt/sql/lexer/LexerParameterizedTest.java | 13 + .../alter/MySqlAlterTableTest_addFk.java | 4 +- .../mysql/create/MySqlCreateViewTest2.java | 81 ++++++ .../create/OracleCreateTableTest76.java | 122 ++++++++ .../create/OracleCreateTableTest77.java | 184 ++++++++++++ .../create/OracleCreateTableTest78.java | 165 +++++++++++ ...OracleCreateViewTest11_error_encoding.java | 192 +++++++++++++ .../oracle/create/OracleCreateViewTest12.java | 266 ++++++++++++++++++ .../select/OracleSelectTest81_join_brace.java | 96 +++++++ .../oracle/visitor/OracleResourceTest.java | 2 +- .../sql/postgresql/PGCreateTableTest_7.java | 67 +++++ .../OracleJoinResolveTest_1_fk.java | 166 +++++++++++ 50 files changed, 1898 insertions(+), 195 deletions(-) create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/lexer/LexerParameterizedTest.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateViewTest2.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/oracle/create/OracleCreateTableTest76.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/oracle/create/OracleCreateTableTest77.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/oracle/create/OracleCreateTableTest78.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/oracle/create/OracleCreateViewTest11_error_encoding.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/oracle/create/OracleCreateViewTest12.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/oracle/select/OracleSelectTest81_join_brace.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/postgresql/PGCreateTableTest_7.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/repository/OracleJoinResolveTest_1_fk.java diff --git a/src/main/java/com/alibaba/druid/filter/stat/StatFilter.java b/src/main/java/com/alibaba/druid/filter/stat/StatFilter.java index 3d66966159..634f3b4313 100644 --- a/src/main/java/com/alibaba/druid/filter/stat/StatFilter.java +++ b/src/main/java/com/alibaba/druid/filter/stat/StatFilter.java @@ -27,6 +27,7 @@ import java.util.Properties; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; +import com.alibaba.druid.VERSION; import com.alibaba.druid.filter.Filter; import com.alibaba.druid.filter.FilterChain; import com.alibaba.druid.filter.FilterEventAdapter; @@ -145,7 +146,7 @@ public class StatFilter extends FilterEventAdapter implements StatFilterMBean { try { sql = ParameterizedOutputVisitorUtils.parameterize(sql, dbType); } catch (Exception e) { - LOG.error("merge sql error, dbType " + dbType + ", sql : " + sql, e); + LOG.error("merge sql error, dbType " + dbType + ", druid-" + VERSION.getVersionNumber() + ", sql : " + sql, e); } return sql; diff --git a/src/main/java/com/alibaba/druid/sql/SQLTransformUtils.java b/src/main/java/com/alibaba/druid/sql/SQLTransformUtils.java index 016f68c803..9e77c8a61c 100644 --- a/src/main/java/com/alibaba/druid/sql/SQLTransformUtils.java +++ b/src/main/java/com/alibaba/druid/sql/SQLTransformUtils.java @@ -168,7 +168,7 @@ public class SQLTransformUtils { dataType = new SQLDataTypeImpl("smallint"); } else if (precision < 9) { dataType = new SQLDataTypeImpl("int"); - } else if (precision < 19) { + } else if (precision <= 20) { dataType = new SQLDataTypeImpl("bigint"); } else { dataType = new SQLDataTypeImpl("decimal", precision); @@ -468,7 +468,7 @@ public class SQLTransformUtils { dataType = new SQLDataTypeImpl("smallint"); } else if (precision < 9) { dataType = new SQLDataTypeImpl("int"); - } else if (precision < 19) { + } else if (precision <= 20) { dataType = new SQLDataTypeImpl("bigint"); } else { dataType = new SQLDataTypeImpl("decimal", precision); diff --git a/src/main/java/com/alibaba/druid/sql/SQLUtils.java b/src/main/java/com/alibaba/druid/sql/SQLUtils.java index 94fe2a33aa..5ca34e520e 100644 --- a/src/main/java/com/alibaba/druid/sql/SQLUtils.java +++ b/src/main/java/com/alibaba/druid/sql/SQLUtils.java @@ -234,7 +234,9 @@ public class SQLUtils { public static String format(String sql, String dbType, List parameters, FormatOption option) { try { - SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, dbType, true); + SQLParserFeature[] features = {SQLParserFeature.KeepComments, SQLParserFeature.EnableSQLBinaryOpExprGroup}; + + SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, dbType, features); parser.setKeepComments(true); List statementList = parser.parseStatementList(); diff --git a/src/main/java/com/alibaba/druid/sql/ast/SQLDataType.java b/src/main/java/com/alibaba/druid/sql/ast/SQLDataType.java index 464f941e7e..884d8c9a04 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/SQLDataType.java +++ b/src/main/java/com/alibaba/druid/sql/ast/SQLDataType.java @@ -33,4 +33,7 @@ public interface SQLDataType extends SQLObject { boolean isWithLocalTimeZone(); SQLDataType clone(); + + void setDbType(String dbType); + String getDbType(); } diff --git a/src/main/java/com/alibaba/druid/sql/ast/SQLDataTypeImpl.java b/src/main/java/com/alibaba/druid/sql/ast/SQLDataTypeImpl.java index 368c31561a..adbf08ebed 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/SQLDataTypeImpl.java +++ b/src/main/java/com/alibaba/druid/sql/ast/SQLDataTypeImpl.java @@ -15,6 +15,7 @@ */ package com.alibaba.druid.sql.ast; +import com.alibaba.druid.sql.SQLUtils; import com.alibaba.druid.sql.ast.expr.SQLIntegerExpr; import com.alibaba.druid.sql.visitor.SQLASTVisitor; import com.alibaba.druid.util.FnvHash; @@ -24,11 +25,12 @@ import java.util.List; public class SQLDataTypeImpl extends SQLObjectImpl implements SQLDataType { - private String name; - private long nameHashCode64; + private String name; + private long nameHashCode64; protected final List arguments = new ArrayList(); - private Boolean withTimeZone; - private boolean withLocalTimeZone = false; + private Boolean withTimeZone; + private boolean withLocalTimeZone = false; + private String dbType; public SQLDataTypeImpl(){ @@ -122,6 +124,14 @@ public class SQLDataTypeImpl extends SQLObjectImpl implements SQLDataType { this.withLocalTimeZone = withLocalTimeZone; } + public String getDbType() { + return dbType; + } + + public void setDbType(String dbType) { + this.dbType = dbType; + } + public SQLDataTypeImpl clone() { SQLDataTypeImpl x = new SQLDataTypeImpl(); @@ -131,6 +141,7 @@ public class SQLDataTypeImpl extends SQLObjectImpl implements SQLDataType { } public void cloneTo(SQLDataTypeImpl x) { + x.dbType = dbType; x.name = name; for (SQLExpr arg : arguments) { @@ -140,4 +151,8 @@ public class SQLDataTypeImpl extends SQLObjectImpl implements SQLDataType { x.withTimeZone = withTimeZone; x.withLocalTimeZone = withLocalTimeZone; } + + public String toString() { + return SQLUtils.toSQLString(this, dbType); + } } diff --git a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLIdentifierExpr.java b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLIdentifierExpr.java index 9daf9a4d3c..07ca9a4e95 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLIdentifierExpr.java +++ b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLIdentifierExpr.java @@ -45,6 +45,14 @@ public class SQLIdentifierExpr extends SQLExprImpl implements SQLName { return name; } + public String getLowerName() { + if (name == null) { + return null; + } + + return name.toLowerCase(); + } + public String getName() { return this.name; } diff --git a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLPropertyExpr.java b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLPropertyExpr.java index a8d912ca67..757f249f34 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLPropertyExpr.java +++ b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLPropertyExpr.java @@ -36,9 +36,6 @@ public class SQLPropertyExpr extends SQLExprImpl implements SQLName { } public SQLPropertyExpr(SQLExpr owner, String name){ - if (name == null) { - throw new IllegalArgumentException("name is null."); - } setOwner(owner); this.name = name; } diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLForeignKeyConstraint.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLForeignKeyConstraint.java index 84db715278..5ad661a249 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLForeignKeyConstraint.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLForeignKeyConstraint.java @@ -23,6 +23,7 @@ public interface SQLForeignKeyConstraint extends SQLConstraint, SQLTableElement, List getReferencingColumns(); + SQLExprTableSource getReferencedTable(); SQLName getReferencedTableName(); void setReferencedTableName(SQLName value); diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLForeignKeyImpl.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLForeignKeyImpl.java index 3099e53bd1..5125ced984 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLForeignKeyImpl.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLForeignKeyImpl.java @@ -22,12 +22,11 @@ import com.alibaba.druid.sql.ast.SQLName; import com.alibaba.druid.sql.visitor.SQLASTVisitor; public class SQLForeignKeyImpl extends SQLConstraintImpl implements SQLForeignKeyConstraint { - - private SQLName referencedTableName; - private List referencingColumns = new ArrayList(); - private List referencedColumns = new ArrayList(); - private boolean onDeleteCascade = false; - private boolean onDeleteSetNull = false; + private SQLExprTableSource referencedTable; + private List referencingColumns = new ArrayList(); + private List referencedColumns = new ArrayList(); + private boolean onDeleteCascade = false; + private boolean onDeleteSetNull = false; public SQLForeignKeyImpl(){ @@ -38,14 +37,33 @@ public class SQLForeignKeyImpl extends SQLConstraintImpl implements SQLForeignKe return referencingColumns; } + @Override + public SQLExprTableSource getReferencedTable() { + return referencedTable; + } + @Override public SQLName getReferencedTableName() { - return referencedTableName; + if (referencedTable == null) { + return null; + } + return referencedTable.getName(); } @Override public void setReferencedTableName(SQLName value) { - this.referencedTableName = value; + if (value == null) { + this.referencedTable = null; + return; + } + this.setReferencedTable(new SQLExprTableSource(value)); + } + + public void setReferencedTable(SQLExprTableSource x) { + if (x != null) { + x.setParent(this); + } + this.referencedTable = x; } @Override @@ -83,8 +101,8 @@ public class SQLForeignKeyImpl extends SQLConstraintImpl implements SQLForeignKe public void cloneTo(SQLForeignKeyImpl x) { super.cloneTo(x); - if (referencedTableName != null) { - x.setReferencedTableName(referencedTableName.clone()); + if (referencedTable != null) { + x.setReferencedTable(referencedTable.clone()); } for (SQLName column : referencingColumns) { diff --git a/src/main/java/com/alibaba/druid/sql/dialect/db2/parser/DB2ExprParser.java b/src/main/java/com/alibaba/druid/sql/dialect/db2/parser/DB2ExprParser.java index 901e56d904..9b7f5d1cfe 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/db2/parser/DB2ExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/db2/parser/DB2ExprParser.java @@ -102,21 +102,21 @@ public class DB2ExprParser extends SQLExprParser { } protected SQLExpr dotRest(SQLExpr expr) { - if (lexer.identifierEquals("NEXTVAL")) { + if (lexer.identifierEquals(FnvHash.Constants.NEXTVAL)) { if (expr instanceof SQLIdentifierExpr) { SQLIdentifierExpr identExpr = (SQLIdentifierExpr) expr; SQLSequenceExpr seqExpr = new SQLSequenceExpr(identExpr, SQLSequenceExpr.Function.NextVal); lexer.nextToken(); return seqExpr; } - } else if (lexer.identifierEquals("PREVVAL")) { + } else if (lexer.identifierEquals(FnvHash.Constants.PREVVAL)) { if (expr instanceof SQLIdentifierExpr) { SQLIdentifierExpr identExpr = (SQLIdentifierExpr) expr; SQLSequenceExpr seqExpr = new SQLSequenceExpr(identExpr, SQLSequenceExpr.Function.PrevVal); lexer.nextToken(); return seqExpr; } - } else if (lexer.identifierEquals("CURRVAL")) { + } else if (lexer.identifierEquals(FnvHash.Constants.CURRVAL)) { if (expr instanceof SQLIdentifierExpr) { SQLIdentifierExpr identExpr = (SQLIdentifierExpr) expr; SQLSequenceExpr seqExpr = new SQLSequenceExpr(identExpr, SQLSequenceExpr.Function.CurrVal); diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlCreateTableParser.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlCreateTableParser.java index ba530ca5b0..ddb29dbb3d 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlCreateTableParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlCreateTableParser.java @@ -63,15 +63,15 @@ public class MySqlCreateTableParser extends SQLCreateTableParser { super(exprParser); } - public SQLCreateTableStatement parseCrateTable() { - return parseCrateTable(true); + public SQLCreateTableStatement parseCreateTable() { + return parseCreateTable(true); } public MySqlExprParser getExprParser() { return (MySqlExprParser) exprParser; } - public MySqlCreateTableStatement parseCrateTable(boolean acceptCreate) { + public MySqlCreateTableStatement parseCreateTable(boolean acceptCreate) { MySqlCreateTableStatement stmt = new MySqlCreateTableStatement(); if (acceptCreate) { if (lexer.hasComment() && lexer.isKeepComments()) { @@ -120,6 +120,7 @@ public class MySqlCreateTableParser extends SQLCreateTableParser { || lexer.token() == Token.PRIMARY // || lexer.token() == Token.UNIQUE) { SQLTableConstraint constraint = this.parseConstraint(); + constraint.setParent(stmt); stmt.getTableElementList().add(constraint); } else if (lexer.token() == (Token.INDEX)) { lexer.nextToken(); diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlExprParser.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlExprParser.java index 7a3e75f2e0..24deb7db26 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlExprParser.java @@ -712,7 +712,7 @@ public class MySqlExprParser extends SQLExprParser { } accept(Token.LPAREN); - this.names(fk.getReferencingColumns()); + this.names(fk.getReferencingColumns(), fk); accept(Token.RPAREN); accept(Token.REFERENCES); diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlLexer.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlLexer.java index 803a2529b8..4ee3faadfb 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlLexer.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlLexer.java @@ -22,6 +22,7 @@ import java.util.HashMap; import java.util.Map; import com.alibaba.druid.sql.parser.*; +import com.alibaba.druid.util.FnvHash; public class MySqlLexer extends Lexer { public static SymbolTable quoteTable = new SymbolTable(8192); @@ -226,7 +227,8 @@ public class MySqlLexer extends Lexer { final char first = ch; - if (ch == 'b' && charAt(pos + 1) == '\'') { + if (ch == 'b' + && charAt(pos + 1) == '\'') { int i = 2; int mark = pos + 2; for (;;++i) { @@ -336,6 +338,7 @@ public class MySqlLexer extends Lexer { token = Token.IDENTIFIER; stringVal = SymbolTable.global.addSymbol(text, mark, bufPos, hash); } + } } @@ -395,7 +398,9 @@ public class MySqlLexer extends Lexer { stringVal = this.subString(mark + startHintSp, starIndex - startHintSp - mark); token = Token.HINT; } else { - stringVal = this.subString(mark, starIndex + 2 - mark); + if (!optimizedForParameterized) { + stringVal = this.subString(mark, starIndex + 2 - mark); + } token = Token.MULTI_LINE_COMMENT; commentCount++; if (keepComments) { diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java index dbfc0f9420..865f8a590c 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java @@ -114,7 +114,7 @@ public class MySqlStatementParser extends SQLStatementParser { public SQLCreateTableStatement parseCreateTable() { MySqlCreateTableParser parser = new MySqlCreateTableParser(this.exprParser); - return parser.parseCrateTable(); + return parser.parseCreateTable(); } public SQLStatement parseSelect() { @@ -230,7 +230,7 @@ public class MySqlStatementParser extends SQLStatementParser { lexer.reset(markBp, markChar, Token.CREATE); } MySqlCreateTableParser parser = new MySqlCreateTableParser(this.exprParser); - MySqlCreateTableStatement stmt = parser.parseCrateTable(false); + MySqlCreateTableStatement stmt = parser.parseCreateTable(false); stmt.setHints(hints); if (comments != null) { diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java index 9c1e7cf2d1..92e849a5af 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java @@ -200,13 +200,13 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV SQLOrderBy orderBy = x.getOrderBy(); if (orderBy != null) { println(); - orderBy.accept(this); + visit(orderBy); } SQLLimit limit = x.getLimit(); if (limit != null) { println(); - limit.accept(this); + visit(limit); } SQLName procedureName = x.getProcedureName(); 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 84031afdd3..548e527d1e 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 @@ -1057,7 +1057,7 @@ public class MySqlSchemaStatVisitor extends SchemaStatVisitor implements MySqlAS @Override public boolean visit(MysqlForeignKey x) { - return super.visit(x); + return super.visit((SQLForeignKeyImpl) x); } @Override @@ -1310,6 +1310,4 @@ public class MySqlSchemaStatVisitor extends SchemaStatVisitor implements MySqlAS public void endVisit(MySqlFlushStatement x) { } - - } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/transform/FromSubqueryResolver.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/transform/FromSubqueryResolver.java index e0d387043e..4638f3b789 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/transform/FromSubqueryResolver.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/transform/FromSubqueryResolver.java @@ -118,6 +118,7 @@ public class FromSubqueryResolver extends OracleASTVisitorAdapter { String entryName = entry.getAlias(); SQLCreateViewStatement entryStmt = new SQLCreateViewStatement(); + entryStmt.setOrReplace(true); entryStmt.setDbType(stmt.getDbType()); String entryViewName = visitor.generateSubViewName(); @@ -136,6 +137,7 @@ public class FromSubqueryResolver extends OracleASTVisitorAdapter { String dbType = stmt.getDbType(); for (int i = 0; i < targetList.size() - 1; ++i) { SQLCreateViewStatement targetStmt = (SQLCreateViewStatement) targetList.get(i); + targetStmt.setOrReplace(true); targetStmt.setDbType(dbType); targetStmt.setAfterSemi(true); } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsCreateTableParser.java b/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsCreateTableParser.java index 9fda1ae104..1fea3c8299 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsCreateTableParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsCreateTableParser.java @@ -35,7 +35,7 @@ public class OdpsCreateTableParser extends SQLCreateTableParser { super(exprParser); } - public SQLCreateTableStatement parseCrateTable(boolean acceptCreate) { + public SQLCreateTableStatement parseCreateTable(boolean acceptCreate) { OdpsCreateTableStatement stmt = new OdpsCreateTableStatement(); if (acceptCreate) { diff --git a/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsStatementParser.java b/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsStatementParser.java index e1c3f8f3d9..953d63a3bd 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsStatementParser.java @@ -72,7 +72,7 @@ public class OdpsStatementParser extends SQLStatementParser { public SQLCreateTableStatement parseCreateTable() { SQLCreateTableParser parser = new OdpsCreateTableParser(this.exprParser); - return parser.parseCrateTable(); + return parser.parseCreateTable(); } public SQLCreateTableParser getSQLCreateTableParser() { diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleCreateTableParser.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleCreateTableParser.java index e11c294f71..344d2c57ff 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleCreateTableParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleCreateTableParser.java @@ -15,19 +15,12 @@ */ package com.alibaba.druid.sql.dialect.oracle.parser; -import com.alibaba.druid.sql.ast.SQLExpr; import com.alibaba.druid.sql.ast.SQLName; import com.alibaba.druid.sql.ast.SQLPartition; -import com.alibaba.druid.sql.ast.SQLPartitionBy; import com.alibaba.druid.sql.ast.SQLPartitionByHash; import com.alibaba.druid.sql.ast.SQLPartitionByList; import com.alibaba.druid.sql.ast.SQLPartitionByRange; -import com.alibaba.druid.sql.ast.SQLSubPartition; -import com.alibaba.druid.sql.ast.SQLSubPartitionBy; -import com.alibaba.druid.sql.ast.SQLSubPartitionByHash; -import com.alibaba.druid.sql.ast.SQLSubPartitionByList; import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; -import com.alibaba.druid.sql.ast.expr.SQLIntegerExpr; import com.alibaba.druid.sql.ast.expr.SQLNumericLiteralExpr; import com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement; import com.alibaba.druid.sql.ast.statement.SQLSelect; @@ -53,8 +46,8 @@ public class OracleCreateTableParser extends SQLCreateTableParser { return new OracleCreateTableStatement(); } - public OracleCreateTableStatement parseCrateTable(boolean acceptCreate) { - OracleCreateTableStatement stmt = (OracleCreateTableStatement) super.parseCrateTable(acceptCreate); + public OracleCreateTableStatement parseCreateTable(boolean acceptCreate) { + OracleCreateTableStatement stmt = (OracleCreateTableStatement) super.parseCreateTable(acceptCreate); if (lexer.token() == Token.OF) { lexer.nextToken(); 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 8768adc522..e501abcee4 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 @@ -216,6 +216,7 @@ public class OracleExprParser extends SQLExprParser { if ("TIMESTAMP".equalsIgnoreCase(typeName)) { SQLDataTypeImpl timestamp = new SQLDataTypeImpl(typeName); + timestamp.setDbType(dbType); if (lexer.token() == Token.LPAREN) { lexer.nextToken(); @@ -280,7 +281,8 @@ public class OracleExprParser extends SQLExprParser { } - SQLDataType dataType = new SQLDataTypeImpl(typeName); + SQLDataTypeImpl dataType = new SQLDataTypeImpl(typeName); + dataType.setDbType(dbType); return parseDataTypeRest(dataType); } @@ -700,14 +702,14 @@ public class OracleExprParser extends SQLExprParser { return expr; } - if (lexer.identifierEquals("NEXTVAL")) { + if (lexer.identifierEquals(FnvHash.Constants.NEXTVAL)) { if (expr instanceof SQLIdentifierExpr) { SQLIdentifierExpr identExpr = (SQLIdentifierExpr) expr; SQLSequenceExpr seqExpr = new SQLSequenceExpr(identExpr, SQLSequenceExpr.Function.NextVal); lexer.nextToken(); return seqExpr; } - } else if (lexer.identifierEquals("CURRVAL")) { + } else if (lexer.identifierEquals(FnvHash.Constants.CURRVAL)) { if (expr instanceof SQLIdentifierExpr) { SQLIdentifierExpr identExpr = (SQLIdentifierExpr) expr; SQLSequenceExpr seqExpr = new SQLSequenceExpr(identExpr, SQLSequenceExpr.Function.CurrVal); @@ -1404,12 +1406,12 @@ public class OracleExprParser extends SQLExprParser { continue; } - if (lexer.identifierEquals("VALIDATE")) { + if (lexer.identifierEquals(FnvHash.Constants.VALIDATE)) { lexer.nextToken(); constraint.setValidate(Boolean.TRUE); continue; } - if (lexer.identifierEquals("NOVALIDATE")) { + if (lexer.identifierEquals(FnvHash.Constants.NOVALIDATE)) { lexer.nextToken(); constraint.setValidate(Boolean.FALSE); continue; @@ -1431,7 +1433,7 @@ public class OracleExprParser extends SQLExprParser { if (lexer.token() == Token.NOT) { lexer.nextToken(); - if (lexer.identifierEquals("DEFERRABLE")) { + if (lexer.identifierEquals(FnvHash.Constants.DEFERRABLE)) { lexer.nextToken(); constraint.setDeferrable(false); continue; @@ -1439,11 +1441,16 @@ public class OracleExprParser extends SQLExprParser { throw new ParserException("TODO " + lexer.info()); } - if (lexer.identifierEquals("DEFERRABLE")) { + if (lexer.identifierEquals(FnvHash.Constants.DEFERRABLE)) { lexer.nextToken(); constraint.setDeferrable(true); continue; } + + if (lexer.token() == Token.USING) { + OracleUsingIndexClause using = parseUsingIndex(); + constraint.setUsing(using); + } break; } 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 927811cb5b..01b8f01c3f 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 @@ -247,7 +247,7 @@ public class OracleSelectParser extends SQLSelectParser { } public SQLSelectQuery query() { - if (lexer.token() == (Token.LPAREN)) { + if (lexer.token() == Token.LPAREN) { lexer.nextToken(); SQLSelectQuery select = query(); @@ -270,13 +270,13 @@ public class OracleSelectParser extends SQLSelectParser { parseHints(queryBlock); - if (lexer.token() == (Token.DISTINCT)) { + if (lexer.token() == Token.DISTINCT) { queryBlock.setDistionOption(SQLSetQuantifier.DISTINCT); lexer.nextToken(); - } else if (lexer.token() == (Token.UNIQUE)) { + } else if (lexer.token() == Token.UNIQUE) { queryBlock.setDistionOption(SQLSetQuantifier.UNIQUE); lexer.nextToken(); - } else if (lexer.token() == (Token.ALL)) { + } else if (lexer.token() == Token.ALL) { queryBlock.setDistionOption(SQLSetQuantifier.ALL); lexer.nextToken(); } @@ -304,16 +304,16 @@ public class OracleSelectParser extends SQLSelectParser { } public SQLSelectQuery queryRest(SQLSelectQuery selectQuery) { - if (lexer.token() == (Token.UNION)) { + if (lexer.token() == Token.UNION) { SQLUnionQuery union = new SQLUnionQuery(); union.setLeft(selectQuery); lexer.nextToken(); - if (lexer.token() == (Token.ALL)) { + if (lexer.token() == Token.ALL) { union.setOperator(SQLUnionOperator.UNION_ALL); lexer.nextToken(); - } else if (lexer.token() == (Token.DISTINCT)) { + } else if (lexer.token() == Token.DISTINCT) { union.setOperator(SQLUnionOperator.DISTINCT); lexer.nextToken(); } @@ -582,10 +582,6 @@ public class OracleSelectParser extends SQLSelectParser { } } - protected String as() { - return super.as(); - } - @Override public SQLTableSource parseTableSource() { SQLTableSource tableSource = parseTableSourcePrimary(); @@ -601,11 +597,11 @@ public class OracleSelectParser extends SQLSelectParser { if (lexer.token() == (Token.LPAREN)) { lexer.nextToken(); - OracleSelectSubqueryTableSource tableSource; + OracleSelectTableSource tableSource; if (lexer.token() == Token.SELECT || lexer.token() == Token.WITH) { tableSource = new OracleSelectSubqueryTableSource(select()); - } else if (lexer.token() == (Token.LPAREN)) { - tableSource = new OracleSelectSubqueryTableSource(select()); + } else if (lexer.token() == Token.LPAREN) { + tableSource = (OracleSelectTableSource) parseTableSource(); } else if (lexer.token() == Token.IDENTIFIER) { SQLTableSource identTable = parseTableSource(); accept(Token.RPAREN); @@ -613,9 +609,17 @@ public class OracleSelectParser extends SQLSelectParser { } else { throw new ParserException("TODO :" + lexer.info()); } + accept(Token.RPAREN); - parsePivot((OracleSelectTableSource) tableSource); + if (lexer.token() == Token.UNION && tableSource instanceof OracleSelectSubqueryTableSource) { + OracleSelectSubqueryTableSource selectSubqueryTableSource = (OracleSelectSubqueryTableSource) tableSource; + SQLSelect select = selectSubqueryTableSource.getSelect(); + SQLSelectQuery selectQuery = this.queryRest(select.getQuery()); + select.setQuery(selectQuery); + } + + parsePivot(tableSource); return tableSource; } 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 7dd9f68016..68982cd93a 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 @@ -1606,6 +1606,7 @@ public class OracleStatementParser extends SQLStatementParser { accept(Token.CURSOR); dataType = new SQLDataTypeImpl("REF CURSOR"); + dataType.setDbType(dbType); } else if (lexer.token() == Token.TABLE) { lexer.nextToken(); accept(Token.OF); @@ -1619,6 +1620,7 @@ public class OracleStatementParser extends SQLStatementParser { String typeName = "TABLE OF " + name.toString() + "%TYPE"; dataType = new SQLDataTypeImpl(typeName); + dataType.setDbType(dbType); } else if (lexer.identifierEquals("VARRAY")) { lexer.nextToken(); accept(Token.LPAREN); @@ -1630,6 +1632,7 @@ public class OracleStatementParser extends SQLStatementParser { lexer.nextToken(); String typeName = "VARRAY(" + len + ") OF NUMBER"; dataType = new SQLDataTypeImpl(typeName); + dataType.setDbType(dbType); } else { throw new ParserException("TODO : " + lexer.info()); } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/expr/SQLServerObjectReferenceExpr.java b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/expr/SQLServerObjectReferenceExpr.java index e077e0c6cd..a4c5108afd 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/expr/SQLServerObjectReferenceExpr.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/expr/SQLServerObjectReferenceExpr.java @@ -139,10 +139,15 @@ public class SQLServerObjectReferenceExpr extends SQLServerObjectImpl implements @Override public long hashCode64() { if (hashCode64 == 0) { - hashCode64 = new SQLPropertyExpr( - new SQLPropertyExpr(server, database) - , schema) - .hashCode64(); + if (server == null) { + hashCode64 = new SQLPropertyExpr( + new SQLPropertyExpr(server, database) + , schema) + .hashCode64(); + } else { + hashCode64 = new SQLPropertyExpr(database, schema) + .hashCode64(); + } } return hashCode64; } 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 cdcc412115..a9dc8a1240 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/Lexer.java +++ b/src/main/java/com/alibaba/druid/sql/parser/Lexer.java @@ -19,19 +19,9 @@ 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.COLONCOLON; -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; -import static com.alibaba.druid.sql.parser.Token.ERROR; -import static com.alibaba.druid.sql.parser.Token.LBRACE; -import static com.alibaba.druid.sql.parser.Token.LBRACKET; -import static com.alibaba.druid.sql.parser.Token.LITERAL_ALIAS; -import static com.alibaba.druid.sql.parser.Token.LITERAL_CHARS; -import static com.alibaba.druid.sql.parser.Token.LPAREN; -import static com.alibaba.druid.sql.parser.Token.RBRACE; -import static com.alibaba.druid.sql.parser.Token.RBRACKET; -import static com.alibaba.druid.sql.parser.Token.RPAREN; +import static com.alibaba.druid.sql.parser.SQLParserFeature.KeepComments; +import static com.alibaba.druid.sql.parser.SQLParserFeature.OptimizedForParameterized; +import static com.alibaba.druid.sql.parser.Token.*; import java.math.BigDecimal; import java.math.BigInteger; @@ -49,6 +39,7 @@ import com.alibaba.druid.util.StringUtils; * @author wenshao [szujobs@hotmail.com] */ public class Lexer { + protected static SymbolTable symbols_l2 = new SymbolTable(512); protected int features = 0; //SQLParserFeature.of(SQLParserFeature.EnableSQLBinaryOpExprGroup); protected final String text; @@ -69,29 +60,24 @@ public class Lexer { protected long hash; protected int commentCount = 0; - protected List comments = new ArrayList(2); - protected boolean skipComment = true; - private SavePoint savePoint = null; /* * anti sql injection */ private boolean allowComment = true; - private int varIndex = -1; - protected CommentHandler commentHandler; protected boolean endOfComment = false; protected boolean keepComments = false; - protected int line = 0; protected int lines = 0; - protected String dbType; + protected boolean optimizedForParameterized = false; + private int startPos; private int posLine; private int posColumn; @@ -316,6 +302,12 @@ public class Lexer { return; } + if (ch == '.') { + scanChar(); + token = DOT; + return; + } + if (ch == 'a' || ch == 'A') { char ch_next = charAt(pos + 1); if (ch_next == 's' || ch_next == 'S') { @@ -837,6 +829,7 @@ public class Lexer { protected void scanString() { mark = pos; boolean hasSpecial = false; + Token preToken = this.token; for (;;) { if (isEOF()) { @@ -875,7 +868,11 @@ public class Lexer { } if (!hasSpecial) { - stringVal = subString(mark + 1, bufPos); + if (preToken == Token.AS) { + stringVal = subString(mark, bufPos + 2); + } else { + stringVal = subString(mark + 1, bufPos); + } } else { stringVal = new String(buf, 0, bufPos); } @@ -902,7 +899,12 @@ public class Lexer { throw new ParserException("unclosed str. " + info()); } - String stringVal = subString(startIndex, endIndex - startIndex); + String stringVal; + if (token == Token.AS) { + stringVal = subString(pos, endIndex + 1 - pos); + } else { + stringVal = subString(startIndex, endIndex - startIndex); + } // hasSpecial = stringVal.indexOf('\\') != -1; if (!hasSpecial) { @@ -1537,6 +1539,15 @@ public class Lexer { return stringVal; } + private final void stringVal(StringBuffer out) { + if (stringVal != null) { + out.append(stringVal); + return; + } + + out.append(text, mark, mark + bufPos); + } + public final boolean identifierEquals(String text) { if (token != Token.IDENTIFIER) { return false; @@ -1799,9 +1810,69 @@ public class Lexer { public void config(SQLParserFeature feature, boolean state) { features = SQLParserFeature.config(features, feature, state); + + if (feature == OptimizedForParameterized) { + optimizedForParameterized = state; + } else if (feature == KeepComments) { + this.keepComments = state; + } } public final boolean isEnabled(SQLParserFeature feature) { return SQLParserFeature.isEnabled(this.features, feature); } + + public static String parameterize(String sql, String dbType) { + Lexer lexer = SQLParserUtils.createLexer(sql, dbType); + lexer.optimizedForParameterized = true; // optimized + + lexer.nextToken(); + + StringBuffer buf = new StringBuffer(); + + for_: + for (;;) { + Token token = lexer.token; + switch (token) { + case LITERAL_ALIAS: + case LITERAL_FLOAT: + case LITERAL_CHARS: + case LITERAL_INT: + case LITERAL_NCHARS: + case LITERAL_HEX: + case VARIANT: + if (buf.length() != 0) { + buf.append(' '); + } + buf.append('?'); + break; + case COMMA: + buf.append(','); + break; + case EQ: + buf.append('='); + break; + case EOF: + break for_; + case ERROR: + return sql; + case SELECT: + buf.append("SELECT"); + break; + case UPDATE: + buf.append("UPDATE"); + break; + default: + if (buf.length() != 0) { + buf.append(' '); + } + lexer.stringVal(buf); + break; + } + + lexer.nextToken(); + } + + return buf.toString(); + } } diff --git a/src/main/java/com/alibaba/druid/sql/parser/SQLCreateTableParser.java b/src/main/java/com/alibaba/druid/sql/parser/SQLCreateTableParser.java index 779f4c60b1..45824c1668 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLCreateTableParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLCreateTableParser.java @@ -31,13 +31,13 @@ public class SQLCreateTableParser extends SQLDDLParser { super(exprParser); } - public SQLCreateTableStatement parseCrateTable() { + public SQLCreateTableStatement parseCreateTable() { List comments = null; if (lexer.isKeepComments() && lexer.hasComment()) { comments = lexer.readAndResetComments(); } - SQLCreateTableStatement stmt = parseCrateTable(true); + SQLCreateTableStatement stmt = parseCreateTable(true); if (comments != null) { stmt.addBeforeComment(comments); } @@ -45,7 +45,7 @@ public class SQLCreateTableParser extends SQLDDLParser { return stmt; } - public SQLCreateTableStatement parseCrateTable(boolean acceptCreate) { + public SQLCreateTableStatement parseCreateTable(boolean acceptCreate) { SQLCreateTableStatement createTable = newCreateStatement(); if (acceptCreate) { 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 a107db2747..fc9130774a 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java @@ -237,7 +237,14 @@ public class SQLExprParser extends SQLParser { expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.DIV, rightExp, getDbType()); expr = multiplicativeRest(expr); } else if (lexer.identifierEquals(FnvHash.Constants.MOD)) { + Lexer.SavePoint savePoint = lexer.mark(); lexer.nextToken(); + + if (lexer.token == Token.COMMA) { + lexer.reset(savePoint); + return expr; + } + SQLExpr rightExp = primary(); rightExp = relationalRest(rightExp); @@ -308,10 +315,11 @@ public class SQLExprParser extends SQLParser { long hash_lower = lexer.hash_lower; lexer.nextToken(); - if ("DATE".equalsIgnoreCase(ident) + if (hash_lower == FnvHash.Constants.DATE && lexer.token == Token.LITERAL_CHARS - && (JdbcConstants.ORACLE.equals(getDbType()) - || JdbcConstants.POSTGRESQL.equals(getDbType()))) { + && (JdbcConstants.ORACLE.equals(dbType) + || JdbcConstants.POSTGRESQL.equals(dbType) + || JdbcConstants.MYSQL.equals(dbType))) { String literal = lexer.stringVal(); lexer.nextToken(); @@ -450,6 +458,7 @@ public class SQLExprParser extends SQLParser { case DESC: case DO: case GROUP: + case MOD: sqlExpr = new SQLIdentifierExpr(lexer.stringVal()); lexer.nextToken(); break; @@ -1021,42 +1030,7 @@ public class SQLExprParser extends SQLParser { } if (lexer.token == Token.LPAREN) { - lexer.nextToken(); - - if (lexer.token == Token.DISTINCT) { - lexer.nextToken(); - - String aggreateMethodName = expr.toString() + "." + name; - SQLAggregateExpr aggregateExpr = new SQLAggregateExpr(aggreateMethodName, SQLAggregateOption.DISTINCT); - - if (lexer.token == Token.RPAREN) { - lexer.nextToken(); - } else { - if (lexer.token == Token.PLUS) { - aggregateExpr.getArguments().add(new SQLIdentifierExpr("+")); - lexer.nextToken(); - } else { - exprList(aggregateExpr.getArguments(), aggregateExpr); - } - accept(Token.RPAREN); - } - expr = aggregateExpr; - } else { - SQLMethodInvokeExpr methodInvokeExpr = new SQLMethodInvokeExpr(name); - methodInvokeExpr.setOwner(expr); - if (lexer.token == Token.RPAREN) { - lexer.nextToken(); - } else { - if (lexer.token == Token.PLUS) { - methodInvokeExpr.addParameter(new SQLIdentifierExpr("+")); - lexer.nextToken(); - } else { - exprList(methodInvokeExpr.getParameters(), methodInvokeExpr); - } - accept(Token.RPAREN); - } - expr = methodInvokeExpr; - } + expr = methodRest(expr, name); } else { expr = new SQLPropertyExpr(expr, name, hash_lower); } @@ -1066,6 +1040,46 @@ public class SQLExprParser extends SQLParser { return expr; } + private SQLExpr methodRest(SQLExpr expr, String name) { + lexer.nextToken(); + + if (lexer.token == Token.DISTINCT) { + lexer.nextToken(); + + String aggreateMethodName = expr.toString() + "." + name; + SQLAggregateExpr aggregateExpr = new SQLAggregateExpr(aggreateMethodName, SQLAggregateOption.DISTINCT); + + if (lexer.token == Token.RPAREN) { + lexer.nextToken(); + } else { + if (lexer.token == Token.PLUS) { + aggregateExpr.getArguments().add(new SQLIdentifierExpr("+")); + lexer.nextToken(); + } else { + exprList(aggregateExpr.getArguments(), aggregateExpr); + } + accept(Token.RPAREN); + } + expr = aggregateExpr; + } else { + SQLMethodInvokeExpr methodInvokeExpr = new SQLMethodInvokeExpr(name); + methodInvokeExpr.setOwner(expr); + if (lexer.token == Token.RPAREN) { + lexer.nextToken(); + } else { + if (lexer.token == Token.PLUS) { + methodInvokeExpr.addParameter(new SQLIdentifierExpr("+")); + lexer.nextToken(); + } else { + exprList(methodInvokeExpr.getParameters(), methodInvokeExpr); + } + accept(Token.RPAREN); + } + expr = methodInvokeExpr; + } + return expr; + } + public final SQLExpr groupComparisionRest(SQLExpr expr) { return expr; } @@ -2089,7 +2103,7 @@ public class SQLExprParser extends SQLParser { } SQLDataType dataType = new SQLDataTypeImpl(typeName); - + dataType.setDbType(dbType); return parseDataTypeRest(dataType); } @@ -2576,6 +2590,39 @@ public class SQLExprParser extends SQLParser { } token = lexer.token; + + if (token == Token.DOT) { + lexer.nextToken(); + String name; + long name_hash_lower; + + if (lexer.token == Token.STAR) { + name = "*"; + name_hash_lower = FnvHash.Constants.STAR; + } else { + name = lexer.stringVal(); + name_hash_lower = lexer.hash_lower(); + } + + lexer.nextTokenComma(); + + token = lexer.token; + if (token == Token.LPAREN) { + expr = methodRest(expr, name); + token = lexer.token; + } else { + if (name_hash_lower == FnvHash.Constants.NEXTVAL) { + expr = new SQLSequenceExpr((SQLIdentifierExpr) expr, SQLSequenceExpr.Function.NextVal); + } else if (name_hash_lower == FnvHash.Constants.CURRVAL) { + expr = new SQLSequenceExpr((SQLIdentifierExpr) expr, SQLSequenceExpr.Function.CurrVal); + } else if (name_hash_lower == FnvHash.Constants.PREVVAL) { + expr = new SQLSequenceExpr((SQLIdentifierExpr) expr, SQLSequenceExpr.Function.PrevVal); + } else { + expr = new SQLPropertyExpr(expr, name, name_hash_lower); + } + } + } + if (token == Token.COMMA) { return new SQLSelectItem(expr, null, connectByRoot); } @@ -2583,6 +2630,7 @@ public class SQLExprParser extends SQLParser { if (token == Token.AS) { lexer.nextToken(); String as = lexer.stringVal(); + lexer.nextTokenComma(); return new SQLSelectItem(expr, as, connectByRoot); } 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 99bbfc69e5..20b6bdb216 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLParser.java @@ -103,8 +103,8 @@ public class SQLParser { if (token == Token.AS) { lexer.nextToken(); - - alias = alias(); + alias = lexer.stringVal(); + lexer.nextToken(); if (alias != null) { while (lexer.token == Token.DOT) { @@ -142,6 +142,7 @@ public class SQLParser { case OUTER: case DO: case STORE: + case MOD: alias = lexer.stringVal(); lexer.nextToken(); break; diff --git a/src/main/java/com/alibaba/druid/sql/parser/SQLParserFeature.java b/src/main/java/com/alibaba/druid/sql/parser/SQLParserFeature.java index e5a544fd26..fc33d77784 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLParserFeature.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLParserFeature.java @@ -17,7 +17,9 @@ package com.alibaba.druid.sql.parser; public enum SQLParserFeature { KeepInsertValueClauseOriginalString, - EnableSQLBinaryOpExprGroup + EnableSQLBinaryOpExprGroup, + OptimizedForParameterized, + KeepComments ; private SQLParserFeature(){ diff --git a/src/main/java/com/alibaba/druid/sql/parser/SQLParserUtils.java b/src/main/java/com/alibaba/druid/sql/parser/SQLParserUtils.java index 0fcebd7f05..68015f91a2 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLParserUtils.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLParserUtils.java @@ -42,26 +42,37 @@ import com.alibaba.druid.util.JdbcUtils; public class SQLParserUtils { public static SQLStatementParser createSQLStatementParser(String sql, String dbType) { - boolean keepComments; + SQLParserFeature[] features; if (JdbcConstants.ODPS.equals(dbType) || JdbcConstants.MYSQL.equals(dbType)) { - keepComments = true; + features = new SQLParserFeature[] {SQLParserFeature.KeepComments}; } else { - keepComments = false; + features = new SQLParserFeature[] {}; } - return createSQLStatementParser(sql, dbType, keepComments); + return createSQLStatementParser(sql, dbType, features); } public static SQLStatementParser createSQLStatementParser(String sql, String dbType, boolean keepComments) { + SQLParserFeature[] features; + if (keepComments) { + features = new SQLParserFeature[] {SQLParserFeature.KeepComments}; + } else { + features = new SQLParserFeature[] {}; + } + + return createSQLStatementParser(sql, dbType, features); + } + + public static SQLStatementParser createSQLStatementParser(String sql, String dbType, SQLParserFeature... features) { if (JdbcUtils.ORACLE.equals(dbType) || JdbcUtils.ALI_ORACLE.equals(dbType)) { return new OracleStatementParser(sql); } if (JdbcUtils.MYSQL.equals(dbType)) { - return new MySqlStatementParser(sql, keepComments); + return new MySqlStatementParser(sql, features); } if (JdbcUtils.MARIADB.equals(dbType)) { - return new MySqlStatementParser(sql, keepComments); + return new MySqlStatementParser(sql, features); } if (JdbcUtils.POSTGRESQL.equals(dbType) 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 c2a8485ea6..372c7645a3 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java @@ -24,7 +24,6 @@ import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; import com.alibaba.druid.sql.ast.expr.SQLQueryExpr; import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr; import com.alibaba.druid.sql.ast.statement.*; -import com.alibaba.druid.sql.ast.statement.SQLCreateTriggerStatement.TriggerEvent; import com.alibaba.druid.sql.ast.statement.SQLCreateTriggerStatement.TriggerType; import com.alibaba.druid.sql.dialect.oracle.parser.OracleExprParser; import com.alibaba.druid.util.FnvHash; @@ -1814,7 +1813,7 @@ public class SQLStatementParser extends SQLParser { if (token == Token.TABLE || lexer.identifierEquals("GLOBAL")) { SQLCreateTableParser createTableParser = getSQLCreateTableParser(); - SQLCreateTableStatement stmt = createTableParser.parseCrateTable(false); + SQLCreateTableStatement stmt = createTableParser.parseCreateTable(false); if (comments != null) { stmt.addBeforeComment(comments); @@ -2230,7 +2229,7 @@ public class SQLStatementParser extends SQLParser { public SQLCreateTableStatement parseCreateTable() { // SQLCreateTableParser parser = new SQLCreateTableParser(this.lexer); - // return parser.parseCrateTable(); + // return parser.parseCreateTable(); throw new ParserException("TODO"); } diff --git a/src/main/java/com/alibaba/druid/sql/parser/SymbolTable.java b/src/main/java/com/alibaba/druid/sql/parser/SymbolTable.java index 78e247277c..f8abd64f63 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SymbolTable.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SymbolTable.java @@ -27,8 +27,6 @@ public class SymbolTable { public SymbolTable(int tableSize){ this.indexMask = tableSize - 1; this.entries = new Entry[tableSize]; - -// this.addSymbol("id", 0, 2, "id".hashCode()); } diff --git a/src/main/java/com/alibaba/druid/sql/repository/SchemaResolveVisitorFactory.java b/src/main/java/com/alibaba/druid/sql/repository/SchemaResolveVisitorFactory.java index 913d751d9d..c2dbccceee 100644 --- a/src/main/java/com/alibaba/druid/sql/repository/SchemaResolveVisitorFactory.java +++ b/src/main/java/com/alibaba/druid/sql/repository/SchemaResolveVisitorFactory.java @@ -21,6 +21,7 @@ import com.alibaba.druid.sql.ast.expr.*; import com.alibaba.druid.sql.ast.statement.*; import com.alibaba.druid.sql.dialect.db2.ast.stmt.DB2SelectQueryBlock; import com.alibaba.druid.sql.dialect.db2.visitor.DB2ASTVisitorAdapter; +import com.alibaba.druid.sql.dialect.mysql.ast.MysqlForeignKey; import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlCursorDeclareStatement; import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlDeclareStatement; import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlRepeatStatement; @@ -74,6 +75,11 @@ class SchemaResolveVisitorFactory { return true; } + public boolean visit(MysqlForeignKey x) { + resolve(this, x); + return false; + } + public boolean visit(SQLExprTableSource x) { resolve(this, x); return false; @@ -251,6 +257,11 @@ class SchemaResolveVisitorFactory { this.options = options; } + public boolean visit(SQLForeignKeyImpl x) { + resolve(this, x); + return false; + } + public boolean visit(SQLSelectStatement x) { resolve(this, x.getSelect()); return false; @@ -456,6 +467,11 @@ class SchemaResolveVisitorFactory { return false; } + public boolean visit(OracleForeignKey x) { + resolve(this, x); + return false; + } + public boolean visit(SQLIfStatement x) { resolve(this, x); return false; @@ -665,6 +681,11 @@ class SchemaResolveVisitorFactory { this.options = options; } + public boolean visit(SQLForeignKeyImpl x) { + resolve(this, x); + return false; + } + public boolean visit(SQLSelectStatement x) { resolve(this, x.getSelect()); return false; @@ -843,6 +864,11 @@ class SchemaResolveVisitorFactory { this.options = options; } + public boolean visit(SQLForeignKeyImpl x) { + resolve(this, x); + return false; + } + public boolean visit(SQLSelectStatement x) { resolve(this, x.getSelect()); return false; @@ -1032,6 +1058,11 @@ class SchemaResolveVisitorFactory { this.options = options; } + public boolean visit(SQLForeignKeyImpl x) { + resolve(this, x); + return false; + } + public boolean visit(SQLSelectStatement x) { resolve(this, x.getSelect()); return false; @@ -1193,6 +1224,11 @@ class SchemaResolveVisitorFactory { this.options = options; } + public boolean visit(SQLForeignKeyImpl x) { + resolve(this, x); + return false; + } + public boolean visit(SQLSelectStatement x) { resolve(this, x.getSelect()); return false; @@ -2408,6 +2444,62 @@ class SchemaResolveVisitorFactory { return false; } + static void resolve(SchemaResolveVisitor visitor, SQLForeignKeyConstraint x) { + SchemaRepository repository = visitor.getRepository(); + SQLObject parent = x.getParent(); + + if (parent instanceof SQLCreateTableStatement) { + SQLCreateTableStatement createTableStmt = (SQLCreateTableStatement) parent; + SQLTableSource table = createTableStmt.getTableSource(); + for (SQLName item : x.getReferencingColumns()) { + SQLIdentifierExpr columnName = (SQLIdentifierExpr) item; + columnName.setResolvedTableSource(table); + + SQLColumnDefinition column = createTableStmt.findColumn(columnName.nameHashCode64()); + if (column != null) { + columnName.setResolvedColumn(column); + } + } + } else if (parent instanceof SQLAlterTableAddConstraint) { + SQLAlterTableStatement stmt = (SQLAlterTableStatement) parent.getParent(); + SQLTableSource table = stmt.getTableSource(); + for (SQLName item : x.getReferencingColumns()) { + SQLIdentifierExpr columnName = (SQLIdentifierExpr) item; + columnName.setResolvedTableSource(table); + } + } + + + if (repository == null) { + return; + } + + SQLExprTableSource table = x.getReferencedTable(); + for (SQLName item : x.getReferencedColumns()) { + SQLIdentifierExpr columnName = (SQLIdentifierExpr) item; + columnName.setResolvedTableSource(table); + } + + SQLName tableName = table.getName(); + + SchemaObject tableObject = repository.findTable(tableName); + if (tableObject == null) { + return; + } + + SQLStatement tableStmt = tableObject.getStatement(); + if (tableStmt instanceof SQLCreateTableStatement) { + SQLCreateTableStatement refCreateTableStmt = (SQLCreateTableStatement) tableStmt; + for (SQLName item : x.getReferencedColumns()) { + SQLIdentifierExpr columnName = (SQLIdentifierExpr) item; + SQLColumnDefinition column = refCreateTableStmt.findColumn(columnName.nameHashCode64()); + if (column != null) { + columnName.setResolvedColumn(column); + } + } + } + } + // for performance static void resolveExpr(SchemaResolveVisitor visitor, SQLExpr x) { if (x == null) { @@ -2425,4 +2517,6 @@ class SchemaResolveVisitorFactory { x.accept(visitor); } + + } diff --git a/src/main/java/com/alibaba/druid/sql/visitor/ParameterizedOutputVisitorUtils.java b/src/main/java/com/alibaba/druid/sql/visitor/ParameterizedOutputVisitorUtils.java index c6ece5c3e8..44442a3849 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/ParameterizedOutputVisitorUtils.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/ParameterizedOutputVisitorUtils.java @@ -15,30 +15,23 @@ */ package com.alibaba.druid.sql.visitor; -import java.util.ArrayList; import java.util.List; import com.alibaba.druid.sql.ast.*; -import com.alibaba.druid.sql.ast.expr.*; -import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition; -import com.alibaba.druid.sql.ast.statement.SQLSelectOrderByItem; import com.alibaba.druid.sql.dialect.db2.visitor.DB2OutputVisitor; import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlOutputVisitor; import com.alibaba.druid.sql.dialect.oracle.visitor.OracleParameterizedOutputVisitor; import com.alibaba.druid.sql.dialect.phoenix.visitor.PhoenixOutputVisitor; import com.alibaba.druid.sql.dialect.postgresql.visitor.PGOutputVisitor; -import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerTop; import com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerOutputVisitor; -import com.alibaba.druid.sql.parser.SQLParserFeature; -import com.alibaba.druid.sql.parser.SQLParserUtils; -import com.alibaba.druid.sql.parser.SQLStatementParser; -import com.alibaba.druid.util.JdbcConstants; +import com.alibaba.druid.sql.parser.*; import com.alibaba.druid.util.JdbcUtils; public class ParameterizedOutputVisitorUtils { public static String parameterize(String sql, String dbType) { SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, dbType); parser.config(SQLParserFeature.EnableSQLBinaryOpExprGroup, true); + parser.config(SQLParserFeature.OptimizedForParameterized, true); List statementList = parser.parseStatementList(); if (statementList.size() == 0) { return sql; 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 bda6a668d9..00e07a0caf 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java @@ -834,6 +834,12 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet visit((SQLVariantRefExpr) x); } else if (clazz == SQLBinaryOpExprGroup.class) { visit((SQLBinaryOpExprGroup) x); + } else if (clazz == SQLCaseExpr.class) { + visit((SQLCaseExpr) x); + } else if (clazz == SQLInListExpr.class) { + visit((SQLInListExpr) x); + } else if (clazz == SQLNotExpr.class) { + visit((SQLNotExpr) x); } else { x.accept(this); } @@ -861,7 +867,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet if (elExpr instanceof SQLCaseExpr) { this.indentCount++; println(); - printExpr(elExpr); + visit((SQLCaseExpr) elExpr); this.indentCount--; } else { printExpr(elExpr); @@ -1831,14 +1837,22 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet } public boolean visit(SQLOrderBy x) { - if (x.getItems().size() > 0) { + List items = x.getItems(); + + if (items.size() > 0) { if (x.isSibings()) { print0(ucase ? "ORDER SIBLINGS BY " : "order siblings by "); } else { print0(ucase ? "ORDER BY " : "order by "); } - printAndAccept(x.getItems(), ", "); + for (int i = 0, size = items.size(); i < size; ++i) { + if (i != 0) { + print0(", "); + } + SQLSelectOrderByItem item = items.get(i); + visit(item); + } } return false; } @@ -1851,20 +1865,23 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet } else { printExpr(expr); } - if (x.getType() != null) { + + SQLOrderingSpecification type = x.getType(); + if (type != null) { print(' '); - SQLOrderingSpecification type = x.getType(); print0(ucase ? type.name : type.name_lcase); } - if (x.getCollate() != null) { + String collate = x.getCollate(); + if (collate != null) { print0(ucase ? " COLLATE " : " collate "); - print0(x.getCollate()); + print0(collate); } - if (x.getNullsOrderType() != null) { + SQLSelectOrderByItem.NullsOrderType nullsOrderType = x.getNullsOrderType(); + if (nullsOrderType != null) { print(' '); - print0(x.getNullsOrderType().toFormalString()); + print0(nullsOrderType.toFormalString()); } return false; @@ -4887,11 +4904,14 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet public boolean visit(SQLLimit x) { print0(ucase ? "LIMIT " : "limit "); - if (x.getOffset() != null) { - x.getOffset().accept(this); + SQLExpr offset = x.getOffset(); + if (offset != null) { + printExpr(offset); print0(", "); } - x.getRowCount().accept(this); + + SQLExpr rowCount = x.getRowCount(); + printExpr(rowCount); return false; } diff --git a/src/main/java/com/alibaba/druid/util/FnvHash.java b/src/main/java/com/alibaba/druid/util/FnvHash.java index 0503dff5b5..6201e12366 100644 --- a/src/main/java/com/alibaba/druid/util/FnvHash.java +++ b/src/main/java/com/alibaba/druid/util/FnvHash.java @@ -414,5 +414,10 @@ public final class FnvHash { long BEFORE = fnv1a_64_lower("BEFORE"); long AFTER = fnv1a_64_lower("AFTER"); long INSTEAD = fnv1a_64_lower("INSTEAD"); + + long DEFERRABLE = fnv1a_64_lower("DEFERRABLE"); + long AS = fnv1a_64_lower("AS"); + + long STAR = fnv1a_64_lower("*"); } } diff --git a/src/test/java/com/alibaba/druid/benckmark/sql/MySqlParameterizedBenchmark.java b/src/test/java/com/alibaba/druid/benckmark/sql/MySqlParameterizedBenchmark.java index 5d71b9cacf..e63d303463 100644 --- a/src/test/java/com/alibaba/druid/benckmark/sql/MySqlParameterizedBenchmark.java +++ b/src/test/java/com/alibaba/druid/benckmark/sql/MySqlParameterizedBenchmark.java @@ -6,8 +6,10 @@ import com.alibaba.druid.sql.dialect.mysql.parser.MySqlLexer; import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitorAdapter; import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlOutputVisitor; import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor; +import com.alibaba.druid.sql.parser.Lexer; import com.alibaba.druid.sql.parser.Token; import com.alibaba.druid.sql.repository.SchemaRepository; +import com.alibaba.druid.sql.visitor.ParameterizedOutputVisitorUtils; import com.alibaba.druid.sql.visitor.SQLASTOutputVisitor; import com.alibaba.druid.sql.visitor.SQLASTVisitor; import com.alibaba.druid.sql.visitor.SchemaStatVisitor; @@ -33,6 +35,20 @@ public class MySqlParameterizedBenchmark extends TestCase { + "`table_3966` AS `table_3966_11` SET `version` = `version` + 3, `gmt_modified` = NOW(), `optype` = ?, `feature` = ? " + "WHERE `sub_biz_order_id` = ? AND `biz_order_type` = ? AND `id` = ? AND `ti_id` = ? AND `optype` = ? AND `root_id` = ?"; String sql5= "SELECT id, item_id, rule_id, tag_id, ext , gmt_create, gmt_modified FROM wukong_preview_item_tag WHERE item_id = ? AND rule_id = ?"; + String sql6 = "/* 0ab23d3915048393791723851d05b8/9.1.19.1.10176122173.14//8b4757d2/ */SELECT pay_order_id, total_fee, title, alipay_seller_id, alipay_buyer_id, pay_status, out_pay_id, pay_time, end_time, gmt_create, gmt_modified, coupon_fee, actual_total_fee, discount_fee, adjust_fee, closer, point_fee, real_point_fee, obtain_point, refund_fee, confirm_paid_fee, cod_fee, from_group, attributes, attribute_cc, buyer_id, seller_id FROM tc_pay_order_3134 AS tc_pay_order WHERE pay_order_id = 52708022289887078"; + String sql7 = "SELECT batch.warehouse_code AS '仓库CODE', cage.delivery_order_id AS '运单ID', batch.batch_id AS '批次ID', batch.batch_gmt_create AS '批次创建时间', waybill.biz_order_id AS '订单ID'\n" + + "\t, package.box_id AS '包裹ID', cage.cage_id AS '笼车ID', batch.batch_name AS '批次名称', CASE WHEN batch.status = 1 THEN '初始化' ELSE '待揽收' END AS '状态', waybill.biz_order_remark AS '运单备注'\n" + + "\t, CASE WHEN SUBSTRING(batch.batch_name, instr(batch.batch_name, ' ') + 1, 2) + 0 >= 18 THEN '晚上送' ELSE '白天送' END AS '备注'\n" + + "FROM delivery_operator_batch batch, waybill, batch_box package, delivery_order_batch cage\n" + + "WHERE batch.batch_id = waybill.batch_id\n" + + "\tAND batch.batch_id = package.batch_id\n" + + "\tAND package.batch_id = cage.batch_id\n" + + "\tAND package.cage_id = cage.cage_id\n" + + "\tAND batch.status IN (1, 2)\n" + + "\tAND NOT (batch.batch_name IS NULL\n" + + "\tOR batch.batch_name = '')\n" + + "ORDER BY batch_gmt_create DESC\n" + + "LIMIT 0, 50"; for (int i = 0; i < 5; ++i) { // perf(sql); // 6740 6201 4752 4514 4391 4218 4127 4124 @@ -40,14 +56,23 @@ public class MySqlParameterizedBenchmark extends TestCase { // perf(sql3); // 15093 10392 10416 10154 10007 9126 8907 // perf(sql4); // 4429 4190 4023 3747 // perf(sql5); // 1917 +// perf(sql6); // 4193 // perf_parse(sql); // 4643 4377 4345 3801 3627 3228 2961 2959 // perf_parse(sql2); // 1918 1779 1666 1646 // perf_parse(sql3); // 9174 5875 5805 5536 5717 // perf_parse(sql4); // 2953 2502 - perf_parse(sql5); // 1339 +// perf_parse(sql5); // 1339 +// perf_parse(sql6); +// perf_parse(sql7); // 9831 8581 8552 -// perf_lexer(sql5); // 813 +// perf_lexer(sql4); // 2051 1802 +// perf_lexer(sql5); // 1125 1054 +// perf_lexer(sql6); // millis : 2811 + +// perfParameterized(sql6); // 4224 4083 + + perfFormat(sql7); // 14865 14132 13812 13714 12917 // perf_hashCode64(sql5); // 181 @@ -115,22 +140,16 @@ public class MySqlParameterizedBenchmark extends TestCase { public void perf_lexer(String sql) { long startMillis = System.currentTimeMillis(); for (int i = 0; i < 1000 * 1000; ++i) { - int literal_count = 0; - - MySqlLexer lexer = new MySqlLexer(sql); - - for (; ; ) { - lexer.nextToken(); - Token token = lexer.token(); - - if (token == Token.LITERAL_INT || token == Token.LITERAL_CHARS) { - literal_count++; - break; - } else if (token == Token.EOF || token == Token.ERROR) { - break; - } - } + Lexer.parameterize(sql, JdbcConstants.MYSQL); + } + long millis = System.currentTimeMillis() - startMillis; + System.out.println("millis : " + millis); + } + public void perfParameterized(String sql) { + long startMillis = System.currentTimeMillis(); + for (int i = 0; i < 1000 * 1000; ++i) { + ParameterizedOutputVisitorUtils.parameterize(sql, JdbcConstants.MYSQL); } long millis = System.currentTimeMillis() - startMillis; System.out.println("millis : " + millis); @@ -144,4 +163,13 @@ public class MySqlParameterizedBenchmark extends TestCase { long millis = System.currentTimeMillis() - startMillis; System.out.println("millis : " + millis); } + + public void perfFormat(String sql) { + long startMillis = System.currentTimeMillis(); + for (int i = 0; i < 1000 * 1000; ++i) { + SQLUtils.format(sql, JdbcConstants.MYSQL); + } + long millis = System.currentTimeMillis() - startMillis; + System.out.println("millis : " + millis); + } } diff --git a/src/test/java/com/alibaba/druid/bvt/proxy/filter/StatFilterTest3.java b/src/test/java/com/alibaba/druid/bvt/proxy/filter/StatFilterTest3.java index 9ce9f486a0..614acd1bbf 100644 --- a/src/test/java/com/alibaba/druid/bvt/proxy/filter/StatFilterTest3.java +++ b/src/test/java/com/alibaba/druid/bvt/proxy/filter/StatFilterTest3.java @@ -1,5 +1,6 @@ package com.alibaba.druid.bvt.proxy.filter; +import com.alibaba.druid.util.JdbcConstants; import junit.framework.TestCase; import org.junit.Assert; @@ -41,5 +42,22 @@ public class StatFilterTest3 extends TestCase { Assert.assertEquals("select 'x' limit 1" , filter.mergeSql("select 'x' limit 1")); } - + + + public void test_merge_pg() throws Exception { + StatFilter filter = new StatFilter(); + filter.setDbType(JdbcConstants.POSTGRESQL); + filter.setMergeSql(true); + + Assert.assertEquals(JdbcConstants.POSTGRESQL, filter.getDbType()); + + Assert.assertEquals("DROP TABLE IF EXISTS test_site_data_select_111;;\n" + + "CREATE TABLE test_site_data_select_111\n" + + "AS\n" + + "SELECT *\n" + + "FROM postman_trace_info_one\n" + + "WHERE lng > ?\n" + + "\tAND lat > ?\n" + + "\tAND site_id = ?;" , filter.mergeSql("drop table if exists test_site_data_select_111; create table test_site_data_select_111 AS select * from postman_trace_info_one where lng>0 and lat>0 and site_id='17814' ;", JdbcConstants.POSTGRESQL)); + } } diff --git a/src/test/java/com/alibaba/druid/bvt/sql/lexer/LexerParameterizedTest.java b/src/test/java/com/alibaba/druid/bvt/sql/lexer/LexerParameterizedTest.java new file mode 100644 index 0000000000..8e38d88f06 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/lexer/LexerParameterizedTest.java @@ -0,0 +1,13 @@ +package com.alibaba.druid.bvt.sql.lexer; + +import com.alibaba.druid.sql.parser.Lexer; +import com.alibaba.druid.util.JdbcConstants; +import junit.framework.TestCase; + +public class LexerParameterizedTest extends TestCase { + public void test_parameterized() throws Exception { + String sql = "/* 0ab23d3915048393791723851d05b8/9.1.19.1.10176122173.14//8b4757d2/ */SELECT pay_order_id, total_fee, title, alipay_seller_id, alipay_buyer_id, pay_status, out_pay_id, pay_time, end_time, gmt_create, gmt_modified, coupon_fee, actual_total_fee, discount_fee, adjust_fee, closer, point_fee, real_point_fee, obtain_point, refund_fee, confirm_paid_fee, cod_fee, from_group, attributes, attribute_cc, buyer_id, seller_id FROM tc_pay_order_3134 AS tc_pay_order WHERE pay_order_id = 52708022289887078"; + String target = Lexer.parameterize(sql, JdbcConstants.MYSQL); + //assertEquals("SELECT pay_order_id, total_fee, title, alipay_seller_id, alipay_buyer_id, pay_status, out_pay_id, pay_time, end_time, gmt_create, gmt_modified, coupon_fee, actual_total_fee, discount_fee, adjust_fee, closer, point_fee, real_point_fee, obtain_point, refund_fee, confirm_paid_fee, cod_fee, from_group, attributes, attribute_cc, buyer_id, seller_id FROM tc_pay_order_3134 AS tc_pay_order WHERE pay_order_id=?", target); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/alter/MySqlAlterTableTest_addFk.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/alter/MySqlAlterTableTest_addFk.java index c9a0ab5ae7..4bd8a39909 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/mysql/alter/MySqlAlterTableTest_addFk.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/alter/MySqlAlterTableTest_addFk.java @@ -40,8 +40,8 @@ public class MySqlAlterTableTest_addFk extends TestCase { SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.MYSQL); stmt.accept(visitor); -// System.out.println("Tables : " + visitor.getTables()); -// System.out.println("fields : " + visitor.getColumns()); + System.out.println("Tables : " + visitor.getTables()); + System.out.println("fields : " + visitor.getColumns()); // System.out.println("coditions : " + visitor.getConditions()); // System.out.println("orderBy : " + visitor.getOrderByColumns()); diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateViewTest2.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateViewTest2.java new file mode 100644 index 0000000000..7c83912850 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateViewTest2.java @@ -0,0 +1,81 @@ +/* + * Copyright 1999-2017 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.druid.bvt.sql.mysql.create; + +import com.alibaba.druid.sql.MysqlTest; +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.ast.statement.SQLCreateViewStatement; +import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser; +import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor; +import com.alibaba.druid.stat.TableStat; +import com.alibaba.druid.stat.TableStat.Column; +import org.junit.Assert; + +import java.util.List; + +public class MySqlCreateViewTest2 extends MysqlTest { + + public void test_0() throws Exception { + String sql = "create view revenue0 as \n" + + "select l_suppkey as supplier_no, sum(l_extendedprice * (1 - l_discount)) as total_revenue \n" + + "from lineitem \n" + + "where l_shipdate >= date '1993-01-01' and l_shipdate < date '1993-01-01' + interval '3' month \n" + + "group by l_suppkey"; + + MySqlStatementParser parser = new MySqlStatementParser(sql); + List statementList = parser.parseStatementList(); + SQLCreateViewStatement stmt = (SQLCreateViewStatement) statementList.get(0); +// print(statementList); + + Assert.assertEquals(1, statementList.size()); + + MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor(); + stmt.accept(visitor); + + assertEquals("CREATE VIEW revenue0\n" + + "AS\n" + + "SELECT l_suppkey AS supplier_no, SUM(l_extendedprice * (1 - l_discount)) AS total_revenue\n" + + "FROM lineitem\n" + + "WHERE l_shipdate >= DATE '1993-01-01'\n" + + "\tAND l_shipdate < DATE '1993-01-01' + INTERVAL '3' MONTH\n" + + "GROUP BY l_suppkey", // + SQLUtils.toMySqlString(stmt)); + + Assert.assertEquals("create view revenue0\n" + + "as\n" + + "select l_suppkey as supplier_no, sum(l_extendedprice * (1 - l_discount)) as total_revenue\n" + + "from lineitem\n" + + "where l_shipdate >= date '1993-01-01'\n" + + "\tand l_shipdate < date '1993-01-01' + interval '3' month\n" + + "group by l_suppkey", // + SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION)); + +// System.out.println("Tables : " + visitor.getTables()); +// System.out.println("fields : " + visitor.getColumns()); +// System.out.println("coditions : " + visitor.getConditions()); +// System.out.println("orderBy : " + visitor.getOrderByColumns()); + + Assert.assertEquals(1, visitor.getTables().size()); + Assert.assertEquals(4, visitor.getColumns().size()); + Assert.assertEquals(2, visitor.getConditions().size()); + + Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("lineitem"))); + + Assert.assertTrue(visitor.getColumns().contains(new Column("lineitem", "l_shipdate"))); + Assert.assertTrue(visitor.getColumns().contains(new Column("lineitem", "l_suppkey"))); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/oracle/create/OracleCreateTableTest76.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/create/OracleCreateTableTest76.java new file mode 100644 index 0000000000..a143d4e849 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/create/OracleCreateTableTest76.java @@ -0,0 +1,122 @@ +/* + * Copyright 1999-2017 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.druid.bvt.sql.oracle.create; + +import com.alibaba.druid.sql.OracleTest; +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.util.JdbcConstants; + +import java.util.List; + +public class OracleCreateTableTest76 extends OracleTest { + + public void test_types() throws Exception { + String sql = // + " CREATE TABLE \"TCC_CPR\".\"KTV_CONFIG_SCALE_DETAILS_TEMP\" \n" + + " (\t\"ID\" NUMBER(10,0) NOT NULL ENABLE, \n" + + "\t\"CONTRACT_HEAD_ID\" NUMBER(10,0) NOT NULL ENABLE, \n" + + "\t\"PRODUCT_BIG_ID\" NUMBER(10,0), \n" + + "\t\"PRODUCT_ID\" NUMBER(10,0), \n" + + "\t\"SCALE\" NUMBER(10,2), \n" + + "\t\"ENABLED_FLAG\" CHAR(1), \n" + + "\t\"CREATED_BY\" NUMBER(10,0), \n" + + "\t\"CREATION_DATE\" TIMESTAMP (6), \n" + + "\t\"LAST_UPDATED_BY\" NUMBER(10,0), \n" + + "\t\"LAST_UPDATE_DATE\" TIMESTAMP (6), \n" + + "\t\"CON_TYPE\" VARCHAR2(2), \n" + + "\t CONSTRAINT \"P_ID\" PRIMARY KEY (\"ID\") DEFERRABLE INITIALLY DEFERRED\n" + + " USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS \n" + + " STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645\n" + + " PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)\n" + + " TABLESPACE \"TCC_CPR_TSP\" ENABLE\n" + + " ) PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING\n" + + " STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645\n" + + " PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)\n" + + " TABLESPACE \"TCC_CPR_TSP\" "; + + List statementList = SQLUtils.parseStatements(sql, JdbcConstants.ORACLE); + SQLStatement stmt = statementList.get(0); + print(statementList); + + assertEquals(1, statementList.size()); +// + assertEquals("CREATE TABLE \"TCC_CPR\".\"KTV_CONFIG_SCALE_DETAILS_TEMP\" (\n" + + "\t\"ID\" NUMBER(10, 0) NOT NULL ENABLE,\n" + + "\t\"CONTRACT_HEAD_ID\" NUMBER(10, 0) NOT NULL ENABLE,\n" + + "\t\"PRODUCT_BIG_ID\" NUMBER(10, 0),\n" + + "\t\"PRODUCT_ID\" NUMBER(10, 0),\n" + + "\t\"SCALE\" NUMBER(10, 2),\n" + + "\t\"ENABLED_FLAG\" CHAR(1),\n" + + "\t\"CREATED_BY\" NUMBER(10, 0),\n" + + "\t\"CREATION_DATE\" TIMESTAMP(6),\n" + + "\t\"LAST_UPDATED_BY\" NUMBER(10, 0),\n" + + "\t\"LAST_UPDATE_DATE\" TIMESTAMP(6),\n" + + "\t\"CON_TYPE\" VARCHAR2(2),\n" + + "\tCONSTRAINT \"P_ID\" PRIMARY KEY (\"ID\")\n" + + "\t\tUSING INDEX\n" + + "\t\tPCTFREE 10\n" + + "\t\tINITRANS 2\n" + + "\t\tMAXTRANS 255\n" + + "\t\tTABLESPACE \"TCC_CPR_TSP\"\n" + + "\t\tSTORAGE (\n" + + "\t\t\tINITIAL 65536\n" + + "\t\t\tNEXT 1048576\n" + + "\t\t\tMINEXTENTS 1\n" + + "\t\t\tMAXEXTENTS 2147483645\n" + + "\t\t\tPCTINCREASE 0\n" + + "\t\t\tFREELISTS 1\n" + + "\t\t\tFREELIST GROUPS 1\n" + + "\t\t\tBUFFER_POOL DEFAULT\n" + + "\t\t)\n" + + "\t\tCOMPUTE STATISTICS\n" + + "\t\tENABLE INITIALLY DEFERRED DEFERRABLE\n" + + ")\n" + + "PCTFREE 10\n" + + "PCTUSED 40\n" + + "INITRANS 1\n" + + "MAXTRANS 255\n" + + "NOCOMPRESS\n" + + "LOGGING\n" + + "TABLESPACE \"TCC_CPR_TSP\"\n" + + "STORAGE (\n" + + "\tINITIAL 65536\n" + + "\tNEXT 1048576\n" + + "\tMINEXTENTS 1\n" + + "\tMAXEXTENTS 2147483645\n" + + "\tPCTINCREASE 0\n" + + "\tFREELISTS 1\n" + + "\tFREELIST GROUPS 1\n" + + "\tBUFFER_POOL DEFAULT\n" + + ")",// + SQLUtils.toSQLString(stmt, JdbcConstants.ORACLE)); +// +// SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.ORACLE); +// stmt.accept(visitor); +// +// System.out.println("Tables : " + visitor.getTables()); +// System.out.println("fields : " + visitor.getColumns()); +// System.out.println("coditions : " + visitor.getConditions()); +// System.out.println("relationships : " + visitor.getRelationships()); +// System.out.println("orderBy : " + visitor.getOrderByColumns()); +// +// assertEquals(1, visitor.getTables().size()); +// +// assertEquals(3, visitor.getColumns().size()); +// +// assertTrue(visitor.getColumns().contains(new TableStat.Column("JWGZPT.A", "XM"))); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/oracle/create/OracleCreateTableTest77.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/create/OracleCreateTableTest77.java new file mode 100644 index 0000000000..0086ded11e --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/create/OracleCreateTableTest77.java @@ -0,0 +1,184 @@ +/* + * Copyright 1999-2017 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.druid.bvt.sql.oracle.create; + +import com.alibaba.druid.sql.OracleTest; +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.util.JdbcConstants; + +import java.util.List; + +public class OracleCreateTableTest77 extends OracleTest { + + public void test_types() throws Exception { + String sql = // + " CREATE OR REPLACE FORCE VIEW \"TPC_CPR\".\"TPC_CPR_ITEM_PRICE_V\" (\"CONTRACT_HEADER_ID\", \"CONTRACT_NUMBER\", \"CONTRACT_PRODUCT_ID\", \"PROD_ID\", \"PROD_DES\", \"MI\", \"CONTRACT_DEVICE_ID\", \"DEV_ID\", \"DEV_DES\", \"SITE_ID\", \"SITE_QUANTITY\", \"SITE_DES\", \"CONTRACT_MODULE_ID\", \"MOD_ID\", \"MOD_DES\", \"MODULE_QUANTITY\", \"CONTRACT_ITEM_ID\", \"ITEM_ID\", \"ITEM_DES\", \"ITEM_TYPE\", \"ITEM_QUANTITY\", \"HARD_PARAM\", \"SOFT_PARAM\", \"MAKE_PARAM\", \"RISK_PARAM\", \"SOFT_COST_PARAM\", \"PROD_MANAGER\", \"COST_PRICE04\", \"CONFIRM_ITEM_PARAM\", \"CONFIRM_FLAG04\", \"COST_PRICE\", \"COST_PRICE_PARAMETER\", \"OLD_COST\", \"LIST_PRICE\", \"ITEM_CODE\", \"CONFIRM_COST_PRICE04\", \"PROD_ATTRIBUTE_ID\", \"ITEM_CHIP\") AS \n" + + " select Mod.CONTRACT_HEADER_ID,'',Mod.CONTRACT_PRODUCT_ID,\n" + + "Mod.PROD_ID , Mod.PROD_DES,Mod.MI, Mod.CONTRACT_DEVICE_ID, Mod.DEV_ID,Mod.DEV_DES,\n" + + "Mod.SITE_ID , Mod.SITE_QUANTITY, Mod.SITE_DES, Mod.CONTRACT_MODULE_ID,\n" + + "Mod.MOD_ID, Mod.MOD_DES, Mod.module_quantity, I.CONTRACT_ITEM_ID, I.INVENTORY_ITEM_ID\n" + + "ITEM_ID, I.DESCRIPTION ITEM_DES,I.ATTRIBUTE1 ITEM_TYPE , I.item_quantity,\n" + + "Mod.hard_param,Mod.soft_param, Mod.make_param, Mod.risk_param, Mod.soft_cost_param,\n" + + "Mod.prod_manager, I.COST_PRICE04, I.CONFIRM_ITEM_PARAM, I.CONFIRM_FLAG04,\n" + + "I.cost_price, I.COST_PRICE_PARAMETER,I.OLD_COST,I.LIST_PRICE,I.ITEM_CODE,\n" + + "I.CONFIRM_COST_PRICE04,I.PROD_ATTRIBUTE_ID,I.ITEM_CHIP from ( SELECT p.CONTRACT_HEADER_ID,'',P.CONTRACT_PRODUCT_ID,\n" + + "P.INVENTORY_ITEM_ID PROD_ID,P.DESCRIPTION PROD_DES,P.MI, D.CONTRACT_DEVICE_ID,\n" + + "D.INVENTORY_ITEM_ID DEV_ID,D.DESCRIPTION DEV_DES, S.SITE_ID, S.SITE_QUANTITY,\n" + + "( S.SITE_ADDRESS||S.SECOND_LEVEL|| S.THIRD_LEVEL|| S.FOURTH_LEVEL) SITE_DES,\n" + + "M.CONTRACT_MODULE_ID, M.INVENTORY_ITEM_ID MOD_ID , M.DESCRIPTION MOD_DES,\n" + + "M.module_quantity, p.hard_param, p.soft_param, p.make_param,p.risk_param,\n" + + "p.soft_cost_param, p.prod_manager FROM ( SELECT PROD.*,SYS_ITEM1.ATTRIBUTE2\n" + + "MI,SYS_ITEM1.DESCRIPTION, SYS_ITEM1.ATTRIBUTE3 PROD_MANAGER , SYS_ITEM1.HARD_PARAM,\n" + + "SYS_ITEM1.SOFT_PARAM,SYS_ITEM1.MAKE_PARAM,SYS_ITEM1.RISK_PARAM, SYS_ITEM1.SOFT_COST_PARAM\n" + + "FROM TPC_CPR.TPC_CPR_PRODUCTS PROD, TPC_CPR.TPC_CPR_SYSTEM_ITEMS SYS_ITEM1\n" + + "WHERE PROD.INVENTORY_ITEM_ID = SYS_ITEM1.INVENTORY_ITEM_ID AND SYS_ITEM1.ITEM_TYPE\n" + + "= 'CP' AND PROD.ENABLED_FLAG = 'Y') P, ( SELECT DEV.*,SYS_ITEM2.DESCRIPTION\n" + + "FROM TPC_CPR.TPC_CPR_DEVICES DEV,TPC_CPR.TPC_CPR_SYSTEM_ITEMS SYS_ITEM2\n" + + "WHERE DEV.INVENTORY_ITEM_ID = SYS_ITEM2.INVENTORY_ITEM_ID AND SYS_ITEM2.ITEM_TYPE\n" + + "= 'SB' AND DEV.ENABLED_FLAG = 'Y') D, ( SELECT SITE.* FROM TPC_CPR.TPC_CPR_SITES\n" + + "SITE WHERE SITE.ENABLED_FLAG = 'Y') S, ( SELECT MOD.*,SYS_ITEM3.DESCRIPTION\n" + + "FROM TPC_CPR.TPC_CPR_MODULES MOD,TPC_CPR.TPC_CPR_SYSTEM_ITEMS SYS_ITEM3\n" + + "WHERE MOD.INVENTORY_ITEM_ID = SYS_ITEM3.INVENTORY_ITEM_ID AND SYS_ITEM3.ITEM_TYPE\n" + + "= 'MK' AND MOD.ENABLED_FLAG = 'Y') M WHERE P.CONTRACT_PRODUCT_ID = D.CONTRACT_PRODUCT_ID\n" + + "AND D.CONTRACT_DEVICE_ID = S.CONTRACT_DEVICE_ID AND S.SITE_ID = M.SITE_ID\n" + + ") Mod LEFT JOIN ( ( SELECT ITEM.CONTRACT_MODULE_ID CONTRACT_MODULE_ID,\n" + + "ITEM.INVENTORY_ITEM_ID, ITEM.CONTRACT_ITEM_ID, SYS_ITEM.DESCRIPTION, SYS_ITEM.ATTRIBUTE1,\n" + + "ITEM.ITEM_QUANTITY, SYS_ITEM.CATALOG_SOFTWARE_FLAG, P.COST_PRICE, P.COST_PRICE_PARAMETER,\n" + + "P.CONFIRM_FLAG,P.COST_PRICE04, P.CONFIRM_ITEM_PARAM, P.CONFIRM_FLAG04,\n" + + "P.OLD_COST,P.LIST_PRICE, SYS_ITEM.ITEM_CODE, P.CONFIRM_COST_PRICE04, SYS_ITEM.ITEM_ID\n" + + "PROD_ATTRIBUTE_ID,SYS_ITEM.ITEM_CHIP FROM TPC_CPR.TPC_CPR_ITEMS ITEM, TPC_CPR.TPC_CPR_SYSTEM_ITEMS\n" + + "SYS_ITEM, TPC_CPR.TPC_CPR_PRICE P where ITEM.INVENTORY_ITEM_ID = P.INVENTORY_ITEM_ID\n" + + "AND ITEM.INVENTORY_ITEM_ID = SYS_ITEM.INVENTORY_ITEM_ID AND ITEM.ENABLED_FLAG\n" + + "= 'Y' ) ) I ON Mod.CONTRACT_MODULE_ID = I.CONTRACT_MODULE_ID "; + + List statementList = SQLUtils.parseStatements(sql, JdbcConstants.ORACLE); + SQLStatement stmt = statementList.get(0); + print(statementList); + + assertEquals(1, statementList.size()); +// + assertEquals("CREATE OR REPLACE VIEW \"TPC_CPR\".\"TPC_CPR_ITEM_PRICE_V\" (\n" + + "\t\"CONTRACT_HEADER_ID\", \n" + + "\t\"CONTRACT_NUMBER\", \n" + + "\t\"CONTRACT_PRODUCT_ID\", \n" + + "\t\"PROD_ID\", \n" + + "\t\"PROD_DES\", \n" + + "\t\"MI\", \n" + + "\t\"CONTRACT_DEVICE_ID\", \n" + + "\t\"DEV_ID\", \n" + + "\t\"DEV_DES\", \n" + + "\t\"SITE_ID\", \n" + + "\t\"SITE_QUANTITY\", \n" + + "\t\"SITE_DES\", \n" + + "\t\"CONTRACT_MODULE_ID\", \n" + + "\t\"MOD_ID\", \n" + + "\t\"MOD_DES\", \n" + + "\t\"MODULE_QUANTITY\", \n" + + "\t\"CONTRACT_ITEM_ID\", \n" + + "\t\"ITEM_ID\", \n" + + "\t\"ITEM_DES\", \n" + + "\t\"ITEM_TYPE\", \n" + + "\t\"ITEM_QUANTITY\", \n" + + "\t\"HARD_PARAM\", \n" + + "\t\"SOFT_PARAM\", \n" + + "\t\"MAKE_PARAM\", \n" + + "\t\"RISK_PARAM\", \n" + + "\t\"SOFT_COST_PARAM\", \n" + + "\t\"PROD_MANAGER\", \n" + + "\t\"COST_PRICE04\", \n" + + "\t\"CONFIRM_ITEM_PARAM\", \n" + + "\t\"CONFIRM_FLAG04\", \n" + + "\t\"COST_PRICE\", \n" + + "\t\"COST_PRICE_PARAMETER\", \n" + + "\t\"OLD_COST\", \n" + + "\t\"LIST_PRICE\", \n" + + "\t\"ITEM_CODE\", \n" + + "\t\"CONFIRM_COST_PRICE04\", \n" + + "\t\"PROD_ATTRIBUTE_ID\", \n" + + "\t\"ITEM_CHIP\"\n" + + ")\n" + + "AS\n" + + "SELECT Mod.CONTRACT_HEADER_ID, NULL, Mod.CONTRACT_PRODUCT_ID, Mod.PROD_ID, Mod.PROD_DES\n" + + "\t, Mod.MI, Mod.CONTRACT_DEVICE_ID, Mod.DEV_ID, Mod.DEV_DES, Mod.SITE_ID\n" + + "\t, Mod.SITE_QUANTITY, Mod.SITE_DES, Mod.CONTRACT_MODULE_ID, Mod.MOD_ID, Mod.MOD_DES\n" + + "\t, Mod.module_quantity, I.CONTRACT_ITEM_ID, I.INVENTORY_ITEM_ID AS ITEM_ID, I.DESCRIPTION AS ITEM_DES, I.ATTRIBUTE1 AS ITEM_TYPE\n" + + "\t, I.item_quantity, Mod.hard_param, Mod.soft_param, Mod.make_param, Mod.risk_param\n" + + "\t, Mod.soft_cost_param, Mod.prod_manager, I.COST_PRICE04, I.CONFIRM_ITEM_PARAM, I.CONFIRM_FLAG04\n" + + "\t, I.cost_price, I.COST_PRICE_PARAMETER, I.OLD_COST, I.LIST_PRICE, I.ITEM_CODE\n" + + "\t, I.CONFIRM_COST_PRICE04, I.PROD_ATTRIBUTE_ID, I.ITEM_CHIP\n" + + "FROM (\n" + + "\tSELECT p.CONTRACT_HEADER_ID, NULL, P.CONTRACT_PRODUCT_ID, P.INVENTORY_ITEM_ID AS PROD_ID, P.DESCRIPTION AS PROD_DES\n" + + "\t\t, P.MI, D.CONTRACT_DEVICE_ID, D.INVENTORY_ITEM_ID AS DEV_ID, D.DESCRIPTION AS DEV_DES, S.SITE_ID\n" + + "\t\t, S.SITE_QUANTITY, S.SITE_ADDRESS || S.SECOND_LEVEL || S.THIRD_LEVEL || S.FOURTH_LEVEL AS SITE_DES\n" + + "\t\t, M.CONTRACT_MODULE_ID, M.INVENTORY_ITEM_ID AS MOD_ID, M.DESCRIPTION AS MOD_DES, M.module_quantity, p.hard_param\n" + + "\t\t, p.soft_param, p.make_param, p.risk_param, p.soft_cost_param, p.prod_manager\n" + + "\tFROM (\n" + + "\t\tSELECT PROD.*, SYS_ITEM1.ATTRIBUTE2 AS MI, SYS_ITEM1.DESCRIPTION, SYS_ITEM1.ATTRIBUTE3 AS PROD_MANAGER, SYS_ITEM1.HARD_PARAM\n" + + "\t\t\t, SYS_ITEM1.SOFT_PARAM, SYS_ITEM1.MAKE_PARAM, SYS_ITEM1.RISK_PARAM, SYS_ITEM1.SOFT_COST_PARAM\n" + + "\t\tFROM TPC_CPR.TPC_CPR_PRODUCTS PROD, TPC_CPR.TPC_CPR_SYSTEM_ITEMS SYS_ITEM1\n" + + "\t\tWHERE PROD.INVENTORY_ITEM_ID = SYS_ITEM1.INVENTORY_ITEM_ID\n" + + "\t\t\tAND SYS_ITEM1.ITEM_TYPE = 'CP'\n" + + "\t\t\tAND PROD.ENABLED_FLAG = 'Y'\n" + + "\t) P, (\n" + + "\t\tSELECT DEV.*, SYS_ITEM2.DESCRIPTION\n" + + "\t\tFROM TPC_CPR.TPC_CPR_DEVICES DEV, TPC_CPR.TPC_CPR_SYSTEM_ITEMS SYS_ITEM2\n" + + "\t\tWHERE DEV.INVENTORY_ITEM_ID = SYS_ITEM2.INVENTORY_ITEM_ID\n" + + "\t\t\tAND SYS_ITEM2.ITEM_TYPE = 'SB'\n" + + "\t\t\tAND DEV.ENABLED_FLAG = 'Y'\n" + + "\t) D, (\n" + + "\t\tSELECT SITE.*\n" + + "\t\tFROM TPC_CPR.TPC_CPR_SITES SITE\n" + + "\t\tWHERE SITE.ENABLED_FLAG = 'Y'\n" + + "\t) S, (\n" + + "\t\tSELECT MOD.*, SYS_ITEM3.DESCRIPTION\n" + + "\t\tFROM TPC_CPR.TPC_CPR_MODULES MOD, TPC_CPR.TPC_CPR_SYSTEM_ITEMS SYS_ITEM3\n" + + "\t\tWHERE MOD.INVENTORY_ITEM_ID = SYS_ITEM3.INVENTORY_ITEM_ID\n" + + "\t\t\tAND SYS_ITEM3.ITEM_TYPE = 'MK'\n" + + "\t\t\tAND MOD.ENABLED_FLAG = 'Y'\n" + + "\t) M\n" + + "\tWHERE P.CONTRACT_PRODUCT_ID = D.CONTRACT_PRODUCT_ID\n" + + "\t\tAND D.CONTRACT_DEVICE_ID = S.CONTRACT_DEVICE_ID\n" + + "\t\tAND S.SITE_ID = M.SITE_ID\n" + + ") Mod\n" + + "\tLEFT JOIN (\n" + + "\t\tSELECT ITEM.CONTRACT_MODULE_ID AS CONTRACT_MODULE_ID, ITEM.INVENTORY_ITEM_ID, ITEM.CONTRACT_ITEM_ID, SYS_ITEM.DESCRIPTION, SYS_ITEM.ATTRIBUTE1\n" + + "\t\t\t, ITEM.ITEM_QUANTITY, SYS_ITEM.CATALOG_SOFTWARE_FLAG, P.COST_PRICE, P.COST_PRICE_PARAMETER, P.CONFIRM_FLAG\n" + + "\t\t\t, P.COST_PRICE04, P.CONFIRM_ITEM_PARAM, P.CONFIRM_FLAG04, P.OLD_COST, P.LIST_PRICE\n" + + "\t\t\t, SYS_ITEM.ITEM_CODE, P.CONFIRM_COST_PRICE04, SYS_ITEM.ITEM_ID AS PROD_ATTRIBUTE_ID, SYS_ITEM.ITEM_CHIP\n" + + "\t\tFROM TPC_CPR.TPC_CPR_ITEMS ITEM, TPC_CPR.TPC_CPR_SYSTEM_ITEMS SYS_ITEM, TPC_CPR.TPC_CPR_PRICE P\n" + + "\t\tWHERE ITEM.INVENTORY_ITEM_ID = P.INVENTORY_ITEM_ID\n" + + "\t\t\tAND ITEM.INVENTORY_ITEM_ID = SYS_ITEM.INVENTORY_ITEM_ID\n" + + "\t\t\tAND ITEM.ENABLED_FLAG = 'Y'\n" + + "\t) I ON Mod.CONTRACT_MODULE_ID = I.CONTRACT_MODULE_ID ",// + SQLUtils.toSQLString(stmt, JdbcConstants.ORACLE)); +// +// SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.ORACLE); +// stmt.accept(visitor); +// +// System.out.println("Tables : " + visitor.getTables()); +// System.out.println("fields : " + visitor.getColumns()); +// System.out.println("coditions : " + visitor.getConditions()); +// System.out.println("relationships : " + visitor.getRelationships()); +// System.out.println("orderBy : " + visitor.getOrderByColumns()); +// +// assertEquals(1, visitor.getTables().size()); +// +// assertEquals(3, visitor.getColumns().size()); +// +// assertTrue(visitor.getColumns().contains(new TableStat.Column("JWGZPT.A", "XM"))); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/oracle/create/OracleCreateTableTest78.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/create/OracleCreateTableTest78.java new file mode 100644 index 0000000000..96f41c0c21 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/create/OracleCreateTableTest78.java @@ -0,0 +1,165 @@ +/* + * Copyright 1999-2017 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.druid.bvt.sql.oracle.create; + +import com.alibaba.druid.sql.OracleTest; +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.util.JdbcConstants; + +import java.util.List; + +public class OracleCreateTableTest78 extends OracleTest { + + public void test_types() throws Exception { + String sql = // + "CREATE OR REPLACE FORCE VIEW \"TCP_EPM\".\"EPM_VW_CONTRACT\" (\"NID\", \"SCONTRACTNO\", \"SCONTRACTNAME\", \"NOFFICEID\", \"SOFFICENAME\", \"NSALEDEPTID\", \"SSALEDEPTNAME\", \"NPRODDEPTID\", \"SPRODDEPTNAME\", \"NCUSTOMERID\", \"SCUSTOMERNAME\", \"SSERVICEPROVIDERID\", \"SSERVICEPROVIDERNAME\", \"NMAINPRODUCTID\", \"SMAINPRODUCTNAME\", \"SCONTRACTTYPE\", \"SCONTRACTTYPETEXT\", \"SCONTRACTKIND\", \"SCONTRACTKINDTEXT\", \"SISFIRSTCHECKED\", \"SISLASTCHECKED\", \"SISOUTSOURCE\", \"SISRECONSIGN\", \"DGUARANTEE\", \"DCREATEDTIME\", \"NERPCONTRACTID\", \"NSTATE\", \"DFIRSTCHECKTIME\", \"DLASTCHECKTIME\", \"DPLANFIRSTCHECKTIME\", \"DPLANLASTCHECKTIME\") AS \n" + + " select\n" + + " EPM_TBL_CONTRACT.OID as nID,\n" + + " EPM_TBL_CONTRACT.CONTRACTNO as sContractNo,\n" + + " EPM_TBL_CONTRACT.CONTRACTNAME as sCONTRACTNAME,\n" + + " EPM_TBL_CONTRACT.ENGDUTYDEP as nOfficeID,\n" + + " TCP_FND_DEPT.DEPT_NAME as sOfficeName,\n" + + " TCP_EPM.EPM_TB_CONTRACT_EX.nSaleDeptID as nSaleDeptID,\n" + + " TCP_FND_DEPT1.DEPT_NAME as sSaleDeptName,\n" + + " TCP_EPM.EPM_TB_CONTRACT_EX.nProdDeptID as nProdDeptID,\n" + + " TCP_FND_DEPT2.DEPT_NAME as sProdDeptName,\n" + + " EPM_TBL_CONTRACT.CUSTOMID as nCustomerID,\n" + + " TCP_CUST_CUSTOMER.Name as sCustomerName,\n" + + " TCP_EPM.EPM_TB_CONTRACT_EX.sServiceProviderID as sServiceProviderID,\n" + + " TCP_CUST_ENUM.DESC_ as sServiceProviderName,\n" + + " EPM_TBL_CONTRACT.MASTERPRODUCT as nMainProductID,\n" + + " TCP_FND_PRODUCT.CN_NAME as sMainProductName,\n" + + " EPM_TBL_CONTRACT.CONTRACTTYPE as sContractType,\n" + + " TCP_FND_LOOKUP_CODE.MEANING as sContractTypeText,\n" + + " EPM_TBL_CONTRACT.Contrctkind as sContractKind,\n" + + " TCP_FND_LOOKUP_CODE1.MEANING as sContractKindText,\n" + + " TCP_EPM.EPM_TB_CONTRACT_EX.sIsFirstChecked as sIsFirstChecked,\n" + + " TCP_EPM.EPM_TB_CONTRACT_EX.sIsLastChecked as sIsLastChecked,\n" + + " case when (select count(*) from EPM_TBL_ENGINE_PROJECT,EPM_TBL_SUBCONTRACT_DISPATCH where EPM_TBL_ENGINE_PROJECT.CONTRACTID=EPM_TBL_CONTRACT.Oid and EPM_TBL_ENGINE_PROJECT.OID=EPM_TBL_SUBCONTRACT_DISPATCH.ENGINEID) > 0 then '/' else '&' end as sIsOutSource,\n" + + " case when (select count(*) from TCP_EPM.EPM_TBL_RECONSIGN_RECONSIGN where TCP_EPM.EPM_TBL_RECONSIGN_RECONSIGN.CONTRACTID=EPM_TBL_CONTRACT.Oid) > 0 then '/' else '&' end as sIsReconsign,\n" + + " TCP_EPM.EPM_TB_CONTRACT_EX.dGuarantee as dGuarantee,\n" + + " TCP_EPM.EPM_TB_CONTRACT_EX.dCreatedTime as dCreatedTime,\n" + + " TCP_EPM.EPM_TB_CONTRACT_EX.nERPContractID as nERPContractID,\n" + + " TCP_EPM.EPM_TB_CONTRACT_EX.nState as nState,\n" + + " TCP_EPM.EPM_TB_CONTRACT_EX.DFIRSTCHECKTIME as DFIRSTCHECKTIME,\n" + + " TCP_EPM.EPM_TB_CONTRACT_EX.DLASTCHECKTIME as DLASTCHECKTIME,\n" + + " TCP_EPM.EPM_TB_CONTRACT_EX.DPLANFIRSTCHECKTIME as DPLANFIRSTCHECKTIME,\n" + + " TCP_EPM.EPM_TB_CONTRACT_EX.DPLANLASTCHECKTIME as DPLANLASTCHECKTIME\n" + + " from\n" + + " ((((((((( TCP_EPM.Epm_Tbl_Contract left join TCP_FND.TCP_FND_DEPT on TCP_FND_DEPT.Dept_Id=Epm_Tbl_Contract.Engdutydep )\n" + + " left join TCP_EPM.EPM_TB_CONTRACT_EX on EPM_TB_CONTRACT_EX.NCONTRACTID=Epm_Tbl_Contract.Oid)\n" + + " left join TCP_FND.TCP_FND_DEPT TCP_FND_DEPT1 on TCP_FND_DEPT1.Dept_Id=EPM_TB_CONTRACT_EX.nSaleDeptID)\n" + + " left join TCP_FND.TCP_FND_DEPT TCP_FND_DEPT2 on TCP_FND_DEPT2.Dept_Id=EPM_TB_CONTRACT_EX.nProdDeptID)\n" + + " left join TCP_CUST.TCP_CUST_CUSTOMER on TCP_CUST_CUSTOMER.ID=EPM_TBL_CONTRACT.Customid)\n" + + " left join TCP_CUST.TCP_CUST_ENUM on TCP_CUST_ENUM.Codeid=EPM_TB_CONTRACT_EX.sServiceProviderID)\n" + + " left join TCP_FND.TCP_FND_PRODUCT on TCP_FND_PRODUCT.INVENTORY_ITEM_ID=EPM_TBL_CONTRACT.MASTERPRODUCT)\n" + + " left join TCP_FND.TCP_FND_LOOKUP_CODE on TCP_FND_LOOKUP_CODE.LOOKUP_TYPE='CONTRACT_TYPE' and TCP_FND_LOOKUP_CODE.LOOKUP_CODE=EPM_TBL_CONTRACT.CONTRACTTYPE)\n" + + " left join TCP_FND.TCP_FND_LOOKUP_CODE TCP_FND_LOOKUP_CODE1 on TCP_FND_LOOKUP_CODE1.LOOKUP_TYPE='CONTRACT_CATE' and TCP_FND_LOOKUP_CODE1.LOOKUP_CODE=EPM_TBL_CONTRACT.Contrctkind)"; + + List statementList = SQLUtils.parseStatements(sql, JdbcConstants.ORACLE); + SQLStatement stmt = statementList.get(0); + print(statementList); + + assertEquals(1, statementList.size()); +// + assertEquals("CREATE OR REPLACE VIEW \"TCP_EPM\".\"EPM_VW_CONTRACT\" (\n" + + "\t\"NID\", \n" + + "\t\"SCONTRACTNO\", \n" + + "\t\"SCONTRACTNAME\", \n" + + "\t\"NOFFICEID\", \n" + + "\t\"SOFFICENAME\", \n" + + "\t\"NSALEDEPTID\", \n" + + "\t\"SSALEDEPTNAME\", \n" + + "\t\"NPRODDEPTID\", \n" + + "\t\"SPRODDEPTNAME\", \n" + + "\t\"NCUSTOMERID\", \n" + + "\t\"SCUSTOMERNAME\", \n" + + "\t\"SSERVICEPROVIDERID\", \n" + + "\t\"SSERVICEPROVIDERNAME\", \n" + + "\t\"NMAINPRODUCTID\", \n" + + "\t\"SMAINPRODUCTNAME\", \n" + + "\t\"SCONTRACTTYPE\", \n" + + "\t\"SCONTRACTTYPETEXT\", \n" + + "\t\"SCONTRACTKIND\", \n" + + "\t\"SCONTRACTKINDTEXT\", \n" + + "\t\"SISFIRSTCHECKED\", \n" + + "\t\"SISLASTCHECKED\", \n" + + "\t\"SISOUTSOURCE\", \n" + + "\t\"SISRECONSIGN\", \n" + + "\t\"DGUARANTEE\", \n" + + "\t\"DCREATEDTIME\", \n" + + "\t\"NERPCONTRACTID\", \n" + + "\t\"NSTATE\", \n" + + "\t\"DFIRSTCHECKTIME\", \n" + + "\t\"DLASTCHECKTIME\", \n" + + "\t\"DPLANFIRSTCHECKTIME\", \n" + + "\t\"DPLANLASTCHECKTIME\"\n" + + ")\n" + + "AS\n" + + "SELECT EPM_TBL_CONTRACT.OID AS nID, EPM_TBL_CONTRACT.CONTRACTNO AS sContractNo, EPM_TBL_CONTRACT.CONTRACTNAME AS sCONTRACTNAME, EPM_TBL_CONTRACT.ENGDUTYDEP AS nOfficeID, TCP_FND_DEPT.DEPT_NAME AS sOfficeName\n" + + "\t, TCP_EPM.EPM_TB_CONTRACT_EX.nSaleDeptID AS nSaleDeptID, TCP_FND_DEPT1.DEPT_NAME AS sSaleDeptName, TCP_EPM.EPM_TB_CONTRACT_EX.nProdDeptID AS nProdDeptID, TCP_FND_DEPT2.DEPT_NAME AS sProdDeptName, EPM_TBL_CONTRACT.CUSTOMID AS nCustomerID\n" + + "\t, TCP_CUST_CUSTOMER.Name AS sCustomerName, TCP_EPM.EPM_TB_CONTRACT_EX.sServiceProviderID AS sServiceProviderID, TCP_CUST_ENUM.DESC_ AS sServiceProviderName, EPM_TBL_CONTRACT.MASTERPRODUCT AS nMainProductID, TCP_FND_PRODUCT.CN_NAME AS sMainProductName\n" + + "\t, EPM_TBL_CONTRACT.CONTRACTTYPE AS sContractType, TCP_FND_LOOKUP_CODE.MEANING AS sContractTypeText, EPM_TBL_CONTRACT.Contrctkind AS sContractKind, TCP_FND_LOOKUP_CODE1.MEANING AS sContractKindText, TCP_EPM.EPM_TB_CONTRACT_EX.sIsFirstChecked AS sIsFirstChecked\n" + + "\t, TCP_EPM.EPM_TB_CONTRACT_EX.sIsLastChecked AS sIsLastChecked\n" + + "\t, CASE \n" + + "\t\tWHEN (\n" + + "\t\t\tSELECT COUNT(*)\n" + + "\t\t\tFROM EPM_TBL_ENGINE_PROJECT, EPM_TBL_SUBCONTRACT_DISPATCH\n" + + "\t\t\tWHERE EPM_TBL_ENGINE_PROJECT.CONTRACTID = EPM_TBL_CONTRACT.Oid\n" + + "\t\t\t\tAND EPM_TBL_ENGINE_PROJECT.OID = EPM_TBL_SUBCONTRACT_DISPATCH.ENGINEID\n" + + "\t\t) > 0 THEN '/'\n" + + "\t\tELSE '&'\n" + + "\tEND AS sIsOutSource\n" + + "\t, CASE \n" + + "\t\tWHEN (\n" + + "\t\t\tSELECT COUNT(*)\n" + + "\t\t\tFROM TCP_EPM.EPM_TBL_RECONSIGN_RECONSIGN\n" + + "\t\t\tWHERE TCP_EPM.EPM_TBL_RECONSIGN_RECONSIGN.CONTRACTID = EPM_TBL_CONTRACT.Oid\n" + + "\t\t) > 0 THEN '/'\n" + + "\t\tELSE '&'\n" + + "\tEND AS sIsReconsign, TCP_EPM.EPM_TB_CONTRACT_EX.dGuarantee AS dGuarantee, TCP_EPM.EPM_TB_CONTRACT_EX.dCreatedTime AS dCreatedTime, TCP_EPM.EPM_TB_CONTRACT_EX.nERPContractID AS nERPContractID, TCP_EPM.EPM_TB_CONTRACT_EX.nState AS nState\n" + + "\t, TCP_EPM.EPM_TB_CONTRACT_EX.DFIRSTCHECKTIME AS DFIRSTCHECKTIME, TCP_EPM.EPM_TB_CONTRACT_EX.DLASTCHECKTIME AS DLASTCHECKTIME, TCP_EPM.EPM_TB_CONTRACT_EX.DPLANFIRSTCHECKTIME AS DPLANFIRSTCHECKTIME, TCP_EPM.EPM_TB_CONTRACT_EX.DPLANLASTCHECKTIME AS DPLANLASTCHECKTIME\n" + + "FROM TCP_EPM.Epm_Tbl_Contract\n" + + "LEFT JOIN TCP_FND.TCP_FND_DEPT ON TCP_FND_DEPT.Dept_Id = Epm_Tbl_Contract.Engdutydep \n" + + "LEFT JOIN TCP_EPM.EPM_TB_CONTRACT_EX ON EPM_TB_CONTRACT_EX.NCONTRACTID = Epm_Tbl_Contract.Oid \n" + + "LEFT JOIN TCP_FND.TCP_FND_DEPT TCP_FND_DEPT1 ON TCP_FND_DEPT1.Dept_Id = EPM_TB_CONTRACT_EX.nSaleDeptID \n" + + "LEFT JOIN TCP_FND.TCP_FND_DEPT TCP_FND_DEPT2 ON TCP_FND_DEPT2.Dept_Id = EPM_TB_CONTRACT_EX.nProdDeptID \n" + + "LEFT JOIN TCP_CUST.TCP_CUST_CUSTOMER ON TCP_CUST_CUSTOMER.ID = EPM_TBL_CONTRACT.Customid \n" + + "LEFT JOIN TCP_CUST.TCP_CUST_ENUM ON TCP_CUST_ENUM.Codeid = EPM_TB_CONTRACT_EX.sServiceProviderID \n" + + "LEFT JOIN TCP_FND.TCP_FND_PRODUCT ON TCP_FND_PRODUCT.INVENTORY_ITEM_ID = EPM_TBL_CONTRACT.MASTERPRODUCT \n" + + "LEFT JOIN TCP_FND.TCP_FND_LOOKUP_CODE ON TCP_FND_LOOKUP_CODE.LOOKUP_TYPE = 'CONTRACT_TYPE'\n" + + "AND TCP_FND_LOOKUP_CODE.LOOKUP_CODE = EPM_TBL_CONTRACT.CONTRACTTYPE \n" + + "\tLEFT JOIN TCP_FND.TCP_FND_LOOKUP_CODE TCP_FND_LOOKUP_CODE1 ON TCP_FND_LOOKUP_CODE1.LOOKUP_TYPE = 'CONTRACT_CATE'\n" + + "AND TCP_FND_LOOKUP_CODE1.LOOKUP_CODE = EPM_TBL_CONTRACT.Contrctkind ",// + SQLUtils.toSQLString(stmt, JdbcConstants.ORACLE)); +// +// SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.ORACLE); +// stmt.accept(visitor); +// +// System.out.println("Tables : " + visitor.getTables()); +// System.out.println("fields : " + visitor.getColumns()); +// System.out.println("coditions : " + visitor.getConditions()); +// System.out.println("relationships : " + visitor.getRelationships()); +// System.out.println("orderBy : " + visitor.getOrderByColumns()); +// +// assertEquals(1, visitor.getTables().size()); +// +// assertEquals(3, visitor.getColumns().size()); +// +// assertTrue(visitor.getColumns().contains(new TableStat.Column("JWGZPT.A", "XM"))); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/oracle/create/OracleCreateViewTest11_error_encoding.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/create/OracleCreateViewTest11_error_encoding.java new file mode 100644 index 0000000000..7722631fcc --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/create/OracleCreateViewTest11_error_encoding.java @@ -0,0 +1,192 @@ +/* + * Copyright 1999-2017 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.druid.bvt.sql.oracle.create; + +import com.alibaba.druid.sql.OracleTest; +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.oracle.parser.OracleStatementParser; +import com.alibaba.druid.sql.dialect.oracle.visitor.OracleSchemaStatVisitor; +import com.alibaba.druid.stat.TableStat; +import com.alibaba.druid.util.JdbcConstants; + +import java.util.List; + +public class OracleCreateViewTest11_error_encoding extends OracleTest { + + public void test_types() throws Exception { + String sql = // + " CREATE OR REPLACE FORCE VIEW \"TCP_CPR\".\"CPR_SYS_BOM_MODULE_V\" (\"PROD_TYPE_ID\", \"PROD_TYPE_NAME\", \"PROD_ID\", \"PROD_NAME\", \"DEVICE_ID\", \"DEVICE_NAME\", \"MODULE_ID\", \"STRUCTURE_CODE\", \"MODULE_NAME\", \"ENG_DESCRIPTION\", \"ZH_UNIT\", \"EN_UNIT\", \"ITEM_CODE\", \"SALES_DEPT_ID\", \"CLUEIDS\", \"SEQ\", \"ORGANIZATION_ID\", \"ORGANIZATION_NAME\", \"ATTRIBUTE1\", \"ATTRIBUTE2\", \"ATTRIBUTE3\", \"ATTRIBUTE4\", \"ATTRIBUTE5\", \"ATTRIBUTE6\", \"TSM_FLAG\", \"TSM_CODE\", \"HARD_PARAM\", \"SOFT_PARAM\", \"MAKE_PARAM\", \"RISK_PARAM\", \"SOFT_COST_PARAM\", \"FIXED_RATE\", \"TEMP_FIELD1\", \"TEMP_FIELD2\") AS \n" + + " SELECT CP.Parent_System_Bom_Id PROD_TYPE_ID,--Я'{ID\n" + + " FL.DESCRIPTION PROD_TYPE_NAME,--Я'{\n" + + " CP.System_Bom_Id PROD_ID,--ЯID\n" + + " CPD.DESCRIPTION PROD_NAME,--Я\n" + + " DV.System_Bom_Id DEVICE_ID,--:婭D\n" + + " DVD.DESCRIPTION DEVICE_NAME,--:�\n" + + " B1.SYSTEM_BOM_ID MODULE_ID, -- !WID\n" + + " B1.STRUCTURE_CODE, \n" + + " B2.DESCRIPTION MODULE_NAME, --!W\n" + + " B3.DESCRIPTION ENG_DESCRIPTION,--駠\n" + + " B2.PRIMARY_UNIT_OF_MEASURE ZH_UNIT,---嘦M\n" + + " B3.PRIMARY_UNIT_OF_MEASURE EN_UNIT,--駠UM\n" + + " B1.ITEM_CODE, \n" + + " B1.SALES_DEPT_ID, \n" + + " B1.CLUEIDS, \n" + + " B1.SEQ, \n" + + " B1.ORGANIZATION_ID, \n" + + " ORGN.NAME ORGANIZATION_NAME,\n" + + " B1.ATTRIBUTE1, \n" + + " B1.ATTRIBUTE2, \n" + + " B1.ATTRIBUTE3, \n" + + " B1.ATTRIBUTE4, \n" + + " B1.ATTRIBUTE5, \n" + + " B1.ATTRIBUTE6, \n" + + " B1.TSM_FLAG, \n" + + " B1.TSM_CODE, \n" + + " B1.HARD_PARAM, \n" + + " B1.SOFT_PARAM, \n" + + " B1.MAKE_PARAM, \n" + + " B1.RISK_PARAM, \n" + + " B1.SOFT_COST_PARAM, \n" + + " B1.FIXED_RATE,\n" + + " B1.TEMP_FIELD1,\n" + + " B1.TEMP_FIELD2 \n" + + " FROM TCP_CPR.SYSTEM_BOM B1,\n" + + " TCP_CPR.SYSTEM_BOM_DESC B2,\n" + + " TCP_CPR.SYSTEM_BOM_DESC B3,\n" + + " TCP_CPR.SYSTEM_BOM_DESC FL,\n" + + " TCP_CPR.SYSTEM_BOM CP,\n" + + " TCP_CPR.SYSTEM_BOM_DESC CPD,\n" + + " TCP_CPR.SYSTEM_BOM DV,\n" + + " TCP_CPR.SYSTEM_BOM_DESC DVD,\n" + + " TCP_FND.TCP_FND_ORGANIZATION ORGN\n" + + " WHERE B1.SYSTEM_BOM_ID = B2.SYSTEM_BOM_ID(+)\n" + + " AND B2.ENABLED_FLAG(+) = 'Y'\n" + + " AND B1.SYSTEM_BOM_ID = B3.SYSTEM_BOM_ID(+)\n" + + " AND B3.ENABLED_FLAG(+) = 'Y'\n" + + " AND B1.ENABLED_FLAG(+) = 'Y'\n" + + " AND B1.LAYER = 4\n" + + " AND B3.LANGUAGE(+) = 'en-US'\n" + + " AND B2.LANGUAGE(+) = 'zh-CN'\n" + + " AND B1.Parent_System_Bom_Id = DV.SYSTEM_BOM_ID(+)\n" + + " AND DV.ENABLED_FLAG='Y'\n" + + " AND DV.SYSTEM_BOM_ID=DVD.SYSTEM_BOM_ID\n" + + " AND DVD.ENABLED_FLAG(+) = 'Y'\n" + + " AND DVD.LANGUAGE(+) = 'zh-CN'\n" + + " AND DV.Parent_System_Bom_Id = CP.SYSTEM_BOM_ID(+)\n" + + " AND CP.ENABLED_FLAG='Y'\n" + + " AND CP.SYSTEM_BOM_ID=CPD.SYSTEM_BOM_ID\n" + + " AND CPD.ENABLED_FLAG(+) = 'Y'\n" + + " AND CPD.LANGUAGE(+) = 'zh-CN'\n" + + " AND CP.Parent_System_Bom_Id = FL.SYSTEM_BOM_ID(+)\n" + + " AND FL.ENABLED_FLAG(+) = 'Y'\n" + + " AND FL.LANGUAGE(+) = 'zh-CN'\n" + + " AND B1.ORGANIZATION_ID=ORGN.ORGANIZATION_ID(+)"; + + System.out.println(sql); + + OracleStatementParser parser = new OracleStatementParser(sql); + List statementList = parser.parseStatementList(); + SQLStatement stmt = statementList.get(0); + print(statementList); + + assertEquals(1, statementList.size()); + + assertEquals("CREATE OR REPLACE VIEW \"TCP_CPR\".\"CPR_SYS_BOM_MODULE_V\" (\n" + + "\t\"PROD_TYPE_ID\", \n" + + "\t\"PROD_TYPE_NAME\", \n" + + "\t\"PROD_ID\", \n" + + "\t\"PROD_NAME\", \n" + + "\t\"DEVICE_ID\", \n" + + "\t\"DEVICE_NAME\", \n" + + "\t\"MODULE_ID\", \n" + + "\t\"STRUCTURE_CODE\", \n" + + "\t\"MODULE_NAME\", \n" + + "\t\"ENG_DESCRIPTION\", \n" + + "\t\"ZH_UNIT\", \n" + + "\t\"EN_UNIT\", \n" + + "\t\"ITEM_CODE\", \n" + + "\t\"SALES_DEPT_ID\", \n" + + "\t\"CLUEIDS\", \n" + + "\t\"SEQ\", \n" + + "\t\"ORGANIZATION_ID\", \n" + + "\t\"ORGANIZATION_NAME\", \n" + + "\t\"ATTRIBUTE1\", \n" + + "\t\"ATTRIBUTE2\", \n" + + "\t\"ATTRIBUTE3\", \n" + + "\t\"ATTRIBUTE4\", \n" + + "\t\"ATTRIBUTE5\", \n" + + "\t\"ATTRIBUTE6\", \n" + + "\t\"TSM_FLAG\", \n" + + "\t\"TSM_CODE\", \n" + + "\t\"HARD_PARAM\", \n" + + "\t\"SOFT_PARAM\", \n" + + "\t\"MAKE_PARAM\", \n" + + "\t\"RISK_PARAM\", \n" + + "\t\"SOFT_COST_PARAM\", \n" + + "\t\"FIXED_RATE\", \n" + + "\t\"TEMP_FIELD1\", \n" + + "\t\"TEMP_FIELD2\"\n" + + ")\n" + + "AS\n" + + "SELECT CP.Parent_System_Bom_Id AS PROD_TYPE_ID, FL.DESCRIPTION AS PROD_TYPE_NAME, CP.System_Bom_Id AS PROD_ID, CPD.DESCRIPTION AS PROD_NAME, DV.System_Bom_Id AS DEVICE_ID\n" + + "\t, DVD.DESCRIPTION AS DEVICE_NAME, B1.SYSTEM_BOM_ID AS MODULE_ID, B1.STRUCTURE_CODE, B2.DESCRIPTION AS MODULE_NAME, B3.DESCRIPTION AS ENG_DESCRIPTION\n" + + "\t, B2.PRIMARY_UNIT_OF_MEASURE AS ZH_UNIT, B3.PRIMARY_UNIT_OF_MEASURE AS EN_UNIT, B1.ITEM_CODE, B1.SALES_DEPT_ID, B1.CLUEIDS\n" + + "\t, B1.SEQ, B1.ORGANIZATION_ID, ORGN.NAME AS ORGANIZATION_NAME, B1.ATTRIBUTE1, B1.ATTRIBUTE2\n" + + "\t, B1.ATTRIBUTE3, B1.ATTRIBUTE4, B1.ATTRIBUTE5, B1.ATTRIBUTE6, B1.TSM_FLAG\n" + + "\t, B1.TSM_CODE, B1.HARD_PARAM, B1.SOFT_PARAM, B1.MAKE_PARAM, B1.RISK_PARAM\n" + + "\t, B1.SOFT_COST_PARAM, B1.FIXED_RATE, B1.TEMP_FIELD1, B1.TEMP_FIELD2\n" + + "FROM TCP_CPR.SYSTEM_BOM B1, TCP_CPR.SYSTEM_BOM_DESC B2, TCP_CPR.SYSTEM_BOM_DESC B3, TCP_CPR.SYSTEM_BOM_DESC FL, TCP_CPR.SYSTEM_BOM CP, TCP_CPR.SYSTEM_BOM_DESC CPD, TCP_CPR.SYSTEM_BOM DV, TCP_CPR.SYSTEM_BOM_DESC DVD, TCP_FND.TCP_FND_ORGANIZATION ORGN\n" + + "WHERE B1.SYSTEM_BOM_ID = B2.SYSTEM_BOM_ID(+)\n" + + "\tAND B2.ENABLED_FLAG(+) = 'Y'\n" + + "\tAND B1.SYSTEM_BOM_ID = B3.SYSTEM_BOM_ID(+)\n" + + "\tAND B3.ENABLED_FLAG(+) = 'Y'\n" + + "\tAND B1.ENABLED_FLAG(+) = 'Y'\n" + + "\tAND B1.LAYER = 4\n" + + "\tAND B3.LANGUAGE(+) = 'en-US'\n" + + "\tAND B2.LANGUAGE(+) = 'zh-CN'\n" + + "\tAND B1.Parent_System_Bom_Id = DV.SYSTEM_BOM_ID(+)\n" + + "\tAND DV.ENABLED_FLAG = 'Y'\n" + + "\tAND DV.SYSTEM_BOM_ID = DVD.SYSTEM_BOM_ID\n" + + "\tAND DVD.ENABLED_FLAG(+) = 'Y'\n" + + "\tAND DVD.LANGUAGE(+) = 'zh-CN'\n" + + "\tAND DV.Parent_System_Bom_Id = CP.SYSTEM_BOM_ID(+)\n" + + "\tAND CP.ENABLED_FLAG = 'Y'\n" + + "\tAND CP.SYSTEM_BOM_ID = CPD.SYSTEM_BOM_ID\n" + + "\tAND CPD.ENABLED_FLAG(+) = 'Y'\n" + + "\tAND CPD.LANGUAGE(+) = 'zh-CN'\n" + + "\tAND CP.Parent_System_Bom_Id = FL.SYSTEM_BOM_ID(+)\n" + + "\tAND FL.ENABLED_FLAG(+) = 'Y'\n" + + "\tAND FL.LANGUAGE(+) = 'zh-CN'\n" + + "\tAND B1.ORGANIZATION_ID = ORGN.ORGANIZATION_ID(+)",// + SQLUtils.toSQLString(stmt, JdbcConstants.ORACLE)); + + OracleSchemaStatVisitor visitor = new OracleSchemaStatVisitor(); + stmt.accept(visitor); + + System.out.println("Tables : " + visitor.getTables()); + System.out.println("fields : " + visitor.getColumns()); + System.out.println("coditions : " + visitor.getConditions()); + System.out.println("relationships : " + visitor.getRelationships()); + System.out.println("orderBy : " + visitor.getOrderByColumns()); + + assertEquals(3, visitor.getTables().size()); + + assertEquals(33, visitor.getColumns().size()); + + assertTrue(visitor.getColumns().contains(new TableStat.Column("TCP_CPR.SYSTEM_BOM", "Parent_System_Bom_Id"))); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/oracle/create/OracleCreateViewTest12.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/create/OracleCreateViewTest12.java new file mode 100644 index 0000000000..3000512ec4 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/create/OracleCreateViewTest12.java @@ -0,0 +1,266 @@ +/* + * Copyright 1999-2017 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.druid.bvt.sql.oracle.create; + +import com.alibaba.druid.sql.OracleTest; +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.oracle.parser.OracleStatementParser; +import com.alibaba.druid.sql.dialect.oracle.visitor.OracleSchemaStatVisitor; +import com.alibaba.druid.stat.TableStat; +import com.alibaba.druid.util.JdbcConstants; + +import java.util.List; + +public class OracleCreateViewTest12 extends OracleTest { + + public void test_types() throws Exception { + String sql = // + "CREATE OR REPLACE FORCE VIEW \"TCP_CPR\".\"DIFF_CON_CONFIG_ALL_V\" (\"OSG_TYPE_ID\", \"CONTRACT_HEADER_ID\", \"CONTRACT_NUMBER\", \"ORGANIZATION_ID\", \"CONTRACT_PRODUCT_ID\", \"PROD_ID\", \"PROD_DES\", \"MI\", \"CONTRACT_DEVICE_ID\", \"DEV_ID\", \"DEV_DES\", \"SITE_ID\", \"SITE_QUANTITY\", \"SITE_DES\", \"CONTRACT_MODULE_ID\", \"MOD_ID\", \"MOD_DES\", \"MODULE_QUANTITY\", \"CONTRACT_ITEM_ID\", \"ITEM_ID\", \"ITEM_DES\", \"ITEM_TYPE\", \"ITEM_QUANTITY\", \"HARD_PARAM\", \"SOFT_PARAM\", \"MAKE_PARAM\", \"RISK_PARAM\", \"SOFT_COST_PARAM\", \"PROD_MANAGER\", \"COST_PRICE04\", \"CONFIRM_ITEM_PARAM\", \"CONFIRM_FLAG04\", \"COST_PRICE\", \"COST_PRICE_PARAMETER\", \"OLD_COST\", \"LIST_PRICE\", \"ITEM_CODE\", \"CONFIRM_COST_PRICE04\", \"CUSTOMIZE_SITES_ID\", \"SPARE_FLAG\") AS \n" + + " SELECT I.osg_type_id, M.CONTRACT_HEADER_ID,M.CONTRACT_NUMBER,\n" + + " M.ORGANIZATION_ID,\n" + + " M.CONTRACT_PRODUCT_ID,\n" + + " M.prod_id,\n" + + " M.prod_des,M.MI,\n" + + " M.CONTRACT_DEVICE_ID,\n" + + " M.dev_id,\n" + + " m.dev_des,\n" + + " M.SITE_ID ,\n" + + " M.SITE_QUANTITY,\n" + + " M.site_des,\n" + + " M.CONTRACT_MODULE_ID,\n" + + " M.mod_id,\n" + + " M.mod_des,\n" + + " M.MODULE_QUANTITY,\n" + + " I.CONTRACT_ITEM_ID,\n" + + " I.ITEM_ID,\n" + + " I.ITEM_DES,\n" + + " I.ITEM_TYPE,\n" + + " I.item_quantity,\n" + + " M.hard_param,\n" + + " M.soft_param, M.make_param,M.risk_param, M.soft_cost_param,\n" + + " M.prod_manager, I.COST_PRICE04, I.CONFIRM_ITEM_PARAM, I.CONFIRM_FLAG04,\n" + + " I.cost_price,I.COST_PRICE_PARAMETER,I.OLD_COST,I.LIST_PRICE,I.ITEM_CODE,\n" + + " I.CONFIRM_COST_PRICE04\n" + + " --,I.PROD_ATTRIBUTE_ID,I.ITEM_CHIP\n" + + " ,M.customize_sites_id\n" + + " ,M.spare_flag\n" + + " FROM TCP_CPR.DIFF_CON_CONFIG_MODULE_V M\n" + + " LEFT JOIN\n" + + " (\n" + + " (\n" + + " select 0 osg_type_id,\n" + + " v.contract_module_id,\n" + + " v.item_id,\n" + + " v.contract_item_id,\n" + + " v.item_des,\n" + + " v.item_type,\n" + + " v.ITEM_QUANTITY,\n" + + " v.cost_price,\n" + + " v.COST_PRICE_PARAMETER,\n" + + " v.CONFIRM_FLAG,\n" + + " v.COST_PRICE04,\n" + + " v.CONFIRM_ITEM_PARAM,\n" + + " v.CONFIRM_FLAG04,\n" + + " v.OLD_COST,\n" + + " v.LIST_PRICE,\n" + + " v.ITEM_CODE,\n" + + " v.CONFIRM_COST_PRICE04\n" + + " from TCP_CPR.DIFF_CON_CONFIG_ITEM_V v\n" + + " )\n" + + " union all\n" + + " (\n" + + " SELECT header.product_id osg_type_id,\n" + + " HEADER.PARENT_ID CONTRACT_MODULE_ID,\n" + + " HEADER.SERIAL_ID item_id,\n" + + " HEADER.OSG_HEADER_ID CONTRACT_ITEM_ID,\n" + + " ser.product_serial item_name,\n" + + " 'OSG' item_type,\n" + + " HEADER.QUANTITY item_quantity,\n" + + " (LINE.REF_PRICE+ nvl(REPLY.MARKET_REFERENCE_PRICE,0)) COST_PRICE,\n" + + " 1 COST_PRICE_PARAMETER,\n" + + " 'Y' CONFIRM_FLAG,\n" + + " 0 COST_PRICE04,\n" + + " 1 CONFIRM_ITEM_PARAM,\n" + + " 'Y' CONFIRM_FLAG04,\n" + + " 1 OLD_COST,\n" + + " --LINE.PRICE+nvl(REPLY.LIST_PRICE,0) LIST_PRICE,\n" + + " HEADER.LIST_PRICE LIST_PRICE,\n" + + " '+Mn\u0016-�' ITEM_CODE,\n" + + " (LINE.COST+ nvl(REPLY.RMBPRICE_WITHTAX,0)) CONFIRM_COST_PRICE04\n" + + " --0 PROD_ATTRIBUTE_ID,0 ITEM_CHIP\n" + + " FROM TCP_CPR.DIFF_CON_OSG3_HEADERS HEADER,ERP_ZTE.ZTE_KX_OSG3_SERIALS ser, ERP_ZTE.zte_kx_osg3_reply_headers\n" + + " REPLY, (\n" + + " select LINE.OSG_HEADER_ID,SUM((LINE.QUANTITY-LINE.THEORETIC_QTY)*\n" + + " PART.rmbprice_withtax) COST, SUM((LINE.QUANTITY-\n" + + " LINE.THEORETIC_QTY)* PART.LIST_PRICE) PRICE, SUM((\n" + + " LINE.QUANTITY-LINE.THEORETIC_QTY)* PART.MARKET_REFERENCE_PRICE\n" + + " ) REF_PRICE\n" + + " from TCP_CPR.DIFF_CON_OSG3_LINES LINE,\n" + + " ERP_ZTE.ZTE_KX_OSG3_PART_DETAILS PART\n" + + " WHERE LINE.PART_DETAIL_ID = PART.PART_DETAIL_ID\n" + + " AND LINE.ENABLED_FLAG = 'Y'\n" + + " GROUP BY LINE.OSG_HEADER_ID) LINE\n" + + " where HEADER.ENABLED_FLAG = 'Y' AND ser.serial_id=HEADER.Serial_Id\n" + + " and header.REPLY_ID = reply.reply_head_id(+)\n" + + " and header.OSG_HEADER_ID = line.OSG_HEADER_ID\n" + + " )\n" + + " union all\n" + + " (\n" + + " SELECT item.osg_type_id osg_type_id,\n" + + " ITEM.PARENT_ID CONTRACT_MODULE_ID,\n" + + " item.osg_item_id item_id,\n" + + " ITEM.OSG_ITEM_ID CONTRACT_ITEM_ID,\n" + + " SYS_ITEM.DESCRIPTION item_name,\n" + + " 'SINGLEOSG' item_type,\n" + + " ITEM.QUANTITY item_quantity,\n" + + " SYS_ITEM.MARKET_REFERENCE_PRICE COST_PRICE,\n" + + " 1 COST_PRICE_PARAMETER,\n" + + " SYS_ITEM.ENABLED_FLAG CONFIRM_FLAG,\n" + + " 0 COST_PRICE04,\n" + + " 1 CONFIRM_ITEM_PARAM,\n" + + " 'Y' CONFIRM_FLAG04,\n" + + " 1 OLD_COST,\n" + + " --SYS_ITEM.LIST_PRICE LIST_PRICE,\n" + + " ITEM.LIST_PRICE LIST_PRICE,\n" + + " SYS_ITEM.INVENTORY_ID||'\n" + + "+Mn\u0016-�' ITEM_CODE,\n" + + " SYS_ITEM.PRICE CONFIRM_COST_PRICE04--, 0 PROD_ATTRIBUTE_ID--,0 ITEM_CHIP\n" + + " FROM TCP_CPR.DIFF_CON_OSG3A_HEADERS ITEM,ERP_ZTE.ZTE_KX_OSG3_ITEMS\n" + + " SYS_ITEM\n" + + " where ITEM.OSG_ITEM_ID = SYS_ITEM.OSG_ITEM_ID\n" + + " AND ITEM.ENABLED_FLAG = 'Y'\n" + + " )\n" + + " ) I\n" + + " ON M.CONTRACT_MODULE_ID = I.CONTRACT_MODULE_ID\n" + + " WHERE item_quantity>=0"; + + System.out.println(sql); + + OracleStatementParser parser = new OracleStatementParser(sql); + List statementList = parser.parseStatementList(); + SQLStatement stmt = statementList.get(0); + print(statementList); + + assertEquals(1, statementList.size()); + + assertEquals("CREATE OR REPLACE VIEW \"TCP_CPR\".\"DIFF_CON_CONFIG_ALL_V\" (\n" + + "\t\"OSG_TYPE_ID\", \n" + + "\t\"CONTRACT_HEADER_ID\", \n" + + "\t\"CONTRACT_NUMBER\", \n" + + "\t\"ORGANIZATION_ID\", \n" + + "\t\"CONTRACT_PRODUCT_ID\", \n" + + "\t\"PROD_ID\", \n" + + "\t\"PROD_DES\", \n" + + "\t\"MI\", \n" + + "\t\"CONTRACT_DEVICE_ID\", \n" + + "\t\"DEV_ID\", \n" + + "\t\"DEV_DES\", \n" + + "\t\"SITE_ID\", \n" + + "\t\"SITE_QUANTITY\", \n" + + "\t\"SITE_DES\", \n" + + "\t\"CONTRACT_MODULE_ID\", \n" + + "\t\"MOD_ID\", \n" + + "\t\"MOD_DES\", \n" + + "\t\"MODULE_QUANTITY\", \n" + + "\t\"CONTRACT_ITEM_ID\", \n" + + "\t\"ITEM_ID\", \n" + + "\t\"ITEM_DES\", \n" + + "\t\"ITEM_TYPE\", \n" + + "\t\"ITEM_QUANTITY\", \n" + + "\t\"HARD_PARAM\", \n" + + "\t\"SOFT_PARAM\", \n" + + "\t\"MAKE_PARAM\", \n" + + "\t\"RISK_PARAM\", \n" + + "\t\"SOFT_COST_PARAM\", \n" + + "\t\"PROD_MANAGER\", \n" + + "\t\"COST_PRICE04\", \n" + + "\t\"CONFIRM_ITEM_PARAM\", \n" + + "\t\"CONFIRM_FLAG04\", \n" + + "\t\"COST_PRICE\", \n" + + "\t\"COST_PRICE_PARAMETER\", \n" + + "\t\"OLD_COST\", \n" + + "\t\"LIST_PRICE\", \n" + + "\t\"ITEM_CODE\", \n" + + "\t\"CONFIRM_COST_PRICE04\", \n" + + "\t\"CUSTOMIZE_SITES_ID\", \n" + + "\t\"SPARE_FLAG\"\n" + + ")\n" + + "AS\n" + + "SELECT I.osg_type_id, M.CONTRACT_HEADER_ID, M.CONTRACT_NUMBER, M.ORGANIZATION_ID, M.CONTRACT_PRODUCT_ID\n" + + "\t, M.prod_id, M.prod_des, M.MI, M.CONTRACT_DEVICE_ID, M.dev_id\n" + + "\t, m.dev_des, M.SITE_ID, M.SITE_QUANTITY, M.site_des, M.CONTRACT_MODULE_ID\n" + + "\t, M.mod_id, M.mod_des, M.MODULE_QUANTITY, I.CONTRACT_ITEM_ID, I.ITEM_ID\n" + + "\t, I.ITEM_DES, I.ITEM_TYPE, I.item_quantity, M.hard_param, M.soft_param\n" + + "\t, M.make_param, M.risk_param, M.soft_cost_param, M.prod_manager, I.COST_PRICE04\n" + + "\t, I.CONFIRM_ITEM_PARAM, I.CONFIRM_FLAG04, I.cost_price, I.COST_PRICE_PARAMETER, I.OLD_COST\n" + + "\t, I.LIST_PRICE, I.ITEM_CODE, I.CONFIRM_COST_PRICE04, M.customize_sites_id, M.spare_flag\n" + + "FROM TCP_CPR.DIFF_CON_CONFIG_MODULE_V M\n" + + "\tLEFT JOIN (\n" + + "\t\tSELECT 0 AS osg_type_id, v.contract_module_id, v.item_id, v.contract_item_id, v.item_des\n" + + "\t\t\t, v.item_type, v.ITEM_QUANTITY, v.cost_price, v.COST_PRICE_PARAMETER, v.CONFIRM_FLAG\n" + + "\t\t\t, v.COST_PRICE04, v.CONFIRM_ITEM_PARAM, v.CONFIRM_FLAG04, v.OLD_COST, v.LIST_PRICE\n" + + "\t\t\t, v.ITEM_CODE, v.CONFIRM_COST_PRICE04\n" + + "\t\tFROM TCP_CPR.DIFF_CON_CONFIG_ITEM_V v\n" + + "\t\tUNION ALL\n" + + "\t\tSELECT header.product_id AS osg_type_id, HEADER.PARENT_ID AS CONTRACT_MODULE_ID, HEADER.SERIAL_ID AS item_id, HEADER.OSG_HEADER_ID AS CONTRACT_ITEM_ID, ser.product_serial AS item_name\n" + + "\t\t\t, 'OSG' AS item_type, HEADER.QUANTITY AS item_quantity\n" + + "\t\t\t, LINE.REF_PRICE + nvl(REPLY.MARKET_REFERENCE_PRICE, 0) AS COST_PRICE\n" + + "\t\t\t, 1 AS COST_PRICE_PARAMETER, 'Y' AS CONFIRM_FLAG, 0 AS COST_PRICE04, 1 AS CONFIRM_ITEM_PARAM, 'Y' AS CONFIRM_FLAG04\n" + + "\t\t\t, 1 AS OLD_COST, HEADER.LIST_PRICE AS LIST_PRICE, '+Mn\u0016-�' AS ITEM_CODE\n" + + "\t\t\t, LINE.COST + nvl(REPLY.RMBPRICE_WITHTAX, 0) AS CONFIRM_COST_PRICE04\n" + + "\t\tFROM TCP_CPR.DIFF_CON_OSG3_HEADERS HEADER, ERP_ZTE.ZTE_KX_OSG3_SERIALS ser, ERP_ZTE.zte_kx_osg3_reply_headers REPLY, (\n" + + "\t\t\tSELECT LINE.OSG_HEADER_ID, SUM((LINE.QUANTITY - LINE.THEORETIC_QTY) * PART.rmbprice_withtax) AS COST\n" + + "\t\t\t\t, SUM((LINE.QUANTITY - LINE.THEORETIC_QTY) * PART.LIST_PRICE) AS PRICE\n" + + "\t\t\t\t, SUM((LINE.QUANTITY - LINE.THEORETIC_QTY) * PART.MARKET_REFERENCE_PRICE) AS REF_PRICE\n" + + "\t\t\tFROM TCP_CPR.DIFF_CON_OSG3_LINES LINE, ERP_ZTE.ZTE_KX_OSG3_PART_DETAILS PART\n" + + "\t\t\tWHERE LINE.PART_DETAIL_ID = PART.PART_DETAIL_ID\n" + + "\t\t\t\tAND LINE.ENABLED_FLAG = 'Y'\n" + + "\t\t\tGROUP BY LINE.OSG_HEADER_ID\n" + + "\t\t) LINE\n" + + "\t\tWHERE HEADER.ENABLED_FLAG = 'Y'\n" + + "\t\t\tAND ser.serial_id = HEADER.Serial_Id\n" + + "\t\t\tAND header.REPLY_ID = reply.reply_head_id(+)\n" + + "\t\t\tAND header.OSG_HEADER_ID = line.OSG_HEADER_ID\n" + + "\t\tUNION ALL\n" + + "\t\tSELECT item.osg_type_id AS osg_type_id, ITEM.PARENT_ID AS CONTRACT_MODULE_ID, item.osg_item_id AS item_id, ITEM.OSG_ITEM_ID AS CONTRACT_ITEM_ID, SYS_ITEM.DESCRIPTION AS item_name\n" + + "\t\t\t, 'SINGLEOSG' AS item_type, ITEM.QUANTITY AS item_quantity, SYS_ITEM.MARKET_REFERENCE_PRICE AS COST_PRICE, 1 AS COST_PRICE_PARAMETER, SYS_ITEM.ENABLED_FLAG AS CONFIRM_FLAG\n" + + "\t\t\t, 0 AS COST_PRICE04, 1 AS CONFIRM_ITEM_PARAM, 'Y' AS CONFIRM_FLAG04, 1 AS OLD_COST, ITEM.LIST_PRICE AS LIST_PRICE\n" + + "\t\t\t, SYS_ITEM.INVENTORY_ID || '\n" + + "+Mn\u0016-�' AS ITEM_CODE, SYS_ITEM.PRICE AS CONFIRM_COST_PRICE04\n" + + "\t\tFROM TCP_CPR.DIFF_CON_OSG3A_HEADERS ITEM, ERP_ZTE.ZTE_KX_OSG3_ITEMS SYS_ITEM\n" + + "\t\tWHERE ITEM.OSG_ITEM_ID = SYS_ITEM.OSG_ITEM_ID\n" + + "\t\t\tAND ITEM.ENABLED_FLAG = 'Y'\n" + + "\t) I ON M.CONTRACT_MODULE_ID = I.CONTRACT_MODULE_ID \n" + + "WHERE item_quantity >= 0",// + SQLUtils.toSQLString(stmt, JdbcConstants.ORACLE)); + + OracleSchemaStatVisitor visitor = new OracleSchemaStatVisitor(); + stmt.accept(visitor); + + System.out.println("Tables : " + visitor.getTables()); + System.out.println("fields : " + visitor.getColumns()); + System.out.println("coditions : " + visitor.getConditions()); + System.out.println("relationships : " + visitor.getRelationships()); + System.out.println("orderBy : " + visitor.getOrderByColumns()); + + assertEquals(9, visitor.getTables().size()); + + assertEquals(75, visitor.getColumns().size()); + + assertTrue(visitor.getColumns().contains(new TableStat.Column("TCP_CPR.DIFF_CON_CONFIG_ITEM_V", "contract_module_id"))); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/oracle/select/OracleSelectTest81_join_brace.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/select/OracleSelectTest81_join_brace.java new file mode 100644 index 0000000000..d245ebabca --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/select/OracleSelectTest81_join_brace.java @@ -0,0 +1,96 @@ +/* + * Copyright 1999-2017 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.druid.bvt.sql.oracle.select; + +import com.alibaba.druid.sql.OracleTest; +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.oracle.parser.OracleStatementParser; +import com.alibaba.druid.sql.dialect.oracle.visitor.OracleSchemaStatVisitor; +import org.junit.Assert; + +import java.util.List; + +public class OracleSelectTest81_join_brace extends OracleTest { + + public void test_0() throws Exception { + String sql = // + "select * \n" + + "FROM ((tcp_cpr.con_config c1 INNER JOIN tcp_cpr.con_osg3a_headers osg ON\n" + + " c1.contract_config_id = osg.parent_id) LEFT OUTER JOIN\n" + + " erp_zte.zte_kx_osg3_items kx ON osg.osg_item_id = kx.osg_item_id),\n" + + " tcp_cpr.con_sites sites,\n" + + " tcp_cpr.system_bom b4\n" + + " WHERE sites.site_id = c1.site_id\n" + + " AND b4.system_bom_id = c1.system_bom_id\n" + + " AND c1.layer = 4\n" + + " AND sites.site_id IN (71242000)\n" + + " AND osg.quantity > 0\n" + + " AND c1.enabled_flag = 'Y'\n" + + " AND c1.contract_header_id = :headerid\n" + + " AND sites.contract_header_id = :headerid\n" + + " AND c1.partition_date = :partiondate;"; // + + System.out.println(sql); + + OracleStatementParser parser = new OracleStatementParser(sql); + List statementList = parser.parseStatementList(); + SQLStatement stmt = statementList.get(0); + print(statementList); + + + + Assert.assertEquals(1, statementList.size()); + + OracleSchemaStatVisitor visitor = new OracleSchemaStatVisitor(); + stmt.accept(visitor); + + { + String text = SQLUtils.toOracleString(stmt); + + assertEquals("SELECT *\n" + + "FROM tcp_cpr.con_config c1\n" + + "INNER JOIN tcp_cpr.con_osg3a_headers osg ON c1.contract_config_id = osg.parent_id \n" + + "LEFT JOIN erp_zte.zte_kx_osg3_items kx ON osg.osg_item_id = kx.osg_item_id , tcp_cpr.con_sites sites, tcp_cpr.system_bom b4\n" + + "WHERE sites.site_id = c1.site_id\n" + + "\tAND b4.system_bom_id = c1.system_bom_id\n" + + "\tAND c1.layer = 4\n" + + "\tAND sites.site_id IN (71242000)\n" + + "\tAND osg.quantity > 0\n" + + "\tAND c1.enabled_flag = 'Y'\n" + + "\tAND c1.contract_header_id = :headerid\n" + + "\tAND sites.contract_header_id = :headerid\n" + + "\tAND c1.partition_date = :partiondate;", text); + } + + System.out.println("Tables : " + visitor.getTables()); + System.out.println("fields : " + visitor.getColumns()); + System.out.println("coditions : " + visitor.getConditions()); + System.out.println("relationships : " + visitor.getRelationships()); + System.out.println("orderBy : " + visitor.getOrderByColumns()); + + assertEquals(5, visitor.getTables().size()); + assertEquals(14, visitor.getColumns().size()); + assertEquals(15, visitor.getConditions().size()); + assertEquals(4, visitor.getRelationships().size()); + assertEquals(0, visitor.getOrderByColumns().size()); + + + Assert.assertTrue(visitor.containsColumn("tcp_cpr.con_config", "contract_config_id")); + Assert.assertTrue(visitor.containsColumn("tcp_cpr.con_osg3a_headers", "parent_id")); +// + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/oracle/visitor/OracleResourceTest.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/visitor/OracleResourceTest.java index b5cb1aa22c..e5554dd852 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/oracle/visitor/OracleResourceTest.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/visitor/OracleResourceTest.java @@ -36,7 +36,7 @@ public class OracleResourceTest extends OracleTest { public void test_0() throws Exception { // 13 // exec_test("bvt/parser/oracle-56.txt"); - for (int i = 0; i <= 57; ++i) { + for (int i = 0; i <= 57; ++i) { // 57 exec_test("bvt/parser/oracle-" + i + ".txt"); } } diff --git a/src/test/java/com/alibaba/druid/bvt/sql/postgresql/PGCreateTableTest_7.java b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/PGCreateTableTest_7.java new file mode 100644 index 0000000000..2621db2c31 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/PGCreateTableTest_7.java @@ -0,0 +1,67 @@ +/* + * Copyright 1999-2017 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.druid.bvt.sql.postgresql; + +import com.alibaba.druid.sql.PGTest; +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.postgresql.parser.PGSQLStatementParser; +import com.alibaba.druid.sql.dialect.postgresql.visitor.PGSchemaStatVisitor; +import com.alibaba.druid.stat.TableStat; + +import java.util.List; + +public class PGCreateTableTest_7 extends PGTest { + + public void test_0() throws Exception { + String sql = "create table test_site_data_select_111 AS select * from postman_trace_info_one where lng>0 and lat>0 and site_id='17814' ;"; + + PGSQLStatementParser parser = new PGSQLStatementParser(sql); + List statementList = parser.parseStatementList(); + SQLStatement stmt = statementList.get(0); + + assertEquals("CREATE TABLE test_site_data_select_111\n" + + "AS\n" + + "SELECT *\n" + + "FROM postman_trace_info_one\n" + + "WHERE lng > 0\n" + + "\tAND lat > 0\n" + + "\tAND site_id = '17814';", SQLUtils.toPGString(stmt)); + + assertEquals("create table test_site_data_select_111\n" + + "as\n" + + "select *\n" + + "from postman_trace_info_one\n" + + "where lng > 0\n" + + "\tand lat > 0\n" + + "\tand site_id = '17814';", SQLUtils.toPGString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION)); + + assertEquals(1, statementList.size()); + + PGSchemaStatVisitor visitor = new PGSchemaStatVisitor(); + stmt.accept(visitor); + +// System.out.println("Tables : " + visitor.getTables()); +// System.out.println("fields : " + visitor.getColumns()); + + assertTrue(visitor.getTables().containsKey(new TableStat.Name("test_site_data_select_111"))); + + assertTrue(visitor.getTables().get(new TableStat.Name("test_site_data_select_111")).getCreateCount() == 1); + + assertEquals(4, visitor.getColumns().size() ); + } + +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/repository/OracleJoinResolveTest_1_fk.java b/src/test/java/com/alibaba/druid/bvt/sql/repository/OracleJoinResolveTest_1_fk.java new file mode 100644 index 0000000000..677ed14c96 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/repository/OracleJoinResolveTest_1_fk.java @@ -0,0 +1,166 @@ +package com.alibaba.druid.bvt.sql.repository; + +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleCreateTableStatement; +import com.alibaba.druid.sql.parser.SQLParserUtils; +import com.alibaba.druid.sql.repository.SchemaRepository; +import com.alibaba.druid.util.JdbcConstants; +import junit.framework.TestCase; + +/** + * Created by wenshao on 03/08/2017. + */ +public class OracleJoinResolveTest_1_fk extends TestCase { + protected SchemaRepository repository = new SchemaRepository(JdbcConstants.ORACLE); + + public void test_for_issue() throws Exception { + String sql_1 = " CREATE TABLE \"ECC_CPR\".\"ECC_CPR_HC_CON_HEAHERS\" \n" + + " ( \n" + + " \"HC_CON_ID\" NUMBER(10,0) NOT NULL ENABLE, \n" + + " \"HC_CONTRACT_NUMBER\" VARCHAR2(400), \n" + + " \"CONTRACT_NUMBER\" VARCHAR2(40), \n" + + " \"CUSTOMER_ID\" NUMBER(10,0), \n" + + " \"DEPT_ID\" NUMBER(10,0), \n" + + " \"END_USER\" VARCHAR2(200), \n" + + " \"USER_CON_NUMBER\" VARCHAR2(200), \n" + + " \"CONTRACT_STATUS\" NUMBER(10,0) DEFAULT 10, \n" + + " \"HC_RECEIVE_DATE\" DATE, \n" + + " \"ISSUE_CONFIRM_DATE\" DATE, \n" + + " \"CONCLUDE_ADDRESS\" VARCHAR2(200), \n" + + " \"CONCLUDE_DATE\" DATE, \n" + + " \"CHECK_DATE\" DATE, \n" + + " \"E_ORDER_NUMBER\" VARCHAR2(32), \n" + + " \"FIRST_SIGN_PERSON\" VARCHAR2(30), \n" + + " \"SECOND_SIGN_PERSON\" VARCHAR2(30), \n" + + " \"SMALL_SIGN_DATE\" DATE, \n" + + " \"TRAIN_FLAG\" CHAR(1), \n" + + " \"MEMO\" VARCHAR2(200), \n" + + " \"SYNC_STATUS\" CHAR(1) DEFAULT 'N', \n" + + " \"SYNC_TIME\" TIMESTAMP (6), \n" + + " \"CREATED_BY\" NUMBER(10,0), \n" + + " \"CREATION_DATE\" TIMESTAMP (6), \n" + + " \"LAST_UPDATED_BY\" NUMBER(10,0), \n" + + " \"LAST_UPDATE_DATE\" TIMESTAMP (6), \n" + + " \"ENABLED_FLAG\" CHAR(1), \n" + + " \"CONTRACT_TYPE\" NUMBER(10,0), \n" + + " \"CONTRACT_ATTRIBUTE\" VARCHAR2(10), \n" + + " \"DELIVER_METHOD\" VARCHAR2(10), \n" + + " \"TRANSPORT_METHOD\" VARCHAR2(10), \n" + + " \"MASTER_DEPT_ID\" NUMBER(10,0), \n" + + " \"CONTRACT_CLASS\" VARCHAR2(30), \n" + + " \"ACTUAL_EFFECT_DATE\" DATE, \n" + + " \"FORMAL_FLAG\" CHAR(1), \n" + + " \"THIRD_FLAG\" CHAR(1), \n" + + " \"ACCEPTANCE_FORMAL_DATE\" DATE, \n" + + " \"CURRENCY_CODE\" VARCHAR2(30), \n" + + " \"ORG_ID\" NUMBER(10,0) DEFAULT 1, \n" + + " \"PROJECT_NUMBER\" VARCHAR2(50), \n" + + " \"CONTRACT_PROPERTY\" VARCHAR2(10), \n" + + " \"MARKET_PROPERTY_ID\" VARCHAR2(11), \n" + + " \"SUBMIT_TIME\" TIMESTAMP (6), \n" + + " \"PRODUCT_BIG_TYPE\" NUMBER(10,0), \n" + + " \"CONTRACT_SUM_CORPORATION\" VARCHAR2(200), \n" + + " \"CONTRACT_SUM_MONEY\" NUMBER(18,4), \n" + + " \"CONTRACT_MONEY_TYPE\" NUMBER(10,0), \n" + + " \"TAKE_EFFECT_CONDITION\" VARCHAR2(200), \n" + + " \"PROJECT_EST_OID\" NUMBER(10,0), \n" + + " \"NEW_FLAG\" VARCHAR2(1) DEFAULT 'N', \n" + + " \"LEGAL_ENTITY_ID\" NUMBER(10,0), \n" + + " \"PO_FLAG\" VARCHAR2(1) DEFAULT 'N', \n" + + " \"EFFECT_DEPT_ID\" NUMBER(10,0), \n" + + " \"PROJECT_ID\" NUMBER(12,0), \n" + + " \"SELLER\" VARCHAR2(60), \n" + + " \"BUYER\" VARCHAR2(60), \n" + + " \"BUYER_TYPE\" VARCHAR2(5), \n" + + " \"SIGN_TYPE\" VARCHAR2(5), \n" + + " \"TRANS_CON_ID\" VARCHAR2(200), \n" + + " \"TRANS_CON_NUMBER\" VARCHAR2(1000), \n" + + " \"CON_HEADER_ID\" NUMBER(10,0), \n" + + " \"SUBMIT_FLAG\" VARCHAR2(1), \n" + + " \"APPROVE_DATE\" TIMESTAMP (6), \"CURR_HIS_ID\" NUMBER, \"LAST_UPD_HIS_ID\" NUMBER, \n" + + " \"TRANS_CON_FLAG\" VARCHAR2(1), \"SUPPLY_FLAG\" VARCHAR2(1), \"SUPPLY_PATH\" VARCHAR2(300), \n" + + " \"CON_TYPE\" NUMBER(2,0), \"TRANS_TYPE\" NUMBER(2,0), \n" + + " \"TRANS_SUBCOMPANY\" VARCHAR2(100), \"SIGN_CUSTOMER\" VARCHAR2(100), \"MTO\" NUMBER(3,0), \n" + + " \"NEED_SURVEY\" VARCHAR2(1), \"TRANS_CURRENCY_CODE\" VARCHAR2(30), \"TRANS_CONTRACT_MONEY\" NUMBER(15,2), \n" + + " \"OPERATING_DEPARTMENT\" VARCHAR2(500), \"SIEBLE_ID\" VARCHAR2(15), \"ORDER_TYPE\" VARCHAR2(50), \n" + + " \"SIEBLE_SALE_CONTRACT_ID\" VARCHAR2(15), \"ECC_SALE_CONTRACT_ID\" NUMBER(10,0), \"SALE_CONTRACT_NO\" VARCHAR2(40), \n" + + " \"MID_TRANS_CURRENCY_CODE\" VARCHAR2(30), \"PROJECT_TASK_ID\" VARCHAR2(15), \"SALE_MODEL_ONE\" VARCHAR2(30), \n" + + " \"SALE_MODEL_TWO\" VARCHAR2(30), \"CONTRACTHEAD_TYPE\" VARCHAR2(30), \n" + + " \"PO_RECEIVE_DATE\" DATE, \"TRANS_CODE\" VARCHAR2(10), \"TRANS_MONEY4\" VARCHAR2(30), \n" + + " \"CALC_CON_ID\" VARCHAR2(10), \"ELECTRONPO\" VARCHAR2(1), \"TRANS_MONEY\" NUMBER(22,4), \n" + + " \"IS_COUPON\" VARCHAR2(1), \"TRADE_TERM\" VARCHAR2(50), \"IS_TAX\" VARCHAR2(1), \n" + + " \"TAX_CATEGORIES\" VARCHAR2(50), \"TAX_CODE\" VARCHAR2(50), \"PACT_CURRENCY\" VARCHAR2(10), \n" + + " \"IS_AUTO_EMERGE\" VARCHAR2(1), \"SEND_MAIL_TIME\" TIMESTAMP (6), \"CREATE_TYPE\" VARCHAR2(10), \n" + + " CONSTRAINT \"P_ECC_CPR_HC_CON_H\" PRIMARY KEY (\"HC_CON_ID\") \n" + + " USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS \n" + + " STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 \n" + + " PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT) \n" + + " TABLESPACE \"ECC_CPR_IDX_TSP\" ENABLE \n" + + ") PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING \n" + + " STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 \n" + + " PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT) \n" + + " TABLESPACE \"ECC_CPR_TSP\";\n" + ; + + String sql_2 = "\nCREATE TABLE \"ECC_CPR\".\"ECC_CPR_HC_CON_PERSON\" (\n" + + "\t\"LAST_UPDATE_DATE\" TIMESTAMP(6),\n" + + "\t\"LAST_UPDATED_BY\" NUMBER,\n" + + "\t\"CREATION_DATE\" TIMESTAMP(6),\n" + + "\t\"CREATED_BY\" NUMBER,\n" + + "\t\"LAST_UPDATE_LOGIN\" NUMBER,\n" + + "\t\"CON_PERSON_ID\" NUMBER NOT NULL ENABLE,\n" + + "\t\"HC_CON_ID\" NUMBER NOT NULL ENABLE,\n" + + "\t\"PERSON_CLASS\" VARCHAR2(30),\n" + + "\t\"CONTACT_NAME\" VARCHAR2(120),\n" + + "\t\"CONTACT_TEL\" VARCHAR2(80),\n" + + "\t\"SUBMIT_FLAG\" CHAR(1),\n" + + "\t\"SYNC_STATUS\" CHAR(1) DEFAULT 'N',\n" + + "\t\"SYNC_TIME\" TIMESTAMP(6),\n" + + "\t\"ENABLED_FLAG\" CHAR(1),\n" + + "\tCONSTRAINT \"ECC_CPR_HC_CON_PERSON_PK\" PRIMARY KEY (\"CON_PERSON_ID\")\n" + + "\t\tUSING INDEX\n" + + "\t\tPCTFREE 10\n" + + "\t\tINITRANS 2\n" + + "\t\tMAXTRANS 255\n" + + "\t\tTABLESPACE \"ECC_CPR_IDX_TSP\"\n" + + "\t\tSTORAGE (\n" + + "\t\t\tINITIAL 65536\n" + + "\t\t\tNEXT 1048576\n" + + "\t\t\tMINEXTENTS 1\n" + + "\t\t\tMAXEXTENTS 2147483645\n" + + "\t\t\tPCTINCREASE 0\n" + + "\t\t\tFREELISTS 1\n" + + "\t\t\tFREELIST GROUPS 1\n" + + "\t\t\tBUFFER_POOL DEFAULT\n" + + "\t\t)\n" + + "\t\tCOMPUTE STATISTICS\n" + + "\t\tENABLE,\n" + + "\tCONSTRAINT \"ECC_CPR_HC_CON_PERSON_FK\" FOREIGN KEY (\"HC_CON_ID\")\n" + + "\t\tREFERENCES \"ECC_CPR\".\"ECC_CPR_HC_CON_HEAHERS\" (\"HC_CON_ID\") ENABLE\n" + + ")\n" + + "PCTFREE 10\n" + + "PCTUSED 40\n" + + "INITRANS 1\n" + + "MAXTRANS 255\n" + + "NOCOMPRESS\n" + + "LOGGING\n" + + "TABLESPACE \"ECC_CPR_TSP\"\n" + + "STORAGE (\n" + + "\tINITIAL 65536\n" + + "\tNEXT 1048576\n" + + "\tMINEXTENTS 1\n" + + "\tMAXEXTENTS 2147483645\n" + + "\tPCTINCREASE 0\n" + + "\tFREELISTS 1\n" + + "\tFREELIST GROUPS 1\n" + + "\tBUFFER_POOL DEFAULT\n" + + ");"; + + repository.console(sql_1); + + + OracleCreateTableStatement stmt = (OracleCreateTableStatement) SQLParserUtils.createSQLStatementParser(sql_2, JdbcConstants.ORACLE).parseStatement(); + + repository.resolve(stmt); + } +}