From c8d8409d309ebd43e390cd2d9ad2e02e9aa169e9 Mon Sep 17 00:00:00 2001 From: wenshao Date: Tue, 24 Apr 2018 13:47:12 +0800 Subject: [PATCH] improved sql parser. --- .../statement/MySqlCreateTableStatement.java | 2 +- .../ast/statement/MySqlDeleteStatement.java | 2 +- .../ast/statement/MySqlInsertStatement.java | 2 +- .../ast/statement/MySqlUpdateStatement.java | 2 +- .../oracle/parser/OracleExprParser.java | 55 ++++++++++++++++--- .../ast/stmt/SQLServerRollbackStatement.java | 2 +- .../sql/visitor/SQLASTOutputVisitor.java | 14 +++-- .../{ => bvt}/sql/refactor/AddWhere_0.java | 2 +- .../druid/bvt/sql/refactor/ClearSchema_0.java | 38 +++++++++++++ 9 files changed, 99 insertions(+), 20 deletions(-) rename src/test/java/com/alibaba/druid/{ => bvt}/sql/refactor/AddWhere_0.java (98%) create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/refactor/ClearSchema_0.java diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlCreateTableStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlCreateTableStatement.java index e611ea7558..383a23589e 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlCreateTableStatement.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlCreateTableStatement.java @@ -77,7 +77,7 @@ public class MySqlCreateTableStatement extends SQLCreateTableStatement implement if (visitor instanceof MySqlASTVisitor) { accept0((MySqlASTVisitor) visitor); } else { - throw new IllegalArgumentException("not support visitor type : " + visitor.getClass().getName()); + super.accept0(visitor); } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlDeleteStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlDeleteStatement.java index 5ba9af4516..1c799872a4 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlDeleteStatement.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlDeleteStatement.java @@ -129,7 +129,7 @@ public class MySqlDeleteStatement extends SQLDeleteStatement { if (visitor instanceof MySqlASTVisitor) { accept0((MySqlASTVisitor) visitor); } else { - throw new IllegalArgumentException("not support visitor type : " + visitor.getClass().getName()); + super.accept0(visitor); } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlInsertStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlInsertStatement.java index 3722bc085a..32d5c31729 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlInsertStatement.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlInsertStatement.java @@ -103,7 +103,7 @@ public class MySqlInsertStatement extends SQLInsertStatement { if (visitor instanceof MySqlASTVisitor) { accept0((MySqlASTVisitor) visitor); } else { - throw new IllegalArgumentException("not support visitor type : " + visitor.getClass().getName()); + super.accept0(visitor); } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlUpdateStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlUpdateStatement.java index f6b7c9a83c..ceda416954 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlUpdateStatement.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlUpdateStatement.java @@ -58,7 +58,7 @@ public class MySqlUpdateStatement extends SQLUpdateStatement implements MySqlSta if (visitor instanceof MySqlASTVisitor) { accept0((MySqlASTVisitor) visitor); } else { - throw new IllegalArgumentException("not support visitor type : " + visitor.getClass().getName()); + super.accept0(visitor); } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleExprParser.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleExprParser.java index 10111865e7..12d829dad1 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleExprParser.java @@ -799,8 +799,10 @@ public class OracleExprParser extends SQLExprParser { } } - over.setOrderBy(parseOrderBy()); - if (over.getOrderBy() != null) { + final SQLOrderBy orderBy = parseOrderBy(); + if (orderBy != null) { + over.setOrderBy(orderBy); + OracleAnalyticWindowing windowing = null; if (lexer.identifierEquals(FnvHash.Constants.ROWS)) { lexer.nextToken(); @@ -815,12 +817,9 @@ public class OracleExprParser extends SQLExprParser { if (windowing != null) { if (lexer.identifierEquals(FnvHash.Constants.CURRENT)) { lexer.nextToken(); - if (lexer.stringVal().equalsIgnoreCase("ROW")) { - lexer.nextToken(); - windowing.setExpr(new SQLIdentifierExpr("CURRENT ROW")); - over.setWindowing(windowing); - } - throw new ParserException("syntax error. " + lexer.info()); + accept(Token.ROW); + windowing.setExpr(new SQLIdentifierExpr("CURRENT ROW")); + over.setWindowing(windowing); } if (lexer.identifierEquals(FnvHash.Constants.UNBOUNDED)) { lexer.nextToken(); @@ -830,6 +829,46 @@ public class OracleExprParser extends SQLExprParser { } else { throw new ParserException("syntax error. " + lexer.info()); } + } else if (lexer.token() == Token.BETWEEN) { + lexer.nextToken(); + SQLExpr beginExpr; + + if (lexer.identifierEquals(FnvHash.Constants.CURRENT)) { + lexer.nextToken(); + accept(Token.ROW); + beginExpr = new SQLIdentifierExpr("CURRENT ROW"); + } else if (lexer.identifierEquals(FnvHash.Constants.UNBOUNDED)) { + lexer.nextToken(); + if (lexer.stringVal().equalsIgnoreCase("PRECEDING")) { + lexer.nextToken(); + beginExpr = new SQLIdentifierExpr("UNBOUNDED PRECEDING"); + } else { + throw new ParserException("syntax error. " + lexer.info()); + } + } else { + beginExpr = relational(); + } + + accept(Token.AND); + SQLExpr endExpr; + if (lexer.identifierEquals(FnvHash.Constants.CURRENT)) { + lexer.nextToken(); + accept(Token.ROW); + endExpr = new SQLIdentifierExpr("CURRENT ROW"); + } else if (lexer.identifierEquals(FnvHash.Constants.UNBOUNDED)) { + lexer.nextToken(); + if (lexer.stringVal().equalsIgnoreCase("PRECEDING")) { + lexer.nextToken(); + endExpr = new SQLIdentifierExpr("UNBOUNDED PRECEDING"); + } else { + throw new ParserException("syntax error. " + lexer.info()); + } + } else { + endExpr = relational(); + } + + SQLExpr expr = new SQLBetweenExpr(null, beginExpr, endExpr); + windowing.setExpr(expr); } else { SQLExpr expr = this.expr(); windowing.setExpr(expr); diff --git a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/stmt/SQLServerRollbackStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/stmt/SQLServerRollbackStatement.java index 648d130536..3500ce2dfd 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/stmt/SQLServerRollbackStatement.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/stmt/SQLServerRollbackStatement.java @@ -40,7 +40,7 @@ public class SQLServerRollbackStatement extends SQLRollbackStatement implements if (visitor instanceof SQLServerASTVisitor) { accept0((SQLServerASTVisitor) visitor); } else { - throw new IllegalArgumentException("not support visitor type : " + visitor.getClass().getName()); + super.accept0(visitor); } } diff --git a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java index 827b9f7824..390c50e18e 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java @@ -480,12 +480,14 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet quote = true; } - if (quote) { - print('('); - printExpr(testExpr); - print(')'); - } else { - printExpr(testExpr); + if (testExpr != null) { + if (quote) { + print('('); + printExpr(testExpr); + print(')'); + } else { + printExpr(testExpr); + } } if (x.isNot()) { diff --git a/src/test/java/com/alibaba/druid/sql/refactor/AddWhere_0.java b/src/test/java/com/alibaba/druid/bvt/sql/refactor/AddWhere_0.java similarity index 98% rename from src/test/java/com/alibaba/druid/sql/refactor/AddWhere_0.java rename to src/test/java/com/alibaba/druid/bvt/sql/refactor/AddWhere_0.java index 61a96b3194..33dbdba42d 100644 --- a/src/test/java/com/alibaba/druid/sql/refactor/AddWhere_0.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/refactor/AddWhere_0.java @@ -1,4 +1,4 @@ -package com.alibaba.druid.sql.refactor; +package com.alibaba.druid.bvt.sql.refactor; import com.alibaba.druid.sql.SQLUtils; import com.alibaba.druid.sql.ast.statement.SQLDeleteStatement; diff --git a/src/test/java/com/alibaba/druid/bvt/sql/refactor/ClearSchema_0.java b/src/test/java/com/alibaba/druid/bvt/sql/refactor/ClearSchema_0.java new file mode 100644 index 0000000000..e37063e607 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/refactor/ClearSchema_0.java @@ -0,0 +1,38 @@ +package com.alibaba.druid.bvt.sql.refactor; + +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.ast.expr.SQLCaseExpr; +import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; +import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr; +import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitorAdapter; +import com.alibaba.druid.sql.visitor.SQLASTVisitor; +import com.alibaba.druid.sql.visitor.SQLASTVisitorAdapter; +import com.alibaba.druid.util.JdbcConstants; +import junit.framework.TestCase; + +import java.util.List; + +public class ClearSchema_0 extends TestCase { + public void test_insert_0() throws Exception { + String sql = "INSERT INTO testdb.Websites (name, country)\n" + + "SELECT app_name, country FROM testdb.apps;"; + + SQLStatement stmt = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL).get(0); + + SQLASTVisitor v = new SQLASTVisitorAdapter() { + @Override + public boolean visit(SQLPropertyExpr x) { + if (SQLUtils.replaceInParent(x, new SQLIdentifierExpr(x.getName()))) { + return false; + } + return super.visit(x); + } + }; + stmt.accept(v); + + assertEquals("INSERT INTO Websites (name, country)\n" + + "SELECT app_name, country\n" + + "FROM apps;", stmt.toString()); + } +}