mirror of
https://github.com/alibaba/druid.git
synced 2023-03-04 19:17:16 +00:00
improved sql parser.
This commit is contained in:
@@ -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() {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
+8
@@ -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;
|
||||
}
|
||||
|
||||
+33
-13
@@ -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<SQLSelectOrderByItem> notContainsOrderBy = new ArrayList<SQLSelectOrderByItem>();
|
||||
for (SQLSelectOrderByItem orderByItem : orderBy.getItems()) {
|
||||
SQLExpr orderByExpr = orderByItem.getExpr();
|
||||
if (queryBlock.selectIndexOf(orderByExpr) == -1) {
|
||||
notContainsOrderBy.add(orderByItem);
|
||||
|
||||
if (!queryBlock.selectItemHasAllColumn(false)) {
|
||||
List<SQLSelectOrderByItem> notContainsOrderBy = new ArrayList<SQLSelectOrderByItem>();
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user