From 97322c0b88e309a801ebecd5713331be42a1e158 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B8=A9=E5=B0=91?= Date: Wed, 22 Feb 2012 22:20:31 +0800 Subject: [PATCH] bug fixed for schema stat --- .../sql/ast/statement/SQLDeleteStatement.java | 4 +- .../postgresql/ast/PGDeleteStatement.java | 67 +++++++++++ .../postgresql/ast/PGSelectQueryBlock.java | 72 +----------- .../dialect/postgresql/ast/PGWithClause.java | 35 ++++++ .../dialect/postgresql/ast/PGWithQuery.java | 44 ++++++++ .../dialect/postgresql/parser/PGLexer.java | 1 + .../parser/PGSQLStatementParser.java | 104 ++++++++++++------ .../postgresql/parser/PGSelectParser.java | 11 +- .../postgresql/visitor/PGASTVisitor.java | 15 ++- .../visitor/PGASTVisitorAdapter.java | 24 +++- .../postgresql/visitor/PGOutputVisitor.java | 53 ++++++++- .../visitor/PGSchemaStatVisitor.java | 70 +++++++++++- .../com/alibaba/druid/sql/parser/Token.java | 1 + .../druid/sql/visitor/SchemaStatVisitor.java | 2 - .../bvt/sql/postgresql/PGDeleteTest.java | 39 +++++++ 15 files changed, 411 insertions(+), 131 deletions(-) create mode 100644 src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/PGDeleteStatement.java create mode 100644 src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/PGWithClause.java create mode 100644 src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/PGWithQuery.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/postgresql/PGDeleteTest.java diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLDeleteStatement.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLDeleteStatement.java index 175c902e59..b899e0fd44 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLDeleteStatement.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLDeleteStatement.java @@ -23,8 +23,8 @@ import com.alibaba.druid.sql.visitor.SQLASTVisitor; public class SQLDeleteStatement extends SQLStatementImpl { private static final long serialVersionUID = 1L; - private SQLName tableName; - private SQLExpr where; + protected SQLName tableName; + protected SQLExpr where; public SQLDeleteStatement(){ diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/PGDeleteStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/PGDeleteStatement.java new file mode 100644 index 0000000000..451d7512f3 --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/PGDeleteStatement.java @@ -0,0 +1,67 @@ +package com.alibaba.druid.sql.dialect.postgresql.ast; + +import java.util.ArrayList; +import java.util.List; + +import com.alibaba.druid.sql.ast.SQLName; +import com.alibaba.druid.sql.ast.statement.SQLDeleteStatement; +import com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor; +import com.alibaba.druid.sql.visitor.SQLASTVisitor; + +public class PGDeleteStatement extends SQLDeleteStatement implements PGSQLStatement { + + private static final long serialVersionUID = 1L; + private PGWithClause with; + private boolean only = false; + private List using = new ArrayList(2); + private String alias; + + public String getAlias() { + return alias; + } + + public void setAlias(String alias) { + this.alias = alias; + } + + public List getUsing() { + return using; + } + + public void setUsing(List using) { + this.using = using; + } + + public boolean isOnly() { + return only; + } + + public void setOnly(boolean only) { + this.only = only; + } + + public PGWithClause getWith() { + return with; + } + + public void setWith(PGWithClause with) { + this.with = with; + } + + protected void accept0(SQLASTVisitor visitor) { + accept0((PGASTVisitor) visitor); + } + + @Override + public void accept0(PGASTVisitor visitor) { + if (visitor.visit(this)) { + acceptChild(visitor, with); + acceptChild(visitor, tableName); + acceptChild(visitor, using); + acceptChild(visitor, where); + } + + 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 9197cb47a0..c02e4d9e53 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 @@ -5,7 +5,6 @@ import java.util.List; import com.alibaba.druid.sql.ast.SQLExpr; import com.alibaba.druid.sql.ast.SQLOrderBy; -import com.alibaba.druid.sql.ast.statement.SQLSelectQuery; import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock; import com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor; import com.alibaba.druid.sql.visitor.SQLASTVisitor; @@ -14,7 +13,7 @@ public class PGSelectQueryBlock extends SQLSelectQueryBlock { private static final long serialVersionUID = 1L; - private WithClause with; + private PGWithClause with; private List distinctOn = new ArrayList(2); private SQLExpr limit; private SQLExpr offset; @@ -81,11 +80,11 @@ public class PGSelectQueryBlock extends SQLSelectQueryBlock { this.window = window; } - public WithClause getWith() { + public PGWithClause getWith() { return with; } - public void setWith(WithClause with) { + public void setWith(PGWithClause with) { this.with = with; } @@ -229,71 +228,6 @@ public class PGSelectQueryBlock extends SQLSelectQueryBlock { } } - public static class WithClause extends PGSQLObjectImpl { - private static final long serialVersionUID = 1L; - private boolean recursive = false; - private List withQuery = new ArrayList(2); - - public boolean isRecursive() { - return recursive; - } - - public void setRecursive(boolean recursive) { - this.recursive = recursive; - } - - public List getWithQuery() { - return withQuery; - } - - public void setWithQuery(List withQuery) { - this.withQuery = withQuery; - } - - @Override - public void accept0(PGASTVisitor visitor) { - if (visitor.visit(this)) { - acceptChild(visitor, withQuery); - } - } - } - - public static class WithQuery extends PGSQLObjectImpl { - private static final long serialVersionUID = 1L; - private SQLExpr name; - private final List columns = new ArrayList(); - private SQLSelectQuery subQuery; - - public SQLExpr getName() { - return name; - } - - public void setName(SQLExpr name) { - this.name = name; - } - - public SQLSelectQuery getSubQuery() { - return subQuery; - } - - public void setSubQuery(SQLSelectQuery subQuery) { - this.subQuery = subQuery; - } - - public List getColumns() { - return columns; - } - - @Override - public void accept0(PGASTVisitor visitor) { - if (visitor.visit(this)) { - acceptChild(visitor, name); - acceptChild(visitor, columns); - acceptChild(visitor, subQuery); - } - } - } - public static class IntoClause extends PGSQLObjectImpl { public static enum Option { TEMPORARY, TEMP, UNLOGGED 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 new file mode 100644 index 0000000000..af4c68a4bd --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/PGWithClause.java @@ -0,0 +1,35 @@ +package com.alibaba.druid.sql.dialect.postgresql.ast; + +import java.util.ArrayList; +import java.util.List; + +import com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor; + +public class PGWithClause extends PGSQLObjectImpl { + private static final long serialVersionUID = 1L; + private boolean recursive = false; + private List withQuery = new ArrayList(2); + + public boolean isRecursive() { + return recursive; + } + + public void setRecursive(boolean recursive) { + this.recursive = recursive; + } + + public List getWithQuery() { + return withQuery; + } + + public void setWithQuery(List withQuery) { + this.withQuery = withQuery; + } + + @Override + public void accept0(PGASTVisitor visitor) { + if (visitor.visit(this)) { + acceptChild(visitor, withQuery); + } + } +} \ 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 new file mode 100644 index 0000000000..ef9fedbfc9 --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/PGWithQuery.java @@ -0,0 +1,44 @@ +package com.alibaba.druid.sql.dialect.postgresql.ast; + +import java.util.ArrayList; +import java.util.List; + +import com.alibaba.druid.sql.ast.SQLExpr; +import com.alibaba.druid.sql.ast.statement.SQLSelectQuery; +import com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor; + +public class PGWithQuery extends PGSQLObjectImpl { + private static final long serialVersionUID = 1L; + private SQLExpr name; + private final List columns = new ArrayList(); + private SQLSelectQuery subQuery; + + public SQLExpr getName() { + return name; + } + + public void setName(SQLExpr name) { + this.name = name; + } + + public SQLSelectQuery getSubQuery() { + return subQuery; + } + + public void setSubQuery(SQLSelectQuery subQuery) { + this.subQuery = subQuery; + } + + public List getColumns() { + return columns; + } + + @Override + public void accept0(PGASTVisitor visitor) { + if (visitor.visit(this)) { + acceptChild(visitor, name); + acceptChild(visitor, columns); + acceptChild(visitor, subQuery); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGLexer.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGLexer.java index 6b3322f565..2860728409 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGLexer.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGLexer.java @@ -104,6 +104,7 @@ public class PGLexer extends Lexer { map.put("IDENTITY", Token.IDENTITY); map.put("CASCADE", Token.CASCADE); map.put("RESTRICT", Token.RESTRICT); + map.put("USING", Token.USING); DEFAULT_MYSQL_KEYWORDS = new Keywords(map); } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGSQLStatementParser.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGSQLStatementParser.java index e276ccf6c3..5793767f52 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGSQLStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGSQLStatementParser.java @@ -2,8 +2,11 @@ package com.alibaba.druid.sql.dialect.postgresql.parser; import java.util.List; +import com.alibaba.druid.sql.ast.SQLExpr; import com.alibaba.druid.sql.ast.SQLName; import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.ast.statement.SQLDeleteStatement; +import com.alibaba.druid.sql.dialect.postgresql.ast.PGDeleteStatement; import com.alibaba.druid.sql.dialect.postgresql.ast.PGTruncateStatement; import com.alibaba.druid.sql.parser.Lexer; import com.alibaba.druid.sql.parser.ParserException; @@ -11,45 +14,84 @@ import com.alibaba.druid.sql.parser.SQLStatementParser; import com.alibaba.druid.sql.parser.Token; public class PGSQLStatementParser extends SQLStatementParser { - public PGSQLStatementParser(String sql) throws ParserException { - this(new PGLexer(sql)); - this.lexer.nextToken(); - } - public PGSQLStatementParser(Lexer lexer) { - super(lexer); - } + public PGSQLStatementParser(String sql) throws ParserException{ + this(new PGLexer(sql)); + this.lexer.nextToken(); + } + + public PGSQLStatementParser(Lexer lexer){ + super(lexer); + } + + public PGSelectParser createSQLSelectParser() { + return new PGSelectParser(this.lexer); + } + + public SQLDeleteStatement parseDeleteStatement() throws ParserException { + lexer.nextToken(); + PGDeleteStatement deleteStatement = new PGDeleteStatement(); + + if (lexer.token() == (Token.FROM)) { + lexer.nextToken(); + } + if (lexer.token() == (Token.ONLY)) { + lexer.nextToken(); + deleteStatement.setOnly(true); + } + + SQLName tableName = exprParser.name(); + + deleteStatement.setTableName(tableName); + + if (lexer.token() == Token.USING) { + lexer.nextToken(); + for (;;) { + SQLName name = this.createExprParser().name(); + deleteStatement.getUsing().add(name); + if (lexer.token() == Token.COMMA) { + lexer.nextToken(); + continue; + } + break; + } + } + + if (lexer.token() == (Token.WHERE)) { + lexer.nextToken(); + SQLExpr where = this.exprParser.expr(); + deleteStatement.setWhere(where); + } + + return deleteStatement; + } - public PGSelectParser createSQLSelectParser() { - return new PGSelectParser(this.lexer); - } - public SQLStatement parseTruncate() { accept(Token.TRUNCATE); - + PGTruncateStatement stmt = new PGTruncateStatement(); - + if (lexer.token() == Token.TABLE) { lexer.nextToken(); } - + if (lexer.token() == Token.ONLY) { lexer.nextToken(); stmt.setOnly(true); } - + for (;;) { SQLName name = this.exprParser.name(); stmt.getTableNames().add(name); - + if (lexer.token() == Token.COMMA) { lexer.nextToken(); continue; } - + break; } - + if (lexer.token() == Token.RESTART) { lexer.nextToken(); accept(Token.IDENTITY); @@ -59,7 +101,7 @@ public class PGSQLStatementParser extends SQLStatementParser { accept(Token.IDENTITY); stmt.setRestartIdentity(Boolean.FALSE); } - + if (lexer.token() == Token.CASCADE) { lexer.nextToken(); stmt.setCascade(Boolean.TRUE); @@ -67,17 +109,17 @@ public class PGSQLStatementParser extends SQLStatementParser { lexer.nextToken(); stmt.setCascade(Boolean.FALSE); } - - return stmt; + + return stmt; + } + + public boolean parseStatementListDialect(List statementList) { + if (lexer.token() == Token.WITH) { + SQLStatement stmt = parseSelect(); + statementList.add(stmt); + return true; + } + + return false; } - - public boolean parseStatementListDialect(List statementList) { - if (lexer.token() == Token.WITH) { - SQLStatement stmt = parseSelect(); - statementList.add(stmt); - return true; - } - - 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 72a236a765..44222503e0 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 @@ -6,7 +6,8 @@ import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; import com.alibaba.druid.sql.ast.statement.SQLSelectQuery; import com.alibaba.druid.sql.dialect.postgresql.ast.PGSelectQueryBlock; import com.alibaba.druid.sql.dialect.postgresql.ast.PGSelectQueryBlock.IntoClause; -import com.alibaba.druid.sql.dialect.postgresql.ast.PGSelectQueryBlock.WithQuery; +import com.alibaba.druid.sql.dialect.postgresql.ast.PGWithClause; +import com.alibaba.druid.sql.dialect.postgresql.ast.PGWithQuery; import com.alibaba.druid.sql.parser.Lexer; import com.alibaba.druid.sql.parser.ParserException; import com.alibaba.druid.sql.parser.SQLSelectParser; @@ -30,7 +31,7 @@ public class PGSelectParser extends SQLSelectParser { if (lexer.token() == Token.WITH) { lexer.nextToken(); - PGSelectQueryBlock.WithClause withClause = new PGSelectQueryBlock.WithClause(); + PGWithClause withClause = new PGWithClause(); if (lexer.token() == Token.RECURSIVE) { lexer.nextToken(); @@ -38,7 +39,7 @@ public class PGSelectParser extends SQLSelectParser { } for (;;) { - WithQuery withQuery = withQuery(); + PGWithQuery withQuery = withQuery(); withClause.getWithQuery().add(withQuery); if (lexer.token() == Token.COMMA) { lexer.nextToken(); @@ -220,8 +221,8 @@ public class PGSelectParser extends SQLSelectParser { return queryRest(queryBlock); } - private WithQuery withQuery() { - WithQuery withQuery = new WithQuery(); + private PGWithQuery withQuery() { + PGWithQuery withQuery = new PGWithQuery(); withQuery.setName(expr()); if (lexer.token() == Token.LPAREN) { 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 dc05dae3b5..483219254b 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,7 +1,10 @@ package com.alibaba.druid.sql.dialect.postgresql.visitor; +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; +import com.alibaba.druid.sql.dialect.postgresql.ast.PGWithClause; +import com.alibaba.druid.sql.dialect.postgresql.ast.PGWithQuery; import com.alibaba.druid.sql.visitor.SQLASTVisitor; public interface PGASTVisitor extends SQLASTVisitor { @@ -18,13 +21,13 @@ public interface PGASTVisitor extends SQLASTVisitor { boolean visit(PGSelectQueryBlock.ForClause x); - void endVisit(PGSelectQueryBlock.WithQuery x); + void endVisit(PGWithQuery x); - boolean visit(PGSelectQueryBlock.WithQuery x); + boolean visit(PGWithQuery x); - void endVisit(PGSelectQueryBlock.WithClause x); + void endVisit(PGWithClause x); - boolean visit(PGSelectQueryBlock.WithClause x); + boolean visit(PGWithClause x); void endVisit(PGSelectQueryBlock.IntoClause x); @@ -33,4 +36,8 @@ public interface PGASTVisitor extends SQLASTVisitor { void endVisit(PGTruncateStatement x); boolean visit(PGTruncateStatement x); + + void endVisit(PGDeleteStatement x); + + boolean visit(PGDeleteStatement 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 83121db44f..cfc1019793 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,12 +1,13 @@ package com.alibaba.druid.sql.dialect.postgresql.visitor; +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; import com.alibaba.druid.sql.dialect.postgresql.ast.PGSelectQueryBlock.IntoClause; import com.alibaba.druid.sql.dialect.postgresql.ast.PGSelectQueryBlock.WindowClause; -import com.alibaba.druid.sql.dialect.postgresql.ast.PGSelectQueryBlock.WithClause; -import com.alibaba.druid.sql.dialect.postgresql.ast.PGSelectQueryBlock.WithQuery; import com.alibaba.druid.sql.dialect.postgresql.ast.PGTruncateStatement; +import com.alibaba.druid.sql.dialect.postgresql.ast.PGWithClause; +import com.alibaba.druid.sql.dialect.postgresql.ast.PGWithQuery; import com.alibaba.druid.sql.visitor.SQLASTVisitorAdapter; public class PGASTVisitorAdapter extends SQLASTVisitorAdapter implements PGASTVisitor { @@ -45,23 +46,23 @@ public class PGASTVisitorAdapter extends SQLASTVisitorAdapter implements PGASTVi } @Override - public void endVisit(WithQuery x) { + public void endVisit(PGWithQuery x) { } @Override - public boolean visit(WithQuery x) { + public boolean visit(PGWithQuery x) { return true; } @Override - public void endVisit(WithClause x) { + public void endVisit(PGWithClause x) { } @Override - public boolean visit(WithClause x) { + public boolean visit(PGWithClause x) { return true; } @@ -87,5 +88,16 @@ public class PGASTVisitorAdapter extends SQLASTVisitorAdapter implements PGASTVi return true; } + + @Override + public void endVisit(PGDeleteStatement x) { + + } + + @Override + public boolean visit(PGDeleteStatement 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 3a4a538651..6e0ea2595c 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,14 +2,15 @@ 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.PGDeleteStatement; import com.alibaba.druid.sql.dialect.postgresql.ast.PGSelectQueryBlock; import com.alibaba.druid.sql.dialect.postgresql.ast.PGSelectQueryBlock.FetchClause; import com.alibaba.druid.sql.dialect.postgresql.ast.PGSelectQueryBlock.ForClause; import com.alibaba.druid.sql.dialect.postgresql.ast.PGSelectQueryBlock.IntoClause; import com.alibaba.druid.sql.dialect.postgresql.ast.PGSelectQueryBlock.WindowClause; -import com.alibaba.druid.sql.dialect.postgresql.ast.PGSelectQueryBlock.WithClause; -import com.alibaba.druid.sql.dialect.postgresql.ast.PGSelectQueryBlock.WithQuery; import com.alibaba.druid.sql.dialect.postgresql.ast.PGTruncateStatement; +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 @@ -89,12 +90,12 @@ public class PGOutputVisitor extends SQLASTOutputVisitor implements } @Override - public void endVisit(WithQuery x) { + public void endVisit(PGWithQuery x) { } @Override - public boolean visit(WithQuery x) { + public boolean visit(PGWithQuery x) { x.getName().accept(this); if (x.getColumns().size() > 0) { @@ -117,12 +118,12 @@ public class PGOutputVisitor extends SQLASTOutputVisitor implements } @Override - public void endVisit(WithClause x) { + public void endVisit(PGWithClause x) { } @Override - public boolean visit(WithClause x) { + public boolean visit(PGWithClause x) { print("WITH"); incrementIndent(); println(); @@ -265,4 +266,44 @@ public class PGOutputVisitor extends SQLASTOutputVisitor implements } return false; } + + @Override + public void endVisit(PGDeleteStatement x) { + + } + + @Override + public boolean visit(PGDeleteStatement x) { + if (x.getWith() != null) { + 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 "); + x.getWhere().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 2b29044df0..d2a24bbba1 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 @@ -1,15 +1,22 @@ package com.alibaba.druid.sql.dialect.postgresql.visitor; +import java.util.HashMap; +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.PGDeleteStatement; import com.alibaba.druid.sql.dialect.postgresql.ast.PGSelectQueryBlock.FetchClause; import com.alibaba.druid.sql.dialect.postgresql.ast.PGSelectQueryBlock.ForClause; import com.alibaba.druid.sql.dialect.postgresql.ast.PGSelectQueryBlock.IntoClause; import com.alibaba.druid.sql.dialect.postgresql.ast.PGSelectQueryBlock.WindowClause; -import com.alibaba.druid.sql.dialect.postgresql.ast.PGSelectQueryBlock.WithClause; -import com.alibaba.druid.sql.dialect.postgresql.ast.PGSelectQueryBlock.WithQuery; import com.alibaba.druid.sql.dialect.postgresql.ast.PGTruncateStatement; +import com.alibaba.druid.sql.dialect.postgresql.ast.PGWithClause; +import com.alibaba.druid.sql.dialect.postgresql.ast.PGWithQuery; import com.alibaba.druid.sql.visitor.SchemaStatVisitor; import com.alibaba.druid.stat.TableStat; +import com.alibaba.druid.stat.TableStat.Mode; public class PGSchemaStatVisitor extends SchemaStatVisitor implements PGASTVisitor { @@ -45,23 +52,23 @@ public class PGSchemaStatVisitor extends SchemaStatVisitor implements PGASTVisit } @Override - public void endVisit(WithQuery x) { + public void endVisit(PGWithQuery x) { } @Override - public boolean visit(WithQuery x) { + public boolean visit(PGWithQuery x) { return true; } @Override - public void endVisit(WithClause x) { + public void endVisit(PGWithClause x) { } @Override - public boolean visit(WithClause x) { + public boolean visit(PGWithClause x) { return true; } @@ -94,4 +101,55 @@ public class PGSchemaStatVisitor extends SchemaStatVisitor implements PGASTVisit this.visit((SQLTruncateStatement) x); return false; } + + @Override + public void endVisit(PGDeleteStatement x) { + + } + + @Override + public boolean visit(PGDeleteStatement x) { + if (x.getWith() != null) { + x.getWith().accept(this); + } + + aliasLocal.set(new HashMap()); + + for (SQLName name : x.getUsing()) { + String ident = name.toString(); + + TableStat stat = tableStats.get(ident); + if (stat == null) { + stat = new TableStat(); + tableStats.put(new TableStat.Name(ident), stat); + } + stat.incrementSelectCount(); + + Map aliasMap = aliasLocal.get(); + if (aliasMap != null) { + aliasMap.put(ident, ident); + } + } + + + x.putAttribute("_original_use_mode", modeLocal.get()); + modeLocal.set(Mode.Delete); + + String ident = ((SQLIdentifierExpr) x.getTableName()).getName(); + currentTableLocal.set(ident); + + TableStat stat = tableStats.get(ident); + if (stat == null) { + stat = new TableStat(); + tableStats.put(new TableStat.Name(ident), stat); + if (x.getAlias() != null) { + tableStats.put(new TableStat.Name(x.getAlias()), stat); + } + } + stat.incrementDeleteCount(); + + accept(x.getWhere()); + + return false; + } } diff --git a/src/main/java/com/alibaba/druid/sql/parser/Token.java b/src/main/java/com/alibaba/druid/sql/parser/Token.java index 69189a70a3..04d4f20a85 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/Token.java +++ b/src/main/java/com/alibaba/druid/sql/parser/Token.java @@ -124,6 +124,7 @@ public enum Token { CONTINUE("CONTINUE"), CASCADE("CASCADE"), RESTRICT("RESTRICT"), + USING("USING"), // oracle START("START"), diff --git a/src/main/java/com/alibaba/druid/sql/visitor/SchemaStatVisitor.java b/src/main/java/com/alibaba/druid/sql/visitor/SchemaStatVisitor.java index 556a367015..6f0e3f9617 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SchemaStatVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SchemaStatVisitor.java @@ -350,8 +350,6 @@ public class SchemaStatVisitor extends SQLASTVisitorAdapter { x.putAttribute("_original_use_mode", modeLocal.get()); modeLocal.set(Mode.Delete); - aliasLocal.set(new HashMap()); - String ident = ((SQLIdentifierExpr) x.getTableName()).getName(); currentTableLocal.set(ident); diff --git a/src/test/java/com/alibaba/druid/bvt/sql/postgresql/PGDeleteTest.java b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/PGDeleteTest.java new file mode 100644 index 0000000000..22dccc427b --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/PGDeleteTest.java @@ -0,0 +1,39 @@ +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; +import com.alibaba.druid.stat.TableStat.Column; + +public class PGDeleteTest extends PGTest { + + public void test_0() throws Exception { + String sql = "DELETE FROM films USING producers WHERE producer_id = producers.id AND producers.name = 'foo';"; + + 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("films"))); + Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("producers"))); + + //Assert.assertTrue(visitor.getFields().size() == 0); + } + + +}