From 58fe2966459d38ed4ac25d925d299afdb2e7a7fa Mon Sep 17 00:00:00 2001 From: wenshao Date: Tue, 2 Jun 2015 04:31:06 +0800 Subject: [PATCH] improve postgresql support --- .../postgresql/ast/expr/PGArrayExpr.java | 20 ++++- .../postgresql/parser/PGExprParser.java | 12 ++- .../postgresql/visitor/PGOutputVisitor.java | 3 +- .../bvt/sql/postgresql/PGSelectTest22.java | 83 +++++++++++++++++++ 4 files changed, 115 insertions(+), 3 deletions(-) create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/postgresql/PGSelectTest22.java diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/expr/PGArrayExpr.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/expr/PGArrayExpr.java index 3b6199495e..65783b444c 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/expr/PGArrayExpr.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/expr/PGArrayExpr.java @@ -23,8 +23,18 @@ import com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor; public class PGArrayExpr extends PGExprImpl { + private SQLExpr expr; + private List values = new ArrayList(); + public SQLExpr getExpr() { + return expr; + } + + public void setExpr(SQLExpr expr) { + this.expr = expr; + } + public List getValues() { return values; } @@ -36,6 +46,7 @@ public class PGArrayExpr extends PGExprImpl { @Override public void accept0(PGASTVisitor visitor) { if (visitor.visit(this)) { + acceptChild(visitor, expr); acceptChild(visitor, values); } visitor.endVisit(this); @@ -43,7 +54,11 @@ public class PGArrayExpr extends PGExprImpl { @Override public int hashCode() { - return values.hashCode(); + final int prime = 31; + int result = 1; + result = prime * result + ((expr == null) ? 0 : expr.hashCode()); + result = prime * result + ((values == null) ? 0 : values.hashCode()); + return result; } @Override @@ -52,6 +67,9 @@ public class PGArrayExpr extends PGExprImpl { if (obj == null) return false; if (getClass() != obj.getClass()) return false; PGArrayExpr other = (PGArrayExpr) obj; + if (expr == null) { + if (other.expr != null) return false; + } else if (!expr.equals(other.expr)) return false; if (values == null) { if (other.values != null) return false; } else if (!values.equals(other.values)) return false; 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 6f8963b423..4fa5092a43 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 @@ -69,8 +69,9 @@ public class PGExprParser extends SQLExprParser { public SQLExpr primary() { if (lexer.token() == Token.ARRAY) { - lexer.nextToken(); PGArrayExpr array = new PGArrayExpr(); + array.setExpr(new SQLIdentifierExpr(lexer.stringVal())); + lexer.nextToken(); accept(Token.LBRACKET); this.exprList(array.getValues(), array); accept(Token.RBRACKET); @@ -119,6 +120,15 @@ public class PGExprParser extends SQLExprParser { return primaryRest(castExpr); } + if (lexer.token() == Token.LBRACKET) { + PGArrayExpr array = new PGArrayExpr(); + array.setExpr(expr); + lexer.nextToken(); + this.exprList(array.getValues(), array); + accept(Token.RBRACKET); + return primaryRest(array); + } + if (expr.getClass() == SQLIdentifierExpr.class) { String ident = ((SQLIdentifierExpr)expr).getName(); 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 1a4c8979ab..a61e03a938 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 @@ -519,7 +519,8 @@ public class PGOutputVisitor extends SQLASTOutputVisitor implements PGASTVisitor @Override public boolean visit(PGArrayExpr x) { - print("ARRAY["); + x.getExpr().accept(this); + print("["); printAndAccept(x.getValues(), ", "); print("]"); return false; diff --git a/src/test/java/com/alibaba/druid/bvt/sql/postgresql/PGSelectTest22.java b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/PGSelectTest22.java new file mode 100644 index 0000000000..211a05e486 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/PGSelectTest22.java @@ -0,0 +1,83 @@ +/* + * Copyright 1999-2011 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.druid.bvt.sql.postgresql; + +import java.util.List; + +import org.junit.Assert; + +import com.alibaba.druid.sql.PGTest; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.postgresql.parser.PGSQLStatementParser; +import com.alibaba.druid.sql.dialect.postgresql.visitor.PGSchemaStatVisitor; + +public class PGSelectTest22 extends PGTest { + + public void test_0() throws Exception { + String sql = "SELECT i.relname, d.indisunique, a.attname" + + " FROM pg_class t, pg_class i, pg_index d, pg_attribute " + + " WHERE i.relkind = 'i'" + + " AND d.indexrelid = i.oid" + + " AND d.indisprimary = 'f'" + + " AND t.oid = d.indrelid" + + " AND t.relname = 'schema_migrations'" + + " AND a.attrelid = t.oid" + + " AND ( d.indkey[0]=a.attnum OR d.indkey[1]=a.attnum" + + " OR d.indkey[2]=a.attnum OR d.indkey[3]=a.attnum" + + " OR d.indkey[4]=a.attnum OR d.indkey[5]=a.attnum" + + " OR d.indkey[6]=a.attnum OR d.indkey[7]=a.attnum" + + " OR d.indkey[8]=a.attnum OR d.indkey[9]=a.attnum )" + + " ORDER BY i.relname" + + ""; + + PGSQLStatementParser parser = new PGSQLStatementParser(sql); + List statementList = parser.parseStatementList(); + SQLStatement statemen = statementList.get(0); + print(statementList); + + Assert.assertEquals("SELECT i.relname, d.indisunique, a.attname" + + "\nFROM pg_class t, pg_class i, pg_index d, pg_attribute" + + "\nWHERE i.relkind = 'i'" + + "\n\tAND d.indexrelid = i.oid" + + "\n\tAND d.indisprimary = 'f'" + + "\n\tAND t.oid = d.indrelid" + + "\n\tAND t.relname = 'schema_migrations'" + + "\n\tAND a.attrelid = t.oid" + + "\n\tAND (d.indkey[0] = a.attnum" + + "\n\t\tOR d.indkey[1] = a.attnum" + + "\n\t\tOR d.indkey[2] = a.attnum" + + "\n\t\tOR d.indkey[3] = a.attnum" + + "\n\t\tOR d.indkey[4] = a.attnum" + + "\n\t\tOR d.indkey[5] = a.attnum" + + "\n\t\tOR d.indkey[6] = a.attnum" + + "\n\t\tOR d.indkey[7] = a.attnum" + + "\n\t\tOR d.indkey[8] = a.attnum" + + "\n\t\tOR d.indkey[9] = a.attnum)" + + "\nORDER BY i.relname", output(statementList)); + + Assert.assertEquals(1, statementList.size()); + + PGSchemaStatVisitor visitor = new PGSchemaStatVisitor(); + statemen.accept(visitor); + + System.out.println("Tables : " + visitor.getTables()); + System.out.println("fields : " + visitor.getColumns()); + System.out.println("coditions : " + visitor.getConditions()); + + Assert.assertEquals(11, visitor.getColumns().size()); + Assert.assertEquals(3, visitor.getTables().size()); + } +}