diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/PGCurrentOfExpr.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/PGCurrentOfExpr.java new file mode 100644 index 0000000000..b8a2dd16ac --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/PGCurrentOfExpr.java @@ -0,0 +1,27 @@ +package com.alibaba.druid.sql.dialect.postgresql.ast; + +import com.alibaba.druid.sql.ast.SQLExpr; +import com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor; + +public class PGCurrentOfExpr extends PGSQLObjectImpl implements SQLExpr { + + private static final long serialVersionUID = 1L; + private SQLExpr cursor; + + public SQLExpr getCursor() { + return cursor; + } + + public void setCursor(SQLExpr cursor) { + this.cursor = cursor; + } + + @Override + public void accept0(PGASTVisitor visitor) { + if (visitor.visit(this)) { + acceptChild(visitor, cursor); + } + visitor.endVisit(this); + } + +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/PGSelectQueryBlock.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/PGSelectQueryBlock.java index c02e4d9e53..05fc7d48e8 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/PGSelectQueryBlock.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/PGSelectQueryBlock.java @@ -147,6 +147,7 @@ public class PGSelectQueryBlock extends SQLSelectQueryBlock { acceptChild(visitor, name); acceptChild(visitor, definition); } + visitor.endVisit(this); } } @@ -181,6 +182,7 @@ public class PGSelectQueryBlock extends SQLSelectQueryBlock { if (visitor.visit(this)) { acceptChild(visitor, count); } + visitor.endVisit(this); } } @@ -225,6 +227,7 @@ public class PGSelectQueryBlock extends SQLSelectQueryBlock { if (visitor.visit(this)) { acceptChild(visitor, of); } + visitor.endVisit(this); } } @@ -259,6 +262,7 @@ public class PGSelectQueryBlock extends SQLSelectQueryBlock { if (visitor.visit(this)) { acceptChild(visitor, table); } + visitor.endVisit(this); } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/PGTruncateStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/PGTruncateStatement.java index 97be5503db..a5936963f4 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/PGTruncateStatement.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/PGTruncateStatement.java @@ -39,5 +39,6 @@ public class PGTruncateStatement extends SQLTruncateStatement implements PGSQLSt if (visitor.visit(this)) { acceptChild(visitor, tableNames); } + visitor.endVisit(this); } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/PGWithClause.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/PGWithClause.java index af4c68a4bd..96e835ab88 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/PGWithClause.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/PGWithClause.java @@ -31,5 +31,6 @@ public class PGWithClause extends PGSQLObjectImpl { if (visitor.visit(this)) { acceptChild(visitor, withQuery); } + visitor.endVisit(this); } -} \ No newline at end of file +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/PGWithQuery.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/PGWithQuery.java index ef9fedbfc9..46bb0f703b 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/PGWithQuery.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/PGWithQuery.java @@ -40,5 +40,6 @@ public class PGWithQuery extends PGSQLObjectImpl { acceptChild(visitor, columns); acceptChild(visitor, subQuery); } + visitor.endVisit(this); } -} \ No newline at end of file +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGASTVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGASTVisitor.java index 483219254b..b596f2d7cc 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGASTVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGASTVisitor.java @@ -1,5 +1,6 @@ package com.alibaba.druid.sql.dialect.postgresql.visitor; +import com.alibaba.druid.sql.dialect.postgresql.ast.PGCurrentOfExpr; import com.alibaba.druid.sql.dialect.postgresql.ast.PGDeleteStatement; import com.alibaba.druid.sql.dialect.postgresql.ast.PGSelectQueryBlock; import com.alibaba.druid.sql.dialect.postgresql.ast.PGTruncateStatement; @@ -40,4 +41,8 @@ public interface PGASTVisitor extends SQLASTVisitor { void endVisit(PGDeleteStatement x); boolean visit(PGDeleteStatement x); + + void endVisit(PGCurrentOfExpr x); + + boolean visit(PGCurrentOfExpr x); } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGASTVisitorAdapter.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGASTVisitorAdapter.java index cfc1019793..c4d043f1e4 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGASTVisitorAdapter.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGASTVisitorAdapter.java @@ -1,5 +1,6 @@ package com.alibaba.druid.sql.dialect.postgresql.visitor; +import com.alibaba.druid.sql.dialect.postgresql.ast.PGCurrentOfExpr; import com.alibaba.druid.sql.dialect.postgresql.ast.PGDeleteStatement; import com.alibaba.druid.sql.dialect.postgresql.ast.PGSelectQueryBlock.FetchClause; import com.alibaba.druid.sql.dialect.postgresql.ast.PGSelectQueryBlock.ForClause; @@ -99,5 +100,15 @@ public class PGASTVisitorAdapter extends SQLASTVisitorAdapter implements PGASTVi return true; } + + @Override + public void endVisit(PGCurrentOfExpr x) { + + } + + @Override + public boolean visit(PGCurrentOfExpr x) { + return true; + } } 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 6e0ea2595c..378235a993 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 @@ -2,6 +2,7 @@ package com.alibaba.druid.sql.dialect.postgresql.visitor; import com.alibaba.druid.sql.ast.SQLSetQuantifier; import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock; +import com.alibaba.druid.sql.dialect.postgresql.ast.PGCurrentOfExpr; import com.alibaba.druid.sql.dialect.postgresql.ast.PGDeleteStatement; import com.alibaba.druid.sql.dialect.postgresql.ast.PGSelectQueryBlock; import com.alibaba.druid.sql.dialect.postgresql.ast.PGSelectQueryBlock.FetchClause; @@ -13,263 +14,262 @@ import com.alibaba.druid.sql.dialect.postgresql.ast.PGWithClause; import com.alibaba.druid.sql.dialect.postgresql.ast.PGWithQuery; import com.alibaba.druid.sql.visitor.SQLASTOutputVisitor; -public class PGOutputVisitor extends SQLASTOutputVisitor implements - PGASTVisitor { +public class PGOutputVisitor extends SQLASTOutputVisitor implements PGASTVisitor { - public PGOutputVisitor(Appendable appender) { - super(appender); - } + public PGOutputVisitor(Appendable appender){ + super(appender); + } - @Override - public void endVisit(WindowClause x) { + @Override + public void endVisit(WindowClause x) { - } + } - @Override - public boolean visit(WindowClause x) { - print("WINDOW "); - x.getName().accept(this); - print(" AS "); - for (int i = 0; i < x.getDefinition().size(); ++i) { - if (i != 0) { - println(", "); - } - print("("); - x.getDefinition().get(i).accept(this); - print(")"); - } - return false; - } + @Override + public boolean visit(WindowClause x) { + print("WINDOW "); + x.getName().accept(this); + print(" AS "); + for (int i = 0; i < x.getDefinition().size(); ++i) { + if (i != 0) { + println(", "); + } + print("("); + x.getDefinition().get(i).accept(this); + print(")"); + } + return false; + } - @Override - public void endVisit(FetchClause x) { + @Override + public void endVisit(FetchClause x) { - } + } - @Override - public boolean visit(FetchClause x) { - print("FETCH "); - if (FetchClause.Option.FIRST.equals(x.getOption())) { - print("FIRST "); - } else if (FetchClause.Option.NEXT.equals(x.getOption())) { - print("NEXT "); - } - x.getCount().accept(this); - print(" ROWS ONLY"); - return false; - } + @Override + public boolean visit(FetchClause x) { + print("FETCH "); + if (FetchClause.Option.FIRST.equals(x.getOption())) { + print("FIRST "); + } else if (FetchClause.Option.NEXT.equals(x.getOption())) { + print("NEXT "); + } + x.getCount().accept(this); + print(" ROWS ONLY"); + return false; + } - @Override - public void endVisit(ForClause x) { + @Override + public void endVisit(ForClause x) { - } + } - @Override - public boolean visit(ForClause x) { - print("FOR "); - if (ForClause.Option.UPDATE.equals(x.getOption())) { - print("UPDATE "); - } else if (ForClause.Option.SHARE.equals(x.getOption())) { - print("SHARE "); - } + @Override + public boolean visit(ForClause x) { + print("FOR "); + if (ForClause.Option.UPDATE.equals(x.getOption())) { + print("UPDATE "); + } else if (ForClause.Option.SHARE.equals(x.getOption())) { + print("SHARE "); + } - if (x.getOf().size() > 0) { - for (int i = 0; i < x.getOf().size(); ++i) { - if (i != 0) { - println(", "); - } - x.getOf().get(i).accept(this); - } - } - - if (x.isNoWait()) { - print(" NOWAIT"); - } + if (x.getOf().size() > 0) { + for (int i = 0; i < x.getOf().size(); ++i) { + if (i != 0) { + println(", "); + } + x.getOf().get(i).accept(this); + } + } - return false; - } + if (x.isNoWait()) { + print(" NOWAIT"); + } - @Override - public void endVisit(PGWithQuery x) { + return false; + } - } + @Override + public void endVisit(PGWithQuery x) { - @Override - public boolean visit(PGWithQuery x) { - x.getName().accept(this); + } - if (x.getColumns().size() > 0) { - print(" ("); - printAndAccept(x.getColumns(), ", "); - print(")"); - } - println(); - print("AS"); - println(); - print("("); - incrementIndent(); - println(); - x.getSubQuery().accept(this); - decrementIndent(); - println(); - print(")"); + @Override + public boolean visit(PGWithQuery x) { + x.getName().accept(this); - return false; - } + if (x.getColumns().size() > 0) { + print(" ("); + printAndAccept(x.getColumns(), ", "); + print(")"); + } + println(); + print("AS"); + println(); + print("("); + incrementIndent(); + println(); + x.getSubQuery().accept(this); + decrementIndent(); + println(); + print(")"); - @Override - public void endVisit(PGWithClause x) { + return false; + } - } + @Override + public void endVisit(PGWithClause x) { - @Override - public boolean visit(PGWithClause x) { - print("WITH"); - incrementIndent(); - println(); - printlnAndAccept(x.getWithQuery(), ", "); - decrementIndent(); - return false; - } + } - public boolean visit(SQLSelectQueryBlock x) { - if (x instanceof PGSelectQueryBlock) { - return visit((PGSelectQueryBlock) x); - } + @Override + public boolean visit(PGWithClause x) { + print("WITH"); + incrementIndent(); + println(); + printlnAndAccept(x.getWithQuery(), ", "); + decrementIndent(); + return false; + } - return super.visit(x); - } + public boolean visit(SQLSelectQueryBlock x) { + if (x instanceof PGSelectQueryBlock) { + return visit((PGSelectQueryBlock) x); + } - public boolean visit(PGSelectQueryBlock x) { - if (x.getWith() != null) { - x.getWith().accept(this); - println(); - } + return super.visit(x); + } - print("SELECT "); + public boolean visit(PGSelectQueryBlock x) { + if (x.getWith() != null) { + x.getWith().accept(this); + println(); + } - if (SQLSetQuantifier.ALL == x.getDistionOption()) { - print("ALL "); - } else if (SQLSetQuantifier.DISTINCT == x.getDistionOption()) { - print("DISTINCT "); + print("SELECT "); - if (x.getDistinctOn() != null) { - print("ON "); - printAndAccept(x.getDistinctOn(), ", "); - } - } + if (SQLSetQuantifier.ALL == x.getDistionOption()) { + print("ALL "); + } else if (SQLSetQuantifier.DISTINCT == x.getDistionOption()) { + print("DISTINCT "); - printSelectList(x.getSelectList()); - - if (x.getInto() != null) { - println(); - x.getInto().accept(this); - } + if (x.getDistinctOn() != null) { + print("ON "); + printAndAccept(x.getDistinctOn(), ", "); + } + } - if (x.getFrom() != null) { - println(); - print("FROM "); - x.getFrom().accept(this); - } + printSelectList(x.getSelectList()); - if (x.getWhere() != null) { - println(); - print("WHERE "); - x.getWhere().accept(this); - } + if (x.getInto() != null) { + println(); + x.getInto().accept(this); + } - if (x.getGroupBy() != null) { - print(" "); - x.getGroupBy().accept(this); - } + if (x.getFrom() != null) { + println(); + print("FROM "); + x.getFrom().accept(this); + } - if (x.getWindow() != null) { - println(); - x.getWindow().accept(this); - } + if (x.getWhere() != null) { + println(); + print("WHERE "); + x.getWhere().accept(this); + } - if (x.getOrderBy() != null) { - println(); - x.getOrderBy().accept(this); - } + if (x.getGroupBy() != null) { + print(" "); + x.getGroupBy().accept(this); + } - if (x.getLimit() != null) { - println(); - print("LIMIT "); - x.getLimit().accept(this); - } + if (x.getWindow() != null) { + println(); + x.getWindow().accept(this); + } - if (x.getOffset() != null) { - println(); - print("OFFSET "); - x.getOffset().accept(this); - print(" ROWS"); - } + if (x.getOrderBy() != null) { + println(); + x.getOrderBy().accept(this); + } - if (x.getFetch() != null) { - println(); - x.getFetch().accept(this); - } + if (x.getLimit() != null) { + println(); + print("LIMIT "); + x.getLimit().accept(this); + } - if (x.getForClause() != null) { - println(); - x.getForClause().accept(this); - } + if (x.getOffset() != null) { + println(); + print("OFFSET "); + x.getOffset().accept(this); + print(" ROWS"); + } - return false; - } + if (x.getFetch() != null) { + println(); + x.getFetch().accept(this); + } - @Override - public void endVisit(IntoClause x) { - - } + if (x.getForClause() != null) { + println(); + x.getForClause().accept(this); + } - @Override - public boolean visit(IntoClause x) { - print("INTO "); - if (x.getOption() != null) { - print(x.getOption().name()); - print(" "); - } - x.getTable().accept(this); - return false; - } - - @Override - public void endVisit(PGTruncateStatement x) { - - } - - @Override - public boolean visit(PGTruncateStatement x) { - print("TRUNCATE TABLE "); - if (x.isOnly()) { - print("ONLY "); - } - - printlnAndAccept(x.getTableNames(), ", "); - - if (x.getRestartIdentity() != null) { - if (x.getRestartIdentity().booleanValue()) { - print(" RESTART IDENTITY"); - } else { - print(" CONTINUE IDENTITY"); - } - } - - if (x.getCascade() != null) { + return false; + } + + @Override + public void endVisit(IntoClause x) { + + } + + @Override + public boolean visit(IntoClause x) { + print("INTO "); + if (x.getOption() != null) { + print(x.getOption().name()); + print(" "); + } + x.getTable().accept(this); + return false; + } + + @Override + public void endVisit(PGTruncateStatement x) { + + } + + @Override + public boolean visit(PGTruncateStatement x) { + print("TRUNCATE TABLE "); + if (x.isOnly()) { + print("ONLY "); + } + + printlnAndAccept(x.getTableNames(), ", "); + + if (x.getRestartIdentity() != null) { + if (x.getRestartIdentity().booleanValue()) { + print(" RESTART IDENTITY"); + } else { + print(" CONTINUE IDENTITY"); + } + } + + if (x.getCascade() != null) { if (x.getCascade().booleanValue()) { print(" CASCADE"); } else { print(" RESTRICT"); } } - return false; - } + return false; + } @Override public void endVisit(PGDeleteStatement x) { - + } @Override @@ -278,26 +278,26 @@ public class PGOutputVisitor extends SQLASTOutputVisitor implements x.getWith().accept(this); println(); } - + print("DELETE FROM "); - + if (x.isOnly()) { print("ONLY "); } x.getTableName().accept(this); - + if (x.getAlias() != null) { print(" AS "); print(x.getAlias()); } - + if (x.getUsing().size() > 0) { println(); print("USING "); printAndAccept(x.getUsing(), ", "); } - + if (x.getWhere() != null) { println(); print("WHERE "); @@ -306,4 +306,17 @@ public class PGOutputVisitor extends SQLASTOutputVisitor implements return false; } + + @Override + public void endVisit(PGCurrentOfExpr x) { + + } + + @Override + public boolean visit(PGCurrentOfExpr x) { + print("CURRENT OF "); + x.getCursor().accept(this); + + return false; + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGSchemaStatVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGSchemaStatVisitor.java index d2a24bbba1..16ec0e01c5 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGSchemaStatVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGSchemaStatVisitor.java @@ -6,6 +6,7 @@ import java.util.Map; import com.alibaba.druid.sql.ast.SQLName; import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; import com.alibaba.druid.sql.ast.statement.SQLTruncateStatement; +import com.alibaba.druid.sql.dialect.postgresql.ast.PGCurrentOfExpr; import com.alibaba.druid.sql.dialect.postgresql.ast.PGDeleteStatement; import com.alibaba.druid.sql.dialect.postgresql.ast.PGSelectQueryBlock.FetchClause; import com.alibaba.druid.sql.dialect.postgresql.ast.PGSelectQueryBlock.ForClause; @@ -152,4 +153,14 @@ public class PGSchemaStatVisitor extends SchemaStatVisitor implements PGASTVisit return false; } + + @Override + public void endVisit(PGCurrentOfExpr x) { + + } + + @Override + public boolean visit(PGCurrentOfExpr x) { + return false; + } } diff --git a/src/test/java/com/alibaba/druid/bvt/sql/postgresql/PGDeleteTest2.java b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/PGDeleteTest2.java new file mode 100644 index 0000000000..c176044aaa --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/PGDeleteTest2.java @@ -0,0 +1,37 @@ +package com.alibaba.druid.bvt.sql.postgresql; + +import java.util.List; + +import junit.framework.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; +import com.alibaba.druid.stat.TableStat; + +public class PGDeleteTest2 extends PGTest { + + public void test_0() throws Exception { + String sql = "DELETE FROM tasks WHERE CURRENT OF c_tasks;"; + + PGSQLStatementParser parser = new PGSQLStatementParser(sql); + List statementList = parser.parseStatementList(); + SQLStatement statemen = statementList.get(0); + System.out.println(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.getFields()); + + Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("tasks"))); + + //Assert.assertTrue(visitor.getFields().size() == 0); + } + + +}