diff --git a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLAggregateExpr.java b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLAggregateExpr.java index 8abf08b232..f928dde609 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLAggregateExpr.java +++ b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLAggregateExpr.java @@ -27,16 +27,15 @@ public class SQLAggregateExpr extends SQLExprImpl implements Serializable { private static final long serialVersionUID = 1L; protected String methodName; - protected int option; + protected Option option; protected final List arguments = new ArrayList(); public SQLAggregateExpr(String methodName){ this.methodName = methodName; - this.option = 1; } - public SQLAggregateExpr(String methodName, int option){ + public SQLAggregateExpr(String methodName, Option option){ this.methodName = methodName; this.option = option; } @@ -49,11 +48,11 @@ public class SQLAggregateExpr extends SQLExprImpl implements Serializable { this.methodName = methodName; } - public int getOption() { + public Option getOption() { return this.option; } - public void setOption(int option) { + public void setOption(Option option) { this.option = option; } @@ -86,7 +85,7 @@ public class SQLAggregateExpr extends SQLExprImpl implements Serializable { int result = 1; result = prime * result + ((arguments == null) ? 0 : arguments.hashCode()); result = prime * result + ((methodName == null) ? 0 : methodName.hashCode()); - result = prime * result + option; + result = prime * result + ((option == null) ? 0 : option.hashCode()); return result; } @@ -121,4 +120,8 @@ public class SQLAggregateExpr extends SQLExprImpl implements Serializable { } return true; } + + public static enum Option { + DISTINCT, ALL + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleAggregateExpr.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleAggregateExpr.java index f1619e5157..c87bc58921 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleAggregateExpr.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleAggregateExpr.java @@ -49,7 +49,7 @@ public class OracleAggregateExpr extends SQLAggregateExpr implements Serializabl super(methodName); } - public OracleAggregateExpr(String methodName, int option){ + public OracleAggregateExpr(String methodName, Option option){ super(methodName, option); } 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 bce3bfc56d..a71bab7efe 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 @@ -22,6 +22,7 @@ import com.alibaba.druid.sql.ast.SQLDataTypeImpl; import com.alibaba.druid.sql.ast.SQLExpr; import com.alibaba.druid.sql.ast.SQLName; import com.alibaba.druid.sql.ast.SQLOrderingSpecification; +import com.alibaba.druid.sql.ast.expr.SQLAggregateExpr; import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr; import com.alibaba.druid.sql.ast.expr.SQLBinaryOperator; import com.alibaba.druid.sql.ast.expr.SQLCharExpr; @@ -524,9 +525,11 @@ public class OracleExprParser extends SQLExprParser { return null; } - protected OracleAggregateExpr parseAggregateExpr(String method_name) { + protected OracleAggregateExpr parseAggregateExpr(String methodName) { boolean unique = false; + methodName = methodName.toUpperCase(); + if (lexer.token() == Token.UNIQUE) { lexer.nextToken(); unique = true; @@ -534,13 +537,13 @@ public class OracleExprParser extends SQLExprParser { OracleAggregateExpr aggregateExpr; if (lexer.token() == (Token.ALL)) { - aggregateExpr = new OracleAggregateExpr(method_name, 1); + aggregateExpr = new OracleAggregateExpr(methodName, SQLAggregateExpr.Option.ALL); lexer.nextToken(); } else if (lexer.token() == (Token.DISTINCT)) { - aggregateExpr = new OracleAggregateExpr(method_name, 0); + aggregateExpr = new OracleAggregateExpr(methodName, SQLAggregateExpr.Option.DISTINCT); lexer.nextToken(); } else { - aggregateExpr = new OracleAggregateExpr(method_name, 1); + aggregateExpr = new OracleAggregateExpr(methodName); } aggregateExpr.setUnique(unique); exprList(aggregateExpr.getArguments()); 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 d36d120b78..6c2c2c47cb 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 @@ -211,6 +211,12 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS public boolean visit(OracleAggregateExpr expr) { print(expr.getMethodName()); print("("); + + if (expr.getOption() != null) { + print(expr.getOption().toString()); + print(' '); + } + if (expr.isUnique()) { print("UNIQUE "); } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/PGAggregateExpr.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/PGAggregateExpr.java index 390aed24a9..8a6cf87318 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/PGAggregateExpr.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/PGAggregateExpr.java @@ -20,7 +20,7 @@ public class PGAggregateExpr extends SQLAggregateExpr implements PGSQLObject { private static final long serialVersionUID = 1L; - public PGAggregateExpr(String methodName, int option) { + public PGAggregateExpr(String methodName, Option option) { super(methodName, option); } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGExprParser.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGExprParser.java index 4d4ec91164..5ace50df14 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGExprParser.java @@ -19,16 +19,18 @@ public class PGExprParser extends SQLExprParser{ super(lexer); } - protected SQLAggregateExpr parseAggregateExpr(String method_name) throws ParserException { + protected SQLAggregateExpr parseAggregateExpr(String methodName) throws ParserException { + methodName = methodName.toUpperCase(); + PGAggregateExpr aggregateExpr; if (lexer.token() == Token.ALL) { - aggregateExpr = new PGAggregateExpr(method_name, 1); + aggregateExpr = new PGAggregateExpr(methodName, SQLAggregateExpr.Option.ALL); lexer.nextToken(); } else if (lexer.token() == Token.DISTINCT) { - aggregateExpr = new PGAggregateExpr(method_name, 0); + aggregateExpr = new PGAggregateExpr(methodName, SQLAggregateExpr.Option.DISTINCT); lexer.nextToken(); } else { - aggregateExpr = new PGAggregateExpr(method_name, 1); + aggregateExpr = new PGAggregateExpr(methodName); } exprList(aggregateExpr.getArguments()); diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGOutputVisitor.java index 38ddec0c02..23784425f3 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGOutputVisitor.java @@ -433,12 +433,21 @@ public class PGOutputVisitor extends SQLASTOutputVisitor implements PGASTVisitor @Override public boolean visit(PGAggregateExpr x) { print(x.getMethodName()); + print("("); + + if (x.getOption() != null) { + print(x.getOption().toString()); + print(' '); + } + printAndAccept(x.getArguments(), ", "); print(")"); + if (x.getOver() != null) { x.getOver().accept(this); } + return false; } 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 3d8f089750..9c5aa476d1 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java @@ -675,16 +675,18 @@ public class SQLExprParser extends SQLParser { return false; } - protected SQLAggregateExpr parseAggregateExpr(String method_name) throws ParserException { + protected SQLAggregateExpr parseAggregateExpr(String methodName) throws ParserException { + methodName = methodName.toUpperCase(); + SQLAggregateExpr aggregateExpr; if (lexer.token() == Token.ALL) { - aggregateExpr = new SQLAggregateExpr(method_name, 1); + aggregateExpr = new SQLAggregateExpr(methodName, SQLAggregateExpr.Option.ALL); lexer.nextToken(); } else if (lexer.token() == Token.DISTINCT) { - aggregateExpr = new SQLAggregateExpr(method_name, 0); + aggregateExpr = new SQLAggregateExpr(methodName, SQLAggregateExpr.Option.DISTINCT); lexer.nextToken(); } else { - aggregateExpr = new SQLAggregateExpr(method_name, 1); + aggregateExpr = new SQLAggregateExpr(methodName); } exprList(aggregateExpr.getArguments()); 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 7686462365..3ea42f7244 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java @@ -426,6 +426,12 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter { public boolean visit(SQLAggregateExpr x) { print(x.getMethodName()); print("("); + + if (x.getOption() != null) { + print(x.getOption().toString()); + print(' '); + } + printAndAccept(x.getArguments(), ", "); print(")"); return false; diff --git a/src/main/java/com/alibaba/druid/stat/JdbcStatManagerFactoryBean.java b/src/main/java/com/alibaba/druid/stat/JdbcStatManagerFactoryBean.java index 9bc3f85a4b..68cc92360f 100644 --- a/src/main/java/com/alibaba/druid/stat/JdbcStatManagerFactoryBean.java +++ b/src/main/java/com/alibaba/druid/stat/JdbcStatManagerFactoryBean.java @@ -17,10 +17,10 @@ package com.alibaba.druid.stat; import org.springframework.beans.factory.FactoryBean; -public class JdbcStatManagerFactoryBean implements FactoryBean { +public class JdbcStatManagerFactoryBean implements FactoryBean { @Override - public Object getObject() throws Exception { + public JdbcStatManager getObject() throws Exception { return JdbcStatManager.getInstance(); } diff --git a/src/main/java/com/alibaba/druid/support/spring/MBeanServerFactoryBean.java b/src/main/java/com/alibaba/druid/support/spring/MBeanServerFactoryBean.java index 23e117e639..5ba4e3e697 100644 --- a/src/main/java/com/alibaba/druid/support/spring/MBeanServerFactoryBean.java +++ b/src/main/java/com/alibaba/druid/support/spring/MBeanServerFactoryBean.java @@ -6,7 +6,7 @@ import javax.management.MBeanServer; import org.springframework.beans.factory.FactoryBean; -public class MBeanServerFactoryBean implements FactoryBean { +public class MBeanServerFactoryBean implements FactoryBean { public MBeanServer getObject() throws Exception { return ManagementFactory.getPlatformMBeanServer(); diff --git a/src/test/java/com/alibaba/druid/bvt/sql/DistinctTest.java b/src/test/java/com/alibaba/druid/bvt/sql/DistinctTest.java new file mode 100644 index 0000000000..1eb807dd2e --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/DistinctTest.java @@ -0,0 +1,28 @@ +package com.alibaba.druid.bvt.sql; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.util.JdbcUtils; + + +public class DistinctTest extends TestCase { + private String sql = "select count(distinct *) from t"; + + public void test_mysql() throws Exception { + Assert.assertEquals("SELECT COUNT(DISTINCT *)\nFROM t", SQLUtils.format(sql, JdbcUtils.MYSQL)); + } + + public void test_oracle() throws Exception { + Assert.assertEquals("SELECT COUNT(DISTINCT *)\nFROM t", SQLUtils.format(sql, JdbcUtils.ORACLE)); + } + + public void test_postgres() throws Exception { + Assert.assertEquals("SELECT COUNT(DISTINCT *)\nFROM t", SQLUtils.format(sql, JdbcUtils.POSTGRESQL)); + } + + public void test_sql92() throws Exception { + Assert.assertEquals("SELECT COUNT(DISTINCT *)\nFROM t", SQLUtils.format(sql, null)); + } +}