diff --git a/pom.xml b/pom.xml index bc0bc5bc36..0dbf5fe9e9 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ --> com.alibaba druid - 1.1.3-preview_43 + 1.1.3-preview_47 jar druid diff --git a/src/main/java/com/alibaba/druid/sql/SQLUtils.java b/src/main/java/com/alibaba/druid/sql/SQLUtils.java index ee1b990d25..1d8b2314b0 100644 --- a/src/main/java/com/alibaba/druid/sql/SQLUtils.java +++ b/src/main/java/com/alibaba/druid/sql/SQLUtils.java @@ -818,7 +818,15 @@ public class SQLUtils { } public static boolean nameEquals(SQLName a, SQLName b) { - return nameEquals(a.getSimpleName(), b.getSimpleName()); + if (a == b) { + return true; + } + + if (a == null || b == null) { + return false; + } + + return a.nameHashCode64() == b.nameHashCode64(); } public static boolean nameEquals(String a, String b) { diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableStatement.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableStatement.java index f1b2b71824..2952992848 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableStatement.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableStatement.java @@ -132,6 +132,13 @@ public class SQLAlterTableStatement extends SQLStatementImpl implements SQLDDLSt return (SQLName) getTableSource().getExpr(); } + public long nameHashCode64() { + if (getTableSource() == null) { + return 0L; + } + return ((SQLName) getTableSource().getExpr()).nameHashCode64(); + } + public void setName(SQLName name) { this.setTableSource(new SQLExprTableSource(name)); } 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 faf73eeab0..7e0a4a9df6 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 @@ -601,11 +601,13 @@ public class SQLCreateTableStatement extends SQLStatementImpl implements SQLDDLS } public boolean apply(SQLDropIndexStatement x) { + long indexNameHashCode64 = x.getIndexName().nameHashCode64(); + for (int i = tableElementList.size() - 1; i >= 0; i--) { SQLTableElement e = tableElementList.get(i); if (e instanceof SQLUniqueConstraint) { SQLUniqueConstraint unique = (SQLUniqueConstraint) e; - if (SQLUtils.nameEquals(unique.getName(), x.getIndexName())) { + if (unique.getName().nameHashCode64() == indexNameHashCode64) { tableElementList.remove(i); return true; } @@ -643,7 +645,10 @@ public class SQLCreateTableStatement extends SQLStatementImpl implements SQLDDLS return false; } - SQLColumnDefinition column = this.findColumn(propertyExpr.getName()); + SQLColumnDefinition column + = this.findColumn( + propertyExpr.nameHashCode64()); + if (column != null) { column.setComment(comment.clone()); } 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 cf21d3a0bf..cba2fd9356 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 @@ -74,9 +74,7 @@ public class SQLWithSubqueryClause extends SQLObjectImpl { protected SQLSelect subQuery; protected SQLStatement returningStatement; - public Entry clone() { - Entry x = new Entry(); - + protected void cloneTo(Entry x) { for (SQLName column : columns) { SQLName column2 = column.clone(); column2.setParent(x); @@ -87,6 +85,14 @@ public class SQLWithSubqueryClause extends SQLObjectImpl { x.setSubQuery(subQuery.clone()); } + if (returningStatement != null) { + setReturningStatement(returningStatement.clone()); + } + } + + public Entry clone() { + Entry x = new Entry(); + cloneTo(x); return x; } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/clause/CycleClause.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/clause/CycleClause.java index 14c92cfa93..fb7f99a949 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/clause/CycleClause.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/clause/CycleClause.java @@ -34,6 +34,9 @@ public class CycleClause extends OracleSQLObjectImpl { } public void setMark(SQLExpr mark) { + if (mark != null) { + mark.setParent(this); + } this.mark = mark; } @@ -42,6 +45,9 @@ public class CycleClause extends OracleSQLObjectImpl { } public void setValue(SQLExpr value) { + if (value != null) { + value.setParent(this); + } this.value = value; } @@ -50,6 +56,9 @@ public class CycleClause extends OracleSQLObjectImpl { } public void setDefaultValue(SQLExpr defaultValue) { + if (defaultValue != null) { + defaultValue.setParent(this); + } this.defaultValue = defaultValue; } @@ -68,4 +77,27 @@ public class CycleClause extends OracleSQLObjectImpl { visitor.endVisit(this); } + public CycleClause clone() { + CycleClause x = new CycleClause(); + + for (SQLExpr alias : aliases) { + SQLExpr alias2 = alias.clone(); + alias2.setParent(x); + x.aliases.add(alias2); + } + + if (mark != null) { + setMark(mark.clone()); + } + + if (value != null) { + setValue(value.clone()); + } + + if (defaultValue != null) { + setDefaultValue(defaultValue.clone()); + } + + return 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 0e54a3f96f..44ca042b0f 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 @@ -30,6 +30,9 @@ public class OracleWithSubqueryEntry extends Entry implements OracleSQLObject { } public void setCycleClause(CycleClause cycleClause) { + if (cycleClause != null) { + cycleClause.setParent(this); + } this.cycleClause = cycleClause; } @@ -38,6 +41,9 @@ public class OracleWithSubqueryEntry extends Entry implements OracleSQLObject { } public void setSearchClause(SearchClause searchClause) { + if (searchClause != null) { + searchClause.setParent(this); + } this.searchClause = searchClause; } @@ -57,4 +63,21 @@ public class OracleWithSubqueryEntry extends Entry implements OracleSQLObject { this.accept0((OracleASTVisitor) visitor); } + protected void cloneTo(OracleWithSubqueryEntry x) { + super.cloneTo(x); + + if (searchClause != null) { + setSearchClause(searchClause.clone()); + } + + if (cycleClause != null) { + setCycleClause(cycleClause.clone()); + } + } + + public OracleWithSubqueryEntry clone() { + OracleWithSubqueryEntry x = new OracleWithSubqueryEntry(); + cloneTo(x); + return x; + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/clause/SearchClause.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/clause/SearchClause.java index 6806cb3182..92245411be 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/clause/SearchClause.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/clause/SearchClause.java @@ -59,6 +59,9 @@ public class SearchClause extends OracleSQLObjectImpl { } public void setOrderingColumn(SQLIdentifierExpr orderingColumn) { + if (orderingColumn != null) { + orderingColumn.setParent(this); + } this.orderingColumn = orderingColumn; } @@ -71,4 +74,21 @@ public class SearchClause extends OracleSQLObjectImpl { visitor.endVisit(this); } + public SearchClause clone() { + SearchClause x = new SearchClause(); + + x.type = type; + + for (SQLSelectOrderByItem item : items) { + SQLSelectOrderByItem item2 = item.clone(); + item2.setParent(x); + x.items.add(item2); + } + + if (orderingColumn != null) { + x.setOrderingColumn(orderingColumn.clone()); + } + + return x; + } } diff --git a/src/main/java/com/alibaba/druid/sql/parser/Lexer.java b/src/main/java/com/alibaba/druid/sql/parser/Lexer.java index 45332c5198..cdcc412115 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/Lexer.java +++ b/src/main/java/com/alibaba/druid/sql/parser/Lexer.java @@ -40,6 +40,7 @@ import java.util.Arrays; import java.util.List; import com.alibaba.druid.sql.ast.expr.SQLNumberExpr; +import com.alibaba.druid.sql.dialect.mysql.parser.MySqlLexer; import com.alibaba.druid.util.FnvHash; import com.alibaba.druid.util.JdbcConstants; import com.alibaba.druid.util.StringUtils; @@ -1321,6 +1322,38 @@ public class Lexer { final char first = ch; + if (ch == '`') { + mark = pos; + bufPos = 1; + char ch; + + 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 = MySqlLexer.quoteTable.addSymbol(text, pos, quoteIndex + 1 - pos, hash); + //stringVal = text.substring(mark, pos); + pos = quoteIndex + 1; + this.ch = charAt(pos); + token = Token.IDENTIFIER; + return; + } + final boolean firstFlag = isFirstIdentifierChar(first); if (!firstFlag) { throw new ParserException("illegal identifier. " + info()); diff --git a/src/main/java/com/alibaba/druid/sql/repository/Schema.java b/src/main/java/com/alibaba/druid/sql/repository/Schema.java index f1eeee4802..3a5deb8286 100644 --- a/src/main/java/com/alibaba/druid/sql/repository/Schema.java +++ b/src/main/java/com/alibaba/druid/sql/repository/Schema.java @@ -30,12 +30,11 @@ import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitorAdapter; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleCreateTableStatement; import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitorAdapter; import com.alibaba.druid.sql.visitor.SQLASTVisitor; +import com.alibaba.druid.util.FnvHash; import com.alibaba.druid.util.JdbcConstants; -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentSkipListMap; /** @@ -44,9 +43,9 @@ import java.util.concurrent.ConcurrentSkipListMap; public class Schema { private String name; - protected final Map objects = new ConcurrentSkipListMap(); + protected final Map objects = new ConcurrentHashMap(); - protected final Map functions = new ConcurrentSkipListMap(); + protected final Map functions = new ConcurrentHashMap(); private SchemaRepository repository; @@ -69,9 +68,12 @@ public class Schema { public SchemaObject findTable(String tableName) { - tableName = SQLUtils.normalize(tableName); - String lowerName = tableName.toLowerCase(); - SchemaObject object = objects.get(lowerName); + long hashCode64 = FnvHash.hashCode64(tableName); + return findTable(hashCode64); + } + + public SchemaObject findTable(long nameHashCode64) { + SchemaObject object = objects.get(nameHashCode64); if (object != null && object.getType() == SchemaObjectType.Table) { return object; @@ -81,9 +83,12 @@ public class Schema { } public SchemaObject findTableOrView(String tableName) { - tableName = SQLUtils.normalize(tableName); - String lowerName = tableName.toLowerCase(); - SchemaObject object = objects.get(lowerName); + long hashCode64 = FnvHash.hashCode64(tableName); + return findTableOrView(hashCode64); + } + + public SchemaObject findTableOrView(long hashCode64) { + SchemaObject object = objects.get(hashCode64); if (object == null) { return null; @@ -104,10 +109,8 @@ public class Schema { } public boolean isSequence(String name) { - name = SQLUtils.normalize(name); - String lowerName = name.toLowerCase(); - - SchemaObject object = objects.get(lowerName); + long nameHashCode64 = FnvHash.hashCode64(name); + SchemaObject object = objects.get(nameHashCode64); return object != null && object.getType() == SchemaObjectType.Sequence; } @@ -125,9 +128,9 @@ public class Schema { SQLExpr expr = exprTableSource.getExpr(); if (expr instanceof SQLIdentifierExpr) { - String tableName = ((SQLIdentifierExpr) expr).getName(); + long tableNameHashCode64 = ((SQLIdentifierExpr) expr).nameHashCode64(); - tableObject = findTable(tableName); + tableObject = findTable(tableNameHashCode64); if (tableObject != null) { exprTableSource.setSchemaObject(tableObject); } @@ -135,9 +138,9 @@ public class Schema { } if (expr instanceof SQLPropertyExpr) { - String tableName = ((SQLPropertyExpr) expr).getName(); + long tableNameHashCode64 = ((SQLPropertyExpr) expr).nameHashCode64(); - tableObject = findTable(tableName); + tableObject = findTable(tableNameHashCode64); if (tableObject != null) { exprTableSource.setSchemaObject(tableObject); } @@ -253,11 +256,12 @@ public class Schema { SQLExpr expr = exprTableSource.getExpr(); if (expr instanceof SQLIdentifierExpr) { + long tableNameHashCode64 = ((SQLIdentifierExpr) expr).nameHashCode64(); String tableName = ((SQLIdentifierExpr) expr).getName(); SchemaObject table = exprTableSource.getSchemaObject(); if (table == null) { - table = findTable(tableName); + table = findTable(tableNameHashCode64); if (table != null) { exprTableSource.setSchemaObject(table); @@ -294,8 +298,8 @@ public class Schema { return count; } - public Map getObjects() { - return this.objects; + public Collection getObjects() { + return this.objects.values(); } public int getViewCount() { @@ -315,6 +319,7 @@ public class Schema { tables.add(object.getName()); } } + Collections.sort(tables); return tables; } } 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 35eb2db978..ee80d02a70 100644 --- a/src/main/java/com/alibaba/druid/sql/repository/SchemaObject.java +++ b/src/main/java/com/alibaba/druid/sql/repository/SchemaObject.java @@ -35,6 +35,7 @@ public interface SchemaObject { SchemaObjectType getType(); String getName(); + long nameHashCode64(); long getRowCount(); } 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 8fb1f261fd..e15d0df001 100644 --- a/src/main/java/com/alibaba/druid/sql/repository/SchemaObjectImpl.java +++ b/src/main/java/com/alibaba/druid/sql/repository/SchemaObjectImpl.java @@ -27,6 +27,8 @@ import com.alibaba.druid.util.FnvHash; */ public class SchemaObjectImpl implements SchemaObject { private final String name; + private final long hashCode64; + private final SchemaObjectType type; private SQLStatement statement; @@ -40,6 +42,12 @@ public class SchemaObjectImpl implements SchemaObject { this.name = name; this.type = type; this.statement = statement; + + this.hashCode64 = FnvHash.hashCode64(name); + } + + public long nameHashCode64() { + return hashCode64; } public static enum Type { 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 522f120b19..cee9b4929c 100644 --- a/src/main/java/com/alibaba/druid/sql/repository/SchemaRepository.java +++ b/src/main/java/com/alibaba/druid/sql/repository/SchemaRepository.java @@ -20,23 +20,12 @@ import com.alibaba.druid.sql.SQLUtils; import com.alibaba.druid.sql.ast.*; import com.alibaba.druid.sql.ast.expr.SQLAllColumnExpr; import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; -import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr; 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; @@ -236,7 +225,7 @@ public class SchemaRepository { return getDefaultSchema().getTableCount(); } - public Map getObjects() { + public Collection getObjects() { return getDefaultSchema().getObjects(); } @@ -244,6 +233,15 @@ public class SchemaRepository { return getDefaultSchema().getViewCount(); } + public void resolve(SQLSelectStatement stmt, SchemaResolveVisitor.Option... options) { + if (stmt == null) { + return; + } + + SchemaResolveVisitor resolveVisitor = createResolveVisitor(options); + resolveVisitor.visit(stmt); + } + public void resolve(SQLStatement stmt, SchemaResolveVisitor.Option... options) { if (stmt == null) { return; @@ -312,7 +310,7 @@ public class SchemaRepository { SchemaObject schemaObject = null; if (schema != null) { table = showColumns.getTable(); - schemaObject = schema.findTable(table.getSimpleName()); + schemaObject = schema.findTable(table.nameHashCode64()); } if (schemaObject == null) { @@ -375,14 +373,14 @@ public class SchemaRepository { if (name instanceof SQLPropertyExpr) { SQLPropertyExpr propertyExpr = (SQLPropertyExpr) name; String schema = propertyExpr.getOwnernName(); - String table = propertyExpr.getName(); + long tableHashCode64 = propertyExpr.nameHashCode64(); Schema schemaObj = findSchema(schema); if (schemaObj == null) { return null; } - return schemaObj.findTable(table); + return schemaObj.findTable(tableHashCode64); } return null; @@ -401,19 +399,16 @@ public class SchemaRepository { return false; } - String tableName = name.getSimpleName(); - SchemaObject schemaObject = schema.findTable(tableName); + long nameHashCode64 = name.nameHashCode64(); + SchemaObject schemaObject = schema.findTable(nameHashCode64); if (schemaObject != null) { MySqlCreateTableStatement createTableStmt = (MySqlCreateTableStatement) schemaObject.getStatement(); if (createTableStmt != null) { createTableStmt.setName(to.clone()); } - String toName = SQLUtils.normalize(to.getSimpleName()).toLowerCase(); - schema.objects.put(toName, schemaObject); - - String name_lower = SQLUtils.normalize(tableName).toLowerCase(); - schema.objects.remove(name_lower); + schema.objects.put(to.hashCode64(), schemaObject); + schema.objects.remove(nameHashCode64); } return true; } @@ -679,8 +674,7 @@ public class SchemaRepository { } table = new SchemaObjectImpl(name, SchemaObjectType.Table, x1); - String name_lower = SQLUtils.normalize(name).toLowerCase(); - schema.objects.put(name_lower, table); + schema.objects.put(table.nameHashCode64(), table); return true; } @@ -691,9 +685,8 @@ public class SchemaRepository { if (schema == null) { continue; } - String name = table.getName().getSimpleName(); - String name_lower = SQLUtils.normalize(name).toLowerCase(); - schema.objects.remove(name_lower); + long nameHashCode64 = table.getName().nameHashCode64(); + schema.objects.remove(nameHashCode64); } return true; } @@ -710,8 +703,7 @@ public class SchemaRepository { } SchemaObject object = new SchemaObjectImpl(name, SchemaObjectType.View, x.clone()); - String name_lower = SQLUtils.normalize(name).toLowerCase(); - schema.objects.put(name_lower, object); + schema.objects.put(object.nameHashCode64(), object); return true; } @@ -737,8 +729,7 @@ public class SchemaRepository { String name = x.getName().getSimpleName(); SchemaObject object = new SchemaObjectImpl(name, SchemaObjectType.Index, x.clone()); - String name_lower = SQLUtils.normalize(name).toLowerCase(); - schema.objects.put(name_lower, object); + schema.objects.put(object.nameHashCode64(), object); return true; } @@ -749,8 +740,7 @@ public class SchemaRepository { String name = x.getName().getSimpleName(); SchemaObject object = new SchemaObjectImpl(name, SchemaObjectType.Function, x.clone()); - String name_lower = SQLUtils.normalize(name).toLowerCase(); - schema.functions.put(name_lower, object); + schema.functions.put(object.nameHashCode64(), object); return true; } @@ -759,7 +749,7 @@ public class SchemaRepository { String schemaName = x.getSchema(); Schema schema = findSchema(schemaName, true); - SchemaObject object = schema.findTable(x.getTableName()); + SchemaObject object = schema.findTable(x.nameHashCode64()); if (object != null) { SQLCreateTableStatement stmt = (SQLCreateTableStatement) object.getStatement(); if (stmt != null) { @@ -777,8 +767,7 @@ public class SchemaRepository { String name = x.getName().getSimpleName(); SchemaObject object = new SchemaObjectImpl(name, SchemaObjectType.Sequence); - String name_lower = SQLUtils.normalize(name).toLowerCase(); - schema.objects.put(name_lower, object); + schema.objects.put(object.nameHashCode64(), object); return false; } @@ -786,9 +775,8 @@ public class SchemaRepository { String schemaName = x.getSchema(); Schema schema = findSchema(schemaName, true); - String name = x.getName().getSimpleName(); - String name_lower = SQLUtils.normalize(name).toLowerCase(); - schema.objects.remove(name_lower); + long nameHashCode64 = x.getName().nameHashCode64(); + schema.objects.remove(nameHashCode64); return false; } } diff --git a/src/main/java/com/alibaba/druid/sql/repository/SchemaResolveVisitorFactory.java b/src/main/java/com/alibaba/druid/sql/repository/SchemaResolveVisitorFactory.java index 6f0d9c6e74..edef5ce137 100644 --- a/src/main/java/com/alibaba/druid/sql/repository/SchemaResolveVisitorFactory.java +++ b/src/main/java/com/alibaba/druid/sql/repository/SchemaResolveVisitorFactory.java @@ -54,6 +54,11 @@ class SchemaResolveVisitorFactory { this.options = options; } + public boolean visit(SQLSelectStatement x) { + resolve(this, x.getSelect()); + return false; + } + public boolean visit(MySqlRepeatStatement x) { return true; } @@ -246,6 +251,11 @@ class SchemaResolveVisitorFactory { this.options = options; } + public boolean visit(SQLSelectStatement x) { + resolve(this, x.getSelect()); + return false; + } + public boolean visit(SQLExprTableSource x) { resolve(this, x); return false; @@ -393,6 +403,11 @@ class SchemaResolveVisitorFactory { this.options = options; } + public boolean visit(SQLSelectStatement x) { + resolve(this, x.getSelect()); + return false; + } + public boolean visit(OracleCreatePackageStatement x) { Context ctx = createContext(x); @@ -650,6 +665,11 @@ class SchemaResolveVisitorFactory { this.options = options; } + public boolean visit(SQLSelectStatement x) { + resolve(this, x.getSelect()); + return false; + } + public boolean visit(SQLExprTableSource x) { resolve(this, x); return false; @@ -823,6 +843,11 @@ class SchemaResolveVisitorFactory { this.options = options; } + public boolean visit(SQLSelectStatement x) { + resolve(this, x.getSelect()); + return false; + } + public boolean visit(SQLExprTableSource x) { resolve(this, x); return false; @@ -1007,6 +1032,11 @@ class SchemaResolveVisitorFactory { this.options = options; } + public boolean visit(SQLSelectStatement x) { + resolve(this, x.getSelect()); + return false; + } + public boolean visit(SQLExprTableSource x) { resolve(this, x); return false; @@ -1163,6 +1193,11 @@ class SchemaResolveVisitorFactory { this.options = options; } + public boolean visit(SQLSelectStatement x) { + resolve(this, x.getSelect()); + return false; + } + public boolean visit(SQLExprTableSource x) { resolve(this, x); return false; @@ -1837,7 +1872,24 @@ class SchemaResolveVisitorFactory { SQLExpr where = x.getWhere(); if (where != null) { - where.accept(visitor); + if (where instanceof SQLBinaryOpExpr) { + SQLBinaryOpExpr binaryOpExpr = (SQLBinaryOpExpr) where; + resolveExpr(visitor, binaryOpExpr.getLeft()); + resolveExpr(visitor, binaryOpExpr.getRight()); + } else if (where instanceof SQLBinaryOpExprGroup) { + SQLBinaryOpExprGroup binaryOpExprGroup = (SQLBinaryOpExprGroup) where; + for (SQLExpr item : binaryOpExprGroup.getItems()) { + if (item instanceof SQLBinaryOpExpr) { + SQLBinaryOpExpr binaryOpExpr = (SQLBinaryOpExpr) item; + resolveExpr(visitor, binaryOpExpr.getLeft()); + resolveExpr(visitor, binaryOpExpr.getRight()); + } else { + item.accept(visitor); + } + } + } else { + where.accept(visitor); + } } SQLExpr startWith = x.getStartWith(); @@ -2351,4 +2403,22 @@ class SchemaResolveVisitorFactory { } return false; } + + // for performance + static void resolveExpr(SchemaResolveVisitor visitor, SQLExpr x) { + if (x == null) { + return; + } + + Class clazz = x.getClass(); + if (clazz == SQLIdentifierExpr.class) { + visitor.visit((SQLIdentifierExpr) x); + return; + } else if (clazz == SQLIntegerExpr.class || clazz == SQLCharExpr.class) { + // skip + return; + } + + x.accept(visitor); + } } diff --git a/src/main/java/com/alibaba/druid/sql/visitor/SQLEvalVisitorUtils.java b/src/main/java/com/alibaba/druid/sql/visitor/SQLEvalVisitorUtils.java index ff68d8d9dc..167379d49e 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLEvalVisitorUtils.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLEvalVisitorUtils.java @@ -36,22 +36,7 @@ import com.alibaba.druid.DruidRuntimeException; import com.alibaba.druid.sql.SQLUtils; import com.alibaba.druid.sql.ast.SQLExpr; import com.alibaba.druid.sql.ast.SQLObject; -import com.alibaba.druid.sql.ast.expr.SQLBetweenExpr; -import com.alibaba.druid.sql.ast.expr.SQLBinaryExpr; -import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr; -import com.alibaba.druid.sql.ast.expr.SQLBinaryOperator; -import com.alibaba.druid.sql.ast.expr.SQLCaseExpr; -import com.alibaba.druid.sql.ast.expr.SQLCharExpr; -import com.alibaba.druid.sql.ast.expr.SQLHexExpr; -import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; -import com.alibaba.druid.sql.ast.expr.SQLInListExpr; -import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr; -import com.alibaba.druid.sql.ast.expr.SQLNullExpr; -import com.alibaba.druid.sql.ast.expr.SQLNumericLiteralExpr; -import com.alibaba.druid.sql.ast.expr.SQLQueryExpr; -import com.alibaba.druid.sql.ast.expr.SQLUnaryExpr; -import com.alibaba.druid.sql.ast.expr.SQLUnaryOperator; -import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr; +import com.alibaba.druid.sql.ast.expr.*; import com.alibaba.druid.sql.ast.statement.SQLExprTableSource; import com.alibaba.druid.sql.ast.statement.SQLSelect; import com.alibaba.druid.sql.ast.statement.SQLSelectItem; @@ -139,12 +124,19 @@ public class SQLEvalVisitorUtils { public static Object eval(String dbType, SQLObject sqlObject, List parameters, boolean throwError) { SQLEvalVisitor visitor = createEvalVisitor(dbType); visitor.setParameters(parameters); - sqlObject.accept(visitor); - Object value = getValue(sqlObject); - if (value == null) { - if (throwError && !sqlObject.getAttributes().containsKey(EVAL_VALUE)) { - throw new DruidRuntimeException("eval error : " + SQLUtils.toSQLString(sqlObject, dbType)); + Object value; + if (sqlObject instanceof SQLValuableExpr) { + value = ((SQLValuableExpr) sqlObject).getValue(); + } else { + sqlObject.accept(visitor); + + value = getValue(sqlObject); + + if (value == null) { + if (throwError && !sqlObject.getAttributes().containsKey(EVAL_VALUE)) { + throw new DruidRuntimeException("eval error : " + SQLUtils.toSQLString(sqlObject, dbType)); + } } } 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 ebf9ab404d..9a379aff9b 100644 --- a/src/test/java/com/alibaba/druid/benckmark/sql/MySqlParameterizedBenchmark.java +++ b/src/test/java/com/alibaba/druid/benckmark/sql/MySqlParameterizedBenchmark.java @@ -38,7 +38,7 @@ public class MySqlParameterizedBenchmark extends TestCase { // perf_parse(sql3); // 9174 5875 5805 5536 5717 // perf_parse(sql4); // 2953 2502 - perf_stat(sql); // 11793 13628 13561 13259 9946 7637 7444 7389 + perf_stat(sql); // 11793 13628 13561 13259 9946 7637 7444 7389 7326 // perf_resolve(sql); // 4970 4586 3600 } diff --git a/src/test/java/com/alibaba/druid/bvt/sql/oracle/select/OracleSelectTest79.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/select/OracleSelectTest79.java new file mode 100644 index 0000000000..5ad04fb04a --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/select/OracleSelectTest79.java @@ -0,0 +1,68 @@ +/* + * Copyright 1999-2017 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.druid.bvt.sql.oracle.select; + +import com.alibaba.druid.sql.OracleTest; +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.oracle.parser.OracleStatementParser; +import com.alibaba.druid.sql.dialect.oracle.visitor.OracleSchemaStatVisitor; +import org.junit.Assert; + +import java.util.List; + +public class OracleSelectTest79 extends OracleTest { + + public void test_0() throws Exception { + String sql = // + "SELECT * FROM `tasks` where projectId=?"; // + + OracleStatementParser parser = new OracleStatementParser(sql); + List statementList = parser.parseStatementList(); + SQLStatement stmt = statementList.get(0); + print(statementList); + + Assert.assertEquals(1, statementList.size()); + + OracleSchemaStatVisitor visitor = new OracleSchemaStatVisitor(); + stmt.accept(visitor); + + { + String text = SQLUtils.toOracleString(stmt); + + assertEquals("SELECT *\n" + + "FROM `tasks`\n" + + "WHERE projectId = ?", text); + } + + System.out.println("Tables : " + visitor.getTables()); + System.out.println("fields : " + visitor.getColumns()); + System.out.println("coditions : " + visitor.getConditions()); + System.out.println("relationships : " + visitor.getRelationships()); + System.out.println("orderBy : " + visitor.getOrderByColumns()); + + assertEquals(1, visitor.getTables().size()); + assertEquals(2, visitor.getColumns().size()); + assertEquals(1, visitor.getConditions().size()); + assertEquals(0, visitor.getRelationships().size()); + assertEquals(0, visitor.getOrderByColumns().size()); + + + // Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("acduser.vw_acd_info", "xzqh"))); + + // Assert.assertTrue(visitor.getOrderByColumns().contains(new TableStat.Column("employees", "last_name"))); + } +}