refactor sql parser.

This commit is contained in:
wenshao
2017-06-10 07:40:05 +08:00
parent 7c4a43d2c5
commit 5434b65260
310 changed files with 1067 additions and 1091 deletions
@@ -290,11 +290,11 @@ public class SQLUtils {
SQLStatement stmt = statementList.get(i);
if (i > 0) {
if (printStmtSeperator) {
SQLStatement preStmt = statementList.get(i - 1);
if (printStmtSeperator && !preStmt.isAfterSemi()) {
visitor.print(";");
}
SQLStatement preStmt = statementList.get(i - 1);
List<String> comments = preStmt.getAfterCommentsDirect();
if (comments != null){
for (int j = 0; j < comments.size(); ++j) {
@@ -325,11 +325,6 @@ public class SQLUtils {
stmt.accept(visitor);
if (i == size - 1) {
Boolean semi = (Boolean) stmt.getAttribute("format.semi");
if (semi != null && semi.booleanValue() && printStmtSeperator) {
visitor.print(";");
}
List<String> comments = stmt.getAfterCommentsDirect();
if (comments != null){
for (int j = 0; j < comments.size(); ++j) {
@@ -16,8 +16,10 @@
package com.alibaba.druid.sql.dialect.mysql.parser;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLName;
import com.alibaba.druid.sql.ast.SQLSetQuantifier;
import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
import com.alibaba.druid.sql.ast.expr.SQLListExpr;
import com.alibaba.druid.sql.ast.expr.SQLLiteralExpr;
import com.alibaba.druid.sql.ast.statement.*;
import com.alibaba.druid.sql.dialect.mysql.ast.MySqlForceIndexHint;
@@ -371,7 +373,20 @@ public class MySqlSelectParser extends SQLSelectParser {
}
}
} else {
queryBlock.setInto(this.exprParser.name());
SQLExpr intoExpr = this.exprParser.name();
if (lexer.token() == Token.COMMA) {
SQLListExpr list = new SQLListExpr();
list.addItem(intoExpr);
while (lexer.token() == Token.COMMA) {
lexer.nextToken();
SQLName name = this.exprParser.name();
list.addItem(name);
}
intoExpr = list;
}
queryBlock.setInto(intoExpr);
}
}
}
@@ -553,12 +553,6 @@ public class MySqlStatementParser extends SQLStatementParser {
}
public boolean parseStatementListDialect(List<SQLStatement> statementList) {
if (lexer.token() == Token.KILL) {
SQLStatement stmt = parseKill();
statementList.add(stmt);
return true;
}
if (identifierEquals("PREPARE")) {
MySqlPrepareStatement stmt = parsePrepare();
statementList.add(stmt);
@@ -733,6 +727,33 @@ public class MySqlStatementParser extends SQLStatementParser {
return true;
}
if (lexer.token() == Token.IDENTIFIER) {
String label = lexer.stringVal();
char ch = lexer.current();
int bp = lexer.bp();
lexer.nextToken();
if (lexer.token() == Token.VARIANT && lexer.stringVal().equals(":")) {
lexer.nextToken();
if (lexer.token() == Token.LOOP) {
// parse loop statement
statementList.add(this.parseLoop(label));
} else if (lexer.token() == Token.WHILE) {
// parse while statement with label
statementList.add(this.parseWhile(label));
} else if (lexer.token() == Token.BEGIN) {
// parse begin-end statement with label
statementList.add(this.parseBlock(label));
} else if (lexer.token() == Token.REPEAT) {
// parse repeat statement with label
statementList.add(this.parseRepeat(label));
}
return true;
} else {
lexer.reset(bp, ch, Token.IDENTIFIER);
}
}
return false;
}
@@ -740,7 +761,7 @@ public class MySqlStatementParser extends SQLStatementParser {
SQLBlockStatement block = new SQLBlockStatement();
accept(Token.BEGIN);
parseProcedureStatementList(block.getStatementList());
this.parseStatementList(block.getStatementList(), -1, block);
accept(Token.END);
return block;
@@ -3369,7 +3390,8 @@ public class MySqlStatementParser extends SQLStatementParser {
// insert
if (lexer.token() == Token.INSERT) {
statementList.add(parseInsert());
SQLStatement stmt = parseInsert();
statementList.add(stmt);
continue;
}
@@ -3432,7 +3454,8 @@ public class MySqlStatementParser extends SQLStatementParser {
// while statement
if (lexer.token() == Token.WHILE) {
statementList.add(this.parseWhile());
SQLStatement stmt = this.parseWhile();
statementList.add(stmt);
continue;
}
@@ -3731,7 +3754,8 @@ public class MySqlStatementParser extends SQLStatementParser {
stmt.addVar(item);
if (lexer.token() == Token.COMMA) {
accept(Token.COMMA);
lexer.nextToken();
stmt.setAfterSemi(true);
continue;
} else if (lexer.token() != Token.EOF) {
// var type
@@ -3842,15 +3866,16 @@ public class MySqlStatementParser extends SQLStatementParser {
* @return
*/
public MySqlRepeatStatement parseRepeat() {
MySqlRepeatStatement repeatStmt = new MySqlRepeatStatement();
MySqlRepeatStatement stmt = new MySqlRepeatStatement();
accept(Token.REPEAT);
parseProcedureStatementList(repeatStmt.getStatements());
parseStatementList(stmt.getStatements(), -1, stmt);
accept(Token.UNTIL);
repeatStmt.setCondition(exprParser.expr());
stmt.setCondition(exprParser.expr());
accept(Token.END);
accept(Token.REPEAT);
accept(Token.SEMI);
return repeatStmt;
stmt.setAfterSemi(true);
return stmt;
}
/**
@@ -3129,9 +3129,7 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV
println();
}
SQLStatement stmt = x.getStatementList().get(i);
stmt.setParent(x);
stmt.accept(this);
print(';');
}
decrementIndent();
println();
@@ -3377,15 +3375,16 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV
}
print0(ucase ? "REPEAT " : "repeat ");
incrementIndent();
println();
for (int i = 0, size = x.getStatements().size(); i < size; ++i) {
SQLStatement item = x.getStatements().get(i);
item.setParent(x);
item.accept(this);
if (i != size - 1) {
println();
}
}
decrementIndent();
println();
print0(ucase ? "UNTIL " : "until ");
x.getCondition().accept(this);
@@ -65,8 +65,9 @@ public class OdpsStatementParser extends SQLStatementParser {
}
public SQLSelectStatement parseSelect() {
OdpsSelectParser selectParser = new OdpsSelectParser(this.exprParser);
return new SQLSelectStatement(selectParser.select(), JdbcConstants.ODPS);
return new SQLSelectStatement(
new OdpsSelectParser(this.exprParser)
.select(), JdbcConstants.ODPS);
}
public SQLCreateTableStatement parseCreateTable() {
@@ -389,7 +389,8 @@ public class SQLSelectParser extends SQLParser {
lexer.nextToken();
queryBlock.setFrom(parseTableSource());
queryBlock.setFrom(
parseTableSource());
}
public SQLTableSource parseTableSource() {
@@ -31,6 +31,7 @@ import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr;
import com.alibaba.druid.sql.ast.statement.*;
import com.alibaba.druid.sql.ast.statement.SQLCreateTriggerStatement.TriggerEvent;
import com.alibaba.druid.sql.ast.statement.SQLCreateTriggerStatement.TriggerType;
import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlRepeatStatement;
import com.alibaba.druid.util.JdbcConstants;
public class SQLStatementParser extends SQLParser {
@@ -72,7 +73,13 @@ public class SQLStatementParser extends SQLParser {
public List<SQLStatement> parseStatementList() {
List<SQLStatement> statementList = new ArrayList<SQLStatement>();
parseStatementList(statementList);
parseStatementList(statementList, -1, null);
return statementList;
}
public List<SQLStatement> parseStatementList(SQLObject parent) {
List<SQLStatement> statementList = new ArrayList<SQLStatement>();
parseStatementList(statementList, -1, parent);
return statementList;
}
@@ -92,196 +99,198 @@ public class SQLStatementParser extends SQLParser {
}
}
if (lexer.token() == Token.EOF || lexer.token() == Token.END) {
if (lexer.isKeepComments() && lexer.hasComment() && statementList.size() > 0) {
SQLStatement stmt = statementList.get(statementList.size() - 1);
stmt.addAfterComment(lexer.readAndResetComments());
}
return;
}
if (lexer.token() == Token.SEMI) {
int line0 = lexer.getLine();
lexer.nextToken();
int line1 = lexer.getLine();
if (lexer.isKeepComments() && statementList.size() > 0) {
SQLStatement stmt = statementList.get(statementList.size() - 1);
if (line1 - line0 <= 1) {
switch (lexer.token()) {
case EOF:
case END:
case UNTIL:
if (lexer.isKeepComments() && lexer.hasComment() && statementList.size() > 0) {
SQLStatement stmt = statementList.get(statementList.size() - 1);
stmt.addAfterComment(lexer.readAndResetComments());
}
stmt.getAttributes().put("format.semi", Boolean.TRUE);
return;
case SEMI: {
int line0 = lexer.getLine();
lexer.nextToken();
int line1 = lexer.getLine();
if(statementList.size() > 0) {
SQLStatement lastStmt = statementList.get(statementList.size() - 1);
lastStmt.setAfterSemi(true);
if (lexer.isKeepComments()) {
SQLStatement stmt = statementList.get(statementList.size() - 1);
if (line1 - line0 <= 1) {
stmt.addAfterComment(lexer.readAndResetComments());
}
}
}
continue;
}
continue;
}
if (lexer.token() == Token.SELECT) {
statementList.add(parseSelect());
continue;
}
if (lexer.token() == (Token.UPDATE)) {
statementList.add(parseUpdateStatement());
continue;
}
if (lexer.token() == (Token.CREATE)) {
statementList.add(parseCreate());
continue;
}
if (lexer.token() == (Token.INSERT)) {
SQLStatement insertStatement = parseInsert();
statementList.add(insertStatement);
continue;
}
if (lexer.token() == (Token.DELETE)) {
statementList.add(parseDeleteStatement());
continue;
}
if (lexer.token() == (Token.EXPLAIN)) {
statementList.add(parseExplain());
continue;
}
if (lexer.token() == Token.SET) {
statementList.add(parseSet());
continue;
}
if (lexer.token() == Token.ALTER) {
statementList.add(parseAlter());
continue;
}
if (lexer.token() == Token.DROP) {
List<String> beforeComments = null;
if (lexer.isKeepComments() && lexer.hasComment()) {
beforeComments = lexer.readAndResetComments();
case SELECT: {
SQLStatement stmt = parseSelect();
stmt.setParent(parent);
statementList.add(stmt);
continue;
}
lexer.nextToken();
if (lexer.token() == Token.TABLE || identifierEquals("TEMPORARY")) {
SQLDropTableStatement stmt = parseDropTable(false);
if (beforeComments != null) {
stmt.addBeforeComment(beforeComments);
}
case UPDATE: {
SQLStatement stmt = parseUpdateStatement();
stmt.setParent(parent);
statementList.add(stmt);
continue;
} else if (lexer.token() == Token.USER) {
SQLStatement stmt = parseDropUser();
if (beforeComments != null) {
stmt.addBeforeComment(beforeComments);
}
statementList.add(stmt);
continue;
} else if (lexer.token() == Token.INDEX) {
SQLStatement stmt = parseDropIndex();
if (beforeComments != null) {
stmt.addBeforeComment(beforeComments);
}
statementList.add(stmt);
continue;
} else if (lexer.token() == Token.VIEW) {
SQLStatement stmt = parseDropView(false);
if (beforeComments != null) {
stmt.addBeforeComment(beforeComments);
}
statementList.add(stmt);
continue;
} else if (lexer.token() == Token.TRIGGER) {
SQLStatement stmt = parseDropTrigger(false);
if (beforeComments != null) {
stmt.addBeforeComment(beforeComments);
}
statementList.add(stmt);
continue;
} else if (lexer.token() == Token.DATABASE) {
SQLStatement stmt = parseDropDatabase(false);
if (beforeComments != null) {
stmt.addBeforeComment(beforeComments);
}
statementList.add(stmt);
continue;
} else if (lexer.token() == Token.FUNCTION) {
SQLStatement stmt = parseDropFunction(false);
if (beforeComments != null) {
stmt.addBeforeComment(beforeComments);
}
statementList.add(stmt);
continue;
} else if (lexer.token() == Token.TABLESPACE) {
SQLStatement stmt = parseDropTablespace(false);
if (beforeComments != null) {
stmt.addBeforeComment(beforeComments);
}
statementList.add(stmt);
continue;
} else if (lexer.token() == Token.PROCEDURE) {
SQLStatement stmt = parseDropProcedure(false);
if (beforeComments != null) {
stmt.addBeforeComment(beforeComments);
}
statementList.add(stmt);
continue;
} else if (lexer.token() == Token.SEQUENCE) {
SQLStatement stmt = parseDropSequece(false);
if (beforeComments != null) {
stmt.addBeforeComment(beforeComments);
}
statementList.add(stmt);
continue;
} else {
throw new ParserException("TODO " + lexer.token());
}
}
if (lexer.token() == Token.TRUNCATE) {
SQLStatement stmt = parseTruncate();
statementList.add(stmt);
continue;
}
if (lexer.token() == Token.USE) {
SQLStatement stmt = parseUse();
statementList.add(stmt);
continue;
}
if (lexer.token() == Token.GRANT) {
SQLStatement stmt = parseGrant();
statementList.add(stmt);
continue;
}
if (lexer.token() == Token.REVOKE) {
SQLStatement stmt = parseRevoke();
statementList.add(stmt);
continue;
case CREATE: {
SQLStatement stmt = parseCreate();
stmt.setParent(parent);
statementList.add(stmt);
continue;
}
case INSERT: {
SQLStatement stmt = parseInsert();
stmt.setParent(parent);
statementList.add(stmt);
continue;
}
case DELETE: {
SQLStatement stmt = parseDeleteStatement();
stmt.setParent(parent);
statementList.add(stmt);
continue;
}
case EXPLAIN: {
SQLStatement stmt = parseExplain();
stmt.setParent(parent);
statementList.add(stmt);
continue;
}
case SET: {
SQLStatement stmt = parseSet();
stmt.setParent(parent);
statementList.add(stmt);
continue;
}
case ALTER: {
SQLStatement stmt = parseAlter();
stmt.setParent(parent);
statementList.add(stmt);
continue;
}
case TRUNCATE: {
SQLStatement stmt = parseTruncate();
stmt.setParent(parent);
statementList.add(stmt);
continue;
}
case USE: {
SQLStatement stmt = parseUse();
stmt.setParent(parent);
statementList.add(stmt);
continue;
}
case GRANT: {
SQLStatement stmt = parseGrant();
stmt.setParent(parent);
statementList.add(stmt);
continue;
}
case REVOKE: {
SQLStatement stmt = parseRevoke();
stmt.setParent(parent);
statementList.add(stmt);
continue;
}
case SHOW: {
SQLStatement stmt = parseShow();
stmt.setParent(parent);
statementList.add(stmt);
continue;
}
case MERGE: {
SQLStatement stmt = parseMerge();
stmt.setParent(parent);
statementList.add(stmt);
continue;
}
case REPEAT: {
SQLStatement stmt = parseRepeat();
stmt.setParent(parent);
statementList.add(stmt);
continue;
}
case DECLARE: {
SQLStatement stmt = parseDeclare();
stmt.setParent(parent);
statementList.add(stmt);
continue;
}
case WHILE: {
SQLStatement stmt = parseWhile();
stmt.setParent(parent);
statementList.add(stmt);
continue;
}
case IF: {
SQLStatement stmt = parseIf();
stmt.setParent(parent);
statementList.add(stmt);
continue;
}
case CASE: {
SQLStatement stmt = parseCase();
stmt.setParent(parent);
statementList.add(stmt);
continue;
}
case OPEN: {
SQLStatement stmt = parseOpen();
stmt.setParent(parent);
statementList.add(stmt);
continue;
}
case FETCH: {
SQLStatement stmt = parseFetch();
stmt.setParent(parent);
statementList.add(stmt);
continue;
}
case DROP: {
SQLStatement stmt = parseDrop();
stmt.setParent(parent);
statementList.add(stmt);
continue;
}
case COMMENT: {
SQLStatement stmt = parseComment();
stmt.setParent(parent);
statementList.add(stmt);
continue;
}
case KILL: {
SQLStatement stmt = parseKill();
stmt.setParent(parent);
statementList.add(stmt);
continue;
}
case CLOSE: {
SQLStatement stmt = parseClose();
stmt.setParent(parent);
statementList.add(stmt);
continue;
}
case RETURN: {
SQLStatement stmt = parseReturn();
stmt.setParent(parent);
statementList.add(stmt);
continue;
}
case UPSERT: {
SQLStatement stmt = parseUpsert();
stmt.setParent(parent);
statementList.add(stmt);
continue;
}
default:
break;
}
if (lexer.token() == Token.LBRACE || identifierEquals("CALL")) {
@@ -290,6 +299,13 @@ public class SQLStatementParser extends SQLParser {
continue;
}
if (identifierEquals("UPSERT")) {
SQLStatement stmt = parseUpsert();
statementList.add(stmt);
continue;
}
if (identifierEquals("RENAME")) {
SQLStatement stmt = parseRename();
statementList.add(stmt);
@@ -322,9 +338,8 @@ public class SQLStatementParser extends SQLParser {
continue;
}
if (lexer.token() == Token.SHOW) {
SQLStatement stmt = parseShow();
if (identifierEquals("RETURN")) {
SQLStatement stmt = parseReturn();
statementList.add(stmt);
continue;
}
@@ -340,40 +355,86 @@ public class SQLStatementParser extends SQLParser {
continue;
}
}
if (lexer.token() == Token.MERGE) {
statementList.add(this.parseMerge());
continue;
}
if (parseStatementListDialect(statementList)) {
continue;
}
if (lexer.token() == Token.COMMENT) {
statementList.add(this.parseComment());
continue;
}
if (lexer.token() == Token.UPSERT || identifierEquals("UPSERT")) {
SQLStatement stmt = parseUpsert();
statementList.add(stmt);
continue;
}
if (identifierEquals("RETURN")) {
SQLStatement stmt = parseReturn();
statementList.add(stmt);
continue;
}
// throw new ParserException("syntax error, " + lexer.token() + " "
// + lexer.stringVal() + ", pos "
// + lexer.pos());
//throw new ParserException("not supported." + lexer.info());
printError(lexer.token());
}
}
public SQLStatement parseDrop() {
List<String> beforeComments = null;
if (lexer.isKeepComments() && lexer.hasComment()) {
beforeComments = lexer.readAndResetComments();
}
lexer.nextToken();
final SQLStatement stmt;
if (lexer.token() == Token.TABLE || identifierEquals("TEMPORARY")) {
stmt = parseDropTable(false);
} else if (lexer.token() == Token.USER) {
stmt = parseDropUser();
} else if (lexer.token() == Token.INDEX) {
stmt = parseDropIndex();
} else if (lexer.token() == Token.VIEW) {
stmt = parseDropView(false);
} else if (lexer.token() == Token.TRIGGER) {
stmt = parseDropTrigger(false);
} else if (lexer.token() == Token.DATABASE) {
stmt = parseDropDatabase(false);
} else if (lexer.token() == Token.FUNCTION) {
stmt = parseDropFunction(false);
} else if (lexer.token() == Token.TABLESPACE) {
stmt = parseDropTablespace(false);
} else if (lexer.token() == Token.PROCEDURE) {
stmt = parseDropProcedure(false);
} else if (lexer.token() == Token.SEQUENCE) {
stmt = parseDropSequece(false);
} else {
throw new ParserException("TODO " + lexer.token());
}
if (beforeComments != null) {
stmt.addBeforeComment(beforeComments);
}
return stmt;
}
public SQLStatement parseKill() {
throw new ParserException("not supported. " + lexer.info());
}
public SQLStatement parseCase() {
throw new ParserException("not supported. " + lexer.info());
}
public SQLStatement parseIf() {
throw new ParserException("not supported. " + lexer.info());
}
public SQLStatement parseWhile() {
throw new ParserException("not supported. " + lexer.info());
}
public SQLStatement parseDeclare() {
throw new ParserException("not supported. " + lexer.info());
}
public SQLStatement parseRepeat() {
throw new ParserException("not supported. " + lexer.info());
}
public SQLStatement parseReturn() {
if (lexer.token() == Token.RETURN
|| identifierEquals("RETURN")) {
@@ -1514,14 +1575,14 @@ public class SQLStatementParser extends SQLParser {
}
public SQLStatement parseInsert() {
SQLInsertStatement insertStatement = new SQLInsertStatement();
SQLInsertStatement stmt = new SQLInsertStatement();
if (lexer.token() == Token.INSERT) {
accept(Token.INSERT);
}
parseInsert0(insertStatement);
return insertStatement;
parseInsert0(stmt);
return stmt;
}
protected void parseInsert0(SQLInsertInto insertStatement) {
@@ -285,6 +285,10 @@ public class SchemaRepository {
return count;
}
public Map<String, SchemaObject> getObjects() {
return this.objects;
}
public int getViewCount() {
int count = 0;
for (SchemaObject object : this.objects.values()) {