improved sql parser.

This commit is contained in:
wenshao
2017-09-13 20:56:20 +08:00
parent c49078c650
commit f208f42e01
33 changed files with 853 additions and 29 deletions
@@ -214,9 +214,8 @@ public class Lexer {
this.skipComment = skipComment;
this.text = input;
this.pos = -1;
scanChar();
this.pos = 0;
ch = charAt(pos);
}
public Lexer(char[] input, int inputLength, boolean skipComment){
@@ -419,6 +418,12 @@ public class Lexer {
}
}
if (ch == ')') {
scanChar();
token = Token.RPAREN;
return;
}
if (isFirstIdentifierChar(ch)) {
scanIdentifier();
return;
@@ -487,6 +492,25 @@ public class Lexer {
nextToken();
}
public final void nextTokenIdent() {
while (ch == ' ') {
scanChar();
}
if (isFirstIdentifierChar(ch)) {
scanIdentifier();
return;
}
if (ch == ')') {
scanChar();
token = RPAREN;
return;
}
nextToken();
}
public final void nextToken() {
startPos = pos;
bufPos = 0;
@@ -362,6 +362,9 @@ public class SQLExprParser extends SQLParser {
}
SQLVariantRefExpr varRefExpr = new SQLVariantRefExpr(varName);
if (varName.startsWith(":")) {
varRefExpr.setIndex(lexer.nextVarIndex());
}
if (varRefExpr.getName().equals("@") && lexer.token == Token.LITERAL_CHARS) {
varRefExpr.setName("@'" + lexer.stringVal() + "'");
lexer.nextToken();
@@ -1575,11 +1578,12 @@ public class SQLExprParser extends SQLParser {
public final SQLExpr inRest(SQLExpr expr) {
if (lexer.token == Token.IN) {
lexer.nextToken();
lexer.nextTokenLParen();
SQLInListExpr inListExpr = new SQLInListExpr(expr);
List<SQLExpr> targetList = inListExpr.getTargetList();
if (lexer.token == Token.LPAREN) {
lexer.nextToken();
lexer.nextTokenValue();
if (lexer.token == Token.WITH) {
SQLSelect select = this.createSelectParser().select();
@@ -1589,7 +1593,6 @@ public class SQLExprParser extends SQLParser {
return queryExpr;
}
List<SQLExpr> targetList = inListExpr.getTargetList();
for (;;) {
SQLExpr item = this.expr();
item.setParent(inListExpr);
@@ -1605,13 +1608,13 @@ public class SQLExprParser extends SQLParser {
} else {
SQLExpr itemExpr = primary();
itemExpr.setParent(inListExpr);
inListExpr.getTargetList().add(itemExpr);
targetList.add(itemExpr);
}
expr = inListExpr;
if (inListExpr.getTargetList().size() == 1) {
SQLExpr targetExpr = inListExpr.getTargetList().get(0);
if (targetList.size() == 1) {
SQLExpr targetExpr = targetList.get(0);
if (targetExpr instanceof SQLQueryExpr) {
SQLInSubQueryExpr inSubQueryExpr = new SQLInSubQueryExpr();
inSubQueryExpr.setExpr(inListExpr.getExpr());
@@ -2629,7 +2632,7 @@ public class SQLExprParser extends SQLParser {
token = lexer.token;
if (token == Token.DOT) {
lexer.nextToken();
lexer.nextTokenIdent();
String name;
long name_hash_lower;
@@ -21,6 +21,7 @@ import com.alibaba.druid.sql.dialect.db2.parser.DB2ExprParser;
import com.alibaba.druid.sql.dialect.db2.parser.DB2Lexer;
import com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser;
import com.alibaba.druid.sql.dialect.h2.parser.H2StatementParser;
import com.alibaba.druid.sql.dialect.hive.parser.HiveStatementParser;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock;
import com.alibaba.druid.sql.dialect.mysql.parser.MySqlExprParser;
import com.alibaba.druid.sql.dialect.mysql.parser.MySqlLexer;
@@ -105,6 +106,14 @@ public class SQLParserUtils {
return new PhoenixStatementParser(sql);
}
if (JdbcUtils.HIVE.equals(dbType)) {
return new HiveStatementParser(sql);
}
if (JdbcUtils.ELASTIC_SEARCH.equals(dbType)) {
return new MySqlStatementParser(sql);
}
return new SQLStatementParser(sql, dbType);
}
@@ -18,8 +18,7 @@ package com.alibaba.druid.sql.parser;
import java.util.List;
import com.alibaba.druid.sql.ast.*;
import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr;
import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr;
import com.alibaba.druid.sql.ast.expr.*;
import com.alibaba.druid.sql.ast.statement.*;
import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlOrderingExpr;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock;
@@ -318,13 +317,47 @@ public class SQLSelectParser extends SQLParser {
public void parseWhere(SQLSelectQueryBlock queryBlock) {
if (lexer.token == Token.WHERE) {
lexer.nextToken();
lexer.nextTokenIdent();
List<String> beforeComments = null;
if (lexer.hasComment() && lexer.isKeepComments()) {
beforeComments = lexer.readAndResetComments();
}
SQLExpr where = expr();
SQLExpr where;
if (lexer.token == Token.IDENTIFIER) {
String ident = lexer.stringVal();
long hash_lower = lexer.hash_lower();
lexer.nextTokenEq();
SQLExpr identExpr = new SQLIdentifierExpr(ident, hash_lower);
if (lexer.token == Token.DOT) {
identExpr = this.exprParser.primaryRest(identExpr);
}
if (lexer.token == Token.EQ) {
SQLExpr rightExp;
lexer.nextToken();
try {
rightExp = this.exprParser.bitOr();
} catch (EOFParserException e) {
throw new ParserException("EOF, " + ident + "=", e);
}
where = new SQLBinaryOpExpr(identExpr, SQLBinaryOperator.Equality, rightExp, dbType);
where = this.exprParser.andRest(where);
where = this.exprParser.orRest(where);
} else {
identExpr = this.exprParser.primaryRest(identExpr);
where = this.exprParser.exprRest(identExpr);
}
} else {
where = this.exprParser.expr();
}
// where = this.exprParser.expr();
if (beforeComments != null) {
where.addBeforeComment(beforeComments);
@@ -2433,7 +2433,26 @@ public class SQLStatementParser extends SQLParser {
}
public SQLStatement parseStatement() {
return parseStatement(false);
if (lexer.token == Token.SELECT) {
return this.parseSelect();
}
if (lexer.token == Token.INSERT) {
return this.parseInsert();
}
if (lexer.token == Token.UPDATE) {
return this.parseUpdateStatement();
}
if (lexer.token == Token.DELETE) {
return this.parseDeleteStatement();
}
List<SQLStatement> list = new ArrayList<SQLStatement>(1);
this.parseStatementList(list, 1, null);
return list.get(0);
}
/**