From 947190c6a009fa8cda0c3c87b05fa78de17594f4 Mon Sep 17 00:00:00 2001 From: huangtiande Date: Thu, 5 Feb 2015 15:32:12 +0800 Subject: [PATCH] =?UTF-8?q?fix=20postgresql=20parenthesized=20bug=20exampl?= =?UTF-8?q?e:=201=E3=80=81(select=20*=20from=20a)=202=E3=80=81(select=20*?= =?UTF-8?q?=20from=20a)=20union=20all=20select=20*=20from=20b;=20pg?= =?UTF-8?q?=E4=BB=A5=E6=8B=AC=E5=8F=B7=E5=BC=80=E5=A4=B4=E7=9A=84select?= =?UTF-8?q?=E8=AF=AD=E5=8F=A5=E4=BC=9A=E9=99=B7=E5=85=A5=E6=AD=BB=E5=BE=AA?= =?UTF-8?q?=E7=8E=AF=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ast/statement/SQLSelectQueryBlock.java | 13 ++++++++++- .../postgresql/parser/PGSelectParser.java | 13 +++++++++++ .../bvt/sql/postgresql/PGSelectTest1.java | 23 +++++++++++++++++++ 3 files changed, 48 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectQueryBlock.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectQueryBlock.java index e9ed0cab98..79331a3e0e 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectQueryBlock.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectQueryBlock.java @@ -31,6 +31,7 @@ public class SQLSelectQueryBlock extends SQLObjectImpl implements SQLSelectQuery protected SQLExprTableSource into; protected SQLExpr where; protected SQLSelectGroupByClause groupBy; + protected boolean parenthesized = false; public SQLSelectQueryBlock(){ @@ -90,7 +91,15 @@ public class SQLSelectQueryBlock extends SQLObjectImpl implements SQLSelectQuery this.from = from; } - @Override + public boolean isParenthesized() { + return parenthesized; + } + + public void setParenthesized(boolean parenthesized) { + this.parenthesized = parenthesized; + } + + @Override protected void accept0(SQLASTVisitor visitor) { if (visitor.visit(this)) { acceptChild(visitor, this.selectList); @@ -105,6 +114,7 @@ public class SQLSelectQueryBlock extends SQLObjectImpl implements SQLSelectQuery public int hashCode() { final int prime = 31; int result = 1; + result = prime * result + (Boolean.valueOf(parenthesized).hashCode()); result = prime * result + distionOption; result = prime * result + ((from == null) ? 0 : from.hashCode()); result = prime * result + ((groupBy == null) ? 0 : groupBy.hashCode()); @@ -120,6 +130,7 @@ public class SQLSelectQueryBlock extends SQLObjectImpl implements SQLSelectQuery if (obj == null) return false; if (getClass() != obj.getClass()) return false; SQLSelectQueryBlock other = (SQLSelectQueryBlock) obj; + if (parenthesized ^ other.parenthesized) return false; if (distionOption != other.distionOption) return false; if (from == null) { if (other.from != null) return false; diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGSelectParser.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGSelectParser.java index 1b9ff7dd40..d3abbba30d 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGSelectParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGSelectParser.java @@ -22,6 +22,7 @@ import com.alibaba.druid.sql.ast.SQLSetQuantifier; import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; import com.alibaba.druid.sql.ast.statement.SQLExprTableSource; import com.alibaba.druid.sql.ast.statement.SQLSelectQuery; +import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock; import com.alibaba.druid.sql.ast.statement.SQLTableSource; import com.alibaba.druid.sql.dialect.postgresql.ast.expr.PGParameter; import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGFunctionTableSource; @@ -58,6 +59,18 @@ public class PGSelectParser extends SQLSelectParser { return queryRest(valuesQuery); } + if (lexer.token() == Token.LPAREN) { + lexer.nextToken(); + + SQLSelectQuery select = query(); + if (select instanceof SQLSelectQueryBlock) { + ((SQLSelectQueryBlock) select).setParenthesized(true); + } + accept(Token.RPAREN); + + return queryRest(select); + } + PGSelectQueryBlock queryBlock = new PGSelectQueryBlock(); if (lexer.token() == Token.SELECT) { diff --git a/src/test/java/com/alibaba/druid/bvt/sql/postgresql/PGSelectTest1.java b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/PGSelectTest1.java index 54deb993e6..cc9302e42b 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/postgresql/PGSelectTest1.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/PGSelectTest1.java @@ -21,6 +21,9 @@ import org.junit.Assert; import com.alibaba.druid.sql.PGTest; import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock; +import com.alibaba.druid.sql.ast.statement.SQLUnionQuery; +import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectStatement; import com.alibaba.druid.sql.dialect.postgresql.parser.PGSQLStatementParser; import com.alibaba.druid.sql.dialect.postgresql.visitor.PGSchemaStatVisitor; @@ -46,6 +49,26 @@ public class PGSelectTest1 extends PGTest { Assert.assertEquals(0, visitor.getColumns().size()); Assert.assertEquals(2, visitor.getTables().size()); } + + public void test_1() throws Exception { + String sql = "(select * from a) union select * from b"; + PGSQLStatementParser parser = new PGSQLStatementParser(sql); + List statementList = parser.parseStatementList(); + SQLStatement statemen = statementList.get(0); + print(statementList); + + Assert.assertEquals(1, statementList.size()); + assertTrue(statemen instanceof PGSelectStatement); + PGSelectStatement select = (PGSelectStatement) statemen; + assertTrue(select.getSelect().getQuery() instanceof SQLUnionQuery); + SQLUnionQuery unionQuery = (SQLUnionQuery) select.getSelect() + .getQuery(); + assertTrue(unionQuery.getLeft() instanceof SQLSelectQueryBlock); + assertTrue(unionQuery.getRight() instanceof SQLSelectQueryBlock); + SQLSelectQueryBlock leftQueryBlock = (SQLSelectQueryBlock) unionQuery + .getLeft(); + assertTrue(leftQueryBlock.isParenthesized()); + } }