From ce2daf6b9a8499b2a66bf8b4dcc73f83ed98d54a Mon Sep 17 00:00:00 2001 From: wenshao Date: Wed, 30 Aug 2017 21:38:31 +0800 Subject: [PATCH] improved sql parser. --- .../druid/sql/ast/expr/SQLIdentifierExpr.java | 10 +--- .../druid/sql/ast/expr/SQLPropertyExpr.java | 59 ++++++++++++------- .../ast/statement/SQLSelectQueryBlock.java | 34 ++--------- .../clause/MySqlCursorDeclareStatement.java | 8 +++ .../visitor/transform/OrderByResolve.java | 46 +++++++++++---- 5 files changed, 86 insertions(+), 71 deletions(-) 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 a0c8816a41..af6ab6e56c 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 @@ -23,7 +23,6 @@ import com.alibaba.druid.util.FnvHash; public class SQLIdentifierExpr extends SQLExprImpl implements SQLName { protected String name; - private String lowerName; private long hashCode64; private SQLObject resolvedColumn; @@ -52,15 +51,12 @@ public class SQLIdentifierExpr extends SQLExprImpl implements SQLName { public void setName(String name) { this.name = name; - this.lowerName = null; this.hashCode64 = 0L; - } - public String getLowerName() { - if (lowerName == null && name != null) { - lowerName = name.toLowerCase(); + if (parent instanceof SQLPropertyExpr) { + SQLPropertyExpr propertyExpr = (SQLPropertyExpr) parent; + propertyExpr.computeHashCode64(); } - return lowerName; } public long nameHashCode64() { 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 6a6ac7b228..4207ffe7bf 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 @@ -22,14 +22,14 @@ import com.alibaba.druid.sql.visitor.SQLASTVisitor; import com.alibaba.druid.util.FnvHash; public class SQLPropertyExpr extends SQLExprImpl implements SQLName { - private SQLExpr owner; - private String name; + private SQLExpr owner; + private String name; - private transient long nameHashCod64; - private transient long hashCode64; + protected long nameHashCod64; + protected long hashCode64; - private transient SQLColumnDefinition resolvedColumn; - private transient SQLObject resolvedOwnerObject; + protected SQLColumnDefinition resolvedColumn; + protected SQLObject resolvedOwnerObject; public SQLPropertyExpr(String owner, String name){ this(new SQLIdentifierExpr(owner), name); @@ -70,10 +70,35 @@ public class SQLPropertyExpr extends SQLExprImpl implements SQLName { if (owner != null) { owner.setParent(this); } + + if (parent instanceof SQLPropertyExpr) { + SQLPropertyExpr propertyExpr = (SQLPropertyExpr) parent; + propertyExpr.computeHashCode64(); + } + this.owner = owner; this.hashCode64 = 0; } + protected void computeHashCode64() { + long hash; + if (owner instanceof SQLName) { + hash = ((SQLName) owner).hashCode64(); + + hash ^= '.'; + hash *= FnvHash.PRIME; + } else if (owner == null){ + hash = FnvHash.BASIC; + } else { + hash = FnvHash.fnv1a_64_lower(owner.toString()); + + hash ^= '.'; + hash *= FnvHash.PRIME; + } + hash = FnvHash.hashCode64(hash, name); + hashCode64 = hash; + } + public void setOwner(String owner) { this.setOwner(new SQLIdentifierExpr(owner)); } @@ -86,6 +111,11 @@ public class SQLPropertyExpr extends SQLExprImpl implements SQLName { this.name = name; this.hashCode64 = 0; this.nameHashCod64 = 0; + + if (parent instanceof SQLPropertyExpr) { + SQLPropertyExpr propertyExpr = (SQLPropertyExpr) parent; + propertyExpr.computeHashCode64(); + } } public void output(StringBuffer buf) { @@ -110,22 +140,7 @@ public class SQLPropertyExpr extends SQLExprImpl implements SQLName { public long hashCode64() { if (hashCode64 == 0) { - long hash; - if (owner instanceof SQLName) { - hash = ((SQLName) owner).hashCode64(); - - hash ^= '.'; - hash *= FnvHash.PRIME; - } else if (owner == null){ - hash = FnvHash.BASIC; - } else { - hash = FnvHash.fnv1a_64_lower(owner.toString()); - - hash ^= '.'; - hash *= FnvHash.PRIME; - } - hash = FnvHash.hashCode64(hash, name); - hashCode64 = hash; + computeHashCode64(); } return hashCode64; 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 c80de2de4d..b03f518d69 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 @@ -512,6 +512,10 @@ public class SQLSelectQueryBlock extends SQLObjectImpl implements SQLSelectQuery } public boolean selectItemHasAllColumn() { + return selectItemHasAllColumn(true); + } + + public boolean selectItemHasAllColumn(boolean recursive) { for (SQLSelectItem item : this.selectList) { SQLExpr expr = item.getExpr(); @@ -519,7 +523,7 @@ public class SQLSelectQueryBlock extends SQLObjectImpl implements SQLSelectQuery || (expr instanceof SQLPropertyExpr && ((SQLPropertyExpr) expr).getName().equals("*")); if (allColumn) { - if (from instanceof SQLSubqueryTableSource) { + if (recursive && from instanceof SQLSubqueryTableSource) { SQLSelect subSelect = ((SQLSubqueryTableSource) from).select; SQLSelectQueryBlock queryBlock = subSelect.getQueryBlock(); if (queryBlock != null) { @@ -576,32 +580,4 @@ public class SQLSelectQueryBlock extends SQLObjectImpl implements SQLSelectQuery setLimit(limit); } - - public int selectIndexOf(SQLExpr expr) { - String ident = null; - if (expr instanceof SQLIdentifierExpr) { - ident = ((SQLIdentifierExpr) expr).getName(); - } - - for (int i = 0; i < selectList.size(); i++) { - SQLSelectItem selectItem = selectList.get(i); - if (ident != null && SQLUtils.nameEquals(ident, selectItem.alias)) { - return i; - } - - SQLExpr selectItemExpr = selectItem.getExpr(); - if (selectItemExpr instanceof SQLName) { - String name = ((SQLName) selectItemExpr).getSimpleName(); - if (SQLUtils.nameEquals(ident, name)) { - return i; - } - } - - if (expr.equals(selectItemExpr)) { - return i; - } - } - - return -1; - } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/clause/MySqlCursorDeclareStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/clause/MySqlCursorDeclareStatement.java index d9357d475b..e5b7ec0a1b 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/clause/MySqlCursorDeclareStatement.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/clause/MySqlCursorDeclareStatement.java @@ -16,6 +16,7 @@ package com.alibaba.druid.sql.dialect.mysql.ast.clause; import com.alibaba.druid.sql.ast.SQLName; +import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; import com.alibaba.druid.sql.ast.statement.SQLSelect; import com.alibaba.druid.sql.ast.statement.SQLSelectStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlStatementImpl; @@ -36,9 +37,16 @@ public class MySqlCursorDeclareStatement extends MySqlStatementImpl{ } public void setCursorName(SQLName cursorName) { + if (cursorName != null) { + cursorName.setParent(this); + } this.cursorName = cursorName; } + public void setCursorName(String cursorName) { + this.setCursorName(new SQLIdentifierExpr(cursorName)); + } + public SQLSelect getSelect() { return select; } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/transform/OrderByResolve.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/transform/OrderByResolve.java index e7f8c408c4..b30b451f77 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/transform/OrderByResolve.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/transform/OrderByResolve.java @@ -16,12 +16,15 @@ package com.alibaba.druid.sql.dialect.mysql.visitor.transform; import com.alibaba.druid.sql.ast.SQLExpr; +import com.alibaba.druid.sql.ast.SQLName; import com.alibaba.druid.sql.ast.SQLOrderBy; import com.alibaba.druid.sql.ast.statement.SQLSelect; +import com.alibaba.druid.sql.ast.statement.SQLSelectItem; import com.alibaba.druid.sql.ast.statement.SQLSelectOrderByItem; import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectQueryBlock; import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitorAdapter; +import com.alibaba.druid.util.FnvHash; import java.util.ArrayList; import java.util.List; @@ -30,6 +33,8 @@ import java.util.List; * Created by wenshao on 27/07/2017. */ public class OrderByResolve extends OracleASTVisitorAdapter { + final static long DBMS_RANDOM_VALUE = FnvHash.hashCode64("DBMS_RANDOM.value"); + public boolean visit(SQLSelect x) { SQLSelectQueryBlock queryBlock = x.getQueryBlock(); if (queryBlock == null) { @@ -46,23 +51,38 @@ public class OrderByResolve extends OracleASTVisitorAdapter { return super.visit(x); } - List notContainsOrderBy = new ArrayList(); - for (SQLSelectOrderByItem orderByItem : orderBy.getItems()) { - SQLExpr orderByExpr = orderByItem.getExpr(); - if (queryBlock.selectIndexOf(orderByExpr) == -1) { - notContainsOrderBy.add(orderByItem); + + if (!queryBlock.selectItemHasAllColumn(false)) { + List notContainsOrderBy = new ArrayList(); + + for (SQLSelectOrderByItem orderByItem : orderBy.getItems()) { + SQLExpr orderByExpr = orderByItem.getExpr(); + + if (orderByExpr instanceof SQLName) { + if (((SQLName) orderByExpr).hashCode64() == DBMS_RANDOM_VALUE) { + continue; + } + + long hashCode64 = ((SQLName) orderByExpr).nameHashCode64(); + SQLSelectItem selectItem = queryBlock.findSelectItem(hashCode64); + if (selectItem == null) { + queryBlock.addSelectItem(orderByExpr.clone()); + } + } + } + + if (notContainsOrderBy.size() > 0) { + for (SQLSelectOrderByItem orderByItem : notContainsOrderBy) { + queryBlock.addSelectItem(orderByItem.getExpr()); + } + + OracleSelectQueryBlock queryBlock1 = new OracleSelectQueryBlock(); + queryBlock1.setFrom(queryBlock, "x"); + x.setQuery(queryBlock1); } } - if (notContainsOrderBy.size() > 0) { - for (SQLSelectOrderByItem orderByItem : notContainsOrderBy) { - queryBlock.addSelectItem(orderByItem.getExpr()); - } - OracleSelectQueryBlock queryBlock1 = new OracleSelectQueryBlock(); - queryBlock1.setFrom(queryBlock, "x"); - x.setQuery(queryBlock1); - } return super.visit(x); }