improved sql parser. for issue #1933

This commit is contained in:
wenshao
2017-09-04 10:45:28 +08:00
parent 5badd35b7f
commit e8799e61b1
11 changed files with 322 additions and 48 deletions
@@ -18,6 +18,7 @@ package com.alibaba.druid.sql.ast.statement;
import java.util.ArrayList;
import java.util.List;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLName;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.ast.SQLStatementImpl;
@@ -27,15 +28,21 @@ public class SQLCreateTriggerStatement extends SQLStatementImpl implements SQLCr
private SQLName name;
private boolean orReplace = false;
private boolean orReplace = false;
private TriggerType triggerType;
private final List<TriggerEvent> triggerEvents = new ArrayList<TriggerEvent>();
private boolean update;
private boolean delete;
private boolean insert;
private SQLName on;
private boolean forEachRow = false;
private boolean forEachRow = false;
private List<SQLName> updateOfColumns = new ArrayList<SQLName>();
private SQLExpr when;
private SQLStatement body;
public SQLCreateTriggerStatement() {
@@ -49,7 +56,9 @@ public class SQLCreateTriggerStatement extends SQLStatementImpl implements SQLCr
protected void accept0(SQLASTVisitor visitor) {
if (visitor.visit(this)) {
acceptChild(visitor, name);
acceptChild(visitor, updateOfColumns);
acceptChild(visitor, on);
acceptChild(visitor, when);
acceptChild(visitor, body);
}
visitor.endVisit(this);
@@ -102,7 +111,7 @@ public class SQLCreateTriggerStatement extends SQLStatementImpl implements SQLCr
}
public List<TriggerEvent> getTriggerEvents() {
return triggerEvents;
return null;
}
public boolean isForEachRow() {
@@ -113,6 +122,45 @@ public class SQLCreateTriggerStatement extends SQLStatementImpl implements SQLCr
this.forEachRow = forEachRow;
}
public List<SQLName> getUpdateOfColumns() {
return updateOfColumns;
}
public SQLExpr getWhen() {
return when;
}
public void setWhen(SQLExpr when) {
if (when != null) {
when.setParent(this);
}
this.when = when;
}
public boolean isUpdate() {
return update;
}
public void setUpdate(boolean update) {
this.update = update;
}
public boolean isDelete() {
return delete;
}
public void setDelete(boolean delete) {
this.delete = delete;
}
public boolean isInsert() {
return insert;
}
public void setInsert(boolean insert) {
this.insert = insert;
}
public static enum TriggerType {
BEFORE, AFTER, INSTEAD_OF
}
@@ -50,6 +50,7 @@ public class MySqlLexer extends Lexer {
map.put("BEGIN", Token.BEGIN);
map.put("END", Token.END);
map.put("DIV", Token.DIV);
map.put("MERGE", Token.MERGE);
// for oceanbase & mysql 5.7
map.put("PARTITION", Token.PARTITION);
@@ -18,11 +18,7 @@ package com.alibaba.druid.sql.parser;
import java.util.List;
import com.alibaba.druid.sql.ast.SQLName;
import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;
import com.alibaba.druid.sql.ast.statement.SQLConstraint;
import com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;
import com.alibaba.druid.sql.ast.statement.SQLExprTableSource;
import com.alibaba.druid.sql.ast.statement.SQLTableElement;
import com.alibaba.druid.sql.ast.statement.*;
import com.alibaba.druid.util.JdbcConstants;
public class SQLCreateTableParser extends SQLDDLParser {
@@ -143,6 +139,12 @@ public class SQLCreateTableParser extends SQLDDLParser {
}
}
if (lexer.token == Token.AS) {
lexer.nextToken();
SQLSelect select = this.createSQLSelectParser().select();
createTable.setSelect(select);
}
return createTable;
}
@@ -18,6 +18,7 @@ package com.alibaba.druid.sql.parser;
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.mysql.parser.MySqlExprParser;
import com.alibaba.druid.sql.dialect.mysql.parser.MySqlLexer;
import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;
@@ -15,7 +15,6 @@
*/
package com.alibaba.druid.sql.parser;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
@@ -27,11 +26,9 @@ 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.sql.dialect.oracle.parser.OracleExprParser;
import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.*;
import com.alibaba.druid.util.FnvHash;
import com.alibaba.druid.util.JdbcConstants;
import com.alibaba.druid.util.JdbcUtils;
public class SQLStatementParser extends SQLParser {
@@ -2012,13 +2009,13 @@ public class SQLStatementParser extends SQLParser {
stmt.setName(this.exprParser.name());
if (lexer.identifierEquals("BEFORE")) {
if (lexer.identifierEquals(FnvHash.Constants.BEFORE)) {
stmt.setTriggerType(TriggerType.BEFORE);
lexer.nextToken();
} else if (lexer.identifierEquals("AFTER")) {
} else if (lexer.identifierEquals(FnvHash.Constants.AFTER)) {
stmt.setTriggerType(TriggerType.AFTER);
lexer.nextToken();
} else if (lexer.identifierEquals("INSTEAD")) {
} else if (lexer.identifierEquals(FnvHash.Constants.INSTEAD)) {
lexer.nextToken();
accept(Token.OF);
stmt.setTriggerType(TriggerType.INSTEAD_OF);
@@ -2027,21 +2024,26 @@ public class SQLStatementParser extends SQLParser {
for (;;) {
if (lexer.token == Token.INSERT) {
lexer.nextToken();
stmt.getTriggerEvents().add(TriggerEvent.INSERT);
stmt.setInsert(true);
} else if (lexer.token == Token.UPDATE) {
lexer.nextToken();
stmt.setUpdate(true);
if (lexer.token == Token.OF) {
lexer.nextToken();
this.exprParser.names(stmt.getUpdateOfColumns(), stmt);
}
} else if (lexer.token == Token.DELETE) {
lexer.nextToken();
stmt.setDelete(true);
}
if (lexer.token == Token.COMMA
|| lexer.token == Token.OR) {
lexer.nextToken();
continue;
}
if (lexer.token == Token.UPDATE) {
lexer.nextToken();
stmt.getTriggerEvents().add(TriggerEvent.UPDATE);
continue;
}
if (lexer.token == Token.DELETE) {
lexer.nextToken();
stmt.getTriggerEvents().add(TriggerEvent.DELETE);
continue;
}
break;
}
@@ -2055,6 +2057,12 @@ public class SQLStatementParser extends SQLParser {
stmt.setForEachRow(true);
}
if (lexer.token == Token.WHEN) {
lexer.nextToken();
SQLExpr condition = this.exprParser.expr();
stmt.setWhen(condition);
}
List<SQLStatement> body = this.parseStatementList();
if (body == null || body.isEmpty()) {
throw new ParserException("syntax error");
@@ -2392,6 +2392,15 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet
x.getInherits().accept(this);
print(')');
}
SQLSelect select = x.getSelect();
if (select != null) {
println();
print0(ucase ? "AS" : "as");
println();
visit(select);
}
}
public boolean visit(SQLUniqueConstraint x) {
@@ -3735,10 +3744,30 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet
print0(ucase ? triggerTypeName : triggerTypeName.toLowerCase());
}
for (TriggerEvent event : x.getTriggerEvents()) {
print(' ');
print0(event.name());
if (x.isInsert()) {
print0(ucase ? " INSERT" : " insert");
}
if (x.isDelete()) {
if (x.isInsert()) {
print0(ucase ? " OR" : " or");
}
print0(ucase ? " DELETE" : " delete");
}
if (x.isUpdate()) {
if (x.isInsert() || x.isDelete()) {
print0(ucase ? " OR" : " or");
}
print0(ucase ? " UPDATE" : " update");
List<SQLName> colums = x.getUpdateOfColumns();
for (SQLName colum : colums) {
print(' ');
colum.accept(this);
}
}
println();
print0(ucase ? "ON " : "on ");
x.getOn().accept(this);
@@ -3747,6 +3776,13 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet
println();
print0(ucase ? "FOR EACH ROW" : "for each row");
}
SQLExpr when = x.getWhen();
if (when != null) {
println();
print0(ucase ? "WHEN " : "when ");
when.accept(this);
}
this.indentCount--;
println();
x.getBody().accept(this);
@@ -410,5 +410,9 @@ public final class FnvHash {
long HOUR = fnv1a_64_lower("HOUR");
long MINUTE = fnv1a_64_lower("MINUTE");
long SECOND = fnv1a_64_lower("SECOND");
long BEFORE = fnv1a_64_lower("BEFORE");
long AFTER = fnv1a_64_lower("AFTER");
long INSTEAD = fnv1a_64_lower("INSTEAD");
}
}