From 833a9b5a6597116adaf4ff1a7ae771752dc3b14a Mon Sep 17 00:00:00 2001 From: wenshao Date: Mon, 28 Aug 2017 01:26:21 +0800 Subject: [PATCH] refactor sql parser. --- .../com/alibaba/druid/sql/ast/SQLName.java | 2 + .../sql/ast/expr/SQLBinaryOpExprGroup.java | 20 + .../druid/sql/ast/expr/SQLIdentifierExpr.java | 27 +- .../druid/sql/ast/expr/SQLPropertyExpr.java | 37 +- .../statement/SQLCreateTableStatement.java | 14 +- .../sql/ast/statement/SQLExprTableSource.java | 49 +- .../sql/ast/statement/SQLJoinTableSource.java | 29 +- .../sql/ast/statement/SQLSelectItem.java | 33 +- .../ast/statement/SQLSelectQueryBlock.java | 18 +- .../ast/statement/SQLSubqueryTableSource.java | 17 + .../sql/ast/statement/SQLTableSource.java | 4 + .../sql/ast/statement/SQLTableSourceImpl.java | 35 +- .../sql/ast/statement/SQLUpdateStatement.java | 1 + .../ast/statement/SQLWithSubqueryClause.java | 71 +- .../sql/dialect/db2/parser/DB2ExprParser.java | 6 + .../sql/dialect/db2/parser/DB2Lexer.java | 9 + .../db2/parser/DB2StatementParser.java | 5 + .../db2/visitor/DB2SchemaStatVisitor.java | 7 +- .../dialect/mysql/ast/expr/MySqlUserName.java | 28 + .../sql/dialect/mysql/parser/MySqlLexer.java | 27 +- .../mysql/visitor/MySqlOutputVisitor.java | 151 ++- .../mysql/visitor/MySqlSchemaStatVisitor.java | 49 +- .../transform/FromSubqueryResolver.java | 2 +- .../odps/visitor/OdpsOutputVisitor.java | 36 +- .../odps/visitor/OdpsSchemaStatVisitor.java | 5 + .../ast/clause/OracleWithSubqueryEntry.java | 1 - .../oracle/ast/expr/OracleDbLinkExpr.java | 28 + .../oracle/parser/OracleSelectParser.java | 139 +- .../oracle/visitor/OracleOutputVisitor.java | 159 ++- .../visitor/OracleSchemaStatVisitor.java | 5 +- .../visitor/PhoenixSchemaStatVisitor.java | 4 + .../dialect/postgresql/ast/PGWithClause.java | 62 - .../dialect/postgresql/ast/PGWithQuery.java | 85 -- .../ast/stmt/PGDeleteStatement.java | 9 +- .../ast/stmt/PGInsertStatement.java | 8 +- .../ast/stmt/PGSelectQueryBlock.java | 12 - .../ast/stmt/PGSelectStatement.java | 12 - .../ast/stmt/PGUpdateStatement.java | 13 +- .../postgresql/parser/PGExprParser.java | 7 + .../dialect/postgresql/parser/PGLexer.java | 6 +- .../parser/PGSQLStatementParser.java | 93 +- .../postgresql/visitor/PGASTVisitor.java | 10 - .../visitor/PGASTVisitorAdapter.java | 23 - .../postgresql/visitor/PGOutputVisitor.java | 96 +- .../visitor/PGSchemaStatVisitor.java | 50 +- .../expr/SQLServerObjectReferenceExpr.java | 29 + .../ast/stmt/SQLServerUpdateStatement.java | 6 + .../sqlserver/parser/SQLServerExprParser.java | 7 + .../sqlserver/parser/SQLServerLexer.java | 13 +- .../parser/SQLServerSelectParser.java | 11 +- .../parser/SQLServerStatementParser.java | 10 +- .../visitor/SQLServerOutputVisitor.java | 86 +- .../visitor/SQLServerSchemaStatVisitor.java | 7 +- .../druid/sql/parser/SQLExprParser.java | 27 +- .../druid/sql/parser/SQLSelectParser.java | 60 +- .../druid/sql/parser/SQLStatementParser.java | 88 +- .../druid/sql/repository/SchemaObject.java | 1 + .../sql/repository/SchemaObjectImpl.java | 8 +- .../sql/repository/SchemaRepository.java | 288 +--- .../sql/repository/SchemaResolveVisitor.java | 50 +- .../SchemaResolveVisitorFactory.java | 1200 +++++++++++++++++ .../sql/visitor/SQLASTOutputVisitor.java | 371 ++--- .../druid/sql/visitor/SchemaStatVisitor.java | 141 +- .../com/alibaba/druid/stat/TableStat.java | 18 +- .../java/com/alibaba/druid/util/FNVUtils.java | 41 + .../java/com/alibaba/druid/util/Utils.java | 1 + .../druid/wall/spi/DB2WallProvider.java | 3 +- .../druid/wall/spi/MySqlWallProvider.java | 3 +- .../druid/wall/spi/OracleWallProvider.java | 3 +- .../druid/wall/spi/PGWallProvider.java | 3 +- .../druid/wall/spi/SQLServerWallProvider.java | 3 +- .../benckmark/sql/MySqlInsertBenchmark_2.java | 6 +- .../sql/MySqlParameterizedBenchmark.java | 46 +- .../druid/benckmark/sql/SqlHolder.java | 100 +- .../com/alibaba/druid/bvt/sql/HashTest_0.java | 21 + .../bvt/sql/HashTest_1_propertyExpr.java | 22 + .../createTable/MySqlCreateTableTest18.java | 2 +- .../sql/mysql/select/MySqlSelectTest_16.java | 6 +- .../postgresql/PGASTVisitorAdapterTest.java | 4 - .../bvt/sql/postgresql/PGDeleteTest5.java | 2 +- .../bvt/sql/postgresql/PGDeleteTest6.java | 3 +- .../bvt/sql/postgresql/PGDeleteTest8.java | 7 +- .../bvt/sql/postgresql/PGInsertTest5.java | 4 +- .../sql/postgresql/select/PGSelectTest13.java | 8 +- .../sql/postgresql/select/PGSelectTest14.java | 14 +- .../sql/postgresql/select/PGSelectTest15.java | 23 +- .../sql/postgresql/select/PGSelectTest16.java | 10 +- .../sql/postgresql/select/PGSelectTest17.java | 8 +- .../sql/postgresql/select/PGSelectTest18.java | 46 +- .../sql/postgresql/select/PGSelectTest21.java | 8 +- .../sql/postgresql/select/PGSelectTest49.java | 10 +- 91 files changed, 2964 insertions(+), 1368 deletions(-) delete mode 100644 src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/PGWithClause.java delete mode 100644 src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/PGWithQuery.java create mode 100644 src/main/java/com/alibaba/druid/sql/repository/SchemaResolveVisitorFactory.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/HashTest_0.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/HashTest_1_propertyExpr.java diff --git a/src/main/java/com/alibaba/druid/sql/ast/SQLName.java b/src/main/java/com/alibaba/druid/sql/ast/SQLName.java index fd0e02f8fb..65f4e03c6f 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/SQLName.java +++ b/src/main/java/com/alibaba/druid/sql/ast/SQLName.java @@ -19,4 +19,6 @@ public interface SQLName extends SQLExpr { String getSimpleName(); SQLName clone(); + + long name_hash_lower(); } diff --git a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLBinaryOpExprGroup.java b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLBinaryOpExprGroup.java index 0b0bab1f80..b84c4138b7 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLBinaryOpExprGroup.java +++ b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLBinaryOpExprGroup.java @@ -1,5 +1,21 @@ +/* + * 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.sql.ast.expr; +import com.alibaba.druid.sql.SQLUtils; import com.alibaba.druid.sql.ast.SQLExpr; import com.alibaba.druid.sql.ast.SQLExprImpl; import com.alibaba.druid.sql.visitor.SQLASTVisitor; @@ -75,4 +91,8 @@ public class SQLBinaryOpExprGroup extends SQLExprImpl { public SQLBinaryOperator getOperator() { return operator; } + + 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 1052711c10..91b2b48aa7 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 @@ -68,9 +68,28 @@ public class SQLIdentifierExpr extends SQLExprImpl implements SQLName { return lowerName; } - public long hash_lower() { - if (hash_lower == 0) { - hash_lower = FNVUtils.fnv_64_lower(name); + public long name_hash_lower() { + if (hash_lower == 0 + && name != null) { + final int len = name.length(); + + boolean quote = false; + + String name = this.name; + if (len > 2) { + char c0 = name.charAt(0); + char c1 = name.charAt(len - 1); + if ((c0 == '`' && c1 == '`') + || (c0 == '"' && c1 == '"') + || (c0 == '[' && c1 == ']')) { + quote = true; + } + } + if (quote) { + hash_lower = FNVUtils.fnv_64_lower(name, 1, len -1); + } else { + hash_lower = FNVUtils.fnv_64_lower(name); + } } return hash_lower; } @@ -200,7 +219,7 @@ public class SQLIdentifierExpr extends SQLExprImpl implements SQLName { if (queryBlock == null) { return null; } - SQLSelectItem selectItem = queryBlock.findSelectItem(name); + SQLSelectItem selectItem = queryBlock.findSelectItem(name_hash_lower()); if (selectItem != null) { return selectItem.computeDataType(); } 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 c04a2386f4..f432885a1c 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 @@ -23,12 +23,15 @@ import com.alibaba.druid.sql.ast.SQLName; import com.alibaba.druid.sql.ast.statement.*; import com.alibaba.druid.sql.parser.ParserException; import com.alibaba.druid.sql.visitor.SQLASTVisitor; +import com.alibaba.druid.util.FNVUtils; public class SQLPropertyExpr extends SQLExprImpl implements SQLName { private SQLExpr owner; private String name; + protected long name_hash_lower; + private transient SQLColumnDefinition resolvedColumn; private transient SQLTableSource resolvedTableSource; @@ -41,6 +44,12 @@ public class SQLPropertyExpr extends SQLExprImpl implements SQLName { this.name = name; } + public SQLPropertyExpr(SQLExpr owner, String name, long name_hash_lower){ + setOwner(owner); + this.name = name; + this.name_hash_lower = name_hash_lower; + } + public SQLPropertyExpr(){ } @@ -153,6 +162,32 @@ public class SQLPropertyExpr extends SQLExprImpl implements SQLName { return false; } + public long name_hash_lower() { + if (name_hash_lower == 0 + && name != null) { + final int len = name.length(); + + boolean quote = false; + + String name = this.name; + if (len > 2) { + char c0 = name.charAt(0); + char c1 = name.charAt(len - 1); + if ((c0 == '`' && c1 == '`') + || (c0 == '"' && c1 == '"') + || (c0 == '[' && c1 == ']')) { + quote = true; + } + } + if (quote) { + name_hash_lower = FNVUtils.fnv_64_lower(name, 1, len -1); + } else { + name_hash_lower = FNVUtils.fnv_64_lower(name); + } + } + return name_hash_lower; + } + public String normalizedName() { String ownerName; @@ -195,7 +230,7 @@ public class SQLPropertyExpr extends SQLExprImpl implements SQLName { if (queryBlock == null) { return null; } - SQLSelectItem selectItem = queryBlock.findSelectItem(name); + SQLSelectItem selectItem = queryBlock.findSelectItem(name_hash_lower()); if (selectItem != null) { return selectItem.computeDataType(); } diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateTableStatement.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateTableStatement.java index daffd868da..a3373f83d7 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateTableStatement.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateTableStatement.java @@ -28,6 +28,7 @@ import com.alibaba.druid.sql.dialect.mysql.ast.MySqlPrimaryKey; import com.alibaba.druid.sql.dialect.mysql.ast.MySqlUnique; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlTableIndex; import com.alibaba.druid.sql.visitor.SQLASTVisitor; +import com.alibaba.druid.util.FNVUtils; import com.alibaba.druid.util.ListDG; import com.alibaba.druid.util.lang.Consumer; @@ -216,13 +217,20 @@ public class SQLCreateTableStatement extends SQLStatementImpl implements SQLDDLS } public SQLColumnDefinition findColumn(String columName) { - columName = SQLUtils.normalize(columName); + if (columName == null) { + return null; + } + long hash = FNVUtils.fnv_64_lower_normalized(columName); + return findColumn(hash); + } + + public SQLColumnDefinition findColumn(long columName_hash) { for (SQLTableElement element : tableElementList) { if (element instanceof SQLColumnDefinition) { SQLColumnDefinition column = (SQLColumnDefinition) element; - String name = column.computeAlias(); - if (columName.equalsIgnoreCase(name)) { + SQLName columnName = column.getName(); + if (columnName != null && columnName.name_hash_lower() == columName_hash) { return column; } } diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLExprTableSource.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLExprTableSource.java index 67cd45c66b..a9aba9b6c4 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLExprTableSource.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLExprTableSource.java @@ -27,6 +27,7 @@ import com.alibaba.druid.sql.ast.expr.SQLIntegerExpr; import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr; import com.alibaba.druid.sql.repository.SchemaObject; import com.alibaba.druid.sql.visitor.SQLASTVisitor; +import com.alibaba.druid.util.FNVUtils; public class SQLExprTableSource extends SQLTableSourceImpl { @@ -211,7 +212,29 @@ public class SQLExprTableSource extends SQLTableSourceImpl { return false; } + public boolean containsAlias(long aliasHash) { + if (this.alias_hash() == aliasHash) { + return true; + } + + if (expr instanceof SQLName) { + long exprNameHash = ((SQLName) expr).name_hash_lower(); + return exprNameHash == alias_hash; + } + + return false; + } + public SQLColumnDefinition findColumn(String columnName) { + if (columnName == null) { + return null; + } + + long hash = FNVUtils.fnv_64_lower_normalized(columnName); + return findColumn(hash); + } + + public SQLColumnDefinition findColumn(long columnNameHash) { if (schemaObject == null) { return null; } @@ -219,12 +242,21 @@ public class SQLExprTableSource extends SQLTableSourceImpl { SQLStatement stmt = schemaObject.getStatement(); if (stmt instanceof SQLCreateTableStatement) { SQLCreateTableStatement createTableStmt = (SQLCreateTableStatement) stmt; - return createTableStmt.findColumn(columnName); + return createTableStmt.findColumn(columnNameHash); } return null; } public SQLTableSource findTableSourceWithColumn(String columnName) { + if (columnName == null) { + return null; + } + + long hash = FNVUtils.fnv_64_lower_normalized(columnName); + return findTableSourceWithColumn(hash); + } + + public SQLTableSource findTableSourceWithColumn(long columnName_hash) { if (schemaObject == null) { return null; } @@ -232,7 +264,7 @@ public class SQLExprTableSource extends SQLTableSourceImpl { SQLStatement stmt = schemaObject.getStatement(); if (stmt instanceof SQLCreateTableStatement) { SQLCreateTableStatement createTableStmt = (SQLCreateTableStatement) stmt; - if (createTableStmt.findColumn(columnName) != null) { + if (createTableStmt.findColumn(columnName_hash) != null) { return this; } } @@ -240,17 +272,20 @@ public class SQLExprTableSource extends SQLTableSourceImpl { return null; } - public SQLTableSource findTableSource(String alias) { - if (alias == null) { + public SQLTableSource findTableSource(long alias_hash) { + if (alias_hash == 0) { return null; } - if (SQLUtils.nameEquals(alias, computeAlias())) { + if (alias_hash() == alias_hash) { return this; } - if (containsAlias(alias)) { - return this; + if (expr instanceof SQLName) { + long exprNameHash = ((SQLName) expr).name_hash_lower(); + if (exprNameHash == alias_hash) { + return this; + } } return null; diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLJoinTableSource.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLJoinTableSource.java index 6aa48a61b8..f5c147ed42 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLJoinTableSource.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLJoinTableSource.java @@ -28,6 +28,7 @@ import com.alibaba.druid.sql.ast.expr.SQLBinaryOperator; import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr; import com.alibaba.druid.sql.visitor.SQLASTVisitor; +import com.alibaba.druid.util.FNVUtils; public class SQLJoinTableSource extends SQLTableSourceImpl implements SQLReplaceable { @@ -416,15 +417,20 @@ public class SQLJoinTableSource extends SQLTableSourceImpl implements SQLReplace } public SQLColumnDefinition findColumn(String columnName) { + long hash = FNVUtils.fnv_64_lower_normalized(columnName); + return findColumn(hash); + } + + public SQLColumnDefinition findColumn(long columnNameHash) { if (left != null) { - SQLColumnDefinition column = left.findColumn(columnName); + SQLColumnDefinition column = left.findColumn(columnNameHash); if (column != null) { return column; } } if (right != null) { - return right.findColumn(columnName); + return right.findColumn(columnNameHash); } return null; @@ -432,15 +438,20 @@ public class SQLJoinTableSource extends SQLTableSourceImpl implements SQLReplace @Override public SQLTableSource findTableSourceWithColumn(String columnName) { + long hash = FNVUtils.fnv_64_lower_normalized(columnName); + return findTableSourceWithColumn(hash); + } + + public SQLTableSource findTableSourceWithColumn(long columnNameHash) { if (left != null) { - SQLTableSource tableSource = left.findTableSourceWithColumn(columnName); + SQLTableSource tableSource = left.findTableSourceWithColumn(columnNameHash); if (tableSource != null) { return tableSource; } } if (right != null) { - return right.findTableSourceWithColumn(columnName); + return right.findTableSourceWithColumn(columnNameHash); } return null; @@ -517,20 +528,20 @@ public class SQLJoinTableSource extends SQLTableSourceImpl implements SQLReplace return joined; } - public SQLTableSource findTableSource(String alias) { - if (alias == null) { + public SQLTableSource findTableSource(long alias_hash) { + if (alias_hash == 0) { return null; } - if (SQLUtils.nameEquals(alias, computeAlias())) { + if (alias_hash() == alias_hash) { return this; } - SQLTableSource result = left.findTableSource(alias); + SQLTableSource result = left.findTableSource(alias_hash); if (result != null) { return result; } - return right.findTableSource(alias); + return right.findTableSource(alias_hash); } } diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectItem.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectItem.java index 62d89d5982..e5ad85a248 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectItem.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectItem.java @@ -21,13 +21,17 @@ import com.alibaba.druid.sql.ast.expr.SQLAllColumnExpr; import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr; import com.alibaba.druid.sql.visitor.SQLASTVisitor; +import com.alibaba.druid.util.FNVUtils; public class SQLSelectItem extends SQLObjectImpl implements SQLReplaceable { protected SQLExpr expr; protected String alias; + protected boolean connectByRoot = false; + protected transient long alias_hash; + public SQLSelectItem(){ } @@ -170,24 +174,39 @@ public class SQLSelectItem extends SQLObjectImpl implements SQLReplaceable { return false; } - String alias_normalized = SQLUtils.normalize(alias); + long hash = FNVUtils.fnv_64_lower_normalized(alias); + return match(hash); + } - if (alias_normalized.equalsIgnoreCase(this.alias)) { + public long alias_hash() { + if (this.alias_hash == 0) { + this.alias_hash = FNVUtils.fnv_64_lower_normalized(alias); + } + return alias_hash; + } + + public boolean match(long alias_hash) { + if (alias == null) { + return false; + } + + long hash = alias_hash(); + + if (hash == alias_hash) { return true; } if (expr instanceof SQLAllColumnExpr) { SQLTableSource resolvedTableSource = ((SQLAllColumnExpr) expr).getResolvedTableSource(); if (resolvedTableSource != null - && resolvedTableSource.findColumn(alias) != null) { + && resolvedTableSource.findColumn(alias_hash) != null) { return true; } return false; } if (expr instanceof SQLIdentifierExpr) { - String ident = ((SQLIdentifierExpr) expr).getName(); - return alias_normalized.equalsIgnoreCase(SQLUtils.normalize(ident)); + return ((SQLIdentifierExpr) expr).name_hash_lower() == alias_hash; } if (expr instanceof SQLPropertyExpr) { @@ -195,13 +214,13 @@ public class SQLSelectItem extends SQLObjectImpl implements SQLReplaceable { if ("*".equals(ident)) { SQLTableSource resolvedTableSource = ((SQLPropertyExpr) expr).getResolvedTableSource(); if (resolvedTableSource != null - && resolvedTableSource.findColumn(alias) != null) { + && resolvedTableSource.findColumn(alias_hash) != null) { return true; } return false; } - return alias_normalized.equalsIgnoreCase(SQLUtils.normalize(ident)); + return ((SQLPropertyExpr) expr).name_hash_lower() == alias_hash; } return false; diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectQueryBlock.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectQueryBlock.java index c2890036b7..5974306ea9 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectQueryBlock.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectQueryBlock.java @@ -25,6 +25,7 @@ import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; import com.alibaba.druid.sql.ast.expr.SQLIntegerExpr; import com.alibaba.druid.sql.repository.SchemaObject; import com.alibaba.druid.sql.visitor.SQLASTVisitor; +import com.alibaba.druid.util.FNVUtils; public class SQLSelectQueryBlock extends SQLObjectImpl implements SQLSelectQuery, SQLReplaceable { private boolean bracket = false; @@ -448,6 +449,13 @@ public class SQLSelectQueryBlock extends SQLObjectImpl implements SQLSelectQuery return from.findTableSourceWithColumn(column); } + public SQLTableSource findTableSourceWithColumn(long columnHash) { + if (from == null) { + return null; + } + return from.findTableSourceWithColumn(columnHash); + } + @Override public boolean replace(SQLExpr expr, SQLExpr target) { if (where == expr) { @@ -462,10 +470,13 @@ public class SQLSelectQueryBlock extends SQLObjectImpl implements SQLSelectQuery return null; } - String ident_normalized = SQLUtils.normalize(ident); + long hash = FNVUtils.fnv_64_lower_normalized(ident); + return findSelectItem(hash); + } + public SQLSelectItem findSelectItem(long identHash) { for (SQLSelectItem item : this.selectList) { - if (item.match(ident_normalized)) { + if (item.match(identHash)) { return item; } } @@ -478,7 +489,8 @@ public class SQLSelectQueryBlock extends SQLObjectImpl implements SQLSelectQuery return null; } - return from.findColumn(columnName); + long hash = FNVUtils.fnv_64_lower_normalized(columnName); + return from.findColumn(hash); } public void addCondition(SQLExpr expr) { diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSubqueryTableSource.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSubqueryTableSource.java index d7ff0450ed..491d92c6f5 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSubqueryTableSource.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSubqueryTableSource.java @@ -94,4 +94,21 @@ public class SQLSubqueryTableSource extends SQLTableSourceImpl { return null; } + + public SQLTableSource findTableSourceWithColumn(long columnNameHash) { + if (select == null) { + return null; + } + + SQLSelectQueryBlock queryBlock = select.getFirstQueryBlock(); + if (queryBlock == null) { + return null; + } + + if (queryBlock.findSelectItem(columnNameHash) != null) { + return this; + } + + return null; + } } diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLTableSource.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLTableSource.java index 627ed79eca..672904c022 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLTableSource.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLTableSource.java @@ -38,7 +38,11 @@ public interface SQLTableSource extends SQLObject { void setFlashback(SQLExpr flashback); SQLColumnDefinition findColumn(String columnName); + SQLColumnDefinition findColumn(long columnNameHash); + SQLTableSource findTableSourceWithColumn(String columnName); + SQLTableSource findTableSourceWithColumn(long columnName_hash); SQLTableSource findTableSource(String alias); + SQLTableSource findTableSource(long alias_hash); } diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLTableSourceImpl.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLTableSourceImpl.java index d03d018ceb..55996c4147 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLTableSourceImpl.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLTableSourceImpl.java @@ -22,6 +22,7 @@ import com.alibaba.druid.sql.SQLUtils; import com.alibaba.druid.sql.ast.SQLExpr; import com.alibaba.druid.sql.ast.SQLHint; import com.alibaba.druid.sql.ast.SQLObjectImpl; +import com.alibaba.druid.util.FNVUtils; public abstract class SQLTableSourceImpl extends SQLObjectImpl implements SQLTableSource { @@ -31,12 +32,13 @@ public abstract class SQLTableSourceImpl extends SQLObjectImpl implements SQLTab protected SQLExpr flashback; + protected long alias_hash; + public SQLTableSourceImpl(){ } public SQLTableSourceImpl(String alias){ - this.alias = alias; } @@ -46,6 +48,7 @@ public abstract class SQLTableSourceImpl extends SQLObjectImpl implements SQLTab public void setAlias(String alias) { this.alias = alias; + this.alias_hash = 0L; } public int getHintsSize() { @@ -86,7 +89,6 @@ public abstract class SQLTableSourceImpl extends SQLObjectImpl implements SQLTab this.flashback = flashback; } - public boolean containsAlias(String alias) { if (SQLUtils.nameEquals(this.alias, alias)) { return true; @@ -95,23 +97,40 @@ public abstract class SQLTableSourceImpl extends SQLObjectImpl implements SQLTab return false; } + public long alias_hash() { + if (alias_hash == 0 + && alias != null) { + alias_hash = FNVUtils.fnv_64_lower_normalized(alias); + } + return alias_hash; + } + public SQLColumnDefinition findColumn(String columnName) { return null; } + public SQLColumnDefinition findColumn(long columnNameHash) { + return null; + } + public SQLTableSource findTableSourceWithColumn(String columnName) { return null; } - public SQLTableSource findTableSource(String alias) { - if (alias == null) { - return null; - } + public SQLTableSource findTableSourceWithColumn(long columnNameHash) { + return null; + } - if (SQLUtils.nameEquals(alias, computeAlias())) { + public SQLTableSource findTableSource(String alias) { + long hash = FNVUtils.fnv_64_lower_normalized(alias); + return findTableSource(hash); + } + + public SQLTableSource findTableSource(long alias_hash) { + long hash = this.alias_hash(); + if (hash != 0 && hash == alias_hash) { return this; } - return null; } } diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLUpdateStatement.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLUpdateStatement.java index 78f6cdc503..3bb4417e76 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLUpdateStatement.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLUpdateStatement.java @@ -133,6 +133,7 @@ public class SQLUpdateStatement extends SQLStatementImpl implements SQLReplaceab protected void accept0(SQLASTVisitor visitor) { if (visitor.visit(this)) { acceptChild(visitor, tableSource); + acceptChild(visitor, from); acceptChild(visitor, items); acceptChild(visitor, where); } diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLWithSubqueryClause.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLWithSubqueryClause.java index b6e91c6c30..8a8f7103ad 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLWithSubqueryClause.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLWithSubqueryClause.java @@ -20,6 +20,7 @@ import java.util.List; import com.alibaba.druid.sql.ast.SQLName; import com.alibaba.druid.sql.ast.SQLObjectImpl; +import com.alibaba.druid.sql.ast.SQLStatement; import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; import com.alibaba.druid.sql.visitor.SQLASTVisitor; @@ -28,6 +29,19 @@ public class SQLWithSubqueryClause extends SQLObjectImpl { private Boolean recursive; private final List entries = new ArrayList(); + public SQLWithSubqueryClause clone() { + SQLWithSubqueryClause x = new SQLWithSubqueryClause(); + x.recursive = recursive; + + for (Entry entry : entries) { + Entry entry2 = entry.clone(); + entry2.setParent(x); + x.entries.add(entry2); + } + + return x; + } + public List getEntries() { return entries; } @@ -55,41 +69,76 @@ public class SQLWithSubqueryClause extends SQLObjectImpl { visitor.endVisit(this); } - public static class Entry extends SQLObjectImpl { + public static class Entry extends SQLTableSourceImpl { - protected SQLIdentifierExpr name; protected final List columns = new ArrayList(); protected SQLSelect subQuery; + protected SQLStatement returningStatement; + + public Entry clone() { + Entry x = new Entry(); + + for (SQLName column : columns) { + SQLName column2 = column.clone(); + column2.setParent(x); + x.columns.add(column2); + } + + if (subQuery != null) { + x.setSubQuery(subQuery.clone()); + } + + return x; + } @Override protected void accept0(SQLASTVisitor visitor) { if (visitor.visit(this)) { - acceptChild(visitor, name); acceptChild(visitor, columns); acceptChild(visitor, subQuery); + acceptChild(visitor, returningStatement); } visitor.endVisit(this); } - public SQLIdentifierExpr getName() { - return name; - } - - public void setName(SQLIdentifierExpr name) { - this.name = name; - } - public SQLSelect getSubQuery() { return subQuery; } public void setSubQuery(SQLSelect subQuery) { + if (subQuery != null) { + subQuery.setParent(this); + } this.subQuery = subQuery; } + public SQLStatement getReturningStatement() { + return returningStatement; + } + + public void setReturningStatement(SQLStatement returningStatement) { + if (returningStatement != null) { + returningStatement.setParent(this); + } + this.returningStatement = returningStatement; + } + public List getColumns() { return columns; } + } + public Entry findEntry(long alias_hash) { + if (alias_hash == 0) { + return null; + } + + for (Entry entry : entries) { + if (entry.alias_hash() == alias_hash) { + return entry; + } + } + + return null; } } 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 23a8341a56..33abb59583 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 @@ -21,6 +21,7 @@ import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; import com.alibaba.druid.sql.ast.expr.SQLSequenceExpr; import com.alibaba.druid.sql.parser.Lexer; import com.alibaba.druid.sql.parser.SQLExprParser; +import com.alibaba.druid.sql.parser.SQLParserFeature; import com.alibaba.druid.sql.parser.Token; import com.alibaba.druid.util.FNVUtils; @@ -48,6 +49,11 @@ public class DB2ExprParser extends SQLExprParser { this.lexer.nextToken(); } + public DB2ExprParser(String sql, SQLParserFeature... features){ + this(new DB2Lexer(sql, features)); + this.lexer.nextToken(); + } + public DB2ExprParser(Lexer lexer){ super(lexer); this.aggregateFunctions = AGGREGATE_FUNCTIONS; diff --git a/src/main/java/com/alibaba/druid/sql/dialect/db2/parser/DB2Lexer.java b/src/main/java/com/alibaba/druid/sql/dialect/db2/parser/DB2Lexer.java index 1d432c86bd..9b25c6ef57 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/db2/parser/DB2Lexer.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/db2/parser/DB2Lexer.java @@ -20,6 +20,7 @@ import java.util.Map; import com.alibaba.druid.sql.parser.Keywords; import com.alibaba.druid.sql.parser.Lexer; +import com.alibaba.druid.sql.parser.SQLParserFeature; import com.alibaba.druid.sql.parser.Token; @@ -51,4 +52,12 @@ public class DB2Lexer extends Lexer { super(input); super.keywods = DEFAULT_DB2_KEYWORDS; } + + public DB2Lexer(String input, SQLParserFeature... features){ + super(input); + super.keywods = DEFAULT_DB2_KEYWORDS; + for (SQLParserFeature feature : features) { + config(feature, true); + } + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/db2/parser/DB2StatementParser.java b/src/main/java/com/alibaba/druid/sql/dialect/db2/parser/DB2StatementParser.java index 0e9730d070..090253481a 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/db2/parser/DB2StatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/db2/parser/DB2StatementParser.java @@ -20,6 +20,7 @@ import java.util.List; import com.alibaba.druid.sql.ast.SQLStatement; import com.alibaba.druid.sql.dialect.db2.ast.stmt.DB2ValuesStatement; import com.alibaba.druid.sql.parser.Lexer; +import com.alibaba.druid.sql.parser.SQLParserFeature; import com.alibaba.druid.sql.parser.SQLStatementParser; import com.alibaba.druid.sql.parser.Token; @@ -29,6 +30,10 @@ public class DB2StatementParser extends SQLStatementParser { super (new DB2ExprParser(sql)); } + public DB2StatementParser(String sql, SQLParserFeature... features) { + super (new DB2ExprParser(sql, features)); + } + public DB2StatementParser(Lexer lexer){ super(new DB2ExprParser(lexer)); } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/db2/visitor/DB2SchemaStatVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/db2/visitor/DB2SchemaStatVisitor.java index c624edcd4f..daecb927c6 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/db2/visitor/DB2SchemaStatVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/db2/visitor/DB2SchemaStatVisitor.java @@ -19,13 +19,12 @@ import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock; import com.alibaba.druid.sql.dialect.db2.ast.stmt.DB2SelectQueryBlock; import com.alibaba.druid.sql.dialect.db2.ast.stmt.DB2ValuesStatement; import com.alibaba.druid.sql.visitor.SchemaStatVisitor; +import com.alibaba.druid.util.JdbcConstants; import com.alibaba.druid.util.JdbcUtils; public class DB2SchemaStatVisitor extends SchemaStatVisitor implements DB2ASTVisitor { - - @Override - public String getDbType() { - return JdbcUtils.DB2; + public DB2SchemaStatVisitor() { + super (JdbcConstants.DB2); } @Override diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/expr/MySqlUserName.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/expr/MySqlUserName.java index 92b33896a2..3f644e0768 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/expr/MySqlUserName.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/expr/MySqlUserName.java @@ -17,12 +17,15 @@ package com.alibaba.druid.sql.dialect.mysql.ast.expr; import com.alibaba.druid.sql.ast.SQLName; import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor; +import com.alibaba.druid.util.FNVUtils; public class MySqlUserName extends MySqlExprImpl implements SQLName, Cloneable { private String userName; private String host; + protected transient long userName_hash; + public String getUserName() { return userName; } @@ -59,4 +62,29 @@ public class MySqlUserName extends MySqlExprImpl implements SQLName, Cloneable { x.host = host; return x; } + + public long name_hash_lower() { + if (userName_hash == 0 + && userName != null) { + final int len = userName.length(); + + boolean quote = false; + + String name = this.userName; + if (len > 2) { + char c0 = name.charAt(0); + char c1 = name.charAt(len - 1); + if (c0 == c1 + && (c0 == '`' || c1 == '"')) { + quote = true; + } + } + if (quote) { + userName_hash = FNVUtils.fnv_64_lower(name, 1, len -1); + } else { + userName_hash = FNVUtils.fnv_64_lower(name); + } + } + return userName_hash; + } } 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 9edacdd656..22250a0546 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 @@ -24,6 +24,7 @@ import java.util.Map; import com.alibaba.druid.sql.parser.*; public class MySqlLexer extends Lexer { + public static SymbolTable quoteTable = new SymbolTable(8192); public final static Keywords DEFAULT_MYSQL_KEYWORDS; @@ -251,20 +252,30 @@ public class MySqlLexer extends Lexer { bufPos = 1; char ch; - int quoteIndex = text.indexOf('`', pos + 1); + int startPos = pos + 1; + int quoteIndex = text.indexOf('`', startPos); if (quoteIndex == -1) { throw new ParserException("illegal identifier. " + info()); } + hash_lower = 0xcbf29ce484222325L; + hash = 0xcbf29ce484222325L; + + for (int i = startPos; i < quoteIndex; ++i) { + ch = text.charAt(i); + + hash_lower ^= ((ch >= 'A' && ch <= 'Z') ? (ch + 32) : ch); + hash_lower *= 0x100000001b3L; + + hash ^= ch; + hash *= 0x100000001b3L; + } + + stringVal = quoteTable.addSymbol(text, pos, quoteIndex + 1 - pos, hash); + //stringVal = text.substring(mark, pos); pos = quoteIndex + 1; this.ch = charAt(pos); - stringVal = text.substring(mark, pos); - Token tok = keywods.getKeyword(stringVal); - if (tok != null) { - token = tok; - } else { - token = Token.IDENTIFIER; - } + token = Token.IDENTIFIER; } else { final boolean firstFlag = isFirstIdentifierChar(first); if (!firstFlag) { 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 082226dc35..fb41680c8f 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 @@ -171,7 +171,7 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV if (into != null) { println(); print0(ucase ? "INTO " : "into "); - into.accept(this); + printTableSource(into); } SQLTableSource from = x.getFrom(); @@ -479,10 +479,10 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV } if (x.getSelect() != null) { - incrementIndent(); + this.indentCount++; println(); x.getSelect().accept(this); - decrementIndent(); + this.indentCount--; } for (SQLCommentHint hint : x.getOptionHints()) { @@ -580,7 +580,7 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV if (this.parameterized) { this.appender.append('?'); incrementReplaceCunt(); - if (this instanceof ExportParameterVisitor || this.parameters != null) { + if (this.parameters != null) { ExportParameterVisitorUtils.exportParameter(this.parameters, x); } return false; @@ -819,14 +819,16 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV x.getUsing().accept(this); } - if (x.getWhere() != null) { + SQLExpr where = x.getWhere(); + if (where != null) { println(); - incrementIndent(); + this.indentCount++; print0(ucase ? "WHERE " : "where "); - x.getWhere().accept(this); - decrementIndent(); + printExpr(where); + this.indentCount--; } + if (x.getOrderBy() != null) { println(); x.getOrderBy().accept(this); @@ -880,7 +882,7 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV List columns = x.getColumns(); if (columns.size() > 0) { - incrementIndent(); + this.indentCount++; print0(" ("); for (int i = 0, size = columns.size(); i < size; ++i) { if (i != 0) { @@ -890,16 +892,15 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV print0(", "); } - SQLExpr columnn = columns.get(i); - if (columnn instanceof SQLIdentifierExpr) { - visit((SQLIdentifierExpr) columnn); - } - else { - columnn.accept(this); + SQLExpr column = columns.get(i); + if (column instanceof SQLIdentifierExpr) { + visit((SQLIdentifierExpr) column); + } else { + printExpr(column); } } print(')'); - decrementIndent(); + this.indentCount--; } List valuesList = x.getValuesList(); @@ -913,17 +914,18 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV x.getQuery().accept(this); } - if (x.getDuplicateKeyUpdate().size() != 0) { + List duplicateKeyUpdate = x.getDuplicateKeyUpdate(); + if (duplicateKeyUpdate.size() != 0) { println(); print0(ucase ? "ON DUPLICATE KEY UPDATE " : "on duplicate key update "); - for (int i = 0, size = x.getDuplicateKeyUpdate().size(); i < size; ++i) { + for (int i = 0, size = duplicateKeyUpdate.size(); i < size; ++i) { if (i != 0) { if (i % 5 == 0) { println(); } print0(", "); } - x.getDuplicateKeyUpdate().get(i).accept(this); + duplicateKeyUpdate.get(i).accept(this); } } @@ -934,9 +936,9 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV if (this.parameterized) { print0(ucase ? "VALUES " : "values "); - incrementIndent(); + this.indentCount++; valuesList.get(0).accept(this); - decrementIndent(); + this.indentCount--; if (valuesList.size() > 1) { this.incrementReplaceCunt(); } @@ -1070,23 +1072,27 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV print0(ucase ? "INTO " : "into "); - x.getTableName().accept(this); + printExpr(x.getTableName()); - if (x.getColumns().size() > 0) { + List columns = x.getColumns(); + if (columns.size() > 0) { print0(" ("); - for (int i = 0, size = x.getColumns().size(); i < size; ++i) { + for (int i = 0, size = columns.size(); i < size; ++i) { if (i != 0) { print0(", "); } - x.getColumns().get(i).accept(this); + + SQLExpr columnn = columns.get(i); + printExpr(columnn); } print(')'); } - if (x.getValuesList().size() != 0) { + List valuesClauseList = x.getValuesList(); + if (valuesClauseList.size() != 0) { println(); print0(ucase ? "VALUES " : "values "); - int size = x.getValuesList().size(); + int size = valuesClauseList.size(); if (size == 0) { print0("()"); } else { @@ -1094,13 +1100,14 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV if (i != 0) { print0(", "); } - x.getValuesList().get(i).accept(this); + visit(valuesClauseList.get(i)); } } } - if (x.getQuery() != null) { - x.getQuery().accept(this); + SQLQueryExpr query = x.getQuery(); + if (query != null) { + visit(query); } return false; @@ -1596,13 +1603,14 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV print0(ucase ? "QUEUE_ON_PK " : "queue_on_pk "); } - if (x.getTargetAffectRow() != null) { + SQLExpr targetAffectRow = x.getTargetAffectRow(); + if (targetAffectRow != null) { print0(ucase ? "TARGET_AFFECT_ROW " : "target_affect_row "); - x.getTargetAffectRow().accept(this); + printExpr(targetAffectRow); print(' '); } - x.getTableSource().accept(this); + printTableSource(x.getTableSource()); println(); print0(ucase ? "SET " : "set "); @@ -1610,25 +1618,29 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV if (i != 0) { print0(", "); } - x.getItems().get(i).accept(this); + SQLUpdateSetItem item = x.getItems().get(i); + visit(item); } - if (x.getWhere() != null) { + SQLExpr where = x.getWhere(); + if (where != null) { println(); - incrementIndent(); + indentCount++; print0(ucase ? "WHERE " : "where "); - x.getWhere().accept(this); - decrementIndent(); + printExpr(where); + indentCount--; } - if (x.getOrderBy() != null) { + SQLOrderBy orderBy = x.getOrderBy(); + if (orderBy != null) { println(); - x.getOrderBy().accept(this); + visit(orderBy); } - if (x.getLimit() != null) { + SQLLimit limit = x.getLimit(); + if (limit != null) { println(); - x.getLimit().accept(this); + visit(limit); } return false; } @@ -2356,7 +2368,7 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV print0(ucase ? "ALTER TABLE " : "alter table "); } printTableSourceExpr(x.getName()); - incrementIndent(); + this.indentCount++; for (int i = 0; i < x.getItems().size(); ++i) { SQLAlterTableItem item = x.getItems().get(i); if (i != 0) { @@ -2380,7 +2392,7 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV println(); } - decrementIndent(); + this.indentCount--; int i = 0; for (Map.Entry option : x.getTableOptions().entrySet()) { @@ -2532,9 +2544,10 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV public boolean visit(SQLExprTableSource x) { printTableSourceExpr(x.getExpr()); - if (x.getAlias() != null) { + String alias = x.getAlias(); + if (alias != null) { print(' '); - print0(x.getAlias()); + print0(alias); } for (int i = 0; i < x.getHintsSize(); ++i) { @@ -2701,7 +2714,7 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV if (this.parameterized) { print('?'); incrementReplaceCunt(); - if (this instanceof ExportParameterVisitor || this.parameters != null) { + if (this.parameters != null) { ExportParameterVisitorUtils.exportParameter(this.parameters, x); } return false; @@ -2999,7 +3012,7 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV print0(": "); } if (x.getParameters().size() != 0) { - incrementIndent(); + this.indentCount++; if (x.getParent() instanceof SQLCreateProcedureStatement) { printIndent(); } @@ -3017,11 +3030,11 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV print(';'); } - decrementIndent(); + this.indentCount--; println(); } print0(ucase ? "BEGIN" : "begin"); - incrementIndent(); + this.indentCount++; println(); for (int i = 0, size = x.getStatementList().size(); i < size; ++i) { if (i != 0) { @@ -3030,7 +3043,7 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV SQLStatement stmt = x.getStatementList().get(i); stmt.accept(this); } - decrementIndent(); + this.indentCount--; println(); print0(ucase ? "END" : "end"); if (x.getLabelName() != null && !x.getLabelName().equals("")) { @@ -3045,7 +3058,7 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV print0(ucase ? "IF " : "if "); x.getCondition().accept(this); print0(ucase ? " THEN" : " then"); - incrementIndent(); + this.indentCount++; println(); for (int i = 0, size = x.getStatements().size(); i < size; ++i) { SQLStatement item = x.getStatements().get(i); @@ -3054,7 +3067,7 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV println(); } } - decrementIndent(); + this.indentCount--; println(); for (SQLIfStatement.ElseIf iterable_element : x.getElseIfList()) { iterable_element.accept(this); @@ -3071,7 +3084,7 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV print0(ucase ? "ELSE IF " : "else if "); x.getCondition().accept(this); print0(ucase ? " THEN" : " then"); - incrementIndent(); + this.indentCount++; println(); for (int i = 0, size = x.getStatements().size(); i < size; ++i) { SQLStatement item = x.getStatements().get(i); @@ -3080,7 +3093,7 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV println(); } } - decrementIndent(); + this.indentCount--; println(); return false; } @@ -3088,7 +3101,7 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV @Override public boolean visit(SQLIfStatement.Else x) { print0(ucase ? "ELSE " : "else "); - incrementIndent(); + this.indentCount++; println(); for (int i = 0, size = x.getStatements().size(); i < size; ++i) { SQLStatement item = x.getStatements().get(i); @@ -3097,7 +3110,7 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV println(); } } - decrementIndent(); + this.indentCount--; println(); return false; } @@ -3177,7 +3190,7 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV } print0(ucase ? "LOOP " : "loop "); - incrementIndent(); + this.indentCount++; println(); for (int i = 0, size = x.getStatements().size(); i < size; ++i) { SQLStatement item = x.getStatements().get(i); @@ -3186,7 +3199,7 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV println(); } } - decrementIndent(); + this.indentCount--; println(); print0(ucase ? "END LOOP" : "end loop"); if (x.getLabelName() != null && !x.getLabelName().equals("")) { @@ -3231,7 +3244,7 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV } print0(ucase ? "REPEAT " : "repeat "); - incrementIndent(); + this.indentCount++; println(); for (int i = 0, size = x.getStatements().size(); i < size; ++i) { SQLStatement item = x.getStatements().get(i); @@ -3240,7 +3253,7 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV println(); } } - decrementIndent(); + this.indentCount--; println(); print0(ucase ? "UNTIL " : "until "); x.getCondition().accept(this); @@ -3264,10 +3277,10 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV print0(ucase ? "DECLARE " : "declare "); print0(x.getCursorName()); print0(ucase ? " CURSOR FOR" : " cursor for"); - incrementIndent(); + this.indentCount++; println(); x.getSelect().accept(this); - decrementIndent(); + this.indentCount--; return false; } @@ -3389,10 +3402,10 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV } } - incrementIndent(); + this.indentCount++; println(); x.getSpStatement().accept(this); - decrementIndent(); + this.indentCount--; return false; } @@ -3459,7 +3472,7 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV print0(" ("); if (paramSize > 0) { - incrementIndent(); + this.indentCount++; println(); for (int i = 0; i < paramSize; ++i) { @@ -3471,7 +3484,7 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV param.accept(this); } - decrementIndent(); + this.indentCount--; println(); } print(')'); @@ -3517,7 +3530,7 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV if (paramSize > 0) { print0(" ("); - incrementIndent(); + this.indentCount++; println(); for (int i = 0; i < paramSize; ++i) { @@ -3529,7 +3542,7 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV param.accept(this); } - decrementIndent(); + this.indentCount--; println(); print(')'); } 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 801febce31..57c4121869 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 @@ -49,16 +49,26 @@ import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlUserName; import com.alibaba.druid.sql.dialect.mysql.ast.statement.*; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement.TableSpaceOption; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateUserStatement.UserSpecification; +import com.alibaba.druid.sql.repository.SchemaRepository; import com.alibaba.druid.sql.visitor.SchemaStatVisitor; import com.alibaba.druid.stat.TableStat; import com.alibaba.druid.stat.TableStat.Mode; +import com.alibaba.druid.util.JdbcConstants; import com.alibaba.druid.util.JdbcUtils; import java.util.Map; public class MySqlSchemaStatVisitor extends SchemaStatVisitor implements MySqlASTVisitor { + public MySqlSchemaStatVisitor() { + super (JdbcConstants.MYSQL); + } + public boolean visit(SQLSelectStatement x) { + if (repository != null) { + repository.resolve(x); + } + setAliasMap(); getAliasMap().put("DUAL", null); @@ -72,6 +82,10 @@ public class MySqlSchemaStatVisitor extends SchemaStatVisitor implements MySqlAS // DUAL public boolean visit(MySqlDeleteStatement x) { + if (repository != null) { + repository.resolve(x); + } + setAliasMap(); setMode(x, Mode.Delete); @@ -452,11 +466,14 @@ public class MySqlSchemaStatVisitor extends SchemaStatVisitor implements MySqlAS @Override public boolean visit(MySqlExplainStatement x) { - if (x.getTableName() != null) { - String table = x.getTableName().toString(); + SQLName tableName = x.getTableName(); + if (tableName != null) { + String table = tableName.toString(); getTableStat(table); - if (x.getColumnName() != null) { - addColumn(table, x.getColumnName().toString()); + + SQLName columnName = x.getColumnName(); + if (columnName != null) { + addColumn(table, columnName.getSimpleName(), tableName.name_hash_lower(), columnName.name_hash_lower()); } } @@ -474,7 +491,6 @@ public class MySqlSchemaStatVisitor extends SchemaStatVisitor implements MySqlAS @Override public boolean visit(MySqlUpdateStatement x) { - visit((SQLUpdateStatement) x); for (SQLExpr item : x.getReturning()) { item.accept(this); @@ -961,10 +977,13 @@ public class MySqlSchemaStatVisitor extends SchemaStatVisitor implements MySqlAS @Override public boolean visit(MySqlAlterTableChangeColumn x) { SQLAlterTableStatement stmt = (SQLAlterTableStatement) x.getParent(); - String table = stmt.getName().toString(); - String columnName = x.getColumnName().toString(); - addColumn(table, columnName); + SQLName table = stmt.getName(); + String tableName = table.toString(); + + SQLName column = x.getColumnName(); + String columnName = column.toString(); + addColumn(tableName, columnName, table.name_hash_lower(), column.name_hash_lower()); return false; } @@ -976,10 +995,14 @@ public class MySqlSchemaStatVisitor extends SchemaStatVisitor implements MySqlAS @Override public boolean visit(MySqlAlterTableModifyColumn x) { SQLAlterTableStatement stmt = (SQLAlterTableStatement) x.getParent(); - String table = stmt.getName().toString(); - String columnName = x.getNewColumnDefinition().getName().toString(); - addColumn(table, columnName); + SQLName table = stmt.getName(); + String tableName = table.toString(); + + SQLName column = x.getNewColumnDefinition().getName(); + String columnName = column.toString(); + addColumn(tableName, columnName, table.name_hash_lower(), column.name_hash_lower()); + return false; } @@ -1010,6 +1033,10 @@ public class MySqlSchemaStatVisitor extends SchemaStatVisitor implements MySqlAS @Override public boolean visit(MySqlCreateTableStatement x) { + if (repository != null) { + repository.resolve(x); + } + boolean val = super.visit((SQLCreateTableStatement) x); for (SQLObject option : x.getTableOptions().values()) { 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 fa5750f44f..1be1e16fc7 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 @@ -115,7 +115,7 @@ public class FromSubqueryResolver extends OracleASTVisitorAdapter { stmt.getSubQuery().setWithSubQuery(null); for (SQLWithSubqueryClause.Entry entry : withSubqueryClause.getEntries()) { - String entryName = entry.getName().getName(); + String entryName = entry.getAlias(); SQLCreateViewStatement entryStmt = new SQLCreateViewStatement(); entryStmt.setDbType(stmt.getDbType()); diff --git a/src/main/java/com/alibaba/druid/sql/dialect/odps/visitor/OdpsOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/odps/visitor/OdpsOutputVisitor.java index a578c1daf0..38077618ea 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/odps/visitor/OdpsOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/odps/visitor/OdpsOutputVisitor.java @@ -75,7 +75,7 @@ public class OdpsOutputVisitor extends SQLASTOutputVisitor implements OdpsASTVis printlnComment(x.getBodyBeforeCommentsDirect()); } - incrementIndent(); + this.indentCount++; println(); for (int i = 0; i < size; ++i) { SQLTableElement element = x.getTableElementList().get(i); @@ -93,7 +93,7 @@ public class OdpsOutputVisitor extends SQLASTOutputVisitor implements OdpsASTVis println(); } } - decrementIndent(); + this.indentCount--; println(); print(')'); } @@ -108,7 +108,7 @@ public class OdpsOutputVisitor extends SQLASTOutputVisitor implements OdpsASTVis if (partitionSize > 0) { println(); print0(ucase ? "PARTITIONED BY (" : "partitioned by ("); - incrementIndent(); + this.indentCount++; println(); for (int i = 0; i < partitionSize; ++i) { SQLColumnDefinition column = x.getPartitionColumns().get(i); @@ -126,7 +126,7 @@ public class OdpsOutputVisitor extends SQLASTOutputVisitor implements OdpsASTVis println(); } } - decrementIndent(); + this.indentCount--; println(); print(')'); } @@ -194,10 +194,10 @@ public class OdpsOutputVisitor extends SQLASTOutputVisitor implements OdpsASTVis if (from instanceof SQLSubqueryTableSource) { SQLSelect select = ((SQLSubqueryTableSource) from).getSelect(); print0(ucase ? "FROM (" : "from ("); - incrementIndent(); + this.indentCount++; println(); select.accept(this); - decrementIndent(); + this.indentCount--; println(); print0(") "); print0(x.getFrom().getAlias()); @@ -260,7 +260,7 @@ public class OdpsOutputVisitor extends SQLASTOutputVisitor implements OdpsASTVis } // protected void printSelectList(List selectList) { -// incrementIndent(); +// this.indentCount++; // for (int i = 0, size = selectList.size(); i < size; ++i) { // SQLSelectItem selectItem = selectList.get(i); // @@ -282,16 +282,16 @@ public class OdpsOutputVisitor extends SQLASTOutputVisitor implements OdpsASTVis // printlnComments(selectItem.getAfterCommentsDirect()); // } // } -// decrementIndent(); +// this.indentCount--; // } @Override public boolean visit(SQLSubqueryTableSource x) { print('('); - incrementIndent(); + this.indentCount++; println(); x.getSelect().accept(this); - decrementIndent(); + this.indentCount--; println(); print(')'); @@ -319,9 +319,9 @@ public class OdpsOutputVisitor extends SQLASTOutputVisitor implements OdpsASTVis if (x.getCondition() != null) { println(); print0(ucase ? "ON " : "on "); - incrementIndent(); + this.indentCount++; x.getCondition().accept(this); - decrementIndent(); + this.indentCount--; } if (x.getUsing().size() > 0) { @@ -352,7 +352,7 @@ public class OdpsOutputVisitor extends SQLASTOutputVisitor implements OdpsASTVis int aliasSize = x.getAliasList().size(); if (aliasSize > 5) { - incrementIndent(); + this.indentCount++; println(); } @@ -368,7 +368,7 @@ public class OdpsOutputVisitor extends SQLASTOutputVisitor implements OdpsASTVis } if (aliasSize > 5) { - decrementIndent(); + this.indentCount--; println(); } print(')'); @@ -511,14 +511,14 @@ public class OdpsOutputVisitor extends SQLASTOutputVisitor implements OdpsASTVis int itemSize = x.getItems().size(); if (itemSize > 0) { print0(ucase ? "ORDER BY " : "order by "); - incrementIndent(); + this.indentCount++; for (int i = 0; i < itemSize; ++i) { if (i != 0) { println(", "); } x.getItems().get(i).accept(this); } - decrementIndent(); + this.indentCount--; } return false; @@ -807,7 +807,7 @@ public class OdpsOutputVisitor extends SQLASTOutputVisitor implements OdpsASTVis @Override public boolean visit(OdpsLateralViewTableSource x) { x.getTableSource().accept(this); - incrementIndent(); + this.indentCount++; println(); print0(ucase ? "LATERAL VIEW " : "lateral view "); x.getMethod().accept(this); @@ -815,7 +815,7 @@ public class OdpsOutputVisitor extends SQLASTOutputVisitor implements OdpsASTVis print0(x.getAlias()); print0(ucase ? " AS " : " as "); printAndAccept(x.getColumns(), ", "); - decrementIndent(); + this.indentCount--; return false; } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/odps/visitor/OdpsSchemaStatVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/odps/visitor/OdpsSchemaStatVisitor.java index e4662f18cd..8b9c8737e1 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/odps/visitor/OdpsSchemaStatVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/odps/visitor/OdpsSchemaStatVisitor.java @@ -21,11 +21,16 @@ import com.alibaba.druid.sql.ast.statement.*; import com.alibaba.druid.sql.dialect.odps.ast.*; import com.alibaba.druid.sql.visitor.SchemaStatVisitor; import com.alibaba.druid.stat.TableStat; +import com.alibaba.druid.util.JdbcConstants; import java.util.Map; public class OdpsSchemaStatVisitor extends SchemaStatVisitor implements OdpsASTVisitor { + public OdpsSchemaStatVisitor() { + super(JdbcConstants.ODPS); + } + @Override public void endVisit(OdpsCreateTableStatement x) { super.endVisit((SQLCreateTableStatement) x); diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/clause/OracleWithSubqueryEntry.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/clause/OracleWithSubqueryEntry.java index 4ca651cff1..0e54a3f96f 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/clause/OracleWithSubqueryEntry.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/clause/OracleWithSubqueryEntry.java @@ -44,7 +44,6 @@ public class OracleWithSubqueryEntry extends Entry implements OracleSQLObject { @Override public void accept0(OracleASTVisitor visitor) { if (visitor.visit(this)) { - acceptChild(visitor, name); acceptChild(visitor, columns); acceptChild(visitor, subQuery); acceptChild(visitor, searchClause); diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleDbLinkExpr.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleDbLinkExpr.java index 0a7d2f1297..0960579b5c 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleDbLinkExpr.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleDbLinkExpr.java @@ -20,12 +20,15 @@ import com.alibaba.druid.sql.ast.SQLExprImpl; import com.alibaba.druid.sql.ast.SQLName; import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor; import com.alibaba.druid.sql.visitor.SQLASTVisitor; +import com.alibaba.druid.util.FNVUtils; public class OracleDbLinkExpr extends SQLExprImpl implements SQLName, OracleExpr { private SQLExpr expr; private String dbLink; + protected transient long dbLink_hash; + public OracleDbLinkExpr(){ } @@ -117,4 +120,29 @@ public class OracleDbLinkExpr extends SQLExprImpl implements SQLName, OracleExpr return x; } + + public long name_hash_lower() { + if (dbLink_hash == 0 + && dbLink != null) { + final int len = dbLink.length(); + + boolean quote = false; + + String name = this.dbLink; + if (len > 2) { + char c0 = name.charAt(0); + char c1 = name.charAt(len - 1); + if (c0 == c1 + && (c0 == '`' || c1 == '"')) { + quote = true; + } + } + if (quote) { + dbLink_hash = FNVUtils.fnv_64_lower(name, 1, len -1); + } else { + dbLink_hash = FNVUtils.fnv_64_lower(name); + } + } + return dbLink_hash; + } } 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 107bf46c89..6731536b6b 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 @@ -65,7 +65,10 @@ public class OracleSelectParser extends SQLSelectParser { public SQLSelect select() { SQLSelect select = new SQLSelect(); - withSubquery(select); + if (lexer.token() == Token.WITH) { + SQLWithSubqueryClause with = this.parseWith(); + select.setWithSubQuery(with); + } SQLSelectQuery query = query(); select.setQuery(query); @@ -153,79 +156,79 @@ public class OracleSelectParser extends SQLSelectParser { return select; } - protected void withSubquery(SQLSelect select) { - if (lexer.token() == Token.WITH) { + public SQLWithSubqueryClause parseWith() { + accept(Token.WITH); + SQLWithSubqueryClause subqueryFactoringClause = new SQLWithSubqueryClause(); + for (;;) { + OracleWithSubqueryEntry entry = new OracleWithSubqueryEntry(); + + String alias = lexer.stringVal(); lexer.nextToken(); + entry.setAlias(alias); - SQLWithSubqueryClause subqueryFactoringClause = new SQLWithSubqueryClause(); - for (;;) { - OracleWithSubqueryEntry entry = new OracleWithSubqueryEntry(); - entry.setName((SQLIdentifierExpr) this.exprParser.name()); - - if (lexer.token() == Token.LPAREN) { - lexer.nextToken(); - exprParser.names(entry.getColumns()); - accept(Token.RPAREN); - } - - accept(Token.AS); - accept(Token.LPAREN); - entry.setSubQuery(select()); + if (lexer.token() == Token.LPAREN) { + lexer.nextToken(); + exprParser.names(entry.getColumns()); accept(Token.RPAREN); - - if (lexer.identifierEquals("SEARCH")) { - lexer.nextToken(); - SearchClause searchClause = new SearchClause(); - - if (lexer.token() != Token.IDENTIFIER) { - throw new ParserException("syntax erorr : " + lexer.token()); - } - - searchClause.setType(SearchClause.Type.valueOf(lexer.stringVal())); - lexer.nextToken(); - - acceptIdentifier("FIRST"); - accept(Token.BY); - - searchClause.addItem(exprParser.parseSelectOrderByItem()); - - while (lexer.token() == (Token.COMMA)) { - lexer.nextToken(); - searchClause.addItem(exprParser.parseSelectOrderByItem()); - } - - accept(Token.SET); - - searchClause.setOrderingColumn((SQLIdentifierExpr) exprParser.name()); - - entry.setSearchClause(searchClause); - } - - if (lexer.identifierEquals("CYCLE")) { - lexer.nextToken(); - CycleClause cycleClause = new CycleClause(); - exprParser.exprList(cycleClause.getAliases(), cycleClause); - accept(Token.SET); - cycleClause.setMark(exprParser.expr()); - accept(Token.TO); - cycleClause.setValue(exprParser.expr()); - accept(Token.DEFAULT); - cycleClause.setDefaultValue(exprParser.expr()); - entry.setCycleClause(cycleClause); - } - - subqueryFactoringClause.addEntry(entry); - - if (lexer.token() == Token.COMMA) { - lexer.nextToken(); - continue; - } - - break; } - select.setWithSubQuery(subqueryFactoringClause); + accept(Token.AS); + accept(Token.LPAREN); + entry.setSubQuery(select()); + accept(Token.RPAREN); + + if (lexer.identifierEquals("SEARCH")) { + lexer.nextToken(); + SearchClause searchClause = new SearchClause(); + + if (lexer.token() != Token.IDENTIFIER) { + throw new ParserException("syntax erorr : " + lexer.token()); + } + + searchClause.setType(SearchClause.Type.valueOf(lexer.stringVal())); + lexer.nextToken(); + + acceptIdentifier("FIRST"); + accept(Token.BY); + + searchClause.addItem(exprParser.parseSelectOrderByItem()); + + while (lexer.token() == (Token.COMMA)) { + lexer.nextToken(); + searchClause.addItem(exprParser.parseSelectOrderByItem()); + } + + accept(Token.SET); + + searchClause.setOrderingColumn((SQLIdentifierExpr) exprParser.name()); + + entry.setSearchClause(searchClause); + } + + if (lexer.identifierEquals("CYCLE")) { + lexer.nextToken(); + CycleClause cycleClause = new CycleClause(); + exprParser.exprList(cycleClause.getAliases(), cycleClause); + accept(Token.SET); + cycleClause.setMark(exprParser.expr()); + accept(Token.TO); + cycleClause.setValue(exprParser.expr()); + accept(Token.DEFAULT); + cycleClause.setDefaultValue(exprParser.expr()); + entry.setCycleClause(cycleClause); + } + + subqueryFactoringClause.addEntry(entry); + + if (lexer.token() == Token.COMMA) { + lexer.nextToken(); + continue; + } + + break; } + + return subqueryFactoringClause; } public SQLSelectQuery query() { diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleOutputVisitor.java index 6bc4b419c1..a3acad630d 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleOutputVisitor.java @@ -86,11 +86,6 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS } } - public boolean visit(SQLAllColumnExpr x) { - print('*'); - return false; - } - public boolean visit(OracleAnalytic x) { print0(ucase ? "OVER (" : "over ("); @@ -161,10 +156,10 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS if (x.getWhere() != null) { println(); - incrementIndent(); + this.indentCount++; print0(ucase ? "WHERE " : "where "); x.getWhere().accept(this); - decrementIndent(); + this.indentCount--; } if (x.getReturning() != null) { @@ -266,7 +261,7 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS } else { boolean isRoot = x.getParent() instanceof SQLSelectQueryBlock; if (isRoot) { - incrementIndent(); + this.indentCount++; } println(); @@ -282,7 +277,7 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS } if (isRoot) { - decrementIndent(); + this.indentCount--; } if (x.getCondition() != null) { @@ -461,10 +456,10 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS public boolean visit(OracleSelectSubqueryTableSource x) { print('('); - incrementIndent(); + this.indentCount++; println(); x.getSelect().accept(this); - decrementIndent(); + this.indentCount--; println(); print(')'); @@ -607,9 +602,9 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS if (x.getWhere() != null) { println(); print0(ucase ? "WHERE " : "where "); - incrementIndent(); + this.indentCount++; x.getWhere().accept(this); - decrementIndent(); + this.indentCount--; } if (x.getReturning().size() > 0) { @@ -793,7 +788,7 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS @Override public boolean visit(OracleWithSubqueryEntry x) { - x.getName().accept(this); + print0(x.getAlias()); if (x.getColumns().size() > 0) { print0(" ("); @@ -803,10 +798,10 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS print0(ucase ? " AS " : " as "); print('('); - incrementIndent(); + this.indentCount++; println(); x.getSubQuery().accept(this); - decrementIndent(); + this.indentCount--; println(); print(')'); @@ -890,10 +885,10 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS @Override public boolean visit(OracleCursorExpr x) { print0(ucase ? "CURSOR(" : "cursor("); - incrementIndent(); + this.indentCount++; println(); x.getQuery().accept(this); - decrementIndent(); + this.indentCount--; println(); print(')'); return false; @@ -935,7 +930,7 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS public boolean visit(ModelClause x) { print0(ucase ? "MODEL" : "model"); - incrementIndent(); + this.indentCount++; for (CellReferenceOption opt : x.getCellReferenceOptions()) { print(' '); print0(opt.name); @@ -952,7 +947,7 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS } x.getMainModel().accept(this); - decrementIndent(); + this.indentCount--; return false; } @@ -1180,7 +1175,7 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS x.getTableSource().accept(this); if (x.getColumns().size() > 0) { - incrementIndent(); + this.indentCount++; println(); print('('); for (int i = 0, size = x.getColumns().size(); i < size; ++i) { @@ -1193,7 +1188,7 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS x.getColumns().get(i).accept(this); } print(')'); - decrementIndent(); + this.indentCount--; } if (x.getValues() != null) { @@ -1229,10 +1224,10 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS } for (int i = 0, size = x.getEntries().size(); i < size; ++i) { - incrementIndent(); + this.indentCount++; println(); x.getEntries().get(i).accept(this); - decrementIndent(); + this.indentCount--; } println(); @@ -1261,10 +1256,10 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS if (x.getElseItem() != null) { println(); print0(ucase ? "ELSE" : "else"); - incrementIndent(); + this.indentCount++; println(); x.getElseItem().accept(this); - decrementIndent(); + this.indentCount--; } return false; @@ -1280,10 +1275,10 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS print0(ucase ? "WHEN " : "when "); x.getWhen().accept(this); print0(ucase ? " THEN" : " then"); - incrementIndent(); + this.indentCount++; println(); x.getThen().accept(this); - decrementIndent(); + this.indentCount--; return false; } @@ -1300,7 +1295,7 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS @Override public boolean visit(SQLBlockStatement x) { if (x.getParameters().size() != 0) { - incrementIndent(); + this.indentCount++; if (x.getParent() instanceof SQLCreateProcedureStatement) { SQLCreateProcedureStatement procedureStatement = (SQLCreateProcedureStatement) x.getParent(); if (procedureStatement.isCreate()) { @@ -1323,18 +1318,18 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS print(';'); } - decrementIndent(); + this.indentCount--; println(); } print0(ucase ? "BEGIN" : "begin"); - incrementIndent(); + this.indentCount++; for (int i = 0, size = x.getStatementList().size(); i < size; ++i) { println(); SQLStatement stmt = x.getStatementList().get(i); stmt.accept(this); } - decrementIndent(); + this.indentCount--; SQLStatement exception = x.getException(); if (exception != null) { @@ -1445,7 +1440,7 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS x.getWhen().accept(this); print0(ucase ? " THEN" : " then"); - incrementIndent(); + this.indentCount++; if (x.getStatements().size() > 1) { println(); } else { @@ -1465,21 +1460,21 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS stmt.accept(this); } - decrementIndent(); + this.indentCount--; return false; } @Override public boolean visit(OracleExceptionStatement x) { print0(ucase ? "EXCEPTION" : "exception"); - incrementIndent(); + this.indentCount++; List items = x.getItems(); for (int i = 0, size = items.size(); i < size; ++i) { println(); OracleExceptionStatement.Item item = items.get(i); item.accept(this); } - decrementIndent(); + this.indentCount--; return false; } @@ -1525,7 +1520,7 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS @Override public boolean visit(OracleExplainStatement x) { print0(ucase ? "EXPLAIN PLAN" : "explain plan"); - incrementIndent(); + this.indentCount++; println(); if (x.getStatementId() != null) { print0(ucase ? "SET STATEMENT_ID = " : "set statement_id = "); @@ -1543,7 +1538,7 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS println(); x.getStatement().accept(this); - decrementIndent(); + this.indentCount--; return false; } @@ -1599,7 +1594,7 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS print0(ucase ? "ALTER TABLE " : "alter table "); printTableSourceExpr(x.getName()); - incrementIndent(); + this.indentCount++; for (SQLAlterTableItem item : x.getItems()) { println(); item.accept(this); @@ -1608,7 +1603,7 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS println(); print0(ucase ? "UPDATE GLOABL INDEXES" : "update gloabl indexes"); } - decrementIndent(); + this.indentCount--; return false; } @@ -1658,28 +1653,28 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS x.getName().accept(this); if (x.getAt().size() > 0) { - incrementIndent(); + this.indentCount++; println(); print0(ucase ? "AT (" : "at ("); printAndAccept(x.getAt(), ", "); print(')'); - decrementIndent(); + this.indentCount--; } if (x.getInto().size() > 0) { println(); - incrementIndent(); + this.indentCount++; print0(ucase ? "INTO (" : "into ("); printAndAccept(x.getInto(), ", "); print(')'); - decrementIndent(); + this.indentCount--; } if (x.getUpdateIndexes() != null) { println(); - incrementIndent(); + this.indentCount++; x.getUpdateIndexes().accept(this); - decrementIndent(); + this.indentCount--; } return false; } @@ -1708,7 +1703,7 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS @Override public boolean visit(OracleAlterTableModify x) { print0(ucase ? "MODIFY (" : "modify ("); - incrementIndent(); + this.indentCount++; for (int i = 0, size = x.getColumns().size(); i < size; ++i) { println(); SQLColumnDefinition column = x.getColumns().get(i); @@ -1717,7 +1712,7 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS print0(", "); } } - decrementIndent(); + this.indentCount--; println(); print(')'); @@ -1790,10 +1785,10 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS if (x.getLocalPartitions().size() > 0) { println(); print0(ucase ? "LOCAL (" : "local ("); - incrementIndent(); + this.indentCount++; println(); printlnAndAccept(x.getLocalPartitions(), ","); - decrementIndent(); + this.indentCount--; println(); print(')'); } else if (x.isLocal()) { @@ -1895,7 +1890,7 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS println(); print0(ucase ? "LOOP" : "loop"); } - incrementIndent(); + this.indentCount++; println(); for (int i = 0, size = x.getStatements().size(); i < size; ++i) { @@ -1908,7 +1903,7 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS } } - decrementIndent(); + this.indentCount--; if (!all) { println(); print0(ucase ? "END LOOP" : "end loop"); @@ -1929,7 +1924,7 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS @Override public boolean visit(SQLIfStatement.Else x) { print0(ucase ? "ELSE" : "else"); - incrementIndent(); + this.indentCount++; println(); for (int i = 0, size = x.getStatements().size(); i < size; ++i) { @@ -1940,7 +1935,7 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS item.accept(this); } - decrementIndent(); + this.indentCount--; return false; } @@ -1949,7 +1944,7 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS print0(ucase ? "ELSE IF " : "else if "); x.getCondition().accept(this); print0(ucase ? " THEN" : " then"); - incrementIndent(); + this.indentCount++; for (int i = 0, size = x.getStatements().size(); i < size; ++i) { println(); @@ -1957,7 +1952,7 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS item.accept(this); } - decrementIndent(); + this.indentCount--; return false; } @@ -1965,9 +1960,9 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS public boolean visit(SQLIfStatement x) { print0(ucase ? "IF " : "if "); int lines = this.lines; - incrementIndent(); + this.indentCount++; x.getCondition().accept(this); - decrementIndent(); + this.indentCount--; if (lines != this.lines) { println(); @@ -1976,13 +1971,13 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS } print0(ucase ? "THEN" : "then"); - incrementIndent(); + this.indentCount++; for (int i = 0, size = x.getStatements().size(); i < size; ++i) { println(); SQLStatement item = x.getStatements().get(i); item.accept(this); } - decrementIndent(); + this.indentCount--; for (SQLIfStatement.ElseIf elseIf : x.getElseIfList()) { println(); @@ -2053,7 +2048,7 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS } protected void printConstraintState(OracleConstraint x) { - incrementIndent(); + this.indentCount++; if (x.getUsing() != null) { println(); x.getUsing().accept(this); @@ -2086,7 +2081,7 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS print0(ucase ? " NOT DEFERRABLE" : " not deferrable"); } } - decrementIndent(); + this.indentCount--; } @Override @@ -2111,9 +2106,9 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS if (x.getOrganization() != null) { println(); - incrementIndent(); + this.indentCount++; x.getOrganization().accept(this); - decrementIndent(); + this.indentCount--; } printOracleSegmentAttributes(x); @@ -2194,7 +2189,7 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS public boolean visit(OracleStorageClause x) { print0(ucase ? "STORAGE (" : "storage ("); - incrementIndent(); + this.indentCount++; if (x.getInitial() != null) { println(); print0(ucase ? "INITIAL " : "initial "); @@ -2266,7 +2261,7 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS print0(ucase ? "CELL_FLASH_CACHE " : "cell_flash_cache "); print0(ucase ? x.getCellFlashCache().name() : x.getCellFlashCache().name().toLowerCase()); } - decrementIndent(); + this.indentCount--; println(); print(')'); @@ -2438,12 +2433,12 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS @Override public boolean visit(OracleAlterTablespaceAddDataFile x) { print0(ucase ? "ADD DATAFILE" : "add datafile"); - incrementIndent(); + this.indentCount++; for (OracleFileSpecification file : x.getFiles()) { println(); file.accept(this); } - decrementIndent(); + this.indentCount--; return false; } @@ -2568,7 +2563,7 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS if (paramSize > 0) { print0(" ("); - incrementIndent(); + this.indentCount++; println(); for (int i = 0; i < paramSize; ++i) { @@ -2580,7 +2575,7 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS param.accept(this); } - decrementIndent(); + this.indentCount--; println(); print(')'); } @@ -2635,7 +2630,7 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS if (paramSize > 0) { print0(" ("); - incrementIndent(); + this.indentCount++; println(); for (int i = 0; i < paramSize; ++i) { @@ -2647,7 +2642,7 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS param.accept(this); } - decrementIndent(); + this.indentCount--; println(); print(')'); } @@ -2876,7 +2871,7 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS segementName.accept(this); } print0(" ("); - incrementIndent(); + this.indentCount++; printOracleSegmentAttributes(x); if (x.getEnable() != null) { @@ -2917,7 +2912,7 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS print0(ucase ? "RETENTION" : "retention"); } - decrementIndent(); + this.indentCount--; println(); print(')'); return false; @@ -3070,7 +3065,7 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS if ("EXTERNAL".equalsIgnoreCase(type)) { print0(" ("); - incrementIndent(); + this.indentCount++; if (x.getExternalType() != null) { println(); print0(ucase ? "TYPE " : "type "); @@ -3085,10 +3080,10 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS if (x.getExternalDirectoryRecordFormat() != null) { println(); - incrementIndent(); + this.indentCount++; print0(ucase ? "ACCESS PARAMETERS (" : "access parameters ("); x.getExternalDirectoryRecordFormat().accept(this); - decrementIndent(); + this.indentCount--; println(); print(')'); } @@ -3100,7 +3095,7 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS print(')'); } - decrementIndent(); + this.indentCount--; println(); print(')'); @@ -3146,9 +3141,9 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS x.getName().accept(this); } print(" ("); - incrementIndent(); + this.indentCount++; printOracleSegmentAttributes(x); - decrementIndent(); + this.indentCount--; println(); print(")"); return false; @@ -3177,7 +3172,7 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS print0(ucase ? "BEGIN" : "begin"); } - incrementIndent(); + this.indentCount++; for (int i = 0, size = x.getStatements().size(); i < size; ++i) { println(); @@ -3185,7 +3180,7 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS item.accept(this); } - decrementIndent(); + this.indentCount--; if (x.isBody()) { println(); diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleSchemaStatVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleSchemaStatVisitor.java index 306142a38c..0fbd27ee8a 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleSchemaStatVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleSchemaStatVisitor.java @@ -475,10 +475,7 @@ public class OracleSchemaStatVisitor extends SchemaStatVisitor implements Oracle public boolean visit(OracleWithSubqueryEntry x) { Map aliasMap = getAliasMap(); if (aliasMap != null) { - String alias = null; - if (x.getName() != null) { - alias = x.getName().toString(); - } + String alias = x.getAlias(); if (alias != null) { putAliasMap(aliasMap, alias, null); diff --git a/src/main/java/com/alibaba/druid/sql/dialect/phoenix/visitor/PhoenixSchemaStatVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/phoenix/visitor/PhoenixSchemaStatVisitor.java index 7f45080dfe..63b712d4be 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/phoenix/visitor/PhoenixSchemaStatVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/phoenix/visitor/PhoenixSchemaStatVisitor.java @@ -17,9 +17,13 @@ package com.alibaba.druid.sql.dialect.phoenix.visitor; import com.alibaba.druid.sql.dialect.db2.visitor.DB2ASTVisitor; import com.alibaba.druid.sql.visitor.SchemaStatVisitor; +import com.alibaba.druid.util.JdbcConstants; /** * Created by wenshao on 16/9/13. */ public class PhoenixSchemaStatVisitor extends SchemaStatVisitor implements PhoenixASTVisitor { + public PhoenixSchemaStatVisitor() { + super(JdbcConstants.PHOENIX); + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/PGWithClause.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/PGWithClause.java deleted file mode 100644 index e6e5e6215f..0000000000 --- a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/PGWithClause.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * 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.sql.dialect.postgresql.ast; - -import java.util.ArrayList; -import java.util.List; - -import com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor; - -public class PGWithClause extends PGSQLObjectImpl { - - private boolean recursive = false; - private List withQuery = new ArrayList(2); - - public boolean isRecursive() { - return recursive; - } - - public void setRecursive(boolean recursive) { - this.recursive = recursive; - } - - public List getWithQuery() { - return withQuery; - } - - public void setWithQuery(List withQuery) { - this.withQuery = withQuery; - } - - @Override - public void accept0(PGASTVisitor visitor) { - if (visitor.visit(this)) { - acceptChild(visitor, withQuery); - } - visitor.endVisit(this); - } - - public PGWithClause clone() { - PGWithClause x = new PGWithClause(); - x.recursive = recursive; - for (PGWithQuery w : withQuery) { - PGWithQuery w2 = w.clone(); - w2.setParent(x); - x.withQuery.add(w2); - } - return x; - } -} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/PGWithQuery.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/PGWithQuery.java deleted file mode 100644 index 149a03be85..0000000000 --- a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/PGWithQuery.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * 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.sql.dialect.postgresql.ast; - -import java.util.ArrayList; -import java.util.List; - -import com.alibaba.druid.sql.ast.SQLExpr; -import com.alibaba.druid.sql.ast.SQLStatement; -import com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor; - -public class PGWithQuery extends PGSQLObjectImpl { - - private SQLExpr name; - private final List columns = new ArrayList(); - private SQLStatement query; - - public SQLExpr getName() { - return name; - } - - public void setName(SQLExpr name) { - this.name = name; - } - - public SQLStatement getQuery() { - return query; - } - - public void setQuery(SQLStatement query) { - this.query = query; - } - - public List getColumns() { - return columns; - } - - public void addColumn(SQLExpr column) { - if (column != null) { - column.setParent(this); - } - this.columns.add(column); - } - - @Override - public void accept0(PGASTVisitor visitor) { - if (visitor.visit(this)) { - acceptChild(visitor, name); - acceptChild(visitor, columns); - acceptChild(visitor, query); - } - visitor.endVisit(this); - } - - public PGWithQuery clone() { - PGWithQuery x = new PGWithQuery(); - - if (name != null) { - x.setName(name.clone()); - } - for (SQLExpr c : columns) { - SQLExpr c2 = c.clone(); - c2.setParent(x); - x.columns.add(c); - } - if (query != null) { - x.setQuery(query.clone()); - } - - return x; - } -} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGDeleteStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGDeleteStatement.java index 6b99344164..1153d04171 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGDeleteStatement.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGDeleteStatement.java @@ -20,15 +20,14 @@ import java.util.List; import com.alibaba.druid.sql.ast.SQLName; import com.alibaba.druid.sql.ast.statement.SQLDeleteStatement; -import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlDeleteStatement; -import com.alibaba.druid.sql.dialect.postgresql.ast.PGWithClause; +import com.alibaba.druid.sql.ast.statement.SQLWithSubqueryClause; import com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor; import com.alibaba.druid.sql.visitor.SQLASTVisitor; import com.alibaba.druid.util.JdbcConstants; public class PGDeleteStatement extends SQLDeleteStatement implements PGSQLStatement { - private PGWithClause with; + private SQLWithSubqueryClause with; private List using = new ArrayList(2); private boolean returning; private String alias; @@ -63,11 +62,11 @@ public class PGDeleteStatement extends SQLDeleteStatement implements PGSQLStatem - public PGWithClause getWith() { + public SQLWithSubqueryClause getWith() { return with; } - public void setWith(PGWithClause with) { + public void setWith(SQLWithSubqueryClause with) { this.with = with; } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGInsertStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGInsertStatement.java index ee5d540f8f..078f3374dc 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGInsertStatement.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGInsertStatement.java @@ -20,13 +20,13 @@ import java.util.List; import com.alibaba.druid.sql.ast.SQLExpr; import com.alibaba.druid.sql.ast.statement.SQLInsertStatement; -import com.alibaba.druid.sql.dialect.postgresql.ast.PGWithClause; +import com.alibaba.druid.sql.ast.statement.SQLWithSubqueryClause; import com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor; import com.alibaba.druid.sql.visitor.SQLASTVisitor; public class PGInsertStatement extends SQLInsertStatement implements PGSQLStatement { - private PGWithClause with; + private SQLWithSubqueryClause with; private List valuesList = new ArrayList(); private SQLExpr returning; private boolean defaultValues = false; @@ -55,11 +55,11 @@ public class PGInsertStatement extends SQLInsertStatement implements PGSQLStatem this.returning = returning; } - public PGWithClause getWith() { + public SQLWithSubqueryClause getWith() { return with; } - public void setWith(PGWithClause with) { + public void setWith(SQLWithSubqueryClause with) { this.with = with; } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGSelectQueryBlock.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGSelectQueryBlock.java index 89498958f6..7fceeabee5 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGSelectQueryBlock.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGSelectQueryBlock.java @@ -19,18 +19,15 @@ import java.util.ArrayList; import java.util.List; import com.alibaba.druid.sql.ast.SQLExpr; -import com.alibaba.druid.sql.ast.SQLObjectImpl; import com.alibaba.druid.sql.ast.SQLOrderBy; import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock; import com.alibaba.druid.sql.dialect.postgresql.ast.PGSQLObject; import com.alibaba.druid.sql.dialect.postgresql.ast.PGSQLObjectImpl; -import com.alibaba.druid.sql.dialect.postgresql.ast.PGWithClause; import com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor; import com.alibaba.druid.sql.visitor.SQLASTVisitor; public class PGSelectQueryBlock extends SQLSelectQueryBlock implements PGSQLObject{ - private PGWithClause with; private List distinctOn = new ArrayList(2); private WindowClause window; @@ -59,7 +56,6 @@ public class PGSelectQueryBlock extends SQLSelectQueryBlock implements PGSQLObje @Override public void accept0(PGASTVisitor visitor) { if (visitor.visit(this)) { - acceptChild(visitor, this.with); acceptChild(visitor, this.distinctOn); acceptChild(visitor, this.selectList); acceptChild(visitor, this.into); @@ -99,14 +95,6 @@ public class PGSelectQueryBlock extends SQLSelectQueryBlock implements PGSQLObje this.window = window; } - public PGWithClause getWith() { - return with; - } - - public void setWith(PGWithClause with) { - this.with = with; - } - public SQLOrderBy getOrderBy() { return orderBy; } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGSelectStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGSelectStatement.java index a03a9529c6..cecbc651ab 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGSelectStatement.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGSelectStatement.java @@ -17,15 +17,12 @@ package com.alibaba.druid.sql.dialect.postgresql.ast.stmt; import com.alibaba.druid.sql.ast.statement.SQLSelect; import com.alibaba.druid.sql.ast.statement.SQLSelectStatement; -import com.alibaba.druid.sql.dialect.postgresql.ast.PGWithClause; import com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor; import com.alibaba.druid.sql.visitor.SQLASTVisitor; import com.alibaba.druid.util.JdbcConstants; public class PGSelectStatement extends SQLSelectStatement implements PGSQLStatement { - private PGWithClause with; - public PGSelectStatement(){ super(JdbcConstants.POSTGRESQL); } @@ -34,21 +31,12 @@ public class PGSelectStatement extends SQLSelectStatement implements PGSQLStatem super(select, JdbcConstants.POSTGRESQL); } - public PGWithClause getWith() { - return with; - } - - public void setWith(PGWithClause with) { - this.with = with; - } - protected void accept0(SQLASTVisitor visitor) { accept0((PGASTVisitor) visitor); } public void accept0(PGASTVisitor visitor) { if (visitor.visit(this)) { - acceptChild(visitor, this.with); acceptChild(visitor, this.select); } visitor.endVisit(this); diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGUpdateStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGUpdateStatement.java index e4df9432d3..b37749b890 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGUpdateStatement.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGUpdateStatement.java @@ -15,13 +15,8 @@ */ package com.alibaba.druid.sql.dialect.postgresql.ast.stmt; -import java.util.ArrayList; -import java.util.List; - -import com.alibaba.druid.sql.ast.SQLExpr; -import com.alibaba.druid.sql.ast.statement.SQLTableSource; import com.alibaba.druid.sql.ast.statement.SQLUpdateStatement; -import com.alibaba.druid.sql.dialect.postgresql.ast.PGWithClause; +import com.alibaba.druid.sql.ast.statement.SQLWithSubqueryClause; import com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor; import com.alibaba.druid.sql.visitor.SQLASTVisitor; import com.alibaba.druid.util.JdbcConstants; @@ -30,7 +25,7 @@ public class PGUpdateStatement extends SQLUpdateStatement implements PGSQLStatem private boolean only = false; - private PGWithClause with; + private SQLWithSubqueryClause with; public PGUpdateStatement(){ super (JdbcConstants.POSTGRESQL); @@ -44,11 +39,11 @@ public class PGUpdateStatement extends SQLUpdateStatement implements PGSQLStatem this.only = only; } - public PGWithClause getWith() { + public SQLWithSubqueryClause getWith() { return with; } - public void setWith(PGWithClause with) { + public void setWith(SQLWithSubqueryClause with) { this.with = with; } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGExprParser.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGExprParser.java index cd0599d45b..e5fe8069f4 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGExprParser.java @@ -39,6 +39,7 @@ import com.alibaba.druid.sql.dialect.postgresql.ast.expr.PGPolygonExpr; import com.alibaba.druid.sql.dialect.postgresql.ast.expr.PGTypeCastExpr; import com.alibaba.druid.sql.parser.Lexer; import com.alibaba.druid.sql.parser.SQLExprParser; +import com.alibaba.druid.sql.parser.SQLParserFeature; import com.alibaba.druid.sql.parser.Token; import com.alibaba.druid.util.FNVUtils; import com.alibaba.druid.util.JdbcConstants; @@ -68,6 +69,12 @@ public class PGExprParser extends SQLExprParser { this.dbType = JdbcConstants.POSTGRESQL; } + public PGExprParser(String sql, SQLParserFeature... features){ + this(new PGLexer(sql)); + this.lexer.nextToken(); + this.dbType = JdbcConstants.POSTGRESQL; + } + public PGExprParser(Lexer lexer){ super(lexer); this.aggregateFunctions = AGGREGATE_FUNCTIONS; diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGLexer.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGLexer.java index 9007059d10..55ecc0d098 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGLexer.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGLexer.java @@ -22,6 +22,7 @@ import java.util.Map; import com.alibaba.druid.sql.parser.Keywords; import com.alibaba.druid.sql.parser.Lexer; +import com.alibaba.druid.sql.parser.SQLParserFeature; import com.alibaba.druid.sql.parser.Token; import com.alibaba.druid.util.JdbcConstants; @@ -73,10 +74,13 @@ public class PGLexer extends Lexer { DEFAULT_PG_KEYWORDS = new Keywords(map); } - public PGLexer(String input){ + public PGLexer(String input, SQLParserFeature... features){ super(input); super.keywods = DEFAULT_PG_KEYWORDS; super.dbType = JdbcConstants.POSTGRESQL; + for (SQLParserFeature feature : features) { + config(feature, true); + } } protected void scanString() { diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGSQLStatementParser.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGSQLStatementParser.java index 6f3a932c05..a022d1ca82 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGSQLStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGSQLStatementParser.java @@ -23,8 +23,6 @@ import com.alibaba.druid.sql.ast.expr.SQLCurrentOfCursorExpr; import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; import com.alibaba.druid.sql.ast.expr.SQLQueryExpr; import com.alibaba.druid.sql.ast.statement.*; -import com.alibaba.druid.sql.dialect.postgresql.ast.PGWithClause; -import com.alibaba.druid.sql.dialect.postgresql.ast.PGWithQuery; import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGDeleteStatement; import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGInsertStatement; import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectStatement; @@ -53,6 +51,10 @@ public class PGSQLStatementParser extends SQLStatementParser { super(new PGExprParser(sql)); } + public PGSQLStatementParser(String sql, SQLParserFeature... features){ + super(new PGExprParser(sql, features)); + } + public PGSQLStatementParser(Lexer lexer){ super(new PGExprParser(lexer)); } @@ -236,86 +238,6 @@ public class PGSQLStatementParser extends SQLStatementParser { } } - - - public PGWithClause parseWithClause() { - lexer.nextToken(); - - PGWithClause withClause = new PGWithClause(); - - if (lexer.token() == Token.RECURSIVE) { - lexer.nextToken(); - withClause.setRecursive(true); - } - - for (;;) { - PGWithQuery withQuery = withQuery(); - withClause.getWithQuery().add(withQuery); - if (lexer.token() == Token.COMMA) { - lexer.nextToken(); - continue; - } else { - break; - } - } - return withClause; - } - - private PGWithQuery withQuery() { - PGWithQuery withQuery = new PGWithQuery(); - - if (lexer.token() == Token.LITERAL_ALIAS) { - withQuery.setName(new SQLIdentifierExpr("\"" + lexer.stringVal() - + "\"")); - } else { - withQuery.setName(new SQLIdentifierExpr(lexer.stringVal())); - } - lexer.nextToken(); - - if (lexer.token() == Token.LPAREN) { - lexer.nextToken(); - - for (;;) { - SQLExpr expr = this.exprParser.expr(); - withQuery.addColumn(expr); - if (lexer.token() == Token.COMMA) { - lexer.nextToken(); - continue; - } else { - break; - } - } - - accept(Token.RPAREN); - } - - accept(Token.AS); - - if (lexer.token() == Token.LPAREN) { - lexer.nextToken(); - - SQLStatement query; - if (lexer.token() == Token.SELECT) { - query = this.parseSelect(); - } else if (lexer.token() == Token.INSERT) { - query = this.parseInsert(); - } else if (lexer.token() == Token.UPDATE) { - query = this.parseUpdateStatement(); - } else if (lexer.token() == Token.DELETE) { - query = this.parseDeleteStatement(); - } else if (lexer.token() == Token.VALUES) { - query = this.parseSelect(); - } else { - throw new ParserException("syntax error, support token '" + lexer.token() + "', " + lexer.info()); - } - withQuery.setQuery(query); - - accept(Token.RPAREN); - } - - return withQuery; - } - public PGSelectStatement parseSelect() { PGSelectParser selectParser = createSQLSelectParser(); SQLSelect select = selectParser.select(); @@ -323,7 +245,8 @@ public class PGSQLStatementParser extends SQLStatementParser { } public SQLStatement parseWith() { - PGWithClause with = this.parseWithClause(); + SQLWithSubqueryClause with = this.parseWithQuery(); + // PGWithClause with = this.parseWithClause(); if (lexer.token() == Token.INSERT) { PGInsertStatement stmt = this.parseInsert(); stmt.setWith(with); @@ -332,7 +255,7 @@ public class PGSQLStatementParser extends SQLStatementParser { if (lexer.token() == Token.SELECT) { PGSelectStatement stmt = this.parseSelect(); - stmt.setWith(with); + stmt.getSelect().setWithSubQuery(with); return stmt; } @@ -347,6 +270,7 @@ public class PGSQLStatementParser extends SQLStatementParser { stmt.setWith(with); return stmt; } + throw new ParserException("TODO. " + lexer.info()); } @@ -463,4 +387,5 @@ public class PGSQLStatementParser extends SQLStatementParser { return new PGSetStatement(range, parameter, values); } + } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGASTVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGASTVisitor.java index 78d4b689a2..5ccc539cdb 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGASTVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGASTVisitor.java @@ -15,8 +15,6 @@ */ package com.alibaba.druid.sql.dialect.postgresql.visitor; -import com.alibaba.druid.sql.dialect.postgresql.ast.PGWithClause; -import com.alibaba.druid.sql.dialect.postgresql.ast.PGWithQuery; import com.alibaba.druid.sql.dialect.postgresql.ast.expr.*; import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.*; import com.alibaba.druid.sql.visitor.SQLASTVisitor; @@ -39,14 +37,6 @@ public interface PGASTVisitor extends SQLASTVisitor { boolean visit(PGSelectQueryBlock.ForClause x); - void endVisit(PGWithQuery x); - - boolean visit(PGWithQuery x); - - void endVisit(PGWithClause x); - - boolean visit(PGWithClause x); - void endVisit(PGDeleteStatement x); boolean visit(PGDeleteStatement x); diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGASTVisitorAdapter.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGASTVisitorAdapter.java index e6e761c9f4..700642de58 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGASTVisitorAdapter.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGASTVisitorAdapter.java @@ -15,8 +15,6 @@ */ package com.alibaba.druid.sql.dialect.postgresql.visitor; -import com.alibaba.druid.sql.dialect.postgresql.ast.PGWithClause; -import com.alibaba.druid.sql.dialect.postgresql.ast.PGWithQuery; import com.alibaba.druid.sql.dialect.postgresql.ast.expr.PGBoxExpr; import com.alibaba.druid.sql.dialect.postgresql.ast.expr.PGCidrExpr; import com.alibaba.druid.sql.dialect.postgresql.ast.expr.PGCircleExpr; @@ -69,27 +67,6 @@ public class PGASTVisitorAdapter extends SQLASTVisitorAdapter implements PGASTVi return true; } - @Override - public void endVisit(PGWithQuery x) { - - } - - @Override - public boolean visit(PGWithQuery x) { - - return true; - } - - @Override - public void endVisit(PGWithClause x) { - - } - - @Override - public boolean visit(PGWithClause x) { - return true; - } - @Override public void endVisit(PGDeleteStatement x) { diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGOutputVisitor.java index e560a9e936..ce1a92bef9 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGOutputVisitor.java @@ -15,13 +15,11 @@ */ package com.alibaba.druid.sql.dialect.postgresql.visitor; +import com.alibaba.druid.sql.ast.SQLExpr; import com.alibaba.druid.sql.ast.SQLLimit; import com.alibaba.druid.sql.ast.SQLSetQuantifier; import com.alibaba.druid.sql.ast.expr.SQLBinaryExpr; -import com.alibaba.druid.sql.ast.statement.SQLSelectStatement; -import com.alibaba.druid.sql.ast.statement.SQLTruncateStatement; -import com.alibaba.druid.sql.dialect.postgresql.ast.PGWithClause; -import com.alibaba.druid.sql.dialect.postgresql.ast.PGWithQuery; +import com.alibaba.druid.sql.ast.statement.*; import com.alibaba.druid.sql.dialect.postgresql.ast.expr.PGBoxExpr; import com.alibaba.druid.sql.dialect.postgresql.ast.expr.PGCidrExpr; import com.alibaba.druid.sql.dialect.postgresql.ast.expr.PGCircleExpr; @@ -42,6 +40,8 @@ import com.alibaba.druid.sql.parser.Token; import com.alibaba.druid.sql.visitor.SQLASTOutputVisitor; import com.alibaba.druid.util.StringUtils; +import java.util.List; + public class PGOutputVisitor extends SQLASTOutputVisitor implements PGASTVisitor { public PGOutputVisitor(Appendable appender){ @@ -121,58 +121,8 @@ public class PGOutputVisitor extends SQLASTOutputVisitor implements PGASTVisitor return false; } - @Override - public void endVisit(PGWithQuery x) { - - } - - @Override - public boolean visit(PGWithQuery x) { - x.getName().accept(this); - - if (x.getColumns().size() > 0) { - print0(" ("); - printAndAccept(x.getColumns(), ", "); - print(')'); - } - println(); - print0(ucase ? "AS" : "as"); - println(); - print('('); - incrementIndent(); - println(); - x.getQuery().accept(this); - decrementIndent(); - println(); - print(')'); - - return false; - } - - @Override - public void endVisit(PGWithClause x) { - - } - - @Override - public boolean visit(PGWithClause x) { - print0(ucase ? "WITH" : "with"); - if (x.isRecursive()) { - print0(ucase ? " RECURSIVE " : " recursive "); - } - incrementIndent(); - println(); - printlnAndAccept(x.getWithQuery(), ", "); - decrementIndent(); - return false; - } public boolean visit(PGSelectQueryBlock x) { - if (x.getWith() != null) { - x.getWith().accept(this); - println(); - } - print0(ucase ? "SELECT " : "select "); if (SQLSetQuantifier.ALL == x.getDistionOption()) { @@ -305,9 +255,9 @@ public class PGOutputVisitor extends SQLASTOutputVisitor implements PGASTVisitor if (x.getWhere() != null) { println(); print0(ucase ? "WHERE " : "where "); - incrementIndent(); + this.indentCount++; x.getWhere().accept(this); - decrementIndent(); + this.indentCount--; } if (x.isReturning()) { @@ -363,11 +313,6 @@ public class PGOutputVisitor extends SQLASTOutputVisitor implements PGASTVisitor @Override public boolean visit(PGSelectStatement x) { - if (x.getWith() != null) { - x.getWith().accept(this); - println(); - } - return visit((SQLSelectStatement) x); } @@ -378,8 +323,9 @@ public class PGOutputVisitor extends SQLASTOutputVisitor implements PGASTVisitor @Override public boolean visit(PGUpdateStatement x) { - if (x.getWith() != null) { - x.getWith().accept(this); + SQLWithSubqueryClause with = x.getWith(); + if (with != null) { + visit(with); println(); } @@ -389,7 +335,7 @@ public class PGOutputVisitor extends SQLASTOutputVisitor implements PGASTVisitor print0(ucase ? "ONLY " : "only "); } - x.getTableSource().accept(this); + printTableSource(x.getTableSource()); println(); print0(ucase ? "SET " : "set "); @@ -397,27 +343,31 @@ public class PGOutputVisitor extends SQLASTOutputVisitor implements PGASTVisitor if (i != 0) { print0(", "); } - x.getItems().get(i).accept(this); + SQLUpdateSetItem item = x.getItems().get(i); + visit(item); } - if (x.getFrom() != null) { + SQLTableSource from = x.getFrom(); + if (from != null) { println(); print0(ucase ? "FROM " : "from "); - x.getFrom().accept(this); + printTableSource(from); } - if (x.getWhere() != null) { + SQLExpr where = x.getWhere(); + if (where != null) { println(); + indentCount++; print0(ucase ? "WHERE " : "where "); - incrementIndent(); - x.getWhere().accept(this); - decrementIndent(); + printExpr(where); + indentCount--; } - if (x.getReturning().size() > 0) { + List returning = x.getReturning(); + if (returning.size() > 0) { println(); print0(ucase ? "RETURNING " : "returning "); - printAndAccept(x.getReturning(), ", "); + printAndAccept(returning, ", "); } return false; diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGSchemaStatVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGSchemaStatVisitor.java index 6c6d95f523..1ff241affc 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGSchemaStatVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGSchemaStatVisitor.java @@ -21,9 +21,6 @@ import com.alibaba.druid.sql.ast.SQLName; import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock; import com.alibaba.druid.sql.ast.statement.SQLSelectStatement; -import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock; -import com.alibaba.druid.sql.dialect.postgresql.ast.PGWithClause; -import com.alibaba.druid.sql.dialect.postgresql.ast.PGWithQuery; import com.alibaba.druid.sql.dialect.postgresql.ast.expr.PGBoxExpr; import com.alibaba.druid.sql.dialect.postgresql.ast.expr.PGCidrExpr; import com.alibaba.druid.sql.dialect.postgresql.ast.expr.PGCircleExpr; @@ -42,9 +39,13 @@ import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock.Wind import com.alibaba.druid.sql.visitor.SchemaStatVisitor; import com.alibaba.druid.stat.TableStat; import com.alibaba.druid.stat.TableStat.Mode; +import com.alibaba.druid.util.JdbcConstants; import com.alibaba.druid.util.JdbcUtils; public class PGSchemaStatVisitor extends SchemaStatVisitor implements PGASTVisitor { + public PGSchemaStatVisitor() { + super(JdbcConstants.POSTGRESQL); + } @Override public String getDbType() { @@ -82,41 +83,6 @@ public class PGSchemaStatVisitor extends SchemaStatVisitor implements PGASTVisit return true; } - @Override - public void endVisit(PGWithQuery x) { - - } - - @Override - public boolean visit(PGWithQuery x) { - x.getQuery().accept(this); - - Map aliasMap = getAliasMap(); - if (aliasMap != null) { - String alias = null; - if (x.getName() != null) { - alias = x.getName().toString(); - } - - if (alias != null) { - aliasMap.put(alias, null); - addSubQuery(alias, x.getQuery()); - } - } - - return false; - } - - @Override - public void endVisit(PGWithClause x) { - - } - - @Override - public boolean visit(PGWithClause x) { - return true; - } - @Override public void endVisit(PGDeleteStatement x) { @@ -124,6 +90,10 @@ public class PGSchemaStatVisitor extends SchemaStatVisitor implements PGASTVisit @Override public boolean visit(PGDeleteStatement x) { + if (repository != null) { + repository.resolve(x); + } + if (x.getWith() != null) { x.getWith().accept(this); } @@ -204,10 +174,6 @@ public class PGSchemaStatVisitor extends SchemaStatVisitor implements PGASTVisit @Override public boolean visit(PGSelectStatement x) { - if (x.getWith() != null) { - x.getWith().accept(this); - } - return visit((SQLSelectStatement) x); } 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 a94bb87e53..1eadba0bc3 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 @@ -21,6 +21,7 @@ import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr; import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerObjectImpl; import com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerASTVisitor; +import com.alibaba.druid.util.FNVUtils; public class SQLServerObjectReferenceExpr extends SQLServerObjectImpl implements SQLServerExpr, SQLName { @@ -28,6 +29,8 @@ public class SQLServerObjectReferenceExpr extends SQLServerObjectImpl implements private String database; private String schema; + protected long schema_hash; + public SQLServerObjectReferenceExpr(){ } @@ -118,4 +121,30 @@ public class SQLServerObjectReferenceExpr extends SQLServerObjectImpl implements x.schema = schema; return x; } + + public long name_hash_lower() { + if (schema_hash == 0 + && schema != null) { + final int len = schema.length(); + + boolean quote = false; + + String name = this.schema; + if (len > 2) { + char c0 = name.charAt(0); + char c1 = name.charAt(len - 1); + if ((c0 == '`' && c1 == '`') + || (c0 == '"' && c1 == '"') + || (c0 == '[' && c1 == ']')) { + quote = true; + } + } + if (quote) { + schema_hash = FNVUtils.fnv_64_lower(name, 1, len -1); + } else { + schema_hash = FNVUtils.fnv_64_lower(name); + } + } + return schema_hash; + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/stmt/SQLServerUpdateStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/stmt/SQLServerUpdateStatement.java index d5d8af3c13..0c06204591 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/stmt/SQLServerUpdateStatement.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/stmt/SQLServerUpdateStatement.java @@ -38,6 +38,9 @@ public class SQLServerUpdateStatement extends SQLUpdateStatement implements SQLS } public void setTop(SQLServerTop top) { + if (top != null) { + top.setParent(this); + } this.top = top; } @@ -46,6 +49,9 @@ public class SQLServerUpdateStatement extends SQLUpdateStatement implements SQLS } public void setOutput(SQLServerOutput output) { + if (output != null) { + output.setParent(this); + } this.output = output; } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerExprParser.java b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerExprParser.java index 6e527f8721..a9a24998b7 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerExprParser.java @@ -32,6 +32,7 @@ import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerTop; import com.alibaba.druid.sql.dialect.sqlserver.ast.expr.SQLServerObjectReferenceExpr; import com.alibaba.druid.sql.parser.Lexer; import com.alibaba.druid.sql.parser.SQLExprParser; +import com.alibaba.druid.sql.parser.SQLParserFeature; import com.alibaba.druid.sql.parser.Token; import com.alibaba.druid.util.FNVUtils; import com.alibaba.druid.util.JdbcConstants; @@ -65,6 +66,12 @@ public class SQLServerExprParser extends SQLExprParser { this.dbType = JdbcConstants.SQL_SERVER; } + public SQLServerExprParser(String sql, SQLParserFeature... features){ + this(new SQLServerLexer(sql, features)); + this.lexer.nextToken(); + this.dbType = JdbcConstants.SQL_SERVER; + } + public SQLExpr primary() { if (lexer.token() == Token.LBRACKET) { diff --git a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerLexer.java b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerLexer.java index 9af698954c..0f346f1d5a 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerLexer.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerLexer.java @@ -21,10 +21,7 @@ import static com.alibaba.druid.sql.parser.Token.IDENTIFIER; import java.util.HashMap; import java.util.Map; -import com.alibaba.druid.sql.parser.Keywords; -import com.alibaba.druid.sql.parser.Lexer; -import com.alibaba.druid.sql.parser.NotAllowCommentException; -import com.alibaba.druid.sql.parser.Token; +import com.alibaba.druid.sql.parser.*; public class SQLServerLexer extends Lexer { @@ -59,6 +56,14 @@ public class SQLServerLexer extends Lexer { super(input); super.keywods = DEFAULT_SQL_SERVER_KEYWORDS; } + + public SQLServerLexer(String input, SQLParserFeature... features){ + super(input); + super.keywods = DEFAULT_SQL_SERVER_KEYWORDS; + for (SQLParserFeature feature : features) { + config(feature, true); + } + } public void scanComment() { if (ch != '/' && ch != '-') { diff --git a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerSelectParser.java b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerSelectParser.java index 5b1db80014..1e4955c0e0 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerSelectParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerSelectParser.java @@ -17,11 +17,7 @@ package com.alibaba.druid.sql.dialect.sqlserver.parser; import com.alibaba.druid.sql.ast.SQLExpr; import com.alibaba.druid.sql.ast.SQLSetQuantifier; -import com.alibaba.druid.sql.ast.statement.SQLExprHint; -import com.alibaba.druid.sql.ast.statement.SQLExprTableSource; -import com.alibaba.druid.sql.ast.statement.SQLSelect; -import com.alibaba.druid.sql.ast.statement.SQLSelectQuery; -import com.alibaba.druid.sql.ast.statement.SQLTableSource; +import com.alibaba.druid.sql.ast.statement.*; import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerSelectQueryBlock; import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerTop; import com.alibaba.druid.sql.parser.ParserException; @@ -42,7 +38,10 @@ public class SQLServerSelectParser extends SQLSelectParser { public SQLSelect select() { SQLSelect select = new SQLSelect(); - withSubquery(select); + if (lexer.token() == Token.WITH) { + SQLWithSubqueryClause with = this.parseWith(); + select.setWithSubQuery(with); + } select.setQuery(query()); select.setOrderBy(parseOrderBy()); diff --git a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerStatementParser.java b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerStatementParser.java index 5d5599430a..bbca866e71 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerStatementParser.java @@ -37,11 +37,7 @@ import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerSetStatement; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerSetTransactionIsolationLevelStatement; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerUpdateStatement; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerWaitForStatement; -import com.alibaba.druid.sql.parser.Lexer; -import com.alibaba.druid.sql.parser.ParserException; -import com.alibaba.druid.sql.parser.SQLSelectParser; -import com.alibaba.druid.sql.parser.SQLStatementParser; -import com.alibaba.druid.sql.parser.Token; +import com.alibaba.druid.sql.parser.*; public class SQLServerStatementParser extends SQLStatementParser { @@ -49,6 +45,10 @@ public class SQLServerStatementParser extends SQLStatementParser { super(new SQLServerExprParser(sql)); } + public SQLServerStatementParser(String sql, SQLParserFeature... features){ + super(new SQLServerExprParser(sql, features)); + } + public SQLSelectParser createSQLSelectParser() { return new SQLServerSelectParser(this.exprParser); } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerOutputVisitor.java index 2d209cc39b..2c4cc10aa4 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerOutputVisitor.java @@ -15,10 +15,7 @@ */ package com.alibaba.druid.sql.dialect.sqlserver.visitor; -import com.alibaba.druid.sql.ast.SQLName; -import com.alibaba.druid.sql.ast.SQLOrderBy; -import com.alibaba.druid.sql.ast.SQLSetQuantifier; -import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.ast.*; import com.alibaba.druid.sql.ast.statement.*; import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerOutput; import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerSelectQueryBlock; @@ -57,42 +54,45 @@ public class SQLServerOutputVisitor extends SQLASTOutputVisitor implements SQLSe print0(ucase ? "UNIQUE " : "unique "); } - if (x.getTop() != null) { - x.getTop().accept(this); + SQLServerTop top = x.getTop(); + if (top != null) { + visit(top); print(' '); } printSelectList(x.getSelectList()); - if (x.getInto() != null) { + SQLExprTableSource into = x.getInto(); + if (into != null) { println(); print0(ucase ? "INTO " : "into "); - x.getInto().accept(this); + printTableSource(into); } - if (x.getFrom() != null) { + SQLTableSource from = x.getFrom(); + if (from != null) { println(); print0(ucase ? "FROM " : "from "); - x.getFrom().accept(this); + printTableSource(from); } - if (x.getWhere() != null) { + SQLExpr where = x.getWhere(); + if (where != null) { println(); print0(ucase ? "WHERE " : "where "); - x.getWhere().setParent(x); - x.getWhere().accept(this); + printExpr(where); } SQLSelectGroupByClause groupBy = x.getGroupBy(); if (groupBy != null) { println(); - groupBy.accept(this); + visit(groupBy); } SQLOrderBy orderBy = x.getOrderBy(); if (orderBy != null) { println(); - orderBy.accept(this); + visit(orderBy); } printFetchFirst(x); @@ -203,13 +203,13 @@ public class SQLServerOutputVisitor extends SQLASTOutputVisitor implements SQLSe public boolean visit(SQLServerUpdateStatement x) { print0(ucase ? "UPDATE " : "update "); - if (x.getTop() != null) { - x.getTop().setParent(x); - x.getTop().accept(this); + SQLServerTop top = x.getTop(); + if (top != null) { + top.accept(this); print(' '); } - x.getTableSource().accept(this); + printTableSource(x.getTableSource()); println(); print0(ucase ? "SET " : "set "); @@ -217,29 +217,30 @@ public class SQLServerOutputVisitor extends SQLASTOutputVisitor implements SQLSe if (i != 0) { print0(", "); } - x.getItems().get(i).accept(this); - } - - if (x.getOutput() != null) { - println(); - x.getOutput().setParent(x); - x.getOutput().accept(this); + SQLUpdateSetItem item = x.getItems().get(i); + visit(item); } - if (x.getFrom() != null) { + SQLServerOutput output = x.getOutput(); + if (output != null) { + println(); + visit(output); + } + + SQLTableSource from = x.getFrom(); + if (from != null) { println(); print0(ucase ? "FROM " : "from "); - x.getFrom().setParent(x); - x.getFrom().accept(this); + printTableSource(from); } - if (x.getWhere() != null) { + SQLExpr where = x.getWhere(); + if (where != null) { println(); + indentCount++; print0(ucase ? "WHERE " : "where "); - incrementIndent(); - x.getWhere().setParent(x); - x.getWhere().accept(this); - decrementIndent(); + printExpr(where); + indentCount--; } return false; @@ -253,9 +254,10 @@ public class SQLServerOutputVisitor extends SQLASTOutputVisitor implements SQLSe public boolean visit(SQLExprTableSource x) { printTableSourceExpr(x.getExpr()); - if (x.getAlias() != null) { + String alias = x.getAlias(); + if (alias != null) { print(' '); - print0(x.getAlias()); + print0(alias); } if (x.getHints() != null && x.getHints().size() > 0) { @@ -366,13 +368,13 @@ public class SQLServerOutputVisitor extends SQLASTOutputVisitor implements SQLSe printSelectList(x.getSelectList()); if (x.getInto() != null) { - incrementIndent(); + this.indentCount++; println(); print0(ucase ? "INTO " : "into "); x.getInto().accept(this); if (x.getColumns().size() > 0) { - incrementIndent(); + this.indentCount++; println(); print('('); for (int i = 0, size = x.getColumns().size(); i < size; ++i) { @@ -386,10 +388,10 @@ public class SQLServerOutputVisitor extends SQLASTOutputVisitor implements SQLSe x.getColumns().get(i).accept(this); } print(')'); - decrementIndent(); + this.indentCount--; } } - decrementIndent(); + this.indentCount--; return false; } @@ -401,7 +403,7 @@ public class SQLServerOutputVisitor extends SQLASTOutputVisitor implements SQLSe @Override public boolean visit(SQLBlockStatement x) { print0(ucase ? "BEGIN" : "begin"); - incrementIndent(); + this.indentCount++; println(); for (int i = 0, size = x.getStatementList().size(); i < size; ++i) { if (i != 0) { @@ -412,7 +414,7 @@ public class SQLServerOutputVisitor extends SQLASTOutputVisitor implements SQLSe stmt.accept(this); print(';'); } - decrementIndent(); + this.indentCount--; println(); print0(ucase ? "END" : "end"); return false; diff --git a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerSchemaStatVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerSchemaStatVisitor.java index bcf168e9fd..c710696127 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerSchemaStatVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerSchemaStatVisitor.java @@ -33,13 +33,12 @@ import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerUpdateStatement import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerWaitForStatement; import com.alibaba.druid.sql.visitor.SchemaStatVisitor; import com.alibaba.druid.stat.TableStat; +import com.alibaba.druid.util.JdbcConstants; import com.alibaba.druid.util.JdbcUtils; public class SQLServerSchemaStatVisitor extends SchemaStatVisitor implements SQLServerASTVisitor { - - @Override - public String getDbType() { - return JdbcUtils.SQL_SERVER; + public SQLServerSchemaStatVisitor() { + super(JdbcConstants.SQL_SERVER); } @Override 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 3b8ef15f52..7ce3004866 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java @@ -906,7 +906,7 @@ public class SQLExprParser extends SQLParser { if (expr instanceof SQLIdentifierExpr) { SQLIdentifierExpr identifierExpr = (SQLIdentifierExpr) expr; methodName = identifierExpr.getName(); - hash_lower = identifierExpr.hash_lower(); + hash_lower = identifierExpr.name_hash_lower(); if (hash_lower == FNVUtils.TRIM) { if (lexer.identifierEquals(FNVUtils.LEADING)) { @@ -1005,9 +1005,14 @@ public class SQLExprParser extends SQLParser { expr = new SQLPropertyExpr(expr, "*"); } else { String name; + long hash_lower = 0L; - if (lexer.token == Token.IDENTIFIER || lexer.token == Token.LITERAL_CHARS - || lexer.token == Token.LITERAL_ALIAS) { + if (lexer.token == Token.IDENTIFIER) { + name = lexer.stringVal(); + hash_lower = lexer.hash_lower; + lexer.nextToken(); + } else if (lexer.token == Token.LITERAL_CHARS + || lexer.token == Token.LITERAL_ALIAS) { name = lexer.stringVal(); lexer.nextToken(); } else if (lexer.getKeywods().containsValue(lexer.token)) { @@ -1055,7 +1060,7 @@ public class SQLExprParser extends SQLParser { expr = methodInvokeExpr; } } else { - expr = new SQLPropertyExpr(expr, name); + expr = new SQLPropertyExpr(expr, name, hash_lower); } } @@ -1642,7 +1647,7 @@ public class SQLExprParser extends SQLParser { if (lexer.token == Token.AND && lexer.isEnabled(SQLParserFeature.EnableSQLBinaryOpExprGroup)) { - SQLBinaryOpExprGroup group = new SQLBinaryOpExprGroup(SQLBinaryOperator.BooleanAnd); + SQLBinaryOpExprGroup group = new SQLBinaryOpExprGroup(SQLBinaryOperator.BooleanAnd, dbType); group.add(expr); group.add(rightExp); @@ -1697,25 +1702,31 @@ public class SQLExprParser extends SQLParser { } public SQLExpr orRest(SQLExpr expr) { -// SQLBinaryOpExprGroup group = new SQLBinaryOpExprGroup(SQLBinaryOperator.BooleanAnd); for (;;) { if (lexer.token == Token.OR) { lexer.nextToken(); SQLExpr rightExp = and(); -// expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.BooleanOr, rightExp, dbType); if (lexer.token == Token.OR && lexer.isEnabled(SQLParserFeature.EnableSQLBinaryOpExprGroup)) { - SQLBinaryOpExprGroup group = new SQLBinaryOpExprGroup(SQLBinaryOperator.BooleanOr); + SQLBinaryOpExprGroup group = new SQLBinaryOpExprGroup(SQLBinaryOperator.BooleanOr, dbType); group.add(expr); group.add(rightExp); + if (lexer.isKeepComments() && lexer.hasComment()) { + rightExp.addAfterComment(lexer.readAndResetComments()); + } + for (;;) { lexer.nextToken(); SQLExpr more = relational(); group.add(more); if (lexer.token == Token.OR) { + if (lexer.isKeepComments() && lexer.hasComment()) { + more.addAfterComment(lexer.readAndResetComments()); + } + continue; } break; diff --git a/src/main/java/com/alibaba/druid/sql/parser/SQLSelectParser.java b/src/main/java/com/alibaba/druid/sql/parser/SQLSelectParser.java index 0ddfb47aee..b3a2897bf8 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLSelectParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLSelectParser.java @@ -43,7 +43,10 @@ public class SQLSelectParser extends SQLParser { public SQLSelect select() { SQLSelect select = new SQLSelect(); - withSubquery(select); + if (lexer.token() == Token.WITH) { + SQLWithSubqueryClause with = this.parseWith(); + select.setWithSubQuery(with); + } select.setQuery(query()); select.setOrderBy(parseOrderBy()); @@ -211,7 +214,10 @@ public class SQLSelectParser extends SQLParser { for (;;) { SQLWithSubqueryClause.Entry entry = new SQLWithSubqueryClause.Entry(); entry.setParent(withQueryClause); - entry.setName((SQLIdentifierExpr) this.exprParser.name()); + + String alias = this.lexer.stringVal(); + lexer.nextToken(); + entry.setAlias(alias); if (lexer.token == Token.LPAREN) { lexer.nextToken(); @@ -238,6 +244,56 @@ public class SQLSelectParser extends SQLParser { } } + public SQLWithSubqueryClause parseWith() { + accept(Token.WITH); + + SQLWithSubqueryClause withQueryClause = new SQLWithSubqueryClause(); + + if (lexer.token == Token.RECURSIVE || lexer.identifierEquals("RECURSIVE")) { + lexer.nextToken(); + withQueryClause.setRecursive(true); + } + + for (;;) { + SQLWithSubqueryClause.Entry entry = new SQLWithSubqueryClause.Entry(); + entry.setParent(withQueryClause); + + String alias = this.lexer.stringVal(); + lexer.nextToken(); + entry.setAlias(alias); + + if (lexer.token == Token.LPAREN) { + lexer.nextToken(); + exprParser.names(entry.getColumns()); + accept(Token.RPAREN); + } + + accept(Token.AS); + accept(Token.LPAREN); + + switch (lexer.token) { + case SELECT: + entry.setSubQuery(select()); + break; + default: + break; + } + + accept(Token.RPAREN); + + withQueryClause.addEntry(entry); + + if (lexer.token == Token.COMMA) { + lexer.nextToken(); + continue; + } + + break; + } + + return withQueryClause; + } + protected void parseWhere(SQLSelectQueryBlock queryBlock) { if (lexer.token == Token.WHERE) { lexer.nextToken(); 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 6bbf0ed1c8..396de8ea8f 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java @@ -29,6 +29,7 @@ import com.alibaba.druid.sql.ast.statement.SQLCreateTriggerStatement.TriggerEven import com.alibaba.druid.sql.ast.statement.SQLCreateTriggerStatement.TriggerType; import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlRepeatStatement; import com.alibaba.druid.sql.dialect.oracle.parser.OracleExprParser; +import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.*; import com.alibaba.druid.util.JdbcConstants; import com.alibaba.druid.util.JdbcUtils; @@ -127,14 +128,12 @@ public class SQLStatementParser extends SQLParser { continue; } - case WITH: - if (!JdbcConstants.POSTGRESQL.equals(dbType)){ - SQLStatement stmt = parseSelect(); + case WITH: { + SQLStatement stmt = parseWith(); stmt.setParent(parent); statementList.add(stmt); continue; } - break; case SELECT: { SQLStatement stmt = parseSelect(); stmt.setParent(parent); @@ -2778,4 +2777,85 @@ public class SQLStatementParser extends SQLParser { } return stmt; } + + public SQLWithSubqueryClause parseWithQuery() { + accept(Token.WITH); + + SQLWithSubqueryClause withQueryClause = new SQLWithSubqueryClause(); + + if (lexer.token == Token.RECURSIVE || lexer.identifierEquals("RECURSIVE")) { + lexer.nextToken(); + withQueryClause.setRecursive(true); + } + + for (;;) { + SQLWithSubqueryClause.Entry entry = new SQLWithSubqueryClause.Entry(); + entry.setParent(withQueryClause); + + String alias = this.lexer.stringVal(); + lexer.nextToken(); + entry.setAlias(alias); + + if (lexer.token == Token.LPAREN) { + lexer.nextToken(); + exprParser.names(entry.getColumns()); + accept(Token.RPAREN); + } + + accept(Token.AS); + accept(Token.LPAREN); + + switch (lexer.token) { + case VALUES: + case SELECT: + entry.setSubQuery( + this.createSQLSelectParser() + .select()); + break; + case INSERT: + entry.setReturningStatement( + this.parseInsert() + ); + break; + case UPDATE: + entry.setReturningStatement( + this.parseUpdateStatement() + ); + break; + case DELETE: + entry.setReturningStatement( + this.parseDeleteStatement() + ); + break; + default: + break; + } + + accept(Token.RPAREN); + + withQueryClause.addEntry(entry); + + if (lexer.token == Token.COMMA) { + lexer.nextToken(); + continue; + } + + break; + } + + return withQueryClause; + } + + public SQLStatement parseWith() { + SQLWithSubqueryClause with = this.parseWithQuery(); + + if (lexer.token() == Token.SELECT) { + SQLSelectParser selectParser = createSQLSelectParser(); + SQLSelect select = selectParser.select(); + select.setWithSubQuery(with); + return new SQLSelectStatement(select, dbType); + } + + throw new ParserException("TODO. " + lexer.info()); + } } diff --git a/src/main/java/com/alibaba/druid/sql/repository/SchemaObject.java b/src/main/java/com/alibaba/druid/sql/repository/SchemaObject.java index ad75bbfec9..35eb2db978 100644 --- a/src/main/java/com/alibaba/druid/sql/repository/SchemaObject.java +++ b/src/main/java/com/alibaba/druid/sql/repository/SchemaObject.java @@ -26,6 +26,7 @@ public interface SchemaObject { SQLStatement getStatement(); SQLColumnDefinition findColumn(String columName); + SQLColumnDefinition findColumn(long columNameHash); boolean matchIndex(String columnName); diff --git a/src/main/java/com/alibaba/druid/sql/repository/SchemaObjectImpl.java b/src/main/java/com/alibaba/druid/sql/repository/SchemaObjectImpl.java index 430917f5ab..19dbbdebc1 100644 --- a/src/main/java/com/alibaba/druid/sql/repository/SchemaObjectImpl.java +++ b/src/main/java/com/alibaba/druid/sql/repository/SchemaObjectImpl.java @@ -20,6 +20,7 @@ import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition; import com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement; import com.alibaba.druid.sql.ast.statement.SQLTableElement; import com.alibaba.druid.sql.ast.statement.SQLUniqueConstraint; +import com.alibaba.druid.util.FNVUtils; /** * Created by wenshao on 08/06/2017. @@ -50,12 +51,17 @@ public class SchemaObjectImpl implements SchemaObject { } public SQLColumnDefinition findColumn(String columName) { + long hash = FNVUtils.fnv_64_lower_normalized(columName); + return findColumn(hash); + } + + public SQLColumnDefinition findColumn(long columNameHash) { if (statement == null) { return null; } if (statement instanceof SQLCreateTableStatement) { - return ((SQLCreateTableStatement) statement).findColumn(columName); + return ((SQLCreateTableStatement) statement).findColumn(columNameHash); } return null; diff --git a/src/main/java/com/alibaba/druid/sql/repository/SchemaRepository.java b/src/main/java/com/alibaba/druid/sql/repository/SchemaRepository.java index 98856718a1..f550dec943 100644 --- a/src/main/java/com/alibaba/druid/sql/repository/SchemaRepository.java +++ b/src/main/java/com/alibaba/druid/sql/repository/SchemaRepository.java @@ -22,12 +22,20 @@ import com.alibaba.druid.sql.ast.expr.SQLAllColumnExpr; import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr; 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.statement.*; import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitorAdapter; +import com.alibaba.druid.sql.dialect.odps.ast.OdpsSelectQueryBlock; +import com.alibaba.druid.sql.dialect.odps.visitor.OdpsASTVisitorAdapter; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleCreateTableStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectQueryBlock; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectTableReference; import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitorAdapter; +import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock; +import com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitorAdapter; +import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerSelectQueryBlock; +import com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerASTVisitorAdapter; import com.alibaba.druid.sql.visitor.SQLASTVisitor; import com.alibaba.druid.sql.visitor.SQLASTVisitorAdapter; import com.alibaba.druid.support.logging.Log; @@ -65,6 +73,10 @@ public class SchemaRepository { private Map schemas = new LinkedHashMap(); + public String getDbType() { + return dbType; + } + public String getDefaultSchemaName() { return getDefaultSchema().getName(); } @@ -245,17 +257,28 @@ public class SchemaRepository { SchemaResolveVisitor resolveVisitor; if (JdbcConstants.MYSQL.equals(dbType)) { - resolveVisitor = new MySqlResolveVisitor(optionsValue); + resolveVisitor = new SchemaResolveVisitorFactory.MySqlResolveVisitor(this, optionsValue); } else if (JdbcConstants.ORACLE.equals(dbType)) { - resolveVisitor = new OracleResolveVisitor(optionsValue); + resolveVisitor = new SchemaResolveVisitorFactory.OracleResolveVisitor(this, optionsValue); + } else if (JdbcConstants.DB2.equals(dbType)) { + resolveVisitor = new SchemaResolveVisitorFactory.DB2ResolveVisitor(this, optionsValue); + } else if (JdbcConstants.ODPS.equals(dbType)) { + resolveVisitor = new SchemaResolveVisitorFactory.OdpsResolveVisitor(this, optionsValue); + } else if (JdbcConstants.POSTGRESQL.equals(dbType)) { + resolveVisitor = new SchemaResolveVisitorFactory.PGResolveVisitor(this, optionsValue); + } else if (JdbcConstants.SQL_SERVER.equals(dbType)) { + resolveVisitor = new SchemaResolveVisitorFactory.SQLServerResolveVisitor(this, optionsValue); } else { - throw new DruidRuntimeException("dbType not support : " + dbType); + resolveVisitor = new SchemaResolveVisitorFactory.SQLResolveVisitor(this, optionsValue); } return resolveVisitor; } public String resolve(String input) { - SchemaResolveVisitor visitor = createResolveVisitor(SchemaResolveVisitor.Option.ResolveAllColumn); + SchemaResolveVisitor visitor + = createResolveVisitor( + SchemaResolveVisitor.Option.ResolveAllColumn, + SchemaResolveVisitor.Option.ResolveIdentifierAlias); List stmtList = SQLUtils.parseStatements(input, dbType); @@ -393,198 +416,15 @@ public class SchemaRepository { return true; } - private class MySqlResolveVisitor extends MySqlASTVisitorAdapter implements SchemaResolveVisitor { - private int options; - public MySqlResolveVisitor(int options) { - this.options = options; - } - public boolean visit(SQLExprTableSource x) { - resolve(this, x); - return false; - } - public boolean visit(MySqlSelectQueryBlock x) { - x.getFrom().accept(this); - resolve(this, x); - return super.visit(x); - } - public boolean visit(SQLIdentifierExpr x) { - resolve(this, x); - return true; - } - public boolean visit(SQLPropertyExpr x) { - resolve(this, x); - return true; - } - public boolean visit(SQLAllColumnExpr x) { - resolve(this, x); - return false; - } - @Override - public boolean isEnabled(Option option) { - return (options & option.mask) != 0; - } - } - - private class OracleResolveVisitor extends OracleASTVisitorAdapter implements SchemaResolveVisitor { - private int options; - - public OracleResolveVisitor(int options) { - this.options = options; - } - - public boolean visit(OracleSelectTableReference x) { - resolve(this, x); - return false; - } - - public boolean visit(SQLExprTableSource x) { - resolve(this, x); - return false; - } - - public boolean visit(OracleSelectQueryBlock x) { - SQLTableSource from = x.getFrom(); - if (from != null) { - from.accept(this); - } - resolve(this, x); - return super.visit(x); - } - - public boolean visit(SQLIdentifierExpr x) { - resolve(this, x); - return true; - } - - public boolean visit(SQLPropertyExpr x) { - resolve(this, x); - return true; - } - - public boolean visit(SQLAllColumnExpr x) { - resolve(this, x); - return false; - } - - @Override - public boolean isEnabled(Option option) { - return (options & option.mask) != 0; - } - } - - private void resolve(SchemaResolveVisitor visitor, SQLAllColumnExpr x) { - SQLSelectQueryBlock queryBlock = null; - for (SQLObject parent = x.getParent(); parent != null; parent = parent.getParent()) { - if (parent instanceof SQLTableSource) { - return; - } - if (parent instanceof SQLSelectQueryBlock) { - queryBlock = (SQLSelectQueryBlock) parent; - break; - } - } - - if (queryBlock == null) { - return; - } - - SQLTableSource from = queryBlock.getFrom(); - if (from == null || from instanceof SQLJoinTableSource) { - return; - } - - x.setResolvedTableSource(from); - } - - private void resolve(SchemaResolveVisitor visitor, SQLPropertyExpr x) { - String owner = x.getOwnernName(); - if (owner == null) { - return; - } - - SQLSelectQueryBlock queryBlock = null; - for (SQLObject parent = x.getParent(); parent != null; parent = parent.getParent()) { - if (parent instanceof SQLTableSource) { - return; - } - if (parent instanceof SQLSelectQueryBlock) { - queryBlock = (SQLSelectQueryBlock) parent; - break; - } - } - - if (queryBlock == null) { - return; - } - - SQLTableSource tableSource = queryBlock.findTableSource(owner); - if (tableSource != null) { - x.setResolvedTableSource(tableSource); - SQLColumnDefinition column = tableSource.findColumn(x.getName()); - if (column != null) { - x.setResolvedColumn(column); - } - } - } - - private void resolve(SchemaResolveVisitor visitor, SQLIdentifierExpr x) { - SQLSelectQueryBlock queryBlock = null; - for (SQLObject parent = x.getParent(); parent != null; parent = parent.getParent()) { - if (parent instanceof SQLTableSource) { - return; - } - if (parent instanceof SQLSelectQueryBlock) { - queryBlock = (SQLSelectQueryBlock) parent; - break; - } - } - - if (queryBlock == null) { - return; - } - - String ident = x.getName(); - SQLTableSource tableSource = null; - if (queryBlock.getFrom() instanceof SQLJoinTableSource - || queryBlock.getFrom() instanceof SQLSubqueryTableSource) { - tableSource = queryBlock.findTableSourceWithColumn(ident); - } else { - tableSource = queryBlock.getFrom(); - if (tableSource instanceof SQLExprTableSource) { - SchemaObject table = ((SQLExprTableSource) tableSource).getSchemaObject(); - if (table != null) { - if (table.findColumn(ident) == null) { - tableSource = null; // maybe parent - } - } - } - } - - if (tableSource != null) { - x.setResolvedTableSource(tableSource); - - SQLColumnDefinition column = tableSource.findColumn(ident); - if (column != null) { - x.setResolvedColumn(column); - } - - if (queryBlock.getFrom() instanceof SQLJoinTableSource) { - String alias = tableSource.computeAlias(); - SQLPropertyExpr propertyExpr = new SQLPropertyExpr(alias, ident); - SQLUtils.replaceInParent(x, propertyExpr); - } - } - } - - private void resolve(SchemaResolveVisitor visitor, SQLExprTableSource x) { + protected void resolve(SchemaResolveVisitor visitor, SQLExprTableSource x) { if (x.getSchemaObject() != null) { return; } @@ -598,81 +438,9 @@ public class SchemaRepository { } } - private void resolve(SchemaResolveVisitor visitor, SQLSelectQueryBlock x) { - SQLTableSource from = x.getFrom(); - if (from != null) { - from.accept(visitor); - } - List selectList = x.getSelectList(); - List columns = new ArrayList(); - for (int i = selectList.size() - 1; i >= 0; i--) { - SQLSelectItem selectItem = selectList.get(i); - SQLExpr expr = selectItem.getExpr(); - if (expr instanceof SQLAllColumnExpr) { - if (visitor.isEnabled(SchemaResolveVisitor.Option.ResolveAllColumn)) { - extractColumns(from, columns); - } - } else if (expr instanceof SQLPropertyExpr) { - SQLPropertyExpr propertyExpr = (SQLPropertyExpr) expr; - String ownerName = propertyExpr.getOwnernName(); - if (propertyExpr.getName().equals("*")) { - if (visitor.isEnabled(SchemaResolveVisitor.Option.ResolveAllColumn)) { - SQLTableSource tableSource = x.findTableSource(ownerName); - extractColumns(tableSource, columns); - } - } - SQLColumnDefinition column = propertyExpr.getResolvedColumn(); - if (column != null) { - continue; - } - SQLTableSource tableSource = x.findTableSource(propertyExpr.getOwnernName()); - if (tableSource != null) { - column = tableSource.findColumn(propertyExpr.getName()); - if (column != null) { - propertyExpr.setResolvedColumn(column); - } - } - } else if (expr instanceof SQLIdentifierExpr) { - SQLIdentifierExpr identExpr = (SQLIdentifierExpr) expr; - SQLColumnDefinition column = identExpr.getResolvedColumn(); - if (column != null) { - continue; - } - column = from.findColumn(identExpr.getName()); - if (column != null) { - identExpr.setResolvedColumn(column); - } - } - if (columns.size() > 0) { - for (SQLSelectItem column : columns) { - column.setParent(x); - } - - selectList.remove(i); - selectList.addAll(i, columns); - } - } - } - - private void extractColumns(SQLTableSource from, List columns) { - if (from instanceof SQLExprTableSource) { - SchemaObject table = findTable((SQLExprTableSource) from); - if (table != null) { - SQLCreateTableStatement createTableStmt = (SQLCreateTableStatement) table.getStatement(); - for (SQLTableElement e : createTableStmt.getTableElementList()) { - if (e instanceof SQLColumnDefinition) { - SQLColumnDefinition column = (SQLColumnDefinition) e; - SQLIdentifierExpr name = (SQLIdentifierExpr) column.getName().clone(); - name.setResolvedColumn(column); - columns.add(new SQLSelectItem(name)); - } - } - } - } - } public SchemaObject findTable(SQLExprTableSource x) { if (x == null) { diff --git a/src/main/java/com/alibaba/druid/sql/repository/SchemaResolveVisitor.java b/src/main/java/com/alibaba/druid/sql/repository/SchemaResolveVisitor.java index bdf8f959a0..c4c29b4f00 100644 --- a/src/main/java/com/alibaba/druid/sql/repository/SchemaResolveVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/repository/SchemaResolveVisitor.java @@ -15,8 +15,13 @@ */ package com.alibaba.druid.sql.repository; +import com.alibaba.druid.sql.ast.SQLObject; +import com.alibaba.druid.sql.ast.statement.SQLTableSource; import com.alibaba.druid.sql.visitor.SQLASTVisitor; +import java.util.HashMap; +import java.util.Map; + /** * Created by wenshao on 03/08/2017. */ @@ -25,7 +30,8 @@ public interface SchemaResolveVisitor extends SQLASTVisitor { boolean isEnabled(Option option); public static enum Option { - ResolveAllColumn + ResolveAllColumn, + ResolveIdentifierAlias ; private Option() { mask = (1 << ordinal()); @@ -47,4 +53,46 @@ public interface SchemaResolveVisitor extends SQLASTVisitor { return value; } } + + SchemaRepository getRepository(); + + Context getContext(); + Context createContext(SQLObject object); + void popContext(); + + static class Context { + public final Context parent; + public final SQLObject object; + + private SQLTableSource tableSource; + + private SQLTableSource from; + + private Map tableSourceMap; + + public Context(SQLObject object, Context parent) { + this.object = object; + this.parent = parent; + } + + public SQLTableSource getFrom() { + return from; + } + + public void setFrom(SQLTableSource from) { + this.from = from; + } + + public SQLTableSource getTableSource() { + return tableSource; + } + + public void setTableSource(SQLTableSource tableSource) { + this.tableSource = tableSource; + } + + public void addTableSource(long alias_hash, SQLTableSource tableSource) { + tableSourceMap.put(alias_hash, tableSource); + } + } } diff --git a/src/main/java/com/alibaba/druid/sql/repository/SchemaResolveVisitorFactory.java b/src/main/java/com/alibaba/druid/sql/repository/SchemaResolveVisitorFactory.java new file mode 100644 index 0000000000..6c3950b4b1 --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/repository/SchemaResolveVisitorFactory.java @@ -0,0 +1,1200 @@ +package com.alibaba.druid.sql.repository; + +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLExpr; +import com.alibaba.druid.sql.ast.SQLName; +import com.alibaba.druid.sql.ast.SQLObject; +import com.alibaba.druid.sql.ast.SQLOrderBy; +import com.alibaba.druid.sql.ast.expr.SQLAllColumnExpr; +import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; +import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr; +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.statement.MySqlCreateTableStatement; +import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlDeleteStatement; +import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock; +import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlUpdateStatement; +import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitorAdapter; +import com.alibaba.druid.sql.dialect.odps.ast.OdpsCreateTableStatement; +import com.alibaba.druid.sql.dialect.odps.ast.OdpsSelectQueryBlock; +import com.alibaba.druid.sql.dialect.odps.visitor.OdpsASTVisitorAdapter; +import com.alibaba.druid.sql.dialect.oracle.ast.stmt.*; +import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitorAdapter; +import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGDeleteStatement; +import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock; +import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectStatement; +import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGUpdateStatement; +import com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitorAdapter; +import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerSelectQueryBlock; +import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerUpdateStatement; +import com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerASTVisitorAdapter; +import com.alibaba.druid.sql.visitor.SQLASTVisitorAdapter; + +import java.util.ArrayList; +import java.util.List; + +class SchemaResolveVisitorFactory { + static class MySqlResolveVisitor extends MySqlASTVisitorAdapter implements SchemaResolveVisitor { + private SchemaRepository repository; + private int options; + private Context context; + + public MySqlResolveVisitor(SchemaRepository repository, int options) { + this.repository = repository; + this.options = options; + } + + public boolean visit(SQLExprTableSource x) { + repository.resolve(this, x); + return false; + } + + public boolean visit(MySqlSelectQueryBlock x) { + resolve(this, x); + return false; + } + + public boolean visit(SQLSelectItem x) { + SQLExpr expr = x.getExpr(); + if (expr instanceof SQLIdentifierExpr) { + resolve(this, (SQLIdentifierExpr) expr); + return false; + } + + if (expr instanceof SQLPropertyExpr) { + resolve(this, (SQLPropertyExpr) expr); + return false; + } + + return true; + } + + public boolean visit(SQLIdentifierExpr x) { + resolve(this, x); + return true; + } + + public boolean visit(SQLPropertyExpr x) { + resolve(this, x); + return false; + } + + public boolean visit(SQLAllColumnExpr x) { + resolve(this, x); + return false; + } + + public boolean visit(MySqlCreateTableStatement x) { + resolve(this, x); + SQLExprTableSource like = x.getLike(); + if (like != null) { + like.accept(this); + } + return false; + } + + public boolean visit(MySqlUpdateStatement x) { + resolve(this, x); + return false; + } + + public boolean visit(MySqlDeleteStatement x) { + resolve(this, x); + return false; + } + + public boolean visit(SQLSelect x) { + resolve(this, x); + return false; + } + + public boolean visit(SQLWithSubqueryClause x) { + resolve(this, x); + return false; + } + + @Override + public boolean isEnabled(Option option) { + return (options & option.mask) != 0; + } + + @Override + public Context getContext() { + return context; + } + + public Context createContext(SQLObject object) { + return this.context = new Context(object, context); + } + + @Override + public void popContext() { + if (context != null) { + context = context.parent; + } + } + + public SchemaRepository getRepository() { + return repository; + } + } + + + + static class DB2ResolveVisitor extends DB2ASTVisitorAdapter implements SchemaResolveVisitor { + private SchemaRepository repository; + private int options; + private Context context; + + public DB2ResolveVisitor(SchemaRepository repository, int options) { + this.repository = repository; + this.options = options; + } + + public boolean visit(SQLExprTableSource x) { + repository.resolve(this, x); + return false; + } + + public boolean visit(DB2SelectQueryBlock x) { + resolve(this, x); + return false; + } + + public boolean visit(SQLSelectItem x) { + SQLExpr expr = x.getExpr(); + if (expr instanceof SQLIdentifierExpr) { + resolve(this, (SQLIdentifierExpr) expr); + return false; + } + + if (expr instanceof SQLPropertyExpr) { + resolve(this, (SQLPropertyExpr) expr); + return false; + } + + return true; + } + + public boolean visit(SQLIdentifierExpr x) { + resolve(this, x); + return true; + } + + public boolean visit(SQLPropertyExpr x) { + resolve(this, x); + return false; + } + + public boolean visit(SQLAllColumnExpr x) { + resolve(this, x); + return false; + } + + public boolean visit(SQLCreateTableStatement x) { + resolve(this, x); + return false; + } + + public boolean visit(SQLUpdateStatement x) { + resolve(this, x); + return false; + } + + public boolean visit(SQLDeleteStatement x) { + resolve(this, x); + return false; + } + + public boolean visit(SQLSelect x) { + resolve(this, x); + return false; + } + + public boolean visit(SQLWithSubqueryClause x) { + resolve(this, x); + return false; + } + + @Override + public boolean isEnabled(Option option) { + return (options & option.mask) != 0; + } + + @Override + public Context getContext() { + return context; + } + + public Context createContext(SQLObject object) { + return this.context = new Context(object, context); + } + + @Override + public void popContext() { + if (context != null) { + context = context.parent; + } + } + + @Override + public SchemaRepository getRepository() { + return repository; + } + } + + static class OracleResolveVisitor extends OracleASTVisitorAdapter implements SchemaResolveVisitor { + private SchemaRepository repository; + private int options; + private Context context; + + public OracleResolveVisitor(SchemaRepository repository, int options) { + this.repository = repository; + this.options = options; + } + + public boolean visit(OracleSelectTableReference x) { + repository.resolve(this, x); + return false; + } + + public boolean visit(SQLExprTableSource x) { + repository.resolve(this, x); + return false; + } + + public boolean visit(OracleSelectQueryBlock x) { + resolve(this, x); + return false; + } + + public boolean visit(SQLSelectItem x) { + SQLExpr expr = x.getExpr(); + if (expr instanceof SQLIdentifierExpr) { + resolve(this, (SQLIdentifierExpr) expr); + return false; + } + + if (expr instanceof SQLPropertyExpr) { + resolve(this, (SQLPropertyExpr) expr); + return false; + } + + return true; + } + + public boolean visit(SQLIdentifierExpr x) { + resolve(this, x); + return true; + } + + public boolean visit(SQLPropertyExpr x) { + resolve(this, x); + return false; + } + + public boolean visit(SQLAllColumnExpr x) { + resolve(this, x); + return false; + } + + public boolean visit(SQLCreateTableStatement x) { + resolve(this, x); + return false; + } + + public boolean visit(OracleCreateTableStatement x) { + resolve(this, x); + return false; + } + + public boolean visit(SQLUpdateStatement x) { + resolve(this, x); + return false; + } + + public boolean visit(OracleUpdateStatement x) { + resolve(this, x); + return false; + } + + public boolean visit(SQLDeleteStatement x) { + resolve(this, x); + return false; + } + + public boolean visit(OracleDeleteStatement x) { + resolve(this, x); + return false; + } + + public boolean visit(SQLSelect x) { + resolve(this, x); + return false; + } + + public boolean visit(SQLWithSubqueryClause x) { + resolve(this, x); + return false; + } + + @Override + public boolean isEnabled(Option option) { + return (options & option.mask) != 0; + } + + @Override + public Context getContext() { + return context; + } + + public Context createContext(SQLObject object) { + return this.context = new Context(object, context); + } + + @Override + public void popContext() { + if (context != null) { + context = context.parent; + } + } + + public SchemaRepository getRepository() { + return repository; + } + } + + static class OdpsResolveVisitor extends OdpsASTVisitorAdapter implements SchemaResolveVisitor { + private int options; + private SchemaRepository repository; + private Context context; + + public OdpsResolveVisitor(SchemaRepository repository, int options) { + this.repository = repository; + this.options = options; + } + + public boolean visit(SQLExprTableSource x) { + repository.resolve(this, x); + return false; + } + + public boolean visit(OdpsSelectQueryBlock x) { + resolve(this, x); + return false; + } + + public boolean visit(SQLSelectItem x) { + SQLExpr expr = x.getExpr(); + if (expr instanceof SQLIdentifierExpr) { + resolve(this, (SQLIdentifierExpr) expr); + return false; + } + + if (expr instanceof SQLPropertyExpr) { + resolve(this, (SQLPropertyExpr) expr); + return false; + } + + return true; + } + + public boolean visit(SQLIdentifierExpr x) { + resolve(this, x); + return true; + } + + public boolean visit(SQLPropertyExpr x) { + resolve(this, x); + return false; + } + + public boolean visit(SQLAllColumnExpr x) { + resolve(this, x); + return false; + } + + public boolean visit(SQLCreateTableStatement x) { + resolve(this, x); + return false; + } + + public boolean visit(OdpsCreateTableStatement x) { + resolve(this, x); + return false; + } + + public boolean visit(SQLUpdateStatement x) { + resolve(this, x); + return false; + } + + public boolean visit(SQLDeleteStatement x) { + resolve(this, x); + return false; + } + + public boolean visit(SQLSelect x) { + resolve(this, x); + return false; + } + + public boolean visit(SQLWithSubqueryClause x) { + resolve(this, x); + return false; + } + + @Override + public boolean isEnabled(Option option) { + return (options & option.mask) != 0; + } + + @Override + public Context getContext() { + return context; + } + + public Context createContext(SQLObject object) { + return this.context = new Context(object, context); + } + + @Override + public void popContext() { + if (context != null) { + context = context.parent; + } + } + + public SchemaRepository getRepository() { + return repository; + } + } + + static class PGResolveVisitor extends PGASTVisitorAdapter implements SchemaResolveVisitor { + private int options; + private SchemaRepository repository; + private Context context; + + public PGResolveVisitor(SchemaRepository repository, int options) { + this.repository = repository; + this.options = options; + } + + public boolean visit(SQLExprTableSource x) { + repository.resolve(this, x); + return false; + } + + public boolean visit(PGSelectQueryBlock x) { + resolve(this, x); + return false; + } + + public boolean visit(SQLSelectItem x) { + SQLExpr expr = x.getExpr(); + if (expr instanceof SQLIdentifierExpr) { + resolve(this, (SQLIdentifierExpr) expr); + return false; + } + + if (expr instanceof SQLPropertyExpr) { + resolve(this, (SQLPropertyExpr) expr); + return false; + } + + return true; + } + + public boolean visit(SQLIdentifierExpr x) { + resolve(this, x); + return true; + } + + public boolean visit(SQLPropertyExpr x) { + resolve(this, x); + return false; + } + + public boolean visit(SQLAllColumnExpr x) { + resolve(this, x); + return false; + } + + public boolean visit(SQLCreateTableStatement x) { + resolve(this, x); + return false; + } + + public boolean visit(SQLUpdateStatement x) { + resolve(this, x); + return false; + } + + public boolean visit(PGUpdateStatement x) { + resolve(this, x); + return false; + } + + public boolean visit(SQLDeleteStatement x) { + resolve(this, x); + return false; + } + + public boolean visit(PGDeleteStatement x) { + resolve(this, x); + return false; + } + + public boolean visit(PGSelectStatement x) { + createContext(x); + visit(x.getSelect()); + popContext(); + return false; + } + + public boolean visit(SQLSelect x) { + resolve(this, x); + return false; + } + + public boolean visit(SQLWithSubqueryClause x) { + resolve(this, x); + return false; + } + + @Override + public boolean isEnabled(Option option) { + return (options & option.mask) != 0; + } + + @Override + public Context getContext() { + return context; + } + + public Context createContext(SQLObject object) { + return this.context = new Context(object, context); + } + + @Override + public void popContext() { + if (context != null) { + context = context.parent; + } + } + + public SchemaRepository getRepository() { + return repository; + } + } + + static class SQLServerResolveVisitor extends SQLServerASTVisitorAdapter implements SchemaResolveVisitor { + private int options; + private SchemaRepository repository; + private Context context; + + public SQLServerResolveVisitor(SchemaRepository repository, int options) { + this.repository = repository; + this.options = options; + } + + public boolean visit(SQLExprTableSource x) { + repository.resolve(this, x); + return false; + } + + public boolean visit(SQLServerSelectQueryBlock x) { + resolve(this, x); + return false; + } + + public boolean visit(SQLSelectItem x) { + SQLExpr expr = x.getExpr(); + if (expr instanceof SQLIdentifierExpr) { + resolve(this, (SQLIdentifierExpr) expr); + return false; + } + + if (expr instanceof SQLPropertyExpr) { + resolve(this, (SQLPropertyExpr) expr); + return false; + } + + return true; + } + + public boolean visit(SQLIdentifierExpr x) { + resolve(this, x); + return true; + } + + public boolean visit(SQLPropertyExpr x) { + resolve(this, x); + return false; + } + + public boolean visit(SQLAllColumnExpr x) { + resolve(this, x); + return false; + } + + public boolean visit(SQLCreateTableStatement x) { + resolve(this, x); + return false; + } + + public boolean visit(SQLUpdateStatement x) { + resolve(this, x); + return false; + } + + public boolean visit(SQLServerUpdateStatement x) { + resolve(this, x); + return false; + } + + public boolean visit(SQLDeleteStatement x) { + resolve(this, x); + return false; + } + + public boolean visit(SQLSelect x) { + resolve(this, x); + return false; + } + + public boolean visit(SQLWithSubqueryClause x) { + resolve(this, x); + return false; + } + + @Override + public boolean isEnabled(Option option) { + return (options & option.mask) != 0; + } + + @Override + public Context getContext() { + return context; + } + + public Context createContext(SQLObject object) { + return this.context = new Context(object, context); + } + + @Override + public void popContext() { + if (context != null) { + context = context.parent; + } + } + + public SchemaRepository getRepository() { + return repository; + } + } + + static class SQLResolveVisitor extends SQLASTVisitorAdapter implements SchemaResolveVisitor { + private int options; + private SchemaRepository repository; + private Context context; + + public SQLResolveVisitor(SchemaRepository repository, int options) { + this.repository = repository; + this.options = options; + } + + public boolean visit(SQLExprTableSource x) { + repository.resolve(this, x); + return false; + } + + public boolean visit(SQLSelectQueryBlock x) { + resolve(this, x); + return false; + } + + public boolean visit(SQLSelectItem x) { + SQLExpr expr = x.getExpr(); + if (expr instanceof SQLIdentifierExpr) { + resolve(this, (SQLIdentifierExpr) expr); + return false; + } + + if (expr instanceof SQLPropertyExpr) { + resolve(this, (SQLPropertyExpr) expr); + return false; + } + + return true; + } + + public boolean visit(SQLIdentifierExpr x) { + resolve(this, x); + return true; + } + + public boolean visit(SQLPropertyExpr x) { + resolve(this, x); + return false; + } + + public boolean visit(SQLAllColumnExpr x) { + resolve(this, x); + return false; + } + + public boolean visit(SQLCreateTableStatement x) { + resolve(this, x); + return false; + } + + public boolean visit(SQLUpdateStatement x) { + resolve(this, x); + return false; + } + + public boolean visit(SQLDeleteStatement x) { + resolve(this, x); + return false; + } + + public boolean visit(SQLSelect x) { + resolve(this, x); + return false; + } + + public boolean visit(SQLWithSubqueryClause x) { + resolve(this, x); + return false; + } + + @Override + public boolean isEnabled(Option option) { + return (options & option.mask) != 0; + } + + @Override + public Context getContext() { + return context; + } + + public Context createContext(SQLObject object) { + return this.context = new Context(object, context); + } + + @Override + public void popContext() { + if (context != null) { + context = context.parent; + } + } + + public SchemaRepository getRepository() { + return repository; + } + } + + static void resolve(SchemaResolveVisitor visitor, SQLCreateTableStatement x) { + SchemaResolveVisitor.Context ctx = visitor.createContext(x); + + SQLExprTableSource table = x.getTableSource(); + ctx.setTableSource(table); + + table.accept(visitor); + + List elements = x.getTableElementList(); + for (int i = 0; i < elements.size(); i++) { + SQLTableElement e = elements.get(i); + if (e instanceof SQLColumnDefinition) { + SQLColumnDefinition columnn = (SQLColumnDefinition) e; + SQLName columnnName = columnn.getName(); + if (columnnName instanceof SQLIdentifierExpr) { + SQLIdentifierExpr identifierExpr = (SQLIdentifierExpr) columnnName; + identifierExpr.setResolvedTableSource(table); + identifierExpr.setResolvedColumn(columnn); + } + } else if (e instanceof SQLUniqueConstraint) { + List columns = ((SQLUniqueConstraint) e).getColumns(); + for (SQLSelectOrderByItem orderByItem : columns) { + SQLExpr orderByItemExpr = orderByItem.getExpr(); + if (orderByItemExpr instanceof SQLIdentifierExpr) { + SQLIdentifierExpr identifierExpr = (SQLIdentifierExpr) orderByItemExpr; + identifierExpr.setResolvedTableSource(table); + + SQLColumnDefinition column = x.findColumn(identifierExpr.name_hash_lower()); + if (column != null) { + identifierExpr.setResolvedColumn(column); + } + } + } + } else { + e.accept(visitor); + } + } + + SQLSelect select = x.getSelect(); + if (select != null) { + visitor.visit(select); + } + + visitor.popContext(); + } + + static void resolve(SchemaResolveVisitor visitor, SQLUpdateStatement x) { + SchemaResolveVisitor.Context ctx = visitor.createContext(x); + + SQLTableSource table = x.getTableSource(); + SQLTableSource from = x.getFrom(); + + ctx.setTableSource(table); + ctx.setFrom(from); + + table.accept(visitor); + if (from != null) { + from.accept(visitor); + } + + List items = x.getItems(); + for (SQLUpdateSetItem item : items) { + SQLExpr column = item.getColumn(); + if (column instanceof SQLIdentifierExpr) { + SQLIdentifierExpr identifierExpr = (SQLIdentifierExpr) column; + identifierExpr.setResolvedTableSource(table); + } else { + column.accept(visitor); + } + SQLExpr value = item.getValue(); + if (value != null) { + value.accept(visitor); + } + } + + SQLExpr where = x.getWhere(); + if (where != null) { + where.accept(visitor); + } + + visitor.popContext(); + } + + static void resolve(SchemaResolveVisitor visitor, SQLDeleteStatement x) { + SchemaResolveVisitor.Context ctx = visitor.createContext(x); + + SQLTableSource table = x.getTableSource(); + SQLTableSource from = x.getFrom(); + + if (table == null && from != null) { + table = from; + from = null; + } + + ctx.setTableSource(table); + ctx.setFrom(from); + + if (table != null) { + table.accept(visitor); + } + + if (from != null) { + from.accept(visitor); + } + + SQLExpr where = x.getWhere(); + if (where != null) { + where.accept(visitor); + } + + visitor.popContext(); + } + + static void resolve(SchemaResolveVisitor visitor, SQLIdentifierExpr x) { + SchemaResolveVisitor.Context ctx = visitor.getContext(); + if (ctx == null) { + return; + } + + String ident = x.getName(); + long hash = x.name_hash_lower(); + SQLTableSource tableSource = null; + + SQLTableSource ctxTable = ctx.getTableSource(); + + if (ctxTable instanceof SQLJoinTableSource + || ctxTable instanceof SQLSubqueryTableSource) { + tableSource = ctxTable.findTableSourceWithColumn(hash); + } else { + tableSource = ctxTable; + if (tableSource instanceof SQLExprTableSource) { + SchemaObject table = ((SQLExprTableSource) tableSource).getSchemaObject(); + if (table != null) { + if (table.findColumn(hash) == null) { + tableSource = null; // maybe parent + } + } + } + } + + if (tableSource instanceof SQLExprTableSource) { + SQLExpr expr = ((SQLExprTableSource) tableSource).getExpr(); + if (expr instanceof SQLIdentifierExpr) { + SQLIdentifierExpr identExpr = (SQLIdentifierExpr) expr; + long identHash = identExpr.name_hash_lower(); + + for (SchemaResolveVisitor.Context parentCtx = ctx.parent; + parentCtx != null; + parentCtx = parentCtx.parent) { + + if (parentCtx.object instanceof SQLSelect) { + SQLSelect select = (SQLSelect) parentCtx.object; + SQLWithSubqueryClause with = select.getWithSubQuery(); + if (with != null) { + SQLWithSubqueryClause.Entry entry = with.findEntry(identHash); + if (entry != null) { + tableSource = entry; + break; + } + } + } else if (parentCtx.object instanceof PGSelectStatement) { + + } + } + } + } + + if (tableSource != null) { + x.setResolvedTableSource(tableSource); + + SQLColumnDefinition column = tableSource.findColumn(hash); + if (column != null) { + x.setResolvedColumn(column); + } + + if (ctxTable instanceof SQLJoinTableSource) { + String alias = tableSource.computeAlias(); + SQLPropertyExpr propertyExpr = new SQLPropertyExpr(new SQLIdentifierExpr(alias), ident, hash); + SQLUtils.replaceInParent(x, propertyExpr); + } + } + } + + static void resolve(SchemaResolveVisitor visitor, SQLSelectQueryBlock x) { + SchemaResolveVisitor.Context ctx = visitor.createContext(x); + + SQLTableSource from = x.getFrom(); + if (from != null) { + ctx.setTableSource(from); + + from.accept(visitor); + } + + List selectList = x.getSelectList(); + + List columns = new ArrayList(); + for (int i = selectList.size() - 1; i >= 0; i--) { + SQLSelectItem selectItem = selectList.get(i); + SQLExpr expr = selectItem.getExpr(); + if (expr instanceof SQLAllColumnExpr) { + if (visitor.isEnabled(SchemaResolveVisitor.Option.ResolveAllColumn)) { + extractColumns(visitor, from, columns); + } + } else if (expr instanceof SQLPropertyExpr) { + SQLPropertyExpr propertyExpr = (SQLPropertyExpr) expr; + visitor.visit(propertyExpr); + + String ownerName = propertyExpr.getOwnernName(); + if (propertyExpr.getName().equals("*")) { + if (visitor.isEnabled(SchemaResolveVisitor.Option.ResolveAllColumn)) { + SQLTableSource tableSource = x.findTableSource(ownerName); + extractColumns(visitor, tableSource, columns); + } + } + + SQLColumnDefinition column = propertyExpr.getResolvedColumn(); + if (column != null) { + continue; + } + SQLTableSource tableSource = x.findTableSource(propertyExpr.getOwnernName()); + if (tableSource != null) { + column = tableSource.findColumn(propertyExpr.name_hash_lower()); + if (column != null) { + propertyExpr.setResolvedColumn(column); + } + } + } else if (expr instanceof SQLIdentifierExpr) { + SQLIdentifierExpr identExpr = (SQLIdentifierExpr) expr; + visitor.visit(identExpr); + + long name_hash = identExpr.name_hash_lower(); + + SQLColumnDefinition column = identExpr.getResolvedColumn(); + if (column != null) { + continue; + } + if (from == null) { + continue; + } + column = from.findColumn(name_hash); + if (column != null) { + identExpr.setResolvedColumn(column); + } + } else { + expr.accept(visitor); + } + + if (columns.size() > 0) { + for (SQLSelectItem column : columns) { + column.setParent(x); + column.getExpr().accept(visitor); + } + + selectList.remove(i); + selectList.addAll(i, columns); + } + } + + SQLExpr where = x.getWhere(); + if (where != null) { + where.accept(visitor); + } + + SQLExpr startWith = x.getStartWith(); + if (startWith != null) { + startWith.accept(visitor); + } + + SQLExpr connectBy = x.getConnectBy(); + if (connectBy != null) { + connectBy.accept(visitor); + } + + SQLSelectGroupByClause groupBy = x.getGroupBy(); + if (groupBy != null) { + groupBy.accept(visitor); + } + + SQLOrderBy orderBy = x.getOrderBy(); + if (orderBy != null) { + orderBy.accept(visitor); + } + + visitor.popContext(); + } + + static void extractColumns(SchemaResolveVisitor visitor, SQLTableSource from, List columns) { + if (from instanceof SQLExprTableSource) { + SchemaRepository repository = visitor.getRepository(); + if (repository == null) { + return; + } + + SchemaObject table = repository.findTable((SQLExprTableSource) from); + if (table != null) { + SQLCreateTableStatement createTableStmt = (SQLCreateTableStatement) table.getStatement(); + for (SQLTableElement e : createTableStmt.getTableElementList()) { + if (e instanceof SQLColumnDefinition) { + SQLColumnDefinition column = (SQLColumnDefinition) e; + SQLIdentifierExpr name = (SQLIdentifierExpr) column.getName().clone(); + name.setResolvedColumn(column); + columns.add(new SQLSelectItem(name)); + } + } + } + } + } + + static void resolve(SchemaResolveVisitor visitor, SQLPropertyExpr x) { + SchemaResolveVisitor.Context ctx = visitor.getContext(); + if (ctx == null) { + return; + } + + SQLIdentifierExpr owner; + { + SQLExpr ownerObj = x.getOwner(); + if (ownerObj instanceof SQLIdentifierExpr) { + owner = (SQLIdentifierExpr) ownerObj; + } else { + return; + } + } + long owner_hash = owner.name_hash_lower(); + + SQLTableSource ctxTable = ctx.getTableSource(); + + SQLTableSource tableSource = ctxTable.findTableSource(owner_hash); + if (tableSource == null) { + SQLTableSource ctxFrom = ctx.getFrom(); + if (ctxFrom != null) { + tableSource = ctxFrom.findTableSource(owner_hash); + } + } + + if (tableSource != null) { + x.setResolvedTableSource(tableSource); + SQLColumnDefinition column = tableSource.findColumn(x.name_hash_lower()); + if (column != null) { + x.setResolvedColumn(column); + } + } + } + + static void resolve(SchemaResolveVisitor visitor, SQLAllColumnExpr x) { + SQLSelectQueryBlock queryBlock = null; + for (SQLObject parent = x.getParent(); parent != null; parent = parent.getParent()) { + if (parent instanceof SQLTableSource) { + return; + } + if (parent instanceof SQLSelectQueryBlock) { + queryBlock = (SQLSelectQueryBlock) parent; + break; + } + } + + if (queryBlock == null) { + return; + } + + SQLTableSource from = queryBlock.getFrom(); + if (from == null || from instanceof SQLJoinTableSource) { + return; + } + + x.setResolvedTableSource(from); + } + + static void resolve(SchemaResolveVisitor visitor, SQLSelect x) { + SchemaResolveVisitor.Context ctx = visitor.createContext(x); + + SQLWithSubqueryClause with = x.getWithSubQuery(); + if (with != null) { + visitor.visit(with); + } + + SQLSelectQuery query = x.getQuery(); + if (query != null) { + query.accept(visitor); + } + + SQLOrderBy orderBy = x.getOrderBy(); + if (orderBy != null) { + visitor.visit(orderBy); + } + + visitor.popContext(); + } + + static void resolve(SchemaResolveVisitor visitor, SQLWithSubqueryClause x) { + List entries = x.getEntries(); + for (SQLWithSubqueryClause.Entry entry : entries) { + SQLSelect query = entry.getSubQuery(); + if (query != null) { + visitor.visit(query); + } else { + entry.getReturningStatement().accept(visitor); + } + } + } + +} 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 3c15d4cb48..8cd48ab91b 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java @@ -414,9 +414,9 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet print0(ucase ? " BETWEEN " : " between "); } - x.getBeginExpr().accept(this); + printExpr(x.getBeginExpr()); print0(ucase ? " AND " : " and "); - x.getEndExpr().accept(this); + printExpr(x.getEndExpr()); return false; } @@ -455,7 +455,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet continue; } - if (this instanceof ExportParameterVisitor || this.parameters != null) { + if (this.parameters != null) { ExportParameterVisitorUtils.exportParameter(parameters, right); } } else if (right instanceof SQLVariantRefExpr) { @@ -496,7 +496,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet printOperator(firstOp); print0(" ?"); - if (this instanceof ExportParameterVisitor || this.parameters != null) { + if (this.parameters != null) { if (parameters.size() > 0) { this.parameters.add(parameters); } @@ -710,7 +710,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet && op.isLogical() )) { if (rightRational) { - incrementIndent(); + this.indentCount++; } print('('); @@ -718,7 +718,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet print(')'); if (rightRational) { - decrementIndent(); + this.indentCount--; } } else { printExpr(right); @@ -747,14 +747,14 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet && op.isLogical() )) { if (leftRational) { - incrementIndent(); + this.indentCount++; } print('('); printExpr(left); print(')'); if (leftRational) { - decrementIndent(); + this.indentCount--; } } else { printExpr(left); @@ -808,23 +808,30 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet visit((SQLIntegerExpr) x); } else if (clazz == SQLNumberExpr.class) { visit((SQLNumberExpr) x); + } else if (clazz == SQLMethodInvokeExpr.class) { + visit((SQLMethodInvokeExpr) x); + } else if (clazz == SQLVariantRefExpr.class) { + visit((SQLVariantRefExpr) x); + } else if (clazz == SQLBinaryOpExprGroup.class) { + visit((SQLBinaryOpExprGroup) x); } else { x.accept(this); } } public boolean visit(SQLCaseExpr x) { - incrementIndent(); + this.indentCount++; print0(ucase ? "CASE " : "case "); SQLExpr valueExpr = x.getValueExpr(); if (valueExpr != null) { - valueExpr.accept(this); + printExpr(valueExpr); } - for (int i = 0, size = x.getItems().size(); i < size; ++i) { + List items = x.getItems(); + for (int i = 0, size = items.size(); i < size; ++i) { println(); - x.getItems().get(i).accept(this); + visit(items.get(i)); } SQLExpr elExpr = x.getElseExpr(); @@ -832,16 +839,16 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet println(); print0(ucase ? "ELSE " : "else "); if (elExpr instanceof SQLCaseExpr) { - incrementIndent(); + this.indentCount++; println(); - elExpr.accept(this); - decrementIndent(); + printExpr(elExpr); + this.indentCount--; } else { - elExpr.accept(this); + printExpr(elExpr); } } - decrementIndent(); + this.indentCount--; println(); print0(ucase ? "END" : "end"); @@ -850,17 +857,18 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet public boolean visit(SQLCaseExpr.Item x) { print0(ucase ? "WHEN " : "when "); - SQLExpr expr = x.getConditionExpr(); - expr.accept(this); + SQLExpr conditionExpr = x.getConditionExpr(); + printExpr(conditionExpr); + print0(ucase ? " THEN " : " then "); SQLExpr valueExpr = x.getValueExpr(); if (valueExpr instanceof SQLCaseExpr) { - incrementIndent(); + this.indentCount++; println(); - valueExpr.accept(this); - decrementIndent(); + visit((SQLCaseExpr) valueExpr); + this.indentCount--; } else { - valueExpr.accept(this); + printExpr(valueExpr); } return false; @@ -868,11 +876,12 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet public boolean visit(SQLCaseStatement x) { print0(ucase ? "CASE" : "case"); - if (x.getValueExpr() != null) { + SQLExpr valueExpr = x.getValueExpr(); + if (valueExpr != null) { print(' '); - x.getValueExpr().accept(this); + printExpr(valueExpr); } - incrementIndent(); + this.indentCount++; println(); printlnAndAccept(x.getItems(), " "); @@ -882,7 +891,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet printlnAndAccept(x.getElseStatements(), ""); } - decrementIndent(); + this.indentCount--; println(); print0(ucase ? "END CASE" : "end case"); @@ -894,7 +903,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet public boolean visit(SQLCaseStatement.Item x) { print0(ucase ? "WHEN " : "when "); - x.getConditionExpr().accept(this); + printExpr(x.getConditionExpr()); print0(ucase ? " THEN " : " then "); SQLStatement stmt = x.getStatement(); @@ -919,7 +928,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet if (this.parameterized) { print('?'); incrementReplaceCunt(); - if (this instanceof ExportParameterVisitor || this.parameters != null) { + if (this.parameters != null) { ExportParameterVisitorUtils.exportParameter(this.parameters, x); } return false; @@ -996,10 +1005,10 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet } else { print0(ucase ? "EXISTS (" : "exists ("); } - incrementIndent(); + this.indentCount++; println(); - x.getSubQuery().accept(this); - decrementIndent(); + visit(x.getSubQuery()); + this.indentCount--; println(); print(')'); return false; @@ -1121,7 +1130,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet changed = false; } - x.getExpr().accept(this); + printExpr(x.getExpr()); if (x.isNot()) { print(isUppCase() ? " NOT IN (?)" : " not in (?)"); @@ -1131,7 +1140,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet if (changed) { incrementReplaceCunt(); - if (this instanceof ExportParameterVisitor || this.parameters != null) { + if (this.parameters != null) { if (parameterizedMergeInList) { List subList = new ArrayList(x.getTargetList().size()); for (SQLExpr target : x.getTargetList()) { @@ -1152,7 +1161,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet } } - x.getExpr().accept(this); + printExpr(x.getExpr()); if (x.isNot()) { print0(ucase ? " NOT IN (" : " not in ("); @@ -1174,19 +1183,26 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet } if (printLn) { - incrementIndent(); + this.indentCount++; println(); for (int i = 0, size = list.size(); i < size; ++i) { if (i != 0) { print0(", "); println(); } - list.get(i).accept(this); + SQLExpr item = list.get(i); + printExpr(item); } - decrementIndent(); + this.indentCount--; println(); } else { - printAndAccept(x.getTargetList(), ", "); + List targetList = x.getTargetList(); + for (int i = 0; i < targetList.size(); i++) { + if (i != 0) { + print0(", "); + } + printExpr(targetList.get(i)); + } } print(')'); @@ -1224,7 +1240,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet print('?'); incrementReplaceCunt(); - if(this instanceof ExportParameterVisitor || this.parameters != null){ + if(this.parameters != null){ ExportParameterVisitorUtils.exportParameter(this.parameters, x); } return; @@ -1283,32 +1299,32 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet SQLBinaryOpExpr binaryOpExpr = (SQLBinaryOpExpr) param; SQLBinaryOperator op = binaryOpExpr.getOperator(); if (op == SQLBinaryOperator.BooleanAnd || op == SQLBinaryOperator.BooleanOr) { - incrementIndent(); - param.accept(this); - decrementIndent(); + this.indentCount++; + printExpr(param); + this.indentCount--; continue; } } - param.accept(this); + printExpr(param); } SQLExpr from = x.getFrom(); if (from != null) { print0(ucase ? " FROM " : " from "); - from.accept(this); + printExpr(from); SQLExpr _for = x.getFor(); if (_for != null) { print0(ucase ? " FOR " : " for "); - _for.accept(this); + printExpr(_for); } } SQLExpr using = x.getUsing(); if (using != null) { print0(ucase ? " USING " : " using "); - using.accept(this); + printExpr(using); } print(')'); @@ -1316,7 +1332,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet } protected void printMethodOwner(SQLExpr owner) { - owner.accept(this); + printExpr(owner); print('.'); } @@ -1348,15 +1364,17 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet print(')'); - if (x.getWithinGroup() != null) { + SQLOrderBy withGroup = x.getWithinGroup(); + if (withGroup != null) { print0(ucase ? " WITHIN GROUP (" : " within group ("); - x.getWithinGroup().accept(this); + withGroup.accept(this); print(')'); } - - if (x.getKeep() != null) { + + SQLKeep keep = x.getKeep(); + if (keep != null) { print(' '); - x.getKeep().accept(this); + keep.accept(this); } if (x.getOver() != null) { @@ -1382,7 +1400,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet print('?'); incrementReplaceCunt(); - if(this instanceof ExportParameterVisitor || this.parameters != null){ + if(this.parameters != null){ ExportParameterVisitorUtils.exportParameter(this.parameters, x); } return false; @@ -1412,7 +1430,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet if (needQuote) { print('('); } - expr.accept(this); + printExpr(expr); if (needQuote) { print(')'); @@ -1426,7 +1444,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet print('?'); incrementReplaceCunt(); - if(this instanceof ExportParameterVisitor || this.parameters != null){ + if(this.parameters != null){ this.getParameters().add(null); } return false; @@ -1441,7 +1459,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet print('?'); incrementReplaceCunt(); - if(this instanceof ExportParameterVisitor || this.parameters != null){ + if(this.parameters != null){ ExportParameterVisitorUtils.exportParameter((this).getParameters(), x); } return false; @@ -1534,28 +1552,29 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet parent = parent.getParent(); } + SQLSelect subQuery = x.getSubQuery(); if (parent instanceof ValuesClause) { println(); print('('); - x.getSubQuery().accept(this); + visit(subQuery); print(')'); println(); } else if (parent instanceof SQLStatement && !(parent instanceof OracleForStatement)) { - incrementIndent(); + this.indentCount++; println(); - x.getSubQuery().accept(this); + visit(subQuery); - decrementIndent(); + this.indentCount--; } else if (parent instanceof SQLOpenStatement) { - x.getSubQuery().accept(this); + visit(subQuery); } else { print('('); - incrementIndent(); + this.indentCount++; println(); - x.getSubQuery().accept(this); - decrementIndent(); + visit(subQuery); + this.indentCount--; println(); print(')'); } @@ -1576,7 +1595,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet } else if (oracle && cube) { print0(ucase ? "CUBE (" : "cube ("); } - incrementIndent(); + this.indentCount++; for (int i = 0; i < itemSize; ++i) { if (i != 0) { if (groupItemSingleLine) { @@ -1590,7 +1609,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet if (oracle && rollup) { print(')'); } - decrementIndent(); + this.indentCount--; } if (x.getHaving() != null) { @@ -1908,9 +1927,10 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet public boolean visit(SQLExprTableSource x) { printTableSourceExpr(x.getExpr()); - if (x.getAlias() != null) { + String alias = x.getAlias(); + if (alias != null) { print(' '); - print0(x.getAlias()); + print0(alias); } if (isPrettyFormat() && x.hasAfterComment()) { @@ -2101,14 +2121,6 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet return false; } - public boolean visit(SQLTableElement x) { - if (x instanceof SQLColumnDefinition) { - return visit((SQLColumnDefinition) x); - } - - throw new RuntimeException("TODO"); - } - public boolean visit(SQLColumnDefinition x) { boolean parameterized = this.parameterized; this.parameterized = false; @@ -2131,7 +2143,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet || item instanceof SQLColumnCheck // || item.getName() != null; if (newLine) { - incrementIndent(); + this.indentCount++; println(); } else { print(' '); @@ -2140,7 +2152,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet item.accept(this); if (newLine) { - decrementIndent(); + this.indentCount--; } } @@ -2191,12 +2203,13 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet from.accept(this); } - if (x.getWhere() != null) { + SQLExpr where = x.getWhere(); + if (where != null) { println(); print0(ucase ? "WHERE " : "where "); - incrementIndent(); - x.getWhere().accept(this); - decrementIndent(); + this.indentCount++; + where.accept(this); + this.indentCount--; } return false; @@ -2204,7 +2217,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet public boolean visit(SQLCurrentOfCursorExpr x) { print0(ucase ? "CURRENT OF " : "current of "); - x.getCursorName().accept(this); + printExpr(x.getCursorName()); return false; } @@ -2237,7 +2250,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet final int size = columns.size(); if (size > 0) { if (size > 5) { - incrementIndent(); + this.indentCount++; println(); } else { print(' '); @@ -2252,7 +2265,11 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet } SQLExpr column = columns.get(i); - column.accept(this); + if (column instanceof SQLIdentifierExpr) { + visit((SQLIdentifierExpr) column); + } else { + printExpr(column); + } String dataType = (String) column.getAttribute("dataType"); if (dataType != null) { @@ -2262,22 +2279,22 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet } print(')'); if (size > 5) { - decrementIndent(); + this.indentCount--; } } } public boolean visit(SQLUpdateSetItem x) { - x.getColumn().accept(this); + printExpr(x.getColumn()); print0(" = "); - x.getValue().accept(this); + printExpr(x.getValue()); return false; } public boolean visit(SQLUpdateStatement x) { print0(ucase ? "UPDATE " : "update "); - x.getTableSource().accept(this); + printTableSource(x.getTableSource()); println(); print0(ucase ? "SET " : "set "); @@ -2285,15 +2302,17 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet if (i != 0) { print0(", "); } - x.getItems().get(i).accept(this); + SQLUpdateSetItem item = x.getItems().get(i); + visit(item); } - if (x.getWhere() != null) { + SQLExpr where = x.getWhere(); + if (where != null) { println(); - incrementIndent(); + indentCount++; print0(ucase ? "WHERE " : "where "); - x.getWhere().accept(this); - decrementIndent(); + printExpr(where); + indentCount--; } return false; @@ -2303,7 +2322,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet int size = tableElementList.size(); if (size > 0) { print0(" ("); - incrementIndent(); + this.indentCount++; println(); for (int i = 0; i < size; ++i) { if (i != 0) { @@ -2312,7 +2331,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet } tableElementList.get(i).accept(this); } - decrementIndent(); + this.indentCount--; println(); print(')'); } @@ -2469,7 +2488,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet print('?'); incrementReplaceCunt(); - if(this instanceof ExportParameterVisitor || this.parameters != null){ + if(this.parameters != null){ ExportParameterVisitorUtils.exportParameter(this.parameters, x); } return false; @@ -2546,7 +2565,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet } else { printTableSource(left); } - incrementIndent(); + this.indentCount++; if (x.getJoinType() == JoinType.COMMA) { print(','); @@ -2589,10 +2608,10 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet } else { print(' '); } - incrementIndent(); + this.indentCount++; print0(ucase ? "ON " : "on "); printExpr(condition); - decrementIndent(); + this.indentCount--; } if (x.getUsing().size() > 0) { @@ -2606,7 +2625,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet print0(x.getAlias()); } - decrementIndent(); + this.indentCount--; return false; } @@ -2664,10 +2683,10 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet @Override public boolean visit(SQLSomeExpr x) { print0(ucase ? "SOME (" : "some ("); - incrementIndent(); + this.indentCount++; println(); x.getSubQuery().accept(this); - decrementIndent(); + this.indentCount--; println(); print(')'); return false; @@ -2676,10 +2695,10 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet @Override public boolean visit(SQLAnyExpr x) { print0(ucase ? "ANY (" : "any ("); - incrementIndent(); + this.indentCount++; println(); x.getSubQuery().accept(this); - decrementIndent(); + this.indentCount--; println(); print(')'); return false; @@ -2688,10 +2707,10 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet @Override public boolean visit(SQLAllExpr x) { print0(ucase ? "ALL (" : "all ("); - incrementIndent(); + this.indentCount++; println(); x.getSubQuery().accept(this); - decrementIndent(); + this.indentCount--; println(); print(')'); return false; @@ -2706,10 +2725,10 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet print0(ucase ? " IN (" : " in ("); } - incrementIndent(); + this.indentCount++; println(); x.getSubQuery().accept(this); - decrementIndent(); + this.indentCount--; println(); print(')'); @@ -2728,10 +2747,10 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet @Override public boolean visit(SQLSubqueryTableSource x) { print('('); - incrementIndent(); + this.indentCount++; println(); this.visit(x.getSelect()); - decrementIndent(); + this.indentCount--; println(); print(')'); @@ -2916,7 +2935,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet print0(ucase ? "OR REPLACE " : "or replace "); } - incrementIndent(); + this.indentCount++; String algorithm = x.getAlgorithm(); if (algorithm != null && algorithm.length() > 0) { print0(ucase ? "ALGORITHM = " : "algorithm = "); @@ -2938,7 +2957,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet println(); } - decrementIndent(); + this.indentCount--; print0(ucase ? "VIEW " : "view "); @@ -2950,7 +2969,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet if (x.getColumns().size() > 0) { print0(" ("); - incrementIndent(); + this.indentCount++; println(); for (int i = 0; i < x.getColumns().size(); ++i) { if (i != 0) { @@ -2959,7 +2978,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet } x.getColumns().get(i).accept(this); } - decrementIndent(); + this.indentCount--; println(); print(')'); } @@ -3138,15 +3157,15 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet if (x.getRecursive() == Boolean.TRUE) { print0(ucase ? "RECURSIVE " : "recursive "); } - incrementIndent(); + this.indentCount++; printlnAndAccept(x.getEntries(), ", "); - decrementIndent(); + this.indentCount--; return false; } @Override public boolean visit(SQLWithSubqueryClause.Entry x) { - x.getName().accept(this); + print0(x.getAlias()); if (x.getColumns().size() > 0) { print0(" ("); @@ -3156,10 +3175,15 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet print(' '); print0(ucase ? "AS " : "as "); print('('); - incrementIndent(); + this.indentCount++; println(); - x.getSubQuery().accept(this); - decrementIndent(); + SQLSelect query = x.getSubQuery(); + if (query != null) { + query.accept(this); + } else { + x.getReturningStatement().accept(this); + } + this.indentCount--; println(); print(')'); @@ -3201,9 +3225,9 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet print(' '); } print0(ucase ? "CHECK (" : "check ("); - incrementIndent(); + this.indentCount++; x.getExpr().accept(this); - decrementIndent(); + this.indentCount--; print(')'); return false; } @@ -3263,7 +3287,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet public boolean visit(SQLAlterTableStatement x) { print0(ucase ? "ALTER TABLE " : "alter table "); printTableSourceExpr(x.getName()); - incrementIndent(); + this.indentCount++; for (int i = 0; i < x.getItems().size(); ++i) { SQLAlterTableItem item = x.getItems().get(i); if (i != 0) { @@ -3272,7 +3296,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet println(); item.accept(this); } - decrementIndent(); + this.indentCount--; if (x.isMergeSmallFiles()) { print0(ucase ? " MERGE SMALLFILES" : " merge smallfiles"); @@ -3375,7 +3399,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet printAndAccept(x.getReferencingColumns(), ", "); print(')'); - incrementIndent(); + this.indentCount++; println(); print0(ucase ? "REFERENCES " : "references "); x.getReferencedTableName().accept(this); @@ -3392,7 +3416,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet } else if (x.isOnDeleteSetNull()) { print0(ucase ? "ON DELETE SET NULL" : "on delete set null"); } - decrementIndent(); + this.indentCount--; return false; } @@ -3673,7 +3697,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet x.getName().accept(this); - incrementIndent(); + this.indentCount++; println(); if (TriggerType.INSTEAD_OF.equals(x.getTriggerType())) { print0(ucase ? "INSTEAD OF" : "instead of"); @@ -3694,7 +3718,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet println(); print0(ucase ? "FOR EACH ROW" : "for each row"); } - decrementIndent(); + this.indentCount--; println(); x.getBody().accept(this); return false; @@ -3711,10 +3735,10 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet @Override public boolean visit(SQLUnionQueryTableSource x) { print('('); - incrementIndent(); + this.indentCount++; println(); x.getUnion().accept(this); - decrementIndent(); + this.indentCount--; println(); print(')'); @@ -3988,7 +4012,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet public boolean visit(SQLIfStatement x) { print0(ucase ? "IF " : "if "); x.getCondition().accept(this); - incrementIndent(); + this.indentCount++; println(); for (int i = 0, size = x.getStatements().size(); i < size; ++i) { SQLStatement item = x.getStatements().get(i); @@ -3997,7 +4021,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet println(); } } - decrementIndent(); + this.indentCount--; for (SQLIfStatement.ElseIf elseIf : x.getElseIfList()) { println(); @@ -4014,7 +4038,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet @Override public boolean visit(SQLIfStatement.Else x) { print0(ucase ? "ELSE" : "else"); - incrementIndent(); + this.indentCount++; println(); for (int i = 0, size = x.getStatements().size(); i < size; ++i) { @@ -4025,7 +4049,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet item.accept(this); } - decrementIndent(); + this.indentCount--; return false; } @@ -4034,7 +4058,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet print0(ucase ? "ELSE IF" : "else if"); x.getCondition().accept(this); print0(ucase ? " THEN" : " then"); - incrementIndent(); + this.indentCount++; println(); for (int i = 0, size = x.getStatements().size(); i < size; ++i) { @@ -4045,14 +4069,14 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet item.accept(this); } - decrementIndent(); + this.indentCount--; return false; } @Override public boolean visit(SQLLoopStatement x) { print0(ucase ? "LOOP" : "loop"); - incrementIndent(); + this.indentCount++; println(); @@ -4065,7 +4089,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet } } - decrementIndent(); + this.indentCount--; println(); print0(ucase ? "END LOOP" : "end loop"); if (x.getLabelName() != null) { @@ -4081,11 +4105,11 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet print0(ucase ? "CURSOR " : "cursor "); x.getName().accept(this); print0(ucase ? " IS" : " is"); - incrementIndent(); + this.indentCount++; println(); SQLSelect select = ((SQLQueryExpr) x.getDefaultValue()).getSubQuery(); select.accept(this); - decrementIndent(); + this.indentCount--; } else { SQLDataType dataType = x.getDataType(); @@ -4163,7 +4187,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet if (size > 0) { print0(" ("); - incrementIndent(); + this.indentCount++; println(); for (int i = 0; i < size; ++i) { if (i != 0) { @@ -4172,7 +4196,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet } x.getTableElementList().get(i).accept(this); } - decrementIndent(); + this.indentCount--; println(); print(')'); } @@ -4242,22 +4266,22 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet } if (x.getDataDirectory() != null) { - incrementIndent(); + this.indentCount++; println(); print0(ucase ? "DATA DIRECTORY " : "data directory "); x.getDataDirectory().accept(this); - decrementIndent(); + this.indentCount--; } if (x.getIndexDirectory() != null) { - incrementIndent(); + this.indentCount++; println(); print0(ucase ? "INDEX DIRECTORY " : "index directory "); x.getIndexDirectory().accept(this); - decrementIndent(); + this.indentCount--; } - incrementIndent(); + this.indentCount++; printOracleSegmentAttributes(x); @@ -4266,7 +4290,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet print0(ucase ? "STORAGE ENGINE " : "storage engine "); x.getEngine().accept(this); } - decrementIndent(); + this.indentCount--; if (x.getMaxRows() != null) { print0(ucase ? " MAX_ROWS " : " max_rows "); @@ -4284,16 +4308,16 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet } if (x.getSubPartitionsCount() != null) { - incrementIndent(); + this.indentCount++; println(); print0(ucase ? "SUBPARTITIONS " : "subpartitions "); x.getSubPartitionsCount().accept(this); - decrementIndent(); + this.indentCount--; } if (x.getSubPartitions().size() > 0) { print(" ("); - incrementIndent(); + this.indentCount++; for (int i = 0; i < x.getSubPartitions().size(); ++i) { if (i != 0) { print(','); @@ -4301,7 +4325,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet println(); x.getSubPartitions().get(i).accept(this); } - decrementIndent(); + this.indentCount--; println(); print(')'); } @@ -4336,7 +4360,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet printPartitionsCountAndSubPartitions(x); print(" ("); - incrementIndent(); + this.indentCount++; for (int i = 0, size = x.getPartitions().size(); i < size; ++i) { if (i != 0) { print(','); @@ -4344,7 +4368,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet println(); x.getPartitions().get(i).accept(this); } - decrementIndent(); + this.indentCount--; println(); print(')'); @@ -4397,7 +4421,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet int partitionsSize = partitions.size(); if (partitionsSize > 0) { print0(" ("); - incrementIndent(); + this.indentCount++; for (int i = 0; i < partitionsSize; ++i) { println(); partitions.get(i).accept(this); @@ -4405,7 +4429,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet print0(", "); } } - decrementIndent(); + this.indentCount--; println(); print(')'); } @@ -4478,16 +4502,16 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet } if (x.getSubPartitionTemplate().size() > 0) { - incrementIndent(); + this.indentCount++; println(); print0(ucase ? "SUBPARTITION TEMPLATE (" : "subpartition template ("); - incrementIndent(); + this.indentCount++; println(); printlnAndAccept(x.getSubPartitionTemplate(), ","); - decrementIndent(); + this.indentCount--; println(); print(')'); - decrementIndent(); + this.indentCount--; } return false; @@ -4660,20 +4684,23 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet public boolean visit(MergeUpdateClause x) { print0(ucase ? "WHEN MATCHED THEN UPDATE SET " : "when matched then update set "); printAndAccept(x.getItems(), ", "); - if (x.getWhere() != null) { - incrementIndent(); + + SQLExpr where = x.getWhere(); + if (where != null) { + this.indentCount++; println(); print0(ucase ? "WHERE " : "where "); - x.getWhere().accept(this); - decrementIndent(); + printExpr(where); + this.indentCount--; } - if (x.getDeleteWhere() != null) { - incrementIndent(); + SQLExpr deleteWhere = x.getDeleteWhere(); + if (deleteWhere != null) { + this.indentCount++; println(); print0(ucase ? "DELETE WHERE " : "delete where "); - x.getDeleteWhere().accept(this); - decrementIndent(); + printExpr(deleteWhere); + this.indentCount--; } return false; @@ -4690,11 +4717,11 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet printAndAccept(x.getValues(), ", "); print(')'); if (x.getWhere() != null) { - incrementIndent(); + this.indentCount++; println(); print0(ucase ? "WHERE " : "where "); x.getWhere().accept(this); - decrementIndent(); + this.indentCount--; } return false; diff --git a/src/main/java/com/alibaba/druid/sql/visitor/SchemaStatVisitor.java b/src/main/java/com/alibaba/druid/sql/visitor/SchemaStatVisitor.java index 3a29ec42dc..cc43605afe 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SchemaStatVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SchemaStatVisitor.java @@ -33,6 +33,7 @@ import com.alibaba.druid.sql.dialect.odps.ast.OdpsValuesTableSource; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleExpr; import com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitorAdapter; import com.alibaba.druid.sql.ast.statement.SQLDeclareStatement; +import com.alibaba.druid.sql.repository.SchemaRepository; import com.alibaba.druid.stat.TableStat; import com.alibaba.druid.stat.TableStat.Column; import com.alibaba.druid.stat.TableStat.Condition; @@ -43,6 +44,8 @@ import com.alibaba.druid.util.StringUtils; public class SchemaStatVisitor extends SQLASTVisitorAdapter { + protected SchemaRepository repository; + protected final HashMap tableStats = new LinkedHashMap(); protected final Map columns = new LinkedHashMap(); protected final List conditions = new ArrayList(); @@ -67,14 +70,32 @@ public class SchemaStatVisitor extends SQLASTVisitorAdapter { private Mode mode; + protected String dbType; + public SchemaStatVisitor(){ - this(new ArrayList()); + this((String) null); + } + + public SchemaStatVisitor(String dbType){ + this(new SchemaRepository(dbType), new ArrayList()); + this.dbType = dbType; } public SchemaStatVisitor(List parameters){ this.parameters = parameters; } + public SchemaStatVisitor(SchemaRepository repository, List parameters){ + this.repository = repository; + this.parameters = parameters; + if (repository != null) { + String dbType = repository.getDbType(); + if (dbType != null && this.dbType == null) { + this.dbType = dbType; + } + } + } + public List getParameters() { return parameters; } @@ -87,7 +108,11 @@ public class SchemaStatVisitor extends SQLASTVisitorAdapter { return getTableStat(ident, null); } - public Column addColumn(String tableName, String columnName) { + protected Column addColumn(String tableName, String columnName) { + return addColumn(tableName, columnName, 0, 0); + } + + protected Column addColumn(String tableName, String columnName, long table_hash, long name_hash) { tableName = handleName(tableName); columnName = handleName(columnName); @@ -533,7 +558,7 @@ public class SchemaStatVisitor extends SQLASTVisitorAdapter { } public String getDbType() { - return null; + return dbType; } protected Column getColumn(SQLExpr expr) { @@ -675,6 +700,10 @@ public class SchemaStatVisitor extends SQLASTVisitorAdapter { @Override public boolean visit(SQLInsertStatement x) { + if (repository != null) { + repository.resolve(x); + } + setMode(x, Mode.Insert); setAliasMap(); @@ -833,7 +862,8 @@ public class SchemaStatVisitor extends SQLASTVisitorAdapter { public boolean visit(SQLPropertyExpr x) { if (x.getOwner() instanceof SQLIdentifierExpr) { - String owner = ((SQLIdentifierExpr) x.getOwner()).getName(); + SQLIdentifierExpr ownerExpr = (SQLIdentifierExpr) x.getOwner(); + String owner = ownerExpr.getName(); if (containsSubQuery(owner)) { return false; @@ -842,7 +872,7 @@ public class SchemaStatVisitor extends SQLASTVisitorAdapter { owner = aliasWrap(owner); if (owner != null) { - Column column = addColumn(owner, x.getName()); + Column column = addColumn(owner, x.getName(), ownerExpr.name_hash_lower(), x.name_hash_lower()); x.putAttribute(ATTR_COLUMN, column); if (column != null) { if (isParentGroupBy(x)) { @@ -996,6 +1026,74 @@ public class SchemaStatVisitor extends SQLASTVisitorAdapter { return null; } + public boolean visit2(SQLIdentifierExpr x) { + if (isParam(x)) { + return false; + } + + Column column = null; + String ident = x.getName(); + + SQLTableSource tableSource = x.getResolvedTableSource(); + if (tableSource instanceof SQLExprTableSource) { + SQLExpr expr = ((SQLExprTableSource) tableSource).getExpr(); + if (expr instanceof SQLIdentifierExpr) { + SQLIdentifierExpr table = (SQLIdentifierExpr) expr; + column = addColumn(table.getName(), ident, table.name_hash_lower(), x.name_hash_lower()); + + if (column != null && isParentGroupBy(x)) { + this.groupByColumns.add(column); + } + x.putAttribute(ATTR_COLUMN, column); + } else if (expr instanceof SQLPropertyExpr) { + SQLPropertyExpr table = (SQLPropertyExpr) expr; + String tableName = table.toString(); + column = addColumn(tableName, ident, 0, x.name_hash_lower()); + + if (column != null && isParentGroupBy(x)) { + this.groupByColumns.add(column); + } + x.putAttribute(ATTR_COLUMN, column); + } + } else { + boolean skip = false; + for (SQLObject parent = x.getParent();parent != null;parent = parent.getParent()) { + if (parent instanceof SQLSelectQueryBlock) { + SQLTableSource from = ((SQLSelectQueryBlock) parent).getFrom(); + + if (from instanceof OdpsValuesTableSource) { + skip = true; + break; + } + } else if (parent instanceof SQLSelectQuery) { + break; + } + } + if (!skip) { + column = handleUnkownColumn(ident); + } + if (column != null) { + x.putAttribute(ATTR_COLUMN, column); + } + } + + if (column != null) { + SQLObject parent = x.getParent(); + if (parent instanceof SQLSelectOrderByItem) { + parent = parent.getParent(); + } + if (parent instanceof SQLPrimaryKey) { + column.setPrimaryKey(true); + } else if (parent instanceof SQLUnique) { + column.setUnique(true); + } + + setColumn(x, column); + } + + return false; + } + public boolean visit(SQLIdentifierExpr x) { if (isParam(x)) { return false; @@ -1027,7 +1125,7 @@ public class SchemaStatVisitor extends SQLASTVisitorAdapter { Column column = null; if (currentTable != null) { - column = addColumn(currentTable, ident); + column = addColumn(currentTable, ident, 0, x.name_hash_lower()); if (column != null && isParentGroupBy(x)) { this.groupByColumns.add(column); @@ -1196,6 +1294,10 @@ public class SchemaStatVisitor extends SQLASTVisitorAdapter { } public boolean visit(SQLSelectStatement x) { + if (repository != null) { + repository.resolve(x); + } + setAliasMap(); return true; } @@ -1205,7 +1307,7 @@ public class SchemaStatVisitor extends SQLASTVisitorAdapter { @Override public boolean visit(SQLWithSubqueryClause.Entry x) { - String alias = x.getName().toString(); + String alias = x.getAlias(); Map aliasMap = getAliasMap(); SQLWithSubqueryClause with = (SQLWithSubqueryClause) x.getParent(); @@ -1213,16 +1315,26 @@ public class SchemaStatVisitor extends SQLASTVisitorAdapter { if (aliasMap != null && alias != null) { putAliasMap(aliasMap, alias, null); - addSubQuery(alias, x.getSubQuery().getQuery()); + addSubQuery(alias, x); } - x.getSubQuery().accept(this); + SQLSelect select = x.getSubQuery(); + if (select != null) { + select.accept(this); + } else { + x.getReturningStatement().accept(this); + } } else { - x.getSubQuery().accept(this); + SQLSelect select = x.getSubQuery(); + if (select != null) { + select.accept(this); + } else { + x.getReturningStatement().accept(this); + } if (aliasMap != null && alias != null) { putAliasMap(aliasMap, alias, null); - addSubQuery(alias, x.getSubQuery().getQuery()); + addSubQuery(alias, x); } } @@ -1391,6 +1503,9 @@ public class SchemaStatVisitor extends SQLASTVisitorAdapter { } public boolean visit(SQLUpdateStatement x) { + if (repository != null) { + repository.resolve(x); + } setAliasMap(); setMode(x, Mode.Update); @@ -1419,6 +1534,10 @@ public class SchemaStatVisitor extends SQLASTVisitorAdapter { } public boolean visit(SQLDeleteStatement x) { + if (repository != null) { + repository.resolve(x); + } + setAliasMap(); setMode(x, Mode.Delete); diff --git a/src/main/java/com/alibaba/druid/stat/TableStat.java b/src/main/java/com/alibaba/druid/stat/TableStat.java index fa8df19a6e..80fdc07b1e 100644 --- a/src/main/java/com/alibaba/druid/stat/TableStat.java +++ b/src/main/java/com/alibaba/druid/stat/TableStat.java @@ -403,8 +403,8 @@ public class TableStat { public static class Column { - private String table; - private String name; + private final String table; + private final String name; private boolean where; private boolean select; private boolean groupBy; @@ -423,10 +423,6 @@ public class TableStat { */ private String dataType; - public Column(){ - - } - public Column(String table, String name){ this.table = table; this.name = name; @@ -436,11 +432,6 @@ public class TableStat { return table; } - public void setTable(String table) { - this.table = table; - this.fullName = null; - } - public String getFullName() { if (fullName == null) { if (table != null) { @@ -512,11 +503,6 @@ public class TableStat { public String getName() { return name; } - - public void setName(String name) { - this.name = name; - this.fullName = null; - } /** * @since 1.0.20 diff --git a/src/main/java/com/alibaba/druid/util/FNVUtils.java b/src/main/java/com/alibaba/druid/util/FNVUtils.java index 67b44e9a6d..ac53248d5e 100644 --- a/src/main/java/com/alibaba/druid/util/FNVUtils.java +++ b/src/main/java/com/alibaba/druid/util/FNVUtils.java @@ -80,6 +80,7 @@ public class FNVUtils { public final static long MATCH = fnv_64_lower("MATCH"); public final static long EXTRACT = fnv_64_lower("EXTRACT"); public final static long POSITION = fnv_64_lower("POSITION"); + public final static long DUAL = fnv_64_lower("DUAL"); public static long fnv_64(String input) { if (input == null) { @@ -112,6 +113,46 @@ public class FNVUtils { return hashCode; } + public static long fnv_64_lower_normalized(String name) { + if (name == null) { + return 0; + } + + boolean quote = false; + + int len = name.length(); + if (len > 2) { + char c0 = name.charAt(0); + char c1 = name.charAt(len - 1); + if ((c0 == '`' && c1 == '`') + || (c0 == '"' && c1 == '"') + || (c0 == '[' && c1 == ']')) { + quote = true; + } + } + if (quote) { + return FNVUtils.fnv_64_lower(name, 1, len -1); + } else { + return FNVUtils.fnv_64_lower(name); + } + } + + public static long fnv_64_lower(String key, int offset, int end) { + long hashCode = 0xcbf29ce484222325L; + for (int i = offset; i < end; ++i) { + char ch = key.charAt(i); + + if (ch >= 'A' && ch <= 'Z') { + ch = (char) (ch + 32); + } + + hashCode ^= ch; + hashCode *= 0x100000001b3L; + } + + return hashCode; + } + public static long fnv_32_lower(String key) { long hashCode = 0x811c9dc5; for (int i = 0; i < key.length(); ++i) { diff --git a/src/main/java/com/alibaba/druid/util/Utils.java b/src/main/java/com/alibaba/druid/util/Utils.java index f8e3ba2c3a..75433c3235 100644 --- a/src/main/java/com/alibaba/druid/util/Utils.java +++ b/src/main/java/com/alibaba/druid/util/Utils.java @@ -446,4 +446,5 @@ public class Utils { JdbcUtils.close(reader); } } + } diff --git a/src/main/java/com/alibaba/druid/wall/spi/DB2WallProvider.java b/src/main/java/com/alibaba/druid/wall/spi/DB2WallProvider.java index 03efd8192d..4bbe4d88a9 100644 --- a/src/main/java/com/alibaba/druid/wall/spi/DB2WallProvider.java +++ b/src/main/java/com/alibaba/druid/wall/spi/DB2WallProvider.java @@ -17,6 +17,7 @@ package com.alibaba.druid.wall.spi; import com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser; import com.alibaba.druid.sql.dialect.db2.visitor.DB2ExportParameterVisitor; +import com.alibaba.druid.sql.parser.SQLParserFeature; import com.alibaba.druid.sql.parser.SQLStatementParser; import com.alibaba.druid.sql.visitor.ExportParameterVisitor; import com.alibaba.druid.util.JdbcConstants; @@ -39,7 +40,7 @@ public class DB2WallProvider extends WallProvider { @Override public SQLStatementParser createParser(String sql) { - return new DB2StatementParser(sql); + return new DB2StatementParser(sql, SQLParserFeature.EnableSQLBinaryOpExprGroup); } @Override diff --git a/src/main/java/com/alibaba/druid/wall/spi/MySqlWallProvider.java b/src/main/java/com/alibaba/druid/wall/spi/MySqlWallProvider.java index 1a147c331b..61d3a71231 100644 --- a/src/main/java/com/alibaba/druid/wall/spi/MySqlWallProvider.java +++ b/src/main/java/com/alibaba/druid/wall/spi/MySqlWallProvider.java @@ -17,6 +17,7 @@ package com.alibaba.druid.wall.spi; import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser; import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlExportParameterVisitor; +import com.alibaba.druid.sql.parser.SQLParserFeature; import com.alibaba.druid.sql.parser.SQLStatementParser; import com.alibaba.druid.sql.visitor.ExportParameterVisitor; import com.alibaba.druid.util.JdbcConstants; @@ -38,7 +39,7 @@ public class MySqlWallProvider extends WallProvider { @Override public SQLStatementParser createParser(String sql) { - return new MySqlStatementParser(sql); + return new MySqlStatementParser(sql, SQLParserFeature.EnableSQLBinaryOpExprGroup); } @Override diff --git a/src/main/java/com/alibaba/druid/wall/spi/OracleWallProvider.java b/src/main/java/com/alibaba/druid/wall/spi/OracleWallProvider.java index 303f8eb634..f18a0ace63 100644 --- a/src/main/java/com/alibaba/druid/wall/spi/OracleWallProvider.java +++ b/src/main/java/com/alibaba/druid/wall/spi/OracleWallProvider.java @@ -17,6 +17,7 @@ package com.alibaba.druid.wall.spi; import com.alibaba.druid.sql.dialect.oracle.parser.OracleStatementParser; import com.alibaba.druid.sql.dialect.oracle.visitor.OracleExportParameterVisitor; +import com.alibaba.druid.sql.parser.SQLParserFeature; import com.alibaba.druid.sql.parser.SQLStatementParser; import com.alibaba.druid.sql.visitor.ExportParameterVisitor; import com.alibaba.druid.util.JdbcConstants; @@ -38,7 +39,7 @@ public class OracleWallProvider extends WallProvider { @Override public SQLStatementParser createParser(String sql) { - return new OracleStatementParser(sql); + return new OracleStatementParser(sql, SQLParserFeature.EnableSQLBinaryOpExprGroup); } @Override diff --git a/src/main/java/com/alibaba/druid/wall/spi/PGWallProvider.java b/src/main/java/com/alibaba/druid/wall/spi/PGWallProvider.java index 08095d3eda..04d8272578 100644 --- a/src/main/java/com/alibaba/druid/wall/spi/PGWallProvider.java +++ b/src/main/java/com/alibaba/druid/wall/spi/PGWallProvider.java @@ -17,6 +17,7 @@ package com.alibaba.druid.wall.spi; import com.alibaba.druid.sql.dialect.postgresql.parser.PGSQLStatementParser; import com.alibaba.druid.sql.dialect.postgresql.visitor.PGExportParameterVisitor; +import com.alibaba.druid.sql.parser.SQLParserFeature; import com.alibaba.druid.sql.parser.SQLStatementParser; import com.alibaba.druid.sql.visitor.ExportParameterVisitor; import com.alibaba.druid.util.JdbcConstants; @@ -39,7 +40,7 @@ public class PGWallProvider extends WallProvider { @Override public SQLStatementParser createParser(String sql) { - return new PGSQLStatementParser(sql); + return new PGSQLStatementParser(sql, SQLParserFeature.EnableSQLBinaryOpExprGroup); } @Override diff --git a/src/main/java/com/alibaba/druid/wall/spi/SQLServerWallProvider.java b/src/main/java/com/alibaba/druid/wall/spi/SQLServerWallProvider.java index 9c851367da..ef8e670706 100644 --- a/src/main/java/com/alibaba/druid/wall/spi/SQLServerWallProvider.java +++ b/src/main/java/com/alibaba/druid/wall/spi/SQLServerWallProvider.java @@ -17,6 +17,7 @@ package com.alibaba.druid.wall.spi; import com.alibaba.druid.sql.dialect.sqlserver.parser.SQLServerStatementParser; import com.alibaba.druid.sql.dialect.sqlserver.visitor.MSSQLServerExportParameterVisitor; +import com.alibaba.druid.sql.parser.SQLParserFeature; import com.alibaba.druid.sql.parser.SQLStatementParser; import com.alibaba.druid.sql.visitor.ExportParameterVisitor; import com.alibaba.druid.util.JdbcConstants; @@ -44,7 +45,7 @@ public class SQLServerWallProvider extends WallProvider { @Override public SQLStatementParser createParser(String sql) { - return new SQLServerStatementParser(sql); + return new SQLServerStatementParser(sql, SQLParserFeature.EnableSQLBinaryOpExprGroup); } @Override diff --git a/src/test/java/com/alibaba/druid/benckmark/sql/MySqlInsertBenchmark_2.java b/src/test/java/com/alibaba/druid/benckmark/sql/MySqlInsertBenchmark_2.java index 6d022dc133..ed5b6e7760 100644 --- a/src/test/java/com/alibaba/druid/benckmark/sql/MySqlInsertBenchmark_2.java +++ b/src/test/java/com/alibaba/druid/benckmark/sql/MySqlInsertBenchmark_2.java @@ -29,8 +29,8 @@ public class MySqlInsertBenchmark_2 extends TestCase { System.out.println(sql); for (int i = 0; i < 5; ++i) { // perf(); // 5043 -// perf_toString(); // 2101 - perf_toString_featured(); + perf_toString(); // 2101 +// perf_toString_featured(); // 7493 } } @@ -70,7 +70,7 @@ public class MySqlInsertBenchmark_2 extends TestCase { public void perf_toString_featured() { long startMillis = System.currentTimeMillis(); - for (int i = 0; i < 1000 * 1000; ++i) { + for (int i = 0; i < 1000 * 1000 * 10; ++i) { SQLUtils.toMySqlString(stmtList.get(0), VisitorFeature.OutputUseInsertValueClauseOriginalString); } long millis = System.currentTimeMillis() - startMillis; 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 237c0d5685..e73cd0f74c 100644 --- a/src/test/java/com/alibaba/druid/benckmark/sql/MySqlParameterizedBenchmark.java +++ b/src/test/java/com/alibaba/druid/benckmark/sql/MySqlParameterizedBenchmark.java @@ -2,8 +2,13 @@ package com.alibaba.druid.benckmark.sql; import com.alibaba.druid.sql.SQLUtils; import com.alibaba.druid.sql.ast.SQLStatement; +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.repository.SchemaRepository; import com.alibaba.druid.sql.visitor.SQLASTOutputVisitor; +import com.alibaba.druid.sql.visitor.SQLASTVisitor; +import com.alibaba.druid.sql.visitor.SchemaStatVisitor; import com.alibaba.druid.util.JdbcConstants; import junit.framework.TestCase; import org.junit.Test; @@ -18,14 +23,24 @@ public class MySqlParameterizedBenchmark extends TestCase { String sql = "select id as id, gmt_create as gmtCreate, gmt_modified as gmtModified, name as name, owner as owner, type as type, statement as statement, datasource as datasource, meta as meta, param_file as paramFile, sharable as sharable, data_type as dataType, status as status, config as config, project_id as projectId, plugins as plugins, field_compare as fieldCompare, field_ext as fieldExt, openx as openx from quark_s_dataset where id = 12569434"; String sql2 = "/* ///6ea6f232/ */select count(*) FROM (SELECT * FROM cluster_ins_mapping WHERE `engine` = 'MySQL' and `status`='Activation' GROUP BY ip,port ) a;"; String sql3 = "/* 0be5256b15035048614234260e129b/0.1//722b9d1a/ */ select count(*) from (SELECT message_id,employee_name,employee_id FROM tunning_overview where instance_info IS NOT NULL and instance_info = '11.179.218.9:3306' and gmt_modified >= '2017-08-23 00:00:00' and gmt_modified <= '2017-08-24 00:00:00' ) o join (SELECT message_id,index_advice_count,index_advice,gmt_created FROM tunning_task_detail where gmt_modified >= '2017-08-23 00:00:00' and gmt_modified <= '2017-08-24 00:00:00' and index_advice_count >= 0 and error_code='0000' ) t on o.message_id=t.message_id where o.employee_name!='system' or ( o.employee_name='system' and t.index_advice_count>0);"; + String sql4 = "UPDATE ROLLBACK_ON_FAIL TARGET_AFFECT_ROW 1 " + + "`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` = ?"; for (int i = 0; i < 5; ++i) { // perf(sql); // 6740 6201 4752 4514 // perf(sql2); // 2948 2928 2869 2780 2502 - perf(sql3); // 15093 10392 10416 10154 10007 9126 8907 -// perf_parse(sql); // 4643 4377 4345 3801 3627 3228 +// perf(sql3); // 15093 10392 10416 10154 10007 9126 8907 +// perf(sql4); // 4429 4190 4023 3747 + +// perf_parse(sql); // 4643 4377 4345 3801 3627 3228 2961 // perf_parse(sql2); // 1918 1779 1666 1646 -// perf_parse(sql3); // 9174 5875 5805 5536 +// perf_parse(sql3); // 9174 5875 5805 5536 5717 +// perf_parse(sql4); // 2953 2502 + + perf_stat(sql); // 11793 13628 13561 13259 + +// perf_resolve(sql); // 4970 4586 } } public void perf(String sql) { @@ -46,4 +61,29 @@ public class MySqlParameterizedBenchmark extends TestCase { System.out.println("millis : " + millis); } + public void perf_stat(String sql) { + long startMillis = System.currentTimeMillis(); + for (int i = 0; i < 1000 * 1000; ++i) { + SqlHolder holder = SqlHolder.of(sql); + holder.ensureParsed(); + + //new SchemaRepository(JdbcConstants.MYSQL).resolve(holder.ast); + SQLASTVisitor visitor = new MySqlSchemaStatVisitor(); + holder.ast.accept(visitor); + } + long millis = System.currentTimeMillis() - startMillis; + System.out.println("millis : " + millis); + } + + public void perf_resolve(String sql) { + long startMillis = System.currentTimeMillis(); + for (int i = 0; i < 1000 * 1000; ++i) { + SqlHolder holder = SqlHolder.of(sql); + holder.ensureParsed(); + + new SchemaRepository(JdbcConstants.MYSQL).resolve(holder.ast); + } + long millis = System.currentTimeMillis() - startMillis; + System.out.println("millis : " + millis); + } } diff --git a/src/test/java/com/alibaba/druid/benckmark/sql/SqlHolder.java b/src/test/java/com/alibaba/druid/benckmark/sql/SqlHolder.java index ba4af3af34..0c97ebebd7 100644 --- a/src/test/java/com/alibaba/druid/benckmark/sql/SqlHolder.java +++ b/src/test/java/com/alibaba/druid/benckmark/sql/SqlHolder.java @@ -8,6 +8,8 @@ import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor; import com.alibaba.druid.sql.parser.ParserException; import com.alibaba.druid.sql.parser.SQLParserFeature; import com.alibaba.druid.sql.visitor.SQLASTOutputVisitor; +import com.alibaba.druid.sql.visitor.SchemaStatVisitor; +import com.alibaba.druid.stat.TableStat; import com.alibaba.druid.util.JdbcConstants; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.serializer.SerializerFeature; @@ -23,7 +25,7 @@ public class SqlHolder { private String dialect; private boolean parsed; - private SQLStatement ast; + public SQLStatement ast; public static SqlHolder of(String sql) { return new SqlHolder(sql); @@ -113,4 +115,100 @@ public class SqlHolder { params = StringUtils.replace(params, "\"", "\\\""); return params; } + + public String getSqlItems(String db) { + Map> itemMap = new HashMap>(); + try { + SchemaStatVisitor schemaStatVisitor = new MySqlSchemaStatVisitor(); + ast.accept(schemaStatVisitor); + List conditionList = schemaStatVisitor.getConditions(); + for (TableStat.Condition condition : conditionList) { + String tableName = condition.getColumn().getTable(); + LinkedHashSet condLinkedSet = itemMap.get(tableName); + if (condLinkedSet == null) { + condLinkedSet = new LinkedHashSet(); + itemMap.put(tableName, condLinkedSet); + } + TableStat.Column column = condition.getColumn(); + String upperClnName = column.toString().toUpperCase(); + String finalClnName = filterChar(db, upperClnName); + condLinkedSet.add(finalClnName); + } + } catch (Exception ex) { + } + if (itemMap.isEmpty()) + return null; + StringBuilder resSb = new StringBuilder(); + for (Map.Entry> entry : itemMap.entrySet()) { + resSb.append(StringUtils.join(entry.getValue(), ",")).append(","); + } + return resSb.substring(0, resSb.length() - 1); + } + + public static String filterChar(String db, String name) { + String resName; + if (StringUtils.isNotBlank(name)) { + String[] names = name.split("\\."); + StringBuilder nameSb = new StringBuilder(); + boolean isFirst = true; + int size = names.length; + int k = 0; + for (String n : names) { + String tempN = n; + if (n.startsWith("`") && n.endsWith("`")) { + tempN = n.substring(1, n.length() - 1); + } + if (k == size - 1) { + nameSb.append(tempN).append("."); + } else if (isFirst) { + if (!n.startsWith(db)) { + nameSb.append(convert(tempN)).append("."); + } + isFirst = false; + } else { + nameSb.append(convert(tempN)).append("."); + } + k++; + } + resName = nameSb.substring(0, nameSb.length() - 1); + } else { + resName = name; + } + return db + "." + resName; + } + + public static String convert(String tableName) { + if (StringUtils.isBlank(tableName)) { + return tableName; + } + int len = tableName.length(); + int k = -1; + int min = Math.min(4, len); + for (int i = 1; i <= min; i++) { + String ch = String.valueOf(tableName.charAt(len - i)); + boolean isNum = StringUtils.isNumeric(ch); + if (isNum) { + k = i; + } else { + break; + } + } + + if (k != -1) { + tableName = tableName.substring(0, len - k); + if (tableName.endsWith("_")) { + tableName = tableName.substring(0, tableName.length() - 1); + } + } + int idx = tableName.lastIndexOf("_"); + if (idx == -1 || (tableName.length() - 1 == idx)) { + return tableName; + } + String num = tableName.substring(idx + 1); + boolean isNum = StringUtils.isNumeric(num); + if (isNum) { + return tableName.substring(0, idx); + } + return tableName; + } } diff --git a/src/test/java/com/alibaba/druid/bvt/sql/HashTest_0.java b/src/test/java/com/alibaba/druid/bvt/sql/HashTest_0.java new file mode 100644 index 0000000000..019bdc2d2c --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/HashTest_0.java @@ -0,0 +1,21 @@ +package com.alibaba.druid.bvt.sql; + +import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; +import junit.framework.TestCase; + +public class HashTest_0 extends TestCase { + public void test_issue() throws Exception { + assertEquals(new SQLIdentifierExpr("a").name_hash_lower() + , new SQLIdentifierExpr("A").name_hash_lower());; + } + + public void test_issue_1() throws Exception { + assertEquals(new SQLIdentifierExpr("a").name_hash_lower() + , new SQLIdentifierExpr("`A`").name_hash_lower());; + } + + public void test_issue_2() throws Exception { + assertEquals(new SQLIdentifierExpr("\"a\"").name_hash_lower() + , new SQLIdentifierExpr("`A`").name_hash_lower());; + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/HashTest_1_propertyExpr.java b/src/test/java/com/alibaba/druid/bvt/sql/HashTest_1_propertyExpr.java new file mode 100644 index 0000000000..1544c08f0a --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/HashTest_1_propertyExpr.java @@ -0,0 +1,22 @@ +package com.alibaba.druid.bvt.sql; + +import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; +import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr; +import junit.framework.TestCase; + +public class HashTest_1_propertyExpr extends TestCase { + public void test_issue() throws Exception { + assertEquals(new SQLPropertyExpr("t","a").name_hash_lower() + , new SQLPropertyExpr("t","A").name_hash_lower());; + } + + public void test_issue_1() throws Exception { + assertEquals(new SQLPropertyExpr("t","a").name_hash_lower() + , new SQLPropertyExpr("t","`A`").name_hash_lower());; + } + + public void test_issue_2() throws Exception { + assertEquals(new SQLPropertyExpr("t","\"a\"").name_hash_lower() + , new SQLPropertyExpr("t","`A`").name_hash_lower());; + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest18.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest18.java index 1e04f5be29..628618839f 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest18.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest18.java @@ -58,7 +58,7 @@ public class MySqlCreateTableTest18 extends MysqlTest { statemen.accept(visitor); // System.out.println("Tables : " + visitor.getTables()); -// System.out.println("fields : " + visitor.getColumns()); + 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/select/MySqlSelectTest_16.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/select/MySqlSelectTest_16.java index 975a6cec08..bbddfdf9e4 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/mysql/select/MySqlSelectTest_16.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/select/MySqlSelectTest_16.java @@ -59,13 +59,17 @@ public class MySqlSelectTest_16 extends MysqlTest { Assert.assertTrue(binaryWhere.getRight() instanceof SQLNotExpr); } -// print(statementList); Assert.assertEquals(1, statementList.size()); MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor(); stmt.accept(visitor); +// System.out.println("Tables : " + visitor.getTables()); + System.out.println("fields : " + visitor.getColumns()); +// System.out.println("coditions : " + visitor.getConditions()); +// System.out.println("orderBy : " + visitor.getOrderByColumns()); + Assert.assertEquals(1, visitor.getTables().size()); Assert.assertEquals(2, visitor.getColumns().size()); Assert.assertEquals(2, visitor.getConditions().size()); diff --git a/src/test/java/com/alibaba/druid/bvt/sql/postgresql/PGASTVisitorAdapterTest.java b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/PGASTVisitorAdapterTest.java index d6558e6c0a..cc555159cc 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/postgresql/PGASTVisitorAdapterTest.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/PGASTVisitorAdapterTest.java @@ -1,7 +1,5 @@ package com.alibaba.druid.bvt.sql.postgresql; -import com.alibaba.druid.sql.dialect.postgresql.ast.PGWithClause; -import com.alibaba.druid.sql.dialect.postgresql.ast.PGWithQuery; import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGDeleteStatement; import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGFunctionTableSource; import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock.FetchClause; @@ -19,8 +17,6 @@ public class PGASTVisitorAdapterTest extends TestCase { new WindowClause().accept(adapter); new FetchClause().accept(adapter); new ForClause().accept(adapter); - new PGWithQuery().accept(adapter); - new PGWithClause().accept(adapter); new PGDeleteStatement().accept(adapter); new PGFunctionTableSource().accept(adapter); } diff --git a/src/test/java/com/alibaba/druid/bvt/sql/postgresql/PGDeleteTest5.java b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/PGDeleteTest5.java index f9852a9ec2..64e7777231 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/postgresql/PGDeleteTest5.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/PGDeleteTest5.java @@ -41,7 +41,7 @@ public class PGDeleteTest5 extends PGTest { statemen.accept(visitor); // System.out.println("Tables : " + visitor.getTables()); -// System.out.println("fields : " + visitor.getColumns()); + System.out.println("fields : " + visitor.getColumns()); // System.out.println("coditions : " + visitor.getConditions()); Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("films"))); diff --git a/src/test/java/com/alibaba/druid/bvt/sql/postgresql/PGDeleteTest6.java b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/PGDeleteTest6.java index 255285aab4..2e33b25f1c 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/postgresql/PGDeleteTest6.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/PGDeleteTest6.java @@ -44,12 +44,11 @@ public class PGDeleteTest6 extends PGTest { // print(statementList); Assert.assertEquals(1, statementList.size()); - PGSchemaStatVisitor visitor = new PGSchemaStatVisitor(); statemen.accept(visitor); // System.out.println("Tables : " + visitor.getTables()); -// System.out.println("fields : " + visitor.getColumns()); + System.out.println("fields : " + visitor.getColumns()); // System.out.println("coditions : " + visitor.getConditions()); Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("products"))); diff --git a/src/test/java/com/alibaba/druid/bvt/sql/postgresql/PGDeleteTest8.java b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/PGDeleteTest8.java index 01265a8661..f3d5be509c 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/postgresql/PGDeleteTest8.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/PGDeleteTest8.java @@ -48,17 +48,16 @@ public class PGDeleteTest8 extends PGTest { PGSchemaStatVisitor visitor = new PGSchemaStatVisitor(); statemen.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()); Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("parts"))); - Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("included_parts"))); Assert.assertTrue(visitor.getColumns().size() == 3); Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("parts", "sub_part"))); - Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("included_parts", "sub_part"))); + Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("parts", "sub_part"))); Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("parts", "part"))); } diff --git a/src/test/java/com/alibaba/druid/bvt/sql/postgresql/PGInsertTest5.java b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/PGInsertTest5.java index 490705ee53..89d08e3a28 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/postgresql/PGInsertTest5.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/PGInsertTest5.java @@ -45,8 +45,8 @@ public class PGInsertTest5 extends PGTest { PGSchemaStatVisitor visitor = new PGSchemaStatVisitor(); 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()); Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("employees_log"))); diff --git a/src/test/java/com/alibaba/druid/bvt/sql/postgresql/select/PGSelectTest13.java b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/select/PGSelectTest13.java index 70f2ea6410..152da56ab8 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/postgresql/select/PGSelectTest13.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/select/PGSelectTest13.java @@ -44,12 +44,12 @@ public class PGSelectTest13 extends PGTest { PGSchemaStatVisitor visitor = new PGSchemaStatVisitor(); statemen.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()); - Assert.assertEquals(1, visitor.getColumns().size()); - Assert.assertEquals(1, visitor.getTables().size()); + Assert.assertEquals(0, visitor.getColumns().size()); + Assert.assertEquals(0, visitor.getTables().size()); } } diff --git a/src/test/java/com/alibaba/druid/bvt/sql/postgresql/select/PGSelectTest14.java b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/select/PGSelectTest14.java index e90f414079..f90a2db515 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/postgresql/select/PGSelectTest14.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/select/PGSelectTest14.java @@ -40,20 +40,20 @@ public class PGSelectTest14 extends PGTest { PGSQLStatementParser parser = new PGSQLStatementParser(sql); List statementList = parser.parseStatementList(); - SQLStatement statemen = statementList.get(0); + SQLStatement stmt = statementList.get(0); // print(statementList); - Assert.assertEquals(1, statementList.size()); + assertEquals(1, statementList.size()); PGSchemaStatVisitor visitor = new PGSchemaStatVisitor(); - statemen.accept(visitor); + 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()); - Assert.assertEquals(5, visitor.getColumns().size()); - Assert.assertEquals(2, visitor.getTables().size()); + assertEquals(4, visitor.getColumns().size()); + assertEquals(1, visitor.getTables().size()); } } diff --git a/src/test/java/com/alibaba/druid/bvt/sql/postgresql/select/PGSelectTest15.java b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/select/PGSelectTest15.java index 2b4a5dd242..67ee600b9d 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/postgresql/select/PGSelectTest15.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/select/PGSelectTest15.java @@ -39,20 +39,31 @@ public class PGSelectTest15 extends PGTest { PGSQLStatementParser parser = new PGSQLStatementParser(sql); List statementList = parser.parseStatementList(); - SQLStatement statemen = statementList.get(0); + SQLStatement stmt = statementList.get(0); // print(statementList); Assert.assertEquals(1, statementList.size()); PGSchemaStatVisitor visitor = new PGSchemaStatVisitor(); - statemen.accept(visitor); + stmt.accept(visitor); -// System.out.println("Tables : " + visitor.getTables()); -// System.out.println("fields : " + visitor.getColumns()); + assertEquals("WITH RECURSIVE search_graph (id, link, data, depth) AS (\n" + + "\t\tSELECT g.id, g.link, g.data, 1\n" + + "\t\tFROM graph g\n" + + "\t\tUNION ALL\n" + + "\t\tSELECT g.id, g.link, g.data, sg.depth + 1\n" + + "\t\tFROM graph g, search_graph sg\n" + + "\t\tWHERE g.id = sg.link\n" + + "\t)\n" + + "SELECT *\n" + + "FROM search_graph;", stmt.toString()); + + System.out.println("Tables : " + visitor.getTables()); + System.out.println("fields : " + visitor.getColumns()); // System.out.println("coditions : " + visitor.getConditions()); - Assert.assertEquals(7, visitor.getColumns().size()); - Assert.assertEquals(2, visitor.getTables().size()); + Assert.assertEquals(5, visitor.getColumns().size()); + Assert.assertEquals(1, visitor.getTables().size()); } } diff --git a/src/test/java/com/alibaba/druid/bvt/sql/postgresql/select/PGSelectTest16.java b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/select/PGSelectTest16.java index 9f8071887f..1b6750b692 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/postgresql/select/PGSelectTest16.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/select/PGSelectTest16.java @@ -52,19 +52,19 @@ public class PGSelectTest16 extends PGTest { PGSchemaStatVisitor visitor = new PGSchemaStatVisitor(); statemen.accept(visitor); -// System.out.println("Tables : " + visitor.getTables()); + System.out.println("Tables : " + visitor.getTables()); System.out.println("fields : " + visitor.getColumns()); // System.out.println("coditions : " + visitor.getConditions()); - assertEquals(9, visitor.getColumns().size()); - assertEquals(2, visitor.getTables().size()); + assertEquals(7, visitor.getColumns().size()); + assertEquals(1, visitor.getTables().size()); assertTrue(visitor.getColumns().contains(new TableStat.Column("graph", "id"))); assertTrue(visitor.getColumns().contains(new TableStat.Column("graph", "link"))); assertTrue(visitor.getColumns().contains(new TableStat.Column("graph", "data"))); - assertTrue(visitor.getColumns().contains(new TableStat.Column("search_graph", "depth"))); +// assertTrue(visitor.getColumns().contains(new TableStat.Column("search_graph", "depth"))); // assertTrue(visitor.getColumns().contains(new TableStat.Column("graph", "path"))); - assertTrue(visitor.getColumns().contains(new TableStat.Column("search_graph", "link"))); +// assertTrue(visitor.getColumns().contains(new TableStat.Column("search_graph", "link"))); // assertTrue(visitor.getColumns().contains(new TableStat.Column("graph", "cycle"))); assertTrue(visitor.getColumns().contains(new TableStat.Column("sg", "depth"))); assertTrue(visitor.getColumns().contains(new TableStat.Column("sg", "link"))); diff --git a/src/test/java/com/alibaba/druid/bvt/sql/postgresql/select/PGSelectTest17.java b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/select/PGSelectTest17.java index 84d766ae72..51f0f09c44 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/postgresql/select/PGSelectTest17.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/select/PGSelectTest17.java @@ -51,12 +51,12 @@ public class PGSelectTest17 extends PGTest { PGSchemaStatVisitor visitor = new PGSchemaStatVisitor(); statemen.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()); - Assert.assertEquals(11, visitor.getColumns().size()); - Assert.assertEquals(2, visitor.getTables().size()); + Assert.assertEquals(9, visitor.getColumns().size()); + Assert.assertEquals(1, visitor.getTables().size()); } } diff --git a/src/test/java/com/alibaba/druid/bvt/sql/postgresql/select/PGSelectTest18.java b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/select/PGSelectTest18.java index ed9f92f634..920940ca13 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/postgresql/select/PGSelectTest18.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/select/PGSelectTest18.java @@ -40,33 +40,27 @@ public class PGSelectTest18 extends PGTest { SQLStatement stmt = statementList.get(0); { String result = SQLUtils.toPGString(stmt); - Assert.assertEquals("WITH RECURSIVE " - + "\n\tt (n)" - + "\n\tAS" - + "\n\t(" - + "\n\t\tSELECT 1" - + "\n\t\tUNION ALL" - + "\n\t\tSELECT n + 1" - + "\n\t\tFROM t" - + "\n\t)" - + "\nSELECT n" - + "\nFROM t" - + "\nLIMIT 100;", result); + Assert.assertEquals("WITH RECURSIVE t (n) AS (\n" + + "\t\tSELECT 1\n" + + "\t\tUNION ALL\n" + + "\t\tSELECT n + 1\n" + + "\t\tFROM t\n" + + "\t)\n" + + "SELECT n\n" + + "FROM t\n" + + "LIMIT 100;", result); } { String result = SQLUtils.toPGString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION); - Assert.assertEquals("with recursive " - + "\n\tt (n)" - + "\n\tas" - + "\n\t(" - + "\n\t\tselect 1" - + "\n\t\tunion all" - + "\n\t\tselect n + 1" - + "\n\t\tfrom t" - + "\n\t)" - + "\nselect n" - + "\nfrom t" - + "\nlimit 100;", result); + Assert.assertEquals("with recursive t (n) as (\n" + + "\t\tselect 1\n" + + "\t\tunion all\n" + + "\t\tselect n + 1\n" + + "\t\tfrom t\n" + + "\t)\n" + + "select n\n" + + "from t\n" + + "limit 100;", result); } Assert.assertEquals(1, statementList.size()); @@ -78,8 +72,8 @@ public class PGSelectTest18 extends PGTest { // System.out.println("fields : " + visitor.getColumns()); // System.out.println("coditions : " + visitor.getConditions()); - Assert.assertEquals(1, visitor.getColumns().size()); - Assert.assertEquals(1, visitor.getTables().size()); + Assert.assertEquals(0, visitor.getColumns().size()); + Assert.assertEquals(0, visitor.getTables().size()); } } diff --git a/src/test/java/com/alibaba/druid/bvt/sql/postgresql/select/PGSelectTest21.java b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/select/PGSelectTest21.java index b95ec07b11..4763110812 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/postgresql/select/PGSelectTest21.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/select/PGSelectTest21.java @@ -59,10 +59,10 @@ public class PGSelectTest21 extends PGTest { // print(statementList); assertTrue(statemen instanceof PGSelectStatement); - assertTrue(((PGSelectStatement)statemen).getWith().getWithQuery().size()==1); + assertEquals(1, ((PGSelectStatement)statemen).getSelect().getWithSubQuery().getEntries().size()); StringBuffer sb = new StringBuffer(); - ((PGSelectStatement)statemen).getWith().getWithQuery().get(0).getName().output(sb); - assertTrue("a".equals(sb.toString())); - assertTrue(((PGSelectStatement)statemen).getWith().getWithQuery().get(0).getColumns().size()==2); + String alias = ((PGSelectStatement)statemen).getSelect().getWithSubQuery().getEntries().get(0).getAlias(); + assertEquals("a", alias); + assertEquals(2, ((PGSelectStatement)statemen).getSelect().getWithSubQuery().getEntries().get(0).getColumns().size()); } } diff --git a/src/test/java/com/alibaba/druid/bvt/sql/postgresql/select/PGSelectTest49.java b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/select/PGSelectTest49.java index e6cc07aca3..525db2b9f3 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/postgresql/select/PGSelectTest49.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/select/PGSelectTest49.java @@ -37,10 +37,7 @@ public class PGSelectTest49 extends TestCase { List stmtList = SQLUtils.parseStatements(sql, dbType); SQLStatement stmt = stmtList.get(0); - assertEquals("WITH\n" + - "\tsel\n" + - "\tAS\n" + - "\t(\n" + + assertEquals("WITH sel AS (\n" + "\t\tSELECT unnest(ARRAY[4275]) AS gdid, unnest(ARRAY[1]) AS gdnumber\n" + "\t)\n" + "UPDATE goods_detail\n" + @@ -48,10 +45,7 @@ public class PGSelectTest49 extends TestCase { "FROM sel\n" + "WHERE gd_id = gdid;", SQLUtils.toPGString(stmt)); - assertEquals("with\n" + - "\tsel\n" + - "\tas\n" + - "\t(\n" + + assertEquals("with sel as (\n" + "\t\tselect unnest(ARRAY[4275]) as gdid, unnest(ARRAY[1]) as gdnumber\n" + "\t)\n" + "update goods_detail\n" +