From b4155d7be2ea3f6a8a4f90b12622ed13a764b8f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=AB=98=E9=93=81?= Date: Sat, 9 Jan 2016 13:56:09 +0800 Subject: [PATCH] refactor sql parser group by --- .../expr/SQLGroupingSetExpr.java} | 8 +- .../ast/statement/SQLSelectGroupByClause.java | 13 ++ .../builder/impl/SQLSelectBuilderImpl.java | 5 - .../dialect/mysql/parser/MySqlExprParser.java | 2 +- .../mysql/parser/MySqlSelectIntoParser.java | 45 ------- .../mysql/parser/MySqlSelectParser.java | 48 +------- .../mysql/visitor/MySqlASTVisitor.java | 5 - .../mysql/visitor/MySqlASTVisitorAdapter.java | 12 -- .../mysql/visitor/MySqlOutputVisitor.java | 17 --- .../mysql/visitor/MySqlSchemaStatVisitor.java | 12 -- .../dialect/odps/parser/OdpsSelectParser.java | 1 - .../oracle/parser/OracleSelectParser.java | 70 ----------- .../oracle/visitor/OracleASTVisitor.java | 5 - .../visitor/OracleASTVisitorAdapter.java | 12 -- .../oracle/visitor/OracleOutputVisitor.java | 15 --- .../visitor/OracleSchemaStatVisitor.java | 12 -- .../druid/sql/parser/SQLExprParser.java | 112 +++++++++++------- .../druid/sql/parser/SQLSelectParser.java | 66 +++++++++-- .../sql/visitor/SQLASTOutputVisitor.java | 15 +++ .../druid/sql/visitor/SQLASTVisitor.java | 6 +- .../sql/visitor/SQLASTVisitorAdapter.java | 11 ++ .../druid/wall/spi/MySqlWallVisitor.java | 6 - .../druid/bvt/sql/EqualTest_groupSet.java | 6 +- .../sql/mysql/MySqlASTVisitorAdapterTest.java | 6 +- .../sql/oracle/OracleGroupingSetsTest.java | 35 ++++++ .../visitor/OracleASTVisitorAdapterTest.java | 4 +- 26 files changed, 220 insertions(+), 329 deletions(-) rename src/main/java/com/alibaba/druid/sql/{dialect/oracle/ast/clause/GroupingSetExpr.java => ast/expr/SQLGroupingSetExpr.java} (87%) create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleGroupingSetsTest.java diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/clause/GroupingSetExpr.java b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLGroupingSetExpr.java similarity index 87% rename from src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/clause/GroupingSetExpr.java rename to src/main/java/com/alibaba/druid/sql/ast/expr/SQLGroupingSetExpr.java index 42e47dceba..49e71c3ad7 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/clause/GroupingSetExpr.java +++ b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLGroupingSetExpr.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.alibaba.druid.sql.dialect.oracle.ast.clause; +package com.alibaba.druid.sql.ast.expr; import java.util.ArrayList; import java.util.List; @@ -23,7 +23,7 @@ import com.alibaba.druid.sql.ast.SQLExprImpl; import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor; import com.alibaba.druid.sql.visitor.SQLASTVisitor; -public class GroupingSetExpr extends SQLExprImpl { +public class SQLGroupingSetExpr extends SQLExprImpl { private final List parameters = new ArrayList(); @@ -59,10 +59,10 @@ public class GroupingSetExpr extends SQLExprImpl { if (obj == null) { return false; } - if (!(obj instanceof GroupingSetExpr)) { + if (!(obj instanceof SQLGroupingSetExpr)) { return false; } - GroupingSetExpr other = (GroupingSetExpr) obj; + SQLGroupingSetExpr other = (SQLGroupingSetExpr) obj; if (parameters == null) { if (other.parameters != null) { return false; diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectGroupByClause.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectGroupByClause.java index 9252b3ed9f..887d7cc590 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectGroupByClause.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectGroupByClause.java @@ -26,6 +26,7 @@ public class SQLSelectGroupByClause extends SQLObjectImpl { private final List items = new ArrayList(); private SQLExpr having; + private boolean rollUp = false; public SQLSelectGroupByClause(){ @@ -39,12 +40,24 @@ public class SQLSelectGroupByClause extends SQLObjectImpl { visitor.endVisit(this); } + + public boolean isRollUp() { + return rollUp; + } + + public void setRollUp(boolean rollUp) { + this.rollUp = rollUp; + } public SQLExpr getHaving() { return this.having; } public void setHaving(SQLExpr having) { + if (having != null) { + having.setParent(this); + } + this.having = having; } diff --git a/src/main/java/com/alibaba/druid/sql/builder/impl/SQLSelectBuilderImpl.java b/src/main/java/com/alibaba/druid/sql/builder/impl/SQLSelectBuilderImpl.java index 93ac0f1653..d5496f1656 100644 --- a/src/main/java/com/alibaba/druid/sql/builder/impl/SQLSelectBuilderImpl.java +++ b/src/main/java/com/alibaba/druid/sql/builder/impl/SQLSelectBuilderImpl.java @@ -34,7 +34,6 @@ import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock; import com.alibaba.druid.sql.ast.statement.SQLSelectStatement; import com.alibaba.druid.sql.builder.SQLSelectBuilder; import com.alibaba.druid.sql.dialect.db2.ast.stmt.DB2SelectQueryBlock; -import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectGroupBy; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock.Limit; import com.alibaba.druid.sql.dialect.odps.ast.OdpsSelectQueryBlock; @@ -370,10 +369,6 @@ public class SQLSelectBuilderImpl implements SQLSelectBuilder { } protected SQLSelectGroupByClause createGroupBy() { - if (JdbcConstants.MYSQL.equals(dbType)) { - return new MySqlSelectGroupBy(); - } - return new SQLSelectGroupByClause(); } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlExprParser.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlExprParser.java index 550a2cbbde..cbfc135ca0 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlExprParser.java @@ -64,7 +64,7 @@ public class MySqlExprParser extends SQLExprParser { public static String[] AGGREGATE_FUNCTIONS = { "AVG", "COUNT", "GROUP_CONCAT", "MAX", "MIN", "STDDEV", "SUM" }; public MySqlExprParser(Lexer lexer){ - super(lexer); + super(lexer, JdbcConstants.MYSQL); this.aggregateFunctions = AGGREGATE_FUNCTIONS; } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlSelectIntoParser.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlSelectIntoParser.java index bbe3d072db..16d1d41c30 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlSelectIntoParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlSelectIntoParser.java @@ -24,7 +24,6 @@ import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; import com.alibaba.druid.sql.ast.expr.SQLLiteralExpr; import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr; import com.alibaba.druid.sql.ast.statement.SQLSelect; -import com.alibaba.druid.sql.ast.statement.SQLSelectGroupByClause; import com.alibaba.druid.sql.ast.statement.SQLSelectQuery; import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock; import com.alibaba.druid.sql.ast.statement.SQLTableSource; @@ -36,7 +35,6 @@ import com.alibaba.druid.sql.dialect.mysql.ast.MySqlIndexHintImpl; import com.alibaba.druid.sql.dialect.mysql.ast.MySqlUseIndexHint; import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlSelectIntoStatement; import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlOutFileExpr; -import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectGroupBy; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock.Limit; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlUnionQuery; @@ -279,49 +277,6 @@ public class MySqlSelectIntoParser extends SQLSelectParser { } } - protected void parseGroupBy(SQLSelectQueryBlock queryBlock) { - SQLSelectGroupByClause groupBy = null; - - if (lexer.token() == Token.GROUP) { - groupBy = new SQLSelectGroupByClause(); - - lexer.nextToken(); - accept(Token.BY); - - while (true) { - groupBy.addItem(this.getExprParser().parseSelectGroupByItem()); - if (!(lexer.token() == (Token.COMMA))) { - break; - } - lexer.nextToken(); - } - - if (lexer.token() == Token.WITH) { - lexer.nextToken(); - acceptIdentifier("ROLLUP"); - - MySqlSelectGroupBy mySqlGroupBy = new MySqlSelectGroupBy(); - for (SQLExpr sqlExpr : groupBy.getItems()) { - mySqlGroupBy.addItem(sqlExpr); - } - mySqlGroupBy.setRollUp(true); - - groupBy = mySqlGroupBy; - } - } - - if (lexer.token() == Token.HAVING) { - lexer.nextToken(); - - if (groupBy == null) { - groupBy = new SQLSelectGroupByClause(); - } - groupBy.setHaving(this.exprParser.expr()); - } - - queryBlock.setGroupBy(groupBy); - } - protected SQLTableSource parseTableSourceRest(SQLTableSource tableSource) { if (identifierEquals("USING")) { return tableSource; diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlSelectParser.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlSelectParser.java index e6b003ae99..10e0f42526 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlSelectParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlSelectParser.java @@ -15,13 +15,11 @@ */ package com.alibaba.druid.sql.dialect.mysql.parser; -import com.alibaba.druid.sql.ast.SQLExpr; import com.alibaba.druid.sql.ast.SQLSetQuantifier; import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; import com.alibaba.druid.sql.ast.expr.SQLLiteralExpr; import com.alibaba.druid.sql.ast.statement.SQLExprTableSource; import com.alibaba.druid.sql.ast.statement.SQLSelect; -import com.alibaba.druid.sql.ast.statement.SQLSelectGroupByClause; import com.alibaba.druid.sql.ast.statement.SQLSelectQuery; import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock; import com.alibaba.druid.sql.ast.statement.SQLSubqueryTableSource; @@ -35,11 +33,10 @@ import com.alibaba.druid.sql.dialect.mysql.ast.MySqlIndexHint; import com.alibaba.druid.sql.dialect.mysql.ast.MySqlIndexHintImpl; import com.alibaba.druid.sql.dialect.mysql.ast.MySqlUseIndexHint; import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlOutFileExpr; -import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectGroupBy; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock; -import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlUpdateStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock.Limit; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlUnionQuery; +import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlUpdateStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlUpdateTableSource; import com.alibaba.druid.sql.parser.ParserException; import com.alibaba.druid.sql.parser.SQLExprParser; @@ -320,49 +317,6 @@ public class MySqlSelectParser extends SQLSelectParser { } } - protected void parseGroupBy(SQLSelectQueryBlock queryBlock) { - SQLSelectGroupByClause groupBy = null; - - if (lexer.token() == Token.GROUP) { - groupBy = new SQLSelectGroupByClause(); - - lexer.nextToken(); - accept(Token.BY); - - while (true) { - groupBy.addItem(this.getExprParser().parseSelectGroupByItem()); - if (!(lexer.token() == (Token.COMMA))) { - break; - } - lexer.nextToken(); - } - - if (lexer.token() == Token.WITH) { - lexer.nextToken(); - acceptIdentifier("ROLLUP"); - - MySqlSelectGroupBy mySqlGroupBy = new MySqlSelectGroupBy(); - for (SQLExpr sqlExpr : groupBy.getItems()) { - mySqlGroupBy.addItem(sqlExpr); - } - mySqlGroupBy.setRollUp(true); - - groupBy = mySqlGroupBy; - } - } - - if (lexer.token() == Token.HAVING) { - lexer.nextToken(); - - if (groupBy == null) { - groupBy = new SQLSelectGroupByClause(); - } - groupBy.setHaving(this.exprParser.expr()); - } - - queryBlock.setGroupBy(groupBy); - } - protected SQLTableSource parseTableSourceRest(SQLTableSource tableSource) { if (identifierEquals("USING")) { return tableSource; diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitor.java index fc2c334ba5..af0db39424 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitor.java @@ -82,7 +82,6 @@ import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlRenameTableStateme import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlReplaceStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlResetStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlRollbackStatement; -import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectGroupBy; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSetCharSetStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSetNamesStatement; @@ -204,10 +203,6 @@ public interface MySqlASTVisitor extends SQLASTVisitor { boolean visit(MySqlReplaceStatement x); - void endVisit(MySqlSelectGroupBy x); - - boolean visit(MySqlSelectGroupBy x); - void endVisit(MySqlStartTransactionStatement x); boolean visit(MySqlStartTransactionStatement x); diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitorAdapter.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitorAdapter.java index 3c129826cc..ae2fa2271d 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitorAdapter.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitorAdapter.java @@ -86,7 +86,6 @@ import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlRenameTableStateme import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlReplaceStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlResetStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlRollbackStatement; -import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectGroupBy; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock.Limit; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSetCharSetStatement; @@ -296,17 +295,6 @@ public class MySqlASTVisitorAdapter extends SQLASTVisitorAdapter implements MySq return true; } - @Override - public void endVisit(MySqlSelectGroupBy x) { - - } - - @Override - public boolean visit(MySqlSelectGroupBy x) { - - return true; - } - @Override public void endVisit(MySqlStartTransactionStatement x) { diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java index 072f6edaf6..e94bad1af3 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java @@ -113,7 +113,6 @@ import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlReplaceStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlResetStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlRollbackStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSQLColumnDefinition; -import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectGroupBy; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock.Limit; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSetCharSetStatement; @@ -1128,22 +1127,6 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV return false; } - @Override - public void endVisit(MySqlSelectGroupBy x) { - - } - - @Override - public boolean visit(MySqlSelectGroupBy x) { - super.visit(x); - - if (x.isRollUp()) { - print0(ucase ? " WITH ROLLUP" : " with rollup"); - } - - return false; - } - @Override public void endVisit(MySqlStartTransactionStatement x) { diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlSchemaStatVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlSchemaStatVisitor.java index 444234d994..3d7d296933 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlSchemaStatVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlSchemaStatVisitor.java @@ -101,7 +101,6 @@ import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlRenameTableStateme import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlReplaceStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlResetStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlRollbackStatement; -import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectGroupBy; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock.Limit; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSetCharSetStatement; @@ -375,17 +374,6 @@ public class MySqlSchemaStatVisitor extends SchemaStatVisitor implements MySqlAS return true; } - @Override - public void endVisit(MySqlSelectGroupBy x) { - - } - - @Override - public boolean visit(MySqlSelectGroupBy x) { - - return true; - } - @Override public void endVisit(MySqlStartTransactionStatement x) { diff --git a/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsSelectParser.java b/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsSelectParser.java index 788e67bfae..59a0c0e1ab 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsSelectParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsSelectParser.java @@ -26,7 +26,6 @@ import com.alibaba.druid.sql.parser.SQLSelectParser; import com.alibaba.druid.sql.parser.Token; public class OdpsSelectParser extends SQLSelectParser { - public OdpsSelectParser(SQLExprParser exprParser){ super(exprParser.getLexer()); this.exprParser = exprParser; diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleSelectParser.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleSelectParser.java index ec1ef80430..c7dd61fcb5 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleSelectParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleSelectParser.java @@ -25,7 +25,6 @@ import com.alibaba.druid.sql.ast.expr.SQLBinaryOperator; import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; import com.alibaba.druid.sql.ast.expr.SQLListExpr; import com.alibaba.druid.sql.ast.statement.SQLSelect; -import com.alibaba.druid.sql.ast.statement.SQLSelectGroupByClause; import com.alibaba.druid.sql.ast.statement.SQLSelectQuery; import com.alibaba.druid.sql.ast.statement.SQLTableSource; import com.alibaba.druid.sql.ast.statement.SQLUnionOperator; @@ -36,7 +35,6 @@ import com.alibaba.druid.sql.dialect.oracle.ast.clause.FlashbackQueryClause; import com.alibaba.druid.sql.dialect.oracle.ast.clause.FlashbackQueryClause.AsOfFlashbackQueryClause; import com.alibaba.druid.sql.dialect.oracle.ast.clause.FlashbackQueryClause.AsOfSnapshotClause; import com.alibaba.druid.sql.dialect.oracle.ast.clause.FlashbackQueryClause.VersionsFlashbackQueryClause; -import com.alibaba.druid.sql.dialect.oracle.ast.clause.GroupingSetExpr; import com.alibaba.druid.sql.dialect.oracle.ast.clause.ModelClause; import com.alibaba.druid.sql.dialect.oracle.ast.clause.ModelClause.CellAssignment; import com.alibaba.druid.sql.dialect.oracle.ast.clause.ModelClause.CellAssignmentItem; @@ -561,74 +559,6 @@ public class OracleSelectParser extends SQLSelectParser { } } - private void parseGroupBy(OracleSelectQueryBlock queryBlock) { - if (lexer.token() == (Token.GROUP)) { - lexer.nextToken(); - accept(Token.BY); - - SQLSelectGroupByClause groupBy = new SQLSelectGroupByClause(); - for (;;) { - if (identifierEquals("GROUPING")) { - GroupingSetExpr groupingSet = new GroupingSetExpr(); - lexer.nextToken(); - acceptIdentifier("SETS"); - accept(Token.LPAREN); - exprParser.exprList(groupingSet.getParameters(), groupingSet); - accept(Token.RPAREN); - groupBy.addItem(groupingSet); - } else { - groupBy.addItem(this.exprParser.expr()); - } - - if (!(lexer.token() == (Token.COMMA))) { - break; - } - - lexer.nextToken(); - } - - if (lexer.token() == (Token.HAVING)) { - lexer.nextToken(); - - groupBy.setHaving(this.exprParser.expr()); - } - - queryBlock.setGroupBy(groupBy); - } else if (lexer.token() == (Token.HAVING)) { - lexer.nextToken(); - - SQLSelectGroupByClause groupBy = new SQLSelectGroupByClause(); - groupBy.setHaving(this.exprParser.expr()); - - if (lexer.token() == (Token.GROUP)) { - lexer.nextToken(); - accept(Token.BY); - - for (;;) { - if (identifierEquals("GROUPING")) { - GroupingSetExpr groupingSet = new GroupingSetExpr(); - lexer.nextToken(); - acceptIdentifier("SETS"); - accept(Token.LPAREN); - exprParser.exprList(groupingSet.getParameters(), groupingSet); - accept(Token.RPAREN); - groupBy.addItem(groupingSet); - } else { - groupBy.addItem(this.exprParser.expr()); - } - - if (!(lexer.token() == (Token.COMMA))) { - break; - } - - lexer.nextToken(); - } - } - - queryBlock.setGroupBy(groupBy); - } - } - protected String as() { if (lexer.token() == Token.CONNECT) { return null; diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVisitor.java index 7cf2f3b65e..4759f3a15f 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVisitor.java @@ -23,7 +23,6 @@ import com.alibaba.druid.sql.dialect.oracle.ast.clause.CycleClause; import com.alibaba.druid.sql.dialect.oracle.ast.clause.FlashbackQueryClause.AsOfFlashbackQueryClause; import com.alibaba.druid.sql.dialect.oracle.ast.clause.FlashbackQueryClause.AsOfSnapshotClause; import com.alibaba.druid.sql.dialect.oracle.ast.clause.FlashbackQueryClause.VersionsFlashbackQueryClause; -import com.alibaba.druid.sql.dialect.oracle.ast.clause.GroupingSetExpr; import com.alibaba.druid.sql.dialect.oracle.ast.clause.ModelClause; import com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleErrorLoggingClause; import com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleLobStorageClause; @@ -223,10 +222,6 @@ public interface OracleASTVisitor extends SQLASTVisitor { void endVisit(AsOfFlashbackQueryClause x); - boolean visit(GroupingSetExpr x); - - void endVisit(GroupingSetExpr x); - boolean visit(OracleWithSubqueryEntry x); void endVisit(OracleWithSubqueryEntry x); diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVisitorAdapter.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVisitorAdapter.java index e5023784ac..35337fd4c2 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVisitorAdapter.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVisitorAdapter.java @@ -23,7 +23,6 @@ import com.alibaba.druid.sql.dialect.oracle.ast.clause.CycleClause; import com.alibaba.druid.sql.dialect.oracle.ast.clause.FlashbackQueryClause.AsOfFlashbackQueryClause; import com.alibaba.druid.sql.dialect.oracle.ast.clause.FlashbackQueryClause.AsOfSnapshotClause; import com.alibaba.druid.sql.dialect.oracle.ast.clause.FlashbackQueryClause.VersionsFlashbackQueryClause; -import com.alibaba.druid.sql.dialect.oracle.ast.clause.GroupingSetExpr; import com.alibaba.druid.sql.dialect.oracle.ast.clause.ModelClause; import com.alibaba.druid.sql.dialect.oracle.ast.clause.ModelClause.CellAssignment; import com.alibaba.druid.sql.dialect.oracle.ast.clause.ModelClause.CellAssignmentItem; @@ -424,17 +423,6 @@ public class OracleASTVisitorAdapter extends SQLASTVisitorAdapter implements Ora } - @Override - public boolean visit(GroupingSetExpr x) { - - return true; - } - - @Override - public void endVisit(GroupingSetExpr x) { - - } - @Override public boolean visit(OracleWithSubqueryEntry x) { diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleOutputVisitor.java index 7515bcc6b0..157dc02f8c 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleOutputVisitor.java @@ -49,7 +49,6 @@ import com.alibaba.druid.sql.dialect.oracle.ast.clause.CycleClause; import com.alibaba.druid.sql.dialect.oracle.ast.clause.FlashbackQueryClause.AsOfFlashbackQueryClause; import com.alibaba.druid.sql.dialect.oracle.ast.clause.FlashbackQueryClause.AsOfSnapshotClause; import com.alibaba.druid.sql.dialect.oracle.ast.clause.FlashbackQueryClause.VersionsFlashbackQueryClause; -import com.alibaba.druid.sql.dialect.oracle.ast.clause.GroupingSetExpr; import com.alibaba.druid.sql.dialect.oracle.ast.clause.ModelClause; import com.alibaba.druid.sql.dialect.oracle.ast.clause.ModelClause.CellAssignment; import com.alibaba.druid.sql.dialect.oracle.ast.clause.ModelClause.CellAssignmentItem; @@ -986,20 +985,6 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS } - @Override - public boolean visit(GroupingSetExpr x) { - print0(ucase ? "GROUPING SETS" : "grouping sets"); - print0(" ("); - printAndAccept(x.getParameters(), ", "); - print(')'); - return false; - } - - @Override - public void endVisit(GroupingSetExpr x) { - - } - @Override public boolean visit(OracleWithSubqueryEntry x) { x.getName().accept(this); diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleSchemaStatVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleSchemaStatVisitor.java index 2dc2e5e84d..3af42132b3 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleSchemaStatVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleSchemaStatVisitor.java @@ -46,7 +46,6 @@ import com.alibaba.druid.sql.dialect.oracle.ast.clause.CycleClause; import com.alibaba.druid.sql.dialect.oracle.ast.clause.FlashbackQueryClause.AsOfFlashbackQueryClause; import com.alibaba.druid.sql.dialect.oracle.ast.clause.FlashbackQueryClause.AsOfSnapshotClause; import com.alibaba.druid.sql.dialect.oracle.ast.clause.FlashbackQueryClause.VersionsFlashbackQueryClause; -import com.alibaba.druid.sql.dialect.oracle.ast.clause.GroupingSetExpr; import com.alibaba.druid.sql.dialect.oracle.ast.clause.ModelClause; import com.alibaba.druid.sql.dialect.oracle.ast.clause.ModelClause.CellAssignment; import com.alibaba.druid.sql.dialect.oracle.ast.clause.ModelClause.CellAssignmentItem; @@ -678,17 +677,6 @@ public class OracleSchemaStatVisitor extends SchemaStatVisitor implements Oracle } - @Override - public boolean visit(GroupingSetExpr x) { - - return true; - } - - @Override - public void endVisit(GroupingSetExpr x) { - - } - @Override public boolean visit(OracleWithSubqueryEntry x) { Map aliasMap = getAliasMap(); diff --git a/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java b/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java index 82dfd7bdfd..186902b4f1 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java @@ -44,6 +44,7 @@ import com.alibaba.druid.sql.ast.expr.SQLCharExpr; import com.alibaba.druid.sql.ast.expr.SQLCurrentOfCursorExpr; import com.alibaba.druid.sql.ast.expr.SQLDefaultExpr; import com.alibaba.druid.sql.ast.expr.SQLExistsExpr; +import com.alibaba.druid.sql.ast.expr.SQLGroupingSetExpr; import com.alibaba.druid.sql.ast.expr.SQLHexExpr; import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; import com.alibaba.druid.sql.ast.expr.SQLInListExpr; @@ -90,7 +91,7 @@ public class SQLExprParser extends SQLParser { public SQLExprParser(String sql){ super(sql); } - + public SQLExprParser(String sql, String dbType){ super(sql, dbType); } @@ -98,7 +99,7 @@ public class SQLExprParser extends SQLParser { public SQLExprParser(Lexer lexer){ super(lexer); } - + public SQLExprParser(Lexer lexer, String dbType){ super(lexer, dbType); } @@ -185,10 +186,10 @@ public class SQLExprParser extends SQLParser { } public SQLExpr primary() { - List beforeComments = null; - if (lexer.isKeepComments() && lexer.hasComment()) { - beforeComments = lexer.readAndResetComments(); - } + List beforeComments = null; + if (lexer.isKeepComments() && lexer.hasComment()) { + beforeComments = lexer.readAndResetComments(); + } SQLExpr sqlExpr = null; @@ -442,12 +443,12 @@ public class SQLExprParser extends SQLParser { case IDENTIFIER: // 当负号后面为字段的情况 sqlExpr = new SQLIdentifierExpr(lexer.stringVal()); lexer.nextToken(); - + if (lexer.token() == Token.LPAREN || lexer.token() == Token.LBRACKET) { sqlExpr = primaryRest(sqlExpr); } sqlExpr = new SQLUnaryExpr(SQLUnaryOperator.Negative, sqlExpr); - + break; case QUES: sqlExpr = new SQLUnaryExpr(SQLUnaryOperator.Negative, new SQLVariantRefExpr("?")); @@ -569,11 +570,11 @@ public class SQLExprParser extends SQLParser { } SQLExpr expr = primaryRest(sqlExpr); - + if (beforeComments != null) { expr.addBeforeComment(beforeComments); } - + return expr; } @@ -614,7 +615,7 @@ public class SQLExprParser extends SQLParser { lexer.nextToken(); if (lexer.token() == Token.LPAREN) { accept(Token.LPAREN); - + if (lexer.token() == Token.IDENTIFIER) { SQLExpr expr = this.expr(); SQLMethodInvokeExpr methodInvokeExpr = new SQLMethodInvokeExpr("ANY"); @@ -622,7 +623,7 @@ public class SQLExprParser extends SQLParser { accept(Token.RPAREN); return methodInvokeExpr; } - + SQLAnyExpr anyExpr = new SQLAnyExpr(); SQLSelect anySubQuery = createSelectParser().select(); anyExpr.setSubQuery(anySubQuery); @@ -636,7 +637,7 @@ public class SQLExprParser extends SQLParser { } return sqlExpr; } - + protected SQLExpr parseAliasExpr(String alias) { return new SQLIdentifierExpr('"' + alias + '"'); } @@ -675,6 +676,19 @@ public class SQLExprParser extends SQLParser { expr = dotRest(expr); return primaryRest(expr); + } else if (identifierEquals("SETS") // + && expr.getClass() == SQLIdentifierExpr.class // + && "GROUPING".equalsIgnoreCase(((SQLIdentifierExpr) expr).getName())) { + SQLGroupingSetExpr groupingSets = new SQLGroupingSetExpr(); + lexer.nextToken(); + + accept(Token.LPAREN); + + this.exprList(groupingSets.getParameters(), groupingSets); + + accept(Token.RPAREN); + + return groupingSets; } else { if (lexer.token() == Token.LPAREN) { return methodRest(expr, true); @@ -713,12 +727,12 @@ public class SQLExprParser extends SQLParser { } accept(Token.RPAREN); - + if (lexer.token() == Token.OVER) { SQLAggregateExpr aggregateExpr = new SQLAggregateExpr(methodName); aggregateExpr.getArguments().addAll(methodInvokeExpr.getParameters()); over(aggregateExpr); - + return primaryRest(aggregateExpr); } @@ -885,7 +899,7 @@ public class SQLExprParser extends SQLParser { case OPTIMIZE: case GRANT: case REVOKE: - //binary有很多含义,lexer识别了这个token,实际上应该当做普通IDENTIFIER + // binary有很多含义,lexer识别了这个token,实际上应该当做普通IDENTIFIER case BINARY: identName = lexer.stringVal(); lexer.nextToken(); @@ -949,7 +963,7 @@ public class SQLExprParser extends SQLParser { } else if (lexer.token() == Token.DISTINCT) { aggregateExpr = new SQLAggregateExpr(methodName, SQLAggregateOption.DISTINCT); lexer.nextToken(); - } else if (identifierEquals("DEDUPLICATION")) { //just for nut + } else if (identifierEquals("DEDUPLICATION")) { // just for nut aggregateExpr = new SQLAggregateExpr(methodName, SQLAggregateOption.DEDUPLICATION); lexer.nextToken(); } else { @@ -1034,7 +1048,7 @@ public class SQLExprParser extends SQLParser { return item; } - + public SQLUpdateSetItem parseUpdateSetItem() { SQLUpdateSetItem item = new SQLUpdateSetItem(); @@ -1052,7 +1066,7 @@ public class SQLExprParser extends SQLParser { } else { accept(Token.EQ); } - + item.setValue(this.expr()); return item; } @@ -1213,9 +1227,9 @@ public class SQLExprParser extends SQLParser { if (lexer.isKeepComments() && lexer.hasComment()) { expr.addAfterComment(lexer.readAndResetComments()); } - + lexer.nextToken(); - + SQLExpr rightExp = relational(); expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.BooleanAnd, rightExp, getDbType()); @@ -1477,15 +1491,12 @@ public class SQLExprParser extends SQLParser { protected boolean isCharType(String dataTypeName) { return "char".equalsIgnoreCase(dataTypeName) // - || "varchar".equalsIgnoreCase(dataTypeName) - || "nchar".equalsIgnoreCase(dataTypeName) - || "nvarchar".equalsIgnoreCase(dataTypeName) - || "tinytext".equalsIgnoreCase(dataTypeName) - || "text".equalsIgnoreCase(dataTypeName) - || "mediumtext".equalsIgnoreCase(dataTypeName) + || "varchar".equalsIgnoreCase(dataTypeName) || "nchar".equalsIgnoreCase(dataTypeName) + || "nvarchar".equalsIgnoreCase(dataTypeName) || "tinytext".equalsIgnoreCase(dataTypeName) + || "text".equalsIgnoreCase(dataTypeName) || "mediumtext".equalsIgnoreCase(dataTypeName) || "longtext".equalsIgnoreCase(dataTypeName) - // - ; + // + ; } protected SQLDataType parseCharTypeRest(SQLCharacterDataType charType) { @@ -1493,7 +1504,7 @@ public class SQLExprParser extends SQLParser { charType.setHasBinary(true); lexer.nextToken(); } - + if (identifierEquals("CHARACTER")) { lexer.nextToken(); @@ -1505,12 +1516,12 @@ public class SQLExprParser extends SQLParser { charType.setCharSetName(lexer.stringVal()); lexer.nextToken(); } - + if (lexer.token() == Token.BINARY) { charType.setHasBinary(true); lexer.nextToken(); } - + if (lexer.token() == Token.IDENTIFIER) { if (lexer.stringVal().equalsIgnoreCase("COLLATE")) { lexer.nextToken(); @@ -1537,9 +1548,9 @@ public class SQLExprParser extends SQLParser { public SQLColumnDefinition parseColumn() { SQLColumnDefinition column = createColumnDefinition(); column.setName(name()); - - if(lexer.token() != Token.SET // - && lexer.token() != Token.DROP) { + + if (lexer.token() != Token.SET // + && lexer.token() != Token.DROP) { column.setDataType(parseDataType()); } return parseColumnRest(column); @@ -1556,7 +1567,7 @@ public class SQLExprParser extends SQLParser { column.setDefaultExpr(bitOr()); return parseColumnRest(column); } - + if (lexer.token() == Token.NOT) { lexer.nextToken(); accept(Token.NULL); @@ -1713,8 +1724,8 @@ public class SQLExprParser extends SQLParser { } else { accept(Token.EQ); } - - if(lexer.token() == Token.ON) { + + if (lexer.token() == Token.ON) { item.setValue(new SQLIdentifierExpr(lexer.stringVal())); lexer.nextToken(); } else { @@ -1725,7 +1736,7 @@ public class SQLExprParser extends SQLParser { item.setValue(expr()); } } - + return item; } @@ -1808,7 +1819,7 @@ public class SQLExprParser extends SQLParser { protected SQLForeignKeyConstraint createForeignKey() { return new SQLForeignKeyImpl(); } - + public SQLSelectItem parseSelectItem() { SQLExpr expr; boolean connectByRoot = false; @@ -1831,4 +1842,25 @@ public class SQLExprParser extends SQLParser { return new SQLSelectItem(expr, alias, connectByRoot); } + + public SQLExpr parseGroupingSet() { + String tmp = lexer.stringVal(); + acceptIdentifier("GROUPING"); + + SQLGroupingSetExpr expr = new SQLGroupingSetExpr(); + + if (identifierEquals("SET")) { + lexer.nextToken(); + } else { + return new SQLIdentifierExpr(tmp); + } + + accept(Token.LPAREN); + + this.exprList(expr.getParameters(), expr); + + accept(Token.RPAREN); + + return expr; + } } diff --git a/src/main/java/com/alibaba/druid/sql/parser/SQLSelectParser.java b/src/main/java/com/alibaba/druid/sql/parser/SQLSelectParser.java index e450cd9237..4a760526f1 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLSelectParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLSelectParser.java @@ -34,9 +34,9 @@ import com.alibaba.druid.sql.ast.statement.SQLUnionOperator; import com.alibaba.druid.sql.ast.statement.SQLUnionQuery; import com.alibaba.druid.sql.ast.statement.SQLUnionQueryTableSource; import com.alibaba.druid.sql.ast.statement.SQLWithSubqueryClause; +import com.alibaba.druid.util.JdbcConstants; public class SQLSelectParser extends SQLParser { - protected SQLExprParser exprParser; public SQLSelectParser(String sql){ @@ -48,7 +48,7 @@ public class SQLSelectParser extends SQLParser { } public SQLSelectParser(SQLExprParser exprParser){ - super(exprParser.getLexer()); + super(exprParser.getLexer(), exprParser.getDbType()); this.exprParser = exprParser; } @@ -257,26 +257,42 @@ public class SQLSelectParser extends SQLParser { queryBlock.setWhere(where); } } - + protected void parseGroupBy(SQLSelectQueryBlock queryBlock) { - if (lexer.token() == Token.GROUP) { + if (lexer.token() == (Token.GROUP)) { lexer.nextToken(); accept(Token.BY); SQLSelectGroupByClause groupBy = new SQLSelectGroupByClause(); - while (true) { - groupBy.addItem(expr()); - if (lexer.token() != Token.COMMA) { + for (;;) { + SQLExpr item = this.exprParser.expr(); + + item.setParent(groupBy); + groupBy.addItem(item); + + if (!(lexer.token() == (Token.COMMA))) { break; } lexer.nextToken(); } - if (lexer.token() == Token.HAVING) { + if (lexer.token() == (Token.HAVING)) { lexer.nextToken(); - groupBy.setHaving(expr()); + SQLExpr having = this.exprParser.expr(); + groupBy.setHaving(having); + } + + if (lexer.token() == Token.WITH) { + lexer.nextToken(); + acceptIdentifier("ROLLUP"); + + groupBy.setRollUp(true); + } + + if(JdbcConstants.MYSQL.equals(getDbType()) && lexer.token() == Token.DESC) { + lexer.nextToken(); // skip } queryBlock.setGroupBy(groupBy); @@ -284,7 +300,37 @@ public class SQLSelectParser extends SQLParser { lexer.nextToken(); SQLSelectGroupByClause groupBy = new SQLSelectGroupByClause(); - groupBy.setHaving(this.expr()); + groupBy.setHaving(this.exprParser.expr()); + + if (lexer.token() == (Token.GROUP)) { + lexer.nextToken(); + accept(Token.BY); + + for (;;) { + SQLExpr item = this.exprParser.expr(); + + item.setParent(groupBy); + groupBy.addItem(item); + + if (!(lexer.token() == (Token.COMMA))) { + break; + } + + lexer.nextToken(); + } + } + + if (lexer.token() == Token.WITH) { + lexer.nextToken(); + acceptIdentifier("ROLLUP"); + + groupBy.setRollUp(true); + } + + if(JdbcConstants.MYSQL.equals(getDbType()) && lexer.token() == Token.DESC) { + lexer.nextToken(); // skip + } + queryBlock.setGroupBy(groupBy); } } 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 a9f2c50847..decf6d524e 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java @@ -50,6 +50,7 @@ import com.alibaba.druid.sql.ast.expr.SQLCharExpr; import com.alibaba.druid.sql.ast.expr.SQLCurrentOfCursorExpr; import com.alibaba.druid.sql.ast.expr.SQLDefaultExpr; import com.alibaba.druid.sql.ast.expr.SQLExistsExpr; +import com.alibaba.druid.sql.ast.expr.SQLGroupingSetExpr; import com.alibaba.druid.sql.ast.expr.SQLHexExpr; import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; import com.alibaba.druid.sql.ast.expr.SQLInListExpr; @@ -743,6 +744,11 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Printab print0(ucase ? "HAVING " : "having "); x.getHaving().accept(this); } + + if (x.isRollUp()) { + print0(ucase ? " WITH ROLLUP" : " with rollup"); + } + return false; } @@ -2434,6 +2440,15 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Printab return false; } + @Override + public boolean visit(SQLGroupingSetExpr x) { + print0(ucase ? "GROUPING SETS" : "grouping sets"); + print0(" ("); + printAndAccept(x.getParameters(), ", "); + print(')'); + return false; + } + public boolean isUppCase() { return ucase; } diff --git a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitor.java b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitor.java index 50007cffc5..dd019e9017 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitor.java @@ -35,6 +35,7 @@ import com.alibaba.druid.sql.ast.expr.SQLCharExpr; import com.alibaba.druid.sql.ast.expr.SQLCurrentOfCursorExpr; import com.alibaba.druid.sql.ast.expr.SQLDefaultExpr; import com.alibaba.druid.sql.ast.expr.SQLExistsExpr; +import com.alibaba.druid.sql.ast.expr.SQLGroupingSetExpr; import com.alibaba.druid.sql.ast.expr.SQLHexExpr; import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; import com.alibaba.druid.sql.ast.expr.SQLInListExpr; @@ -638,5 +639,8 @@ public interface SQLASTVisitor { void endVisit(SQLCloseStatement x); boolean visit(SQLCloseStatement x); - + + boolean visit(SQLGroupingSetExpr x); + + void endVisit(SQLGroupingSetExpr x); } diff --git a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitorAdapter.java b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitorAdapter.java index 4594ae66bd..5712167c4d 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitorAdapter.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitorAdapter.java @@ -36,6 +36,7 @@ import com.alibaba.druid.sql.ast.expr.SQLCharExpr; import com.alibaba.druid.sql.ast.expr.SQLCurrentOfCursorExpr; import com.alibaba.druid.sql.ast.expr.SQLDefaultExpr; import com.alibaba.druid.sql.ast.expr.SQLExistsExpr; +import com.alibaba.druid.sql.ast.expr.SQLGroupingSetExpr; import com.alibaba.druid.sql.ast.expr.SQLHexExpr; import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; import com.alibaba.druid.sql.ast.expr.SQLInListExpr; @@ -1268,5 +1269,15 @@ public class SQLASTVisitorAdapter implements SQLASTVisitor { public boolean visit(SQLCloseStatement x) { return true; } + + @Override + public boolean visit(SQLGroupingSetExpr x) { + return true; + } + + @Override + public void endVisit(SQLGroupingSetExpr x) { + + } } diff --git a/src/main/java/com/alibaba/druid/wall/spi/MySqlWallVisitor.java b/src/main/java/com/alibaba/druid/wall/spi/MySqlWallVisitor.java index 85ac2ecee0..a2b8f62e23 100644 --- a/src/main/java/com/alibaba/druid/wall/spi/MySqlWallVisitor.java +++ b/src/main/java/com/alibaba/druid/wall/spi/MySqlWallVisitor.java @@ -50,7 +50,6 @@ import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStateme import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlDeleteStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlInsertStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlReplaceStatement; -import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectGroupBy; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock.Limit; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlShowCreateTableStatement; @@ -144,11 +143,6 @@ public class MySqlWallVisitor extends MySqlASTVisitorAdapter implements WallVisi return true; } - public boolean visit(MySqlSelectGroupBy x) { - WallVisitorUtils.checkHaving(this, x.getHaving()); - return true; - } - @Override public boolean visit(MySqlDeleteStatement x) { WallVisitorUtils.checkReadOnly(this, x.getFrom()); diff --git a/src/test/java/com/alibaba/druid/bvt/sql/EqualTest_groupSet.java b/src/test/java/com/alibaba/druid/bvt/sql/EqualTest_groupSet.java index 0dfe838e1a..57f3b85289 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/EqualTest_groupSet.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/EqualTest_groupSet.java @@ -4,13 +4,13 @@ import junit.framework.TestCase; import org.junit.Assert; -import com.alibaba.druid.sql.dialect.oracle.ast.clause.GroupingSetExpr; +import com.alibaba.druid.sql.ast.expr.SQLGroupingSetExpr; public class EqualTest_groupSet extends TestCase { public void test_eq() throws Exception { - GroupingSetExpr exprA = new GroupingSetExpr(); - GroupingSetExpr exprB = new GroupingSetExpr(); + SQLGroupingSetExpr exprA = new SQLGroupingSetExpr(); + SQLGroupingSetExpr exprB = new SQLGroupingSetExpr(); Assert.assertEquals(exprA.hashCode(), exprB.hashCode()); Assert.assertEquals(exprA, exprB); } diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlASTVisitorAdapterTest.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlASTVisitorAdapterTest.java index f2fb0cc1c3..b117a30bca 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlASTVisitorAdapterTest.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlASTVisitorAdapterTest.java @@ -1,7 +1,5 @@ package com.alibaba.druid.bvt.sql.mysql; -import junit.framework.TestCase; - import com.alibaba.druid.sql.ast.expr.SQLBinaryExpr; import com.alibaba.druid.sql.ast.expr.SQLBooleanExpr; import com.alibaba.druid.sql.dialect.mysql.ast.MySqlForceIndexHint; @@ -44,7 +42,6 @@ import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlRenameTableStateme import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlReplaceStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlResetStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlRollbackStatement; -import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectGroupBy; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock.Limit; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSetCharSetStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSetNamesStatement; @@ -97,6 +94,8 @@ import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlUnlockTablesStatem import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlUpdateStatement; import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitorAdapter; +import junit.framework.TestCase; + public class MySqlASTVisitorAdapterTest extends TestCase { public void test_adapter() throws Exception { @@ -114,7 +113,6 @@ public class MySqlASTVisitorAdapterTest extends TestCase { new MySqlInsertStatement().accept(adapter); new MySqlLoadXmlStatement().accept(adapter); new MySqlReplaceStatement().accept(adapter); - new MySqlSelectGroupBy().accept(adapter); new MySqlStartTransactionStatement().accept(adapter); new MySqlRollbackStatement().accept(adapter); new MySqlShowColumnsStatement().accept(adapter); diff --git a/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleGroupingSetsTest.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleGroupingSetsTest.java new file mode 100644 index 0000000000..f0f4520e1e --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleGroupingSetsTest.java @@ -0,0 +1,35 @@ +package com.alibaba.druid.bvt.sql.oracle; + +import java.util.List; + +import org.junit.Assert; + +import com.alibaba.druid.sql.OracleTest; +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.oracle.parser.OracleStatementParser; +import com.alibaba.druid.sql.dialect.oracle.visitor.OracleSchemaStatVisitor; +import com.alibaba.druid.util.JdbcConstants; + +public class OracleGroupingSetsTest extends OracleTest { + + public void test_grouping_sets() throws Exception { + String sql = // + "select department_id,job_id,avg(salary) from hr.employees group by grouping sets ((department_id,job_id));"; + + OracleStatementParser parser = new OracleStatementParser(sql); + List statementList = parser.parseStatementList(); + SQLStatement stmt = statementList.get(0); + print(statementList); + Assert.assertEquals(1, statementList.size()); + + Assert.assertEquals("SELECT department_id, job_id, AVG(salary)" + + "\nFROM hr.employees" + + "\nGROUP BY GROUPING SETS ((department_id, job_id))", SQLUtils.toSQLString(stmt, JdbcConstants.ORACLE)); + + OracleSchemaStatVisitor visitor = new OracleSchemaStatVisitor(); + stmt.accept(visitor); + + Assert.assertEquals(1, visitor.getTables().size()); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/oracle/visitor/OracleASTVisitorAdapterTest.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/visitor/OracleASTVisitorAdapterTest.java index 49bb789a19..42471add0b 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/oracle/visitor/OracleASTVisitorAdapterTest.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/visitor/OracleASTVisitorAdapterTest.java @@ -2,6 +2,7 @@ package com.alibaba.druid.bvt.sql.oracle.visitor; import junit.framework.TestCase; +import com.alibaba.druid.sql.ast.expr.SQLGroupingSetExpr; import com.alibaba.druid.sql.ast.expr.SQLTimestampExpr; import com.alibaba.druid.sql.ast.statement.SQLFetchStatement; import com.alibaba.druid.sql.ast.statement.SQLAlterTableRename; @@ -13,7 +14,6 @@ import com.alibaba.druid.sql.dialect.oracle.ast.clause.CycleClause; import com.alibaba.druid.sql.dialect.oracle.ast.clause.FlashbackQueryClause.AsOfFlashbackQueryClause; import com.alibaba.druid.sql.dialect.oracle.ast.clause.FlashbackQueryClause.AsOfSnapshotClause; import com.alibaba.druid.sql.dialect.oracle.ast.clause.FlashbackQueryClause.VersionsFlashbackQueryClause; -import com.alibaba.druid.sql.dialect.oracle.ast.clause.GroupingSetExpr; import com.alibaba.druid.sql.dialect.oracle.ast.clause.ModelClause; import com.alibaba.druid.sql.dialect.oracle.ast.clause.ModelClause.CellAssignment; import com.alibaba.druid.sql.dialect.oracle.ast.clause.ModelClause.CellAssignmentItem; @@ -130,7 +130,7 @@ public class OracleASTVisitorAdapterTest extends TestCase { new VersionsFlashbackQueryClause().accept(adapter); new VersionsFlashbackQueryClause().accept(adapter); new AsOfFlashbackQueryClause().accept(adapter); - new GroupingSetExpr().accept(adapter); + new SQLGroupingSetExpr().accept(adapter); new OracleWithSubqueryEntry().accept(adapter); new OracleFileSpecification().accept(adapter); new OracleAlterTablespaceAddDataFile().accept(adapter);