refactor sql parser group by

This commit is contained in:
高铁
2016-01-09 13:56:09 +08:00
parent 739645fbf1
commit b4155d7be2
26 changed files with 220 additions and 329 deletions
@@ -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<SQLExpr> parameters = new ArrayList<SQLExpr>();
@@ -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;
@@ -26,6 +26,7 @@ public class SQLSelectGroupByClause extends SQLObjectImpl {
private final List<SQLExpr> items = new ArrayList<SQLExpr>();
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;
}
@@ -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();
}
@@ -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;
}
@@ -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;
@@ -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;
@@ -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);
@@ -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) {
@@ -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) {
@@ -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) {
@@ -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;
@@ -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;
@@ -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);
@@ -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) {
@@ -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);
@@ -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<String, String> aliasMap = getAliasMap();
@@ -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<String> beforeComments = null;
if (lexer.isKeepComments() && lexer.hasComment()) {
beforeComments = lexer.readAndResetComments();
}
List<String> 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;
}
}
@@ -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);
}
}
@@ -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;
}
@@ -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);
}
@@ -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) {
}
}
@@ -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());
@@ -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);
}
@@ -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);
@@ -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<SQLStatement> 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());
}
}
@@ -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);