improved sql parser. for issue #2079

This commit is contained in:
wenshao
2017-11-01 16:54:22 +08:00
parent 616ec0d431
commit 434bfe7140
11 changed files with 339 additions and 21 deletions
@@ -21,12 +21,16 @@ import com.alibaba.druid.sql.dialect.db2.ast.DB2Statement;
import com.alibaba.druid.sql.dialect.db2.visitor.DB2ASTVisitor;
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
import java.util.ArrayList;
import java.util.List;
public class DB2CreateTableStatement extends SQLCreateTableStatement implements DB2Statement {
private boolean dataCaptureNone;
private boolean dataCaptureChanges;
protected SQLName database;
protected SQLName validproc;
protected SQLName indexIn;
public boolean isDataCaptureNone() {
return dataCaptureNone;
@@ -59,11 +63,22 @@ public class DB2CreateTableStatement extends SQLCreateTableStatement implements
return validproc;
}
public void setValidproc(SQLName validproc) {
public void setValidproc(SQLName x) {
if (validproc != null) {
validproc.setParent(this);
x.setParent(this);
}
this.validproc = validproc;
this.validproc = x;
}
public SQLName getIndexIn() {
return indexIn;
}
public void setIndexIn(SQLName x) {
if (validproc != null) {
x.setParent(this);
}
this.indexIn = x;
}
@Override
@@ -85,6 +100,7 @@ public class DB2CreateTableStatement extends SQLCreateTableStatement implements
this.acceptChild(visitor, select);
this.acceptChild(visitor, database);
this.acceptChild(visitor, validproc);
this.acceptChild(visitor, indexIn);
}
visitor.endVisit(this);
}
@@ -179,6 +179,12 @@ public class DB2CreateTableParser extends SQLCreateTableParser {
lexer.nextToken();
}
continue;
} else if (lexer.token() == Token.INDEX) {
lexer.nextToken();
accept(Token.IN);
SQLName indexIn = this.exprParser.name();
createTable.setIndexIn(indexIn);
continue;
}
break;
}
@@ -101,6 +101,13 @@ public class DB2OutputVisitor extends SQLASTOutputVisitor implements DB2ASTVisit
tablespace.accept(this);
}
SQLName indexIn = x.getIndexIn();
if (indexIn != null) {
println();
print("INDEX IN ");
indexIn.accept(this);
}
SQLName database = x.getDatabase();
if (database != null) {
println();
@@ -89,7 +89,7 @@ public class SQLExprParser extends SQLParser {
if (token == Token.COMMA) {
return expr;
} else if (token == Token.EQ) {
expr = equalityRest(expr);
expr = equalityRest2(expr);
expr = andRest(expr);
expr = orRest(expr);
return expr;
@@ -1668,6 +1668,53 @@ public class SQLExprParser extends SQLParser {
return equalityRest(expr);
}
private SQLExpr equalityRest2(SQLExpr expr) {
SQLExpr rightExp;
lexer.nextToken();
try {
if (lexer.token == Token.LITERAL_INT) {
rightExp = new SQLIntegerExpr(lexer.integerValue());
lexer.nextToken();
if (lexer.token == Token.AND
|| lexer.token == Token.RPAREN
|| lexer.token == Token.EOF
|| lexer.token == Token.OR) {
return new SQLBinaryOpExpr(expr, SQLBinaryOperator.Equality, rightExp, dbType);
}
rightExp = primaryRest(rightExp);
rightExp = bitXorRest(rightExp);
rightExp = multiplicativeRest(rightExp);
rightExp = additiveRest(rightExp);
rightExp = shiftRest(rightExp);
rightExp = bitAndRest(rightExp);
rightExp = bitOrRest(rightExp);
rightExp = inRest(rightExp);
rightExp = relationalRest(rightExp);
} else {
rightExp = bitOr();
}
} catch (EOFParserException e) {
throw new ParserException("EOF, " + expr + "=", e);
}
if (lexer.token == Token.COLONEQ) {
lexer.nextToken();
SQLExpr colonExpr = expr();
rightExp = new SQLBinaryOpExpr(rightExp, SQLBinaryOperator.Assignment, colonExpr, dbType);
}
expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Equality, rightExp, dbType);
if (lexer.token == Token.IS || lexer.token == Token.BETWEEN) {
expr = relationalRest(expr);
}
return expr;
}
public SQLExpr equalityRest(SQLExpr expr) {
SQLExpr rightExp;
@@ -1728,7 +1775,18 @@ public class SQLExprParser extends SQLParser {
}
for (;;) {
SQLExpr item = this.expr();
SQLExpr item;
if (lexer.token == Token.LITERAL_INT) {
item = new SQLIntegerExpr(lexer.integerValue());
lexer.nextToken();
if (lexer.token != Token.COMMA && lexer.token != Token.RPAREN) {
item = this.primaryRest(item);
item = this.exprRest(item);
}
} else {
item = this.expr();
}
item.setParent(inListExpr);
targetList.add(item);
if (lexer.token == Token.COMMA) {
@@ -3049,15 +3107,39 @@ public class SQLExprParser extends SQLParser {
public SQLLimit parseLimit() {
if (lexer.token == Token.LIMIT) {
lexer.nextToken();
lexer.nextTokenValue();
SQLLimit limit = new SQLLimit();
SQLExpr temp = this.expr();
SQLExpr temp;
if (lexer.token == Token.LITERAL_INT) {
temp = new SQLIntegerExpr(lexer.integerValue());
lexer.nextTokenComma();
if (lexer.token != Token.COMMA && lexer.token != Token.EOF && lexer.token != Token.IDENTIFIER) {
temp = this.primaryRest(temp);
temp = this.exprRest(temp);
}
} else {
temp = this.expr();
}
if (lexer.token == (Token.COMMA)) {
limit.setOffset(temp);
lexer.nextToken();
limit.setRowCount(this.expr());
lexer.nextTokenValue();
SQLExpr rowCount;
if (lexer.token == Token.LITERAL_INT) {
rowCount = new SQLIntegerExpr(lexer.integerValue());
lexer.nextToken();
if (lexer.token != Token.EOF && lexer.token != Token.IDENTIFIER) {
rowCount = this.primaryRest(rowCount);
rowCount = this.exprRest(rowCount);
}
} else {
rowCount = this.expr();
}
limit.setRowCount(rowCount);
} else if (lexer.identifierEquals(FnvHash.Constants.OFFSET)) {
limit.setRowCount(temp);
lexer.nextToken();
@@ -585,7 +585,7 @@ public class SQLSelectParser extends SQLParser {
}
protected SQLTableSource parseTableSourceRest(SQLTableSource tableSource) {
if ((tableSource.getAlias() == null) || (tableSource.getAlias().length() == 0)) {
if (tableSource.getAlias() == null || tableSource.getAlias().length() == 0) {
Token token = lexer.token;
long hash;
if (token != Token.LEFT
@@ -599,6 +599,11 @@ public class SQLSelectParser extends SQLParser {
String alias = tableAlias();
if (alias != null) {
tableSource.setAlias(alias);
if (lexer.token == Token.WHERE) {
return tableSource;
}
return parseTableSourceRest(tableSource);
}
}
@@ -3164,6 +3164,10 @@ public class SQLStatementParser extends SQLParser {
expr = new SQLIntegerExpr(lexer.integerValue());
}
lexer.nextTokenComma();
if (lexer.token != Token.COMMA && lexer.token != Token.RPAREN) {
expr = this.exprParser.exprRest(expr);
}
} else if (lexer.token() == Token.LITERAL_CHARS) {
if (optimizedForParameterized) {
expr = new SQLVariantRefExpr("?");
@@ -3172,6 +3176,9 @@ public class SQLStatementParser extends SQLParser {
expr = new SQLCharExpr(lexer.stringVal());
}
lexer.nextTokenComma();
if (lexer.token != Token.COMMA && lexer.token != Token.RPAREN) {
expr = this.exprParser.exprRest(expr);
}
} else if (lexer.token() == Token.LITERAL_NCHARS) {
if (optimizedForParameterized) {
expr = new SQLVariantRefExpr("?");
@@ -3180,6 +3187,20 @@ public class SQLStatementParser extends SQLParser {
expr = new SQLNCharExpr(lexer.stringVal());
}
lexer.nextTokenComma();
if (lexer.token != Token.COMMA && lexer.token != Token.RPAREN) {
expr = this.exprParser.exprRest(expr);
}
} else if (lexer.token == Token.NULL) {
if (optimizedForParameterized) {
expr = new SQLVariantRefExpr("?");
values.incrementReplaceCount();
} else {
expr = new SQLNullExpr();
}
lexer.nextTokenComma();
if (lexer.token != Token.COMMA && lexer.token != Token.RPAREN) {
expr = this.exprParser.exprRest(expr);
}
} else {
expr = exprParser.expr();
}
@@ -15,6 +15,8 @@
*/
package com.alibaba.druid.sql.parser;
import com.alibaba.druid.util.Utils;
import java.nio.charset.Charset;
/**
@@ -22,8 +24,19 @@ import java.nio.charset.Charset;
*/
public class SymbolTable {
private static final Charset UTF8 = Charset.forName("UTF-8");
private static final boolean JVM_16;
public static SymbolTable global = new SymbolTable(8192);
static {
String version = null;
try {
version = System.getProperty("java.specification.version");
} catch (Throwable error) {
// skip
}
JVM_16 = "1.6".equals(version);
}
public static SymbolTable global = new SymbolTable(32768);
private final Entry[] entries;
private final int indexMask;
@@ -42,12 +55,16 @@ public class SymbolTable {
return entry.value;
}
String str = subString(buffer, offset, len);
String str = JVM_16
? subString(buffer, offset, len)
: buffer.substring(offset, offset + len);
return str;
}
String str = subString(buffer, offset, len);
String str = JVM_16
? subString(buffer, offset, len)
: buffer.substring(offset, offset + len);
entry = new Entry(hash, len, str);
entries[bucket] = entry;
return str;
@@ -66,7 +66,8 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet
protected List<Object> parameters;
protected List<Object> inputParameters;
protected Set<String> tables;
protected Set<String> tables;
protected String table; // for improved
protected boolean exportTables = false;
@@ -149,6 +150,9 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet
}
public Set<String> getTables() {
if (this.table != null && this.tables == null) {
return Collections.singleton(this.table);
}
return this.tables;
}
@@ -1586,7 +1590,9 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet
} else {
if (owner instanceof SQLIdentifierExpr) {
SQLIdentifierExpr ownerIdent = (SQLIdentifierExpr) owner;
printName(ownerIdent, ownerIdent.getName());
printName(ownerIdent
, ownerIdent.getName()
, this.shardingSupport && this.parameterized);
} else {
printExpr(owner);
}
@@ -1944,7 +1950,13 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet
protected void addTable(String table) {
if (tables == null) {
tables = new LinkedHashSet<String>();
if (this.table == null) {
this.table = table;
return;
} else {
tables = new LinkedHashSet<String>();
tables.add(this.table);
}
}
this.tables.add(table);
}
@@ -2842,6 +2854,25 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet
print0(ucase ? joinType.name : joinType.name_lcase);
}
static String[] variantValuesCache = new String[64];
static {
for (int len = 0; len < variantValuesCache.length; ++len) {
StringBuffer buf = new StringBuffer();
buf.append('(');
for (int i = 0; i < len; ++i) {
if (i != 0) {
if (i % 5 == 0) {
buf.append("\n\t\t");
}
buf.append(", ");
}
buf.append('?');
}
buf.append(')');
variantValuesCache[len] = buf.toString();
}
}
@Override
public boolean visit(ValuesClause x) {
if ((!this.parameterized)
@@ -2851,12 +2882,21 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet
return false;
}
int xReplaceCount = x.getReplaceCount();
final List<SQLExpr> values = x.getValues();
this.replaceCount += xReplaceCount;
if (xReplaceCount == values.size() && xReplaceCount < variantValuesCache.length) {
String variantValues = variantValuesCache[xReplaceCount];
print0(variantValues);
return false;
}
print('(');
this.indentCount++;
this.replaceCount += x.getReplaceCount();
final List<SQLExpr> values = x.getValues();
for (int i = 0, size = values.size(); i < size; ++i) {
if (i != 0) {
if (i % 5 == 0) {