diff --git a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLDefaultExpr.java b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLDefaultExpr.java new file mode 100644 index 0000000000..29020b3da9 --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLDefaultExpr.java @@ -0,0 +1,25 @@ +package com.alibaba.druid.sql.ast.expr; + +import com.alibaba.druid.sql.visitor.SQLASTVisitor; + +public class SQLDefaultExpr extends SQLLiteralExpr { + + private static final long serialVersionUID = 1L; + + @Override + public boolean equals(Object o) { + return o instanceof SQLDefaultExpr; + } + + @Override + public int hashCode() { + return 0; + } + + @Override + protected void accept0(SQLASTVisitor visitor) { + visitor.visit(this); + visitor.endVisit(this); + } + +} diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLInsertStatement.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLInsertStatement.java index 291e177099..40c32d74eb 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLInsertStatement.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLInsertStatement.java @@ -27,12 +27,12 @@ import com.alibaba.druid.sql.visitor.SQLASTVisitor; public class SQLInsertStatement extends SQLStatementImpl { private static final long serialVersionUID = 1L; - private SQLName tableName; - private String alias; + protected SQLName tableName; + protected String alias; - private final List columns = new ArrayList(); - private ValuesClause values; - private SQLSelect query; + protected final List columns = new ArrayList(); + protected ValuesClause values; + protected SQLSelect query; public SQLInsertStatement(){ diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectStatement.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectStatement.java index b577c8a3c2..a48806c035 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectStatement.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectStatement.java @@ -22,7 +22,7 @@ public class SQLSelectStatement extends SQLStatementImpl { private static final long serialVersionUID = 1L; - private SQLSelect select; + protected SQLSelect select; public SQLSelectStatement(){ diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/PGSQLStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/PGSQLStatement.java deleted file mode 100644 index 621ba46a53..0000000000 --- a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/PGSQLStatement.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.alibaba.druid.sql.dialect.postgresql.ast; - -import com.alibaba.druid.sql.ast.SQLStatement; - -public interface PGSQLStatement extends SQLStatement, PGSQLObject { - -} 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 46bb0f703b..981b16e9c6 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 @@ -4,42 +4,43 @@ 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.ast.SQLStatement; 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; - } + private static final long serialVersionUID = 1L; + private SQLExpr name; + private final List columns = new ArrayList(); + private SQLStatement query; - public void setName(SQLExpr name) { - this.name = name; - } + public SQLExpr getName() { + return name; + } - public SQLSelectQuery getSubQuery() { - return subQuery; - } + public void setName(SQLExpr name) { + this.name = name; + } - public void setSubQuery(SQLSelectQuery subQuery) { - this.subQuery = subQuery; - } + public SQLStatement getQuery() { + return query; + } - public List getColumns() { - return columns; - } + public void setQuery(SQLStatement query) { + this.query = query; + } - @Override - public void accept0(PGASTVisitor visitor) { - if (visitor.visit(this)) { - acceptChild(visitor, name); - acceptChild(visitor, columns); - acceptChild(visitor, subQuery); - } - visitor.endVisit(this); - } + public List getColumns() { + return columns; + } + + @Override + public void accept0(PGASTVisitor visitor) { + if (visitor.visit(this)) { + acceptChild(visitor, name); + acceptChild(visitor, columns); + acceptChild(visitor, query); + } + visitor.endVisit(this); + } } 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/stmt/PGDeleteStatement.java similarity index 93% rename from src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/PGDeleteStatement.java rename to src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGDeleteStatement.java index ba9c98a610..4c552aaaa1 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/PGDeleteStatement.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGDeleteStatement.java @@ -1,10 +1,11 @@ -package com.alibaba.druid.sql.dialect.postgresql.ast; +package com.alibaba.druid.sql.dialect.postgresql.ast.stmt; 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.ast.PGWithClause; import com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor; import com.alibaba.druid.sql.visitor.SQLASTVisitor; diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGInsertStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGInsertStatement.java new file mode 100644 index 0000000000..92c84b0fcb --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGInsertStatement.java @@ -0,0 +1,72 @@ +package com.alibaba.druid.sql.dialect.postgresql.ast.stmt; + +import java.util.ArrayList; +import java.util.List; + +import com.alibaba.druid.sql.ast.SQLExpr; +import com.alibaba.druid.sql.ast.statement.SQLInsertStatement; +import com.alibaba.druid.sql.dialect.postgresql.ast.PGWithClause; +import com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor; +import com.alibaba.druid.sql.visitor.SQLASTVisitor; + +public class PGInsertStatement extends SQLInsertStatement implements PGSQLStatement { + + private static final long serialVersionUID = 1L; + + private PGWithClause with; + private List valuesList = new ArrayList(); + private SQLExpr returning; + + public SQLExpr getReturning() { + return returning; + } + + public void setReturning(SQLExpr returning) { + this.returning = returning; + } + + public PGWithClause getWith() { + return with; + } + + public void setWith(PGWithClause with) { + this.with = with; + } + + public ValuesClause getValues() { + if (valuesList.size() == 0) { + return null; + } + return valuesList.get(0); + } + + public void setValues(ValuesClause values) { + if (valuesList.size() == 0) { + valuesList.add(values); + } else { + valuesList.set(0, values); + } + } + + public List getValuesList() { + return valuesList; + } + + protected void accept0(SQLASTVisitor visitor) { + accept0((PGASTVisitor) visitor); + } + + @Override + public void accept0(PGASTVisitor visitor) { + if (visitor.visit(this)) { + this.acceptChild(visitor, with); + this.acceptChild(visitor, tableName); + this.acceptChild(visitor, columns); + this.acceptChild(visitor, valuesList); + this.acceptChild(visitor, query); + this.acceptChild(visitor, returning); + } + + visitor.endVisit(this); + } +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGSQLStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGSQLStatement.java new file mode 100644 index 0000000000..d22ef5134e --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGSQLStatement.java @@ -0,0 +1,8 @@ +package com.alibaba.druid.sql.dialect.postgresql.ast.stmt; + +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.postgresql.ast.PGSQLObject; + +public interface PGSQLStatement extends SQLStatement, PGSQLObject { + +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/PGSQLStatementImpl.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGSQLStatementImpl.java similarity index 54% rename from src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/PGSQLStatementImpl.java rename to src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGSQLStatementImpl.java index c6161c79ba..0417193232 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/PGSQLStatementImpl.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGSQLStatementImpl.java @@ -1,4 +1,6 @@ -package com.alibaba.druid.sql.dialect.postgresql.ast; +package com.alibaba.druid.sql.dialect.postgresql.ast.stmt; + +import com.alibaba.druid.sql.dialect.postgresql.ast.PGSQLObjectImpl; public abstract class PGSQLStatementImpl extends PGSQLObjectImpl implements PGSQLStatement { 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/stmt/PGSelectQueryBlock.java similarity index 96% rename from src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/PGSelectQueryBlock.java rename to src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGSelectQueryBlock.java index 05fc7d48e8..a46592560c 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/stmt/PGSelectQueryBlock.java @@ -1,4 +1,4 @@ -package com.alibaba.druid.sql.dialect.postgresql.ast; +package com.alibaba.druid.sql.dialect.postgresql.ast.stmt; import java.util.ArrayList; import java.util.List; @@ -6,6 +6,8 @@ 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.SQLSelectQueryBlock; +import com.alibaba.druid.sql.dialect.postgresql.ast.PGSQLObjectImpl; +import com.alibaba.druid.sql.dialect.postgresql.ast.PGWithClause; import com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor; import com.alibaba.druid.sql.visitor.SQLASTVisitor; diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGSelectStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGSelectStatement.java new file mode 100644 index 0000000000..cd570b372d --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGSelectStatement.java @@ -0,0 +1,32 @@ +package com.alibaba.druid.sql.dialect.postgresql.ast.stmt; + +import com.alibaba.druid.sql.ast.statement.SQLSelectStatement; +import com.alibaba.druid.sql.dialect.postgresql.ast.PGWithClause; +import com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor; +import com.alibaba.druid.sql.visitor.SQLASTVisitor; + +public class PGSelectStatement extends SQLSelectStatement implements PGSQLStatement { + + private static final long serialVersionUID = 1L; + private PGWithClause with; + + public PGWithClause getWith() { + return with; + } + + public void setWith(PGWithClause with) { + this.with = with; + } + + protected void accept0(SQLASTVisitor visitor) { + accept0((PGASTVisitor) visitor); + } + + public void accept0(PGASTVisitor visitor) { + if (visitor.visit(this)) { + acceptChild(visitor, this.with); + acceptChild(visitor, this.select); + } + 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/stmt/PGTruncateStatement.java similarity index 94% rename from src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/PGTruncateStatement.java rename to src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGTruncateStatement.java index a5936963f4..75cf4d2fa5 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/stmt/PGTruncateStatement.java @@ -1,4 +1,4 @@ -package com.alibaba.druid.sql.dialect.postgresql.ast; +package com.alibaba.druid.sql.dialect.postgresql.ast.stmt; import com.alibaba.druid.sql.ast.statement.SQLTruncateStatement; import com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor; 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 b68065d45a..85a7522b4a 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 @@ -5,10 +5,14 @@ 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.ast.expr.SQLQueryExpr; +import com.alibaba.druid.sql.ast.statement.SQLInsertStatement; 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.PGTruncateStatement; +import com.alibaba.druid.sql.dialect.postgresql.ast.PGWithClause; +import com.alibaba.druid.sql.dialect.postgresql.ast.PGWithQuery; +import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGDeleteStatement; +import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGInsertStatement; +import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGTruncateStatement; import com.alibaba.druid.sql.parser.Lexer; import com.alibaba.druid.sql.parser.ParserException; import com.alibaba.druid.sql.parser.SQLStatementParser; @@ -29,7 +33,55 @@ public class PGSQLStatementParser extends SQLStatementParser { return new PGSelectParser(this.lexer); } - public SQLDeleteStatement parseDeleteStatement() throws ParserException { + public PGInsertStatement parseInsert() { + accept(Token.INSERT); + accept(Token.INTO); + + PGInsertStatement stmt = new PGInsertStatement(); + + SQLName tableName = this.exprParser.name(); + stmt.setTableName(tableName); + + if (lexer.token() == Token.IDENTIFIER) { + stmt.setAlias(lexer.stringVal()); + lexer.nextToken(); + } + + if (lexer.token() == (Token.LPAREN)) { + lexer.nextToken(); + this.exprParser.exprList(stmt.getColumns()); + accept(Token.RPAREN); + } + + if (lexer.token() == (Token.VALUES)) { + lexer.nextToken(); + + for (;;) { + accept(Token.LPAREN); + SQLInsertStatement.ValuesClause values = new SQLInsertStatement.ValuesClause(); + this.exprParser.exprList(values.getValues()); + stmt.getValuesList().add(values); + accept(Token.RPAREN); + if (lexer.token() == Token.COMMA) { + lexer.nextToken(); + continue; + } + break; + } + } else if (lexer.token() == (Token.SELECT)) { + SQLQueryExpr queryExpr = (SQLQueryExpr) this.createExprParser().expr(); + stmt.setQuery(queryExpr.getSubQuery()); + } + + if (lexer.token() == Token.RETURNING) { + lexer.nextToken(); + SQLExpr returning = this.exprParser.expr(); + stmt.setReturning(returning); + } + return stmt; + } + + public PGDeleteStatement parseDeleteStatement() throws ParserException { lexer.nextToken(); PGDeleteStatement deleteStatement = new PGDeleteStatement(); @@ -72,7 +124,7 @@ public class PGSQLStatementParser extends SQLStatementParser { deleteStatement.setWhere(where); } } - + if (lexer.token() == Token.RETURNING) { lexer.nextToken(); accept(Token.STAR); @@ -131,11 +183,91 @@ public class PGSQLStatementParser extends SQLStatementParser { public boolean parseStatementListDialect(List statementList) { if (lexer.token() == Token.WITH) { - SQLStatement stmt = parseSelect(); + SQLStatement stmt = parseWith(); statementList.add(stmt); return true; } return false; } + + public PGWithClause parseWithClause() { + lexer.nextToken(); + + PGWithClause withClause = new PGWithClause(); + + if (lexer.token() == Token.RECURSIVE) { + lexer.nextToken(); + withClause.setRecursive(true); + } + + for (;;) { + PGWithQuery withQuery = withQuery(); + withClause.getWithQuery().add(withQuery); + if (lexer.token() == Token.COMMA) { + lexer.nextToken(); + continue; + } else { + break; + } + } + return withClause; + } + + private PGWithQuery withQuery() { + PGWithQuery withQuery = new PGWithQuery(); + withQuery.setName(this.createExprParser().expr()); + + if (lexer.token() == Token.LPAREN) { + lexer.nextToken(); + + for (;;) { + SQLExpr expr = this.createExprParser().expr(); + withQuery.getColumns().add(expr); + if (lexer.token() == Token.COMMA) { + lexer.nextToken(); + continue; + } else { + break; + } + } + + accept(Token.RPAREN); + } + + accept(Token.AS); + + if (lexer.token() == Token.LPAREN) { + lexer.nextToken(); + + SQLStatement query; + if (lexer.token() == Token.SELECT) { + query = this.parseSelect(); + } else if (lexer.token() == Token.INSERT) { + query = this.parseInsert(); + } else if (lexer.token() == Token.UPDATE) { + query = this.parseUpdateStatement(); + } else if (lexer.token() == Token.DELETE) { + query = this.parseDeleteStatement(); + } else { + throw new ParserException("syntax error, support token '" + lexer.token() + "'"); + } + withQuery.setQuery(query); + + accept(Token.RPAREN); + } + + return withQuery; + } + + public SQLStatement parseWith() { + PGWithClause with = this.parseWithClause(); + if (lexer.token() == Token.INSERT) { + PGInsertStatement stmt = this.parseInsert(); + stmt.setWith(with); + return stmt; + } + + throw new ParserException("TODO"); + } } 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 44222503e0..76a8a16812 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 @@ -4,10 +4,8 @@ import com.alibaba.druid.sql.ast.SQLExpr; import com.alibaba.druid.sql.ast.SQLSetQuantifier; 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.PGWithClause; -import com.alibaba.druid.sql.dialect.postgresql.ast.PGWithQuery; +import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock; +import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock.IntoClause; import com.alibaba.druid.sql.parser.Lexer; import com.alibaba.druid.sql.parser.ParserException; import com.alibaba.druid.sql.parser.SQLSelectParser; @@ -28,30 +26,6 @@ public class PGSelectParser extends SQLSelectParser { protected SQLSelectQuery query() throws ParserException { PGSelectQueryBlock queryBlock = new PGSelectQueryBlock(); - if (lexer.token() == Token.WITH) { - lexer.nextToken(); - - PGWithClause withClause = new PGWithClause(); - - if (lexer.token() == Token.RECURSIVE) { - lexer.nextToken(); - withClause.setRecursive(true); - } - - for (;;) { - PGWithQuery withQuery = withQuery(); - withClause.getWithQuery().add(withQuery); - if (lexer.token() == Token.COMMA) { - lexer.nextToken(); - continue; - } else { - break; - } - } - - queryBlock.setWith(withClause); - } - accept(Token.SELECT); if (lexer.token() == Token.DISTINCT) { @@ -221,37 +195,5 @@ public class PGSelectParser extends SQLSelectParser { return queryRest(queryBlock); } - private PGWithQuery withQuery() { - PGWithQuery withQuery = new PGWithQuery(); - withQuery.setName(expr()); - - if (lexer.token() == Token.LPAREN) { - lexer.nextToken(); - - for (;;) { - SQLExpr expr = this.createExprParser().expr(); - withQuery.getColumns().add(expr); - if (lexer.token() == Token.COMMA) { - lexer.nextToken(); - continue; - } else { - break; - } - } - - accept(Token.RPAREN); - } - - accept(Token.AS); - - if (lexer.token() == Token.LPAREN) { - lexer.nextToken(); - - SQLSelectQuery subQuery = query(); - withQuery.setSubQuery(subQuery); - accept(Token.RPAREN); - } - - return withQuery; - } + } 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 b596f2d7cc..d9fe19dad1 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,11 +1,13 @@ 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; import com.alibaba.druid.sql.dialect.postgresql.ast.PGWithClause; import com.alibaba.druid.sql.dialect.postgresql.ast.PGWithQuery; +import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGDeleteStatement; +import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGInsertStatement; +import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock; +import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectStatement; +import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGTruncateStatement; import com.alibaba.druid.sql.visitor.SQLASTVisitor; public interface PGASTVisitor extends SQLASTVisitor { @@ -45,4 +47,12 @@ public interface PGASTVisitor extends SQLASTVisitor { void endVisit(PGCurrentOfExpr x); boolean visit(PGCurrentOfExpr x); + + void endVisit(PGInsertStatement x); + + boolean visit(PGInsertStatement x); + + void endVisit(PGSelectStatement x); + + boolean visit(PGSelectStatement 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 c4d043f1e4..45339130e5 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,14 @@ 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; -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.PGTruncateStatement; +import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGDeleteStatement; +import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGInsertStatement; +import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectStatement; +import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGTruncateStatement; +import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock.FetchClause; +import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock.ForClause; +import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock.IntoClause; +import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock.WindowClause; 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; @@ -110,5 +112,25 @@ public class PGASTVisitorAdapter extends SQLASTVisitorAdapter implements PGASTVi public boolean visit(PGCurrentOfExpr x) { return true; } + + @Override + public void endVisit(PGInsertStatement x) { + + } + + @Override + public boolean visit(PGInsertStatement x) { + return true; + } + + @Override + public void endVisit(PGSelectStatement x) { + + } + + @Override + public boolean visit(PGSelectStatement 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 a64849c3ea..b8bbb91553 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,17 @@ 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.ast.statement.SQLSelectStatement; 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; -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.PGTruncateStatement; +import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGDeleteStatement; +import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGInsertStatement; +import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock; +import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectStatement; +import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGTruncateStatement; +import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock.FetchClause; +import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock.ForClause; +import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock.IntoClause; +import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock.WindowClause; 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; @@ -109,7 +112,7 @@ public class PGOutputVisitor extends SQLASTOutputVisitor implements PGASTVisitor print("("); incrementIndent(); println(); - x.getSubQuery().accept(this); + x.getQuery().accept(this); decrementIndent(); println(); print(")"); @@ -324,4 +327,72 @@ public class PGOutputVisitor extends SQLASTOutputVisitor implements PGASTVisitor return false; } + + @Override + public void endVisit(PGInsertStatement x) { + + } + + @Override + public boolean visit(PGInsertStatement x) { + if (x.getWith() != null) { + x.getWith().accept(this); + println(); + } + + print("INSERT INTO "); + + x.getTableName().accept(this); + + if (x.getColumns().size() > 0) { + incrementIndent(); + println(); + print("("); + for (int i = 0, size = x.getColumns().size(); i < size; ++i) { + if (i != 0) { + if (i % 5 == 0) { + println(); + } + print(", "); + } + x.getColumns().get(i).accept(this); + } + print(")"); + decrementIndent(); + } + + if (x.getValues() != null) { + println(); + print("VALUES "); + printlnAndAccept(x.getValuesList(), ", "); + } else { + if (x.getQuery() != null) { + println(); + x.getQuery().accept(this); + } + } + + if (x.getReturning() != null) { + println(); + print("RETURNING "); + x.getReturning().accept(this); + } + + return false; + } + + @Override + public void endVisit(PGSelectStatement x) { + + } + + @Override + public boolean visit(PGSelectStatement x) { + if (x.getWith() != null) { + x.getWith().accept(this); + println(); + } + + return visit((SQLSelectStatement) x); + } } 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 16ec0e01c5..fc5958da26 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 @@ -5,14 +5,18 @@ 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.SQLInsertStatement; +import com.alibaba.druid.sql.ast.statement.SQLSelectStatement; 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; -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.PGTruncateStatement; +import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGDeleteStatement; +import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGInsertStatement; +import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectStatement; +import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGTruncateStatement; +import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock.FetchClause; +import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock.ForClause; +import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock.IntoClause; +import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock.WindowClause; 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; @@ -163,4 +167,31 @@ public class PGSchemaStatVisitor extends SchemaStatVisitor implements PGASTVisit public boolean visit(PGCurrentOfExpr x) { return false; } + + @Override + public void endVisit(PGInsertStatement x) { + + } + + @Override + public boolean visit(PGInsertStatement x) { + if (x.getWith() != null) { + x.getWith().accept(this); + } + + return visit((SQLInsertStatement) x); + } + @Override + public void endVisit(PGSelectStatement x) { + + } + + @Override + public boolean visit(PGSelectStatement x) { + if (x.getWith() != null) { + x.getWith().accept(this); + } + + return visit((SQLSelectStatement) x); + } } diff --git a/src/main/java/com/alibaba/druid/sql/parser/Keywords.java b/src/main/java/com/alibaba/druid/sql/parser/Keywords.java index d23f20b1c6..1f8975d830 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/Keywords.java +++ b/src/main/java/com/alibaba/druid/sql/parser/Keywords.java @@ -98,6 +98,7 @@ public class Keywords { map.put("LOCK", Token.LOCK); map.put("SOME", Token.SOME); map.put("ANY", Token.ANY); + map.put("DEFAULT", Token.DEFAULT); DEFAULT_KEYWORDS = new Keywords(map); } 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 66bb4586c3..a04e47adeb 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java @@ -34,6 +34,7 @@ import com.alibaba.druid.sql.ast.expr.SQLBinaryOperator; import com.alibaba.druid.sql.ast.expr.SQLCaseExpr; import com.alibaba.druid.sql.ast.expr.SQLCastExpr; import com.alibaba.druid.sql.ast.expr.SQLCharExpr; +import com.alibaba.druid.sql.ast.expr.SQLDefaultExpr; import com.alibaba.druid.sql.ast.expr.SQLExistsExpr; import com.alibaba.druid.sql.ast.expr.SQLHexExpr; import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; @@ -193,6 +194,10 @@ public class SQLExprParser extends SQLParser { sqlExpr = new SQLVariantRefExpr(lexer.stringVal()); lexer.nextToken(); break; + case DEFAULT: + sqlExpr = new SQLDefaultExpr(); + lexer.nextToken(); + break; case CASE: SQLCaseExpr caseExpr = new SQLCaseExpr(); lexer.nextToken(); @@ -352,10 +357,6 @@ public class SQLExprParser extends SQLParser { case INTERVAL: sqlExpr = parseInterval(); break; - case DEFAULT: - lexer.nextToken(); - sqlExpr = new SQLIdentifierExpr("DEFAULT"); - break; case ANY: lexer.nextToken(); if (lexer.token() == Token.LPAREN) { 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 15c6ea4af0..0d164f1c72 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java @@ -34,6 +34,7 @@ import com.alibaba.druid.sql.ast.expr.SQLCaseExpr; import com.alibaba.druid.sql.ast.expr.SQLCastExpr; import com.alibaba.druid.sql.ast.expr.SQLCharExpr; import com.alibaba.druid.sql.ast.expr.SQLCurrentOfCursorExpr; +import com.alibaba.druid.sql.ast.expr.SQLDefaultExpr; import com.alibaba.druid.sql.ast.expr.SQLExistsExpr; import com.alibaba.druid.sql.ast.expr.SQLHexExpr; import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; @@ -865,16 +866,17 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter { return false; } - - @Override - public void endVisit(SQLTruncateStatement x) { - - } - + @Override public boolean visit(SQLTruncateStatement x) { print("TRUNCATE TABLE "); printAndAccept(x.getTableNames(), ", "); return false; } + + @Override + public boolean visit(SQLDefaultExpr x) { + print("DEFAULT"); + return false; + } } diff --git a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitor.java b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitor.java index 6bce389819..31fcd89a19 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitor.java @@ -30,6 +30,7 @@ import com.alibaba.druid.sql.ast.expr.SQLCastExpr; import com.alibaba.druid.sql.ast.expr.SQLCharExpr; import com.alibaba.druid.sql.ast.expr.SQLCurrentOfCursorExpr; import com.alibaba.druid.sql.ast.expr.SQLDateLiteralExpr; +import com.alibaba.druid.sql.ast.expr.SQLDefaultExpr; import com.alibaba.druid.sql.ast.expr.SQLExistsExpr; import com.alibaba.druid.sql.ast.expr.SQLHexExpr; import com.alibaba.druid.sql.ast.expr.SQLHexStringLiteralExpr; @@ -319,4 +320,8 @@ public interface SQLASTVisitor { void endVisit(SQLTruncateStatement x); boolean visit(SQLTruncateStatement x); + + void endVisit(SQLDefaultExpr x); + + boolean visit(SQLDefaultExpr x); } diff --git a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitorAdapter.java b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitorAdapter.java index 57cc9b8cbd..865c35a0d9 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitorAdapter.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitorAdapter.java @@ -30,6 +30,7 @@ import com.alibaba.druid.sql.ast.expr.SQLCastExpr; import com.alibaba.druid.sql.ast.expr.SQLCharExpr; import com.alibaba.druid.sql.ast.expr.SQLCurrentOfCursorExpr; import com.alibaba.druid.sql.ast.expr.SQLDateLiteralExpr; +import com.alibaba.druid.sql.ast.expr.SQLDefaultExpr; import com.alibaba.druid.sql.ast.expr.SQLExistsExpr; import com.alibaba.druid.sql.ast.expr.SQLHexExpr; import com.alibaba.druid.sql.ast.expr.SQLHexStringLiteralExpr; @@ -550,4 +551,14 @@ public class SQLASTVisitorAdapter implements SQLASTVisitor { public boolean visit(SQLTruncateStatement x) { return true; } + + @Override + public void endVisit(SQLDefaultExpr x) { + + } + + @Override + public boolean visit(SQLDefaultExpr x) { + return true; + } } diff --git a/src/test/java/com/alibaba/druid/bvt/sql/postgresql/PGInsertTest2.java b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/PGInsertTest2.java new file mode 100644 index 0000000000..a0c6b84a43 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/PGInsertTest2.java @@ -0,0 +1,44 @@ +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 PGInsertTest2 extends PGTest { + + public void test_0() throws Exception { + String sql = "INSERT INTO films (code, title, did, date_prod, kind) VALUES" + + " ('B6717', 'Tampopo', 110, '1985-02-10', 'Comedy'), " + + "('HG120', 'The Dinner Game', 140, DEFAULT, 'Comedy');"; + + 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.assertEquals(5, visitor.getFields().size()); + + Assert.assertTrue(visitor.getFields().contains(new TableStat.Column("films", "kind"))); + Assert.assertTrue(visitor.getFields().contains(new TableStat.Column("films", "code"))); + Assert.assertTrue(visitor.getFields().contains(new TableStat.Column("films", "date_prod"))); + Assert.assertTrue(visitor.getFields().contains(new TableStat.Column("films", "title"))); + Assert.assertTrue(visitor.getFields().contains(new TableStat.Column("films", "did"))); + } + +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/postgresql/PGInsertTest3.java b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/PGInsertTest3.java new file mode 100644 index 0000000000..45883abd4d --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/PGInsertTest3.java @@ -0,0 +1,40 @@ +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 PGInsertTest3 extends PGTest { + + public void test_0() throws Exception { + String sql = "INSERT INTO films SELECT * FROM tmp_films WHERE date_prod < '2004-05-07';"; + + 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("tmp_films"))); + + Assert.assertEquals(2, visitor.getFields().size()); + + Assert.assertTrue(visitor.getFields().contains(new TableStat.Column("tmp_films", "date_prod"))); + Assert.assertTrue(visitor.getFields().contains(new TableStat.Column("tmp_films", "*"))); + } + +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/postgresql/PGInsertTest4.java b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/PGInsertTest4.java new file mode 100644 index 0000000000..6ec42097da --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/PGInsertTest4.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; + +public class PGInsertTest4 extends PGTest { + + public void test_0() throws Exception { + String sql = "INSERT INTO distributors (did, dname) VALUES (DEFAULT, 'XYZ Widgets') RETURNING did;"; + + 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("distributors"))); + + Assert.assertEquals(2, visitor.getFields().size()); + + Assert.assertTrue(visitor.getFields().contains(new TableStat.Column("distributors", "did"))); + Assert.assertTrue(visitor.getFields().contains(new TableStat.Column("distributors", "dname"))); + } + +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/postgresql/PGInsertTest5.java b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/PGInsertTest5.java new file mode 100644 index 0000000000..d37b9eeed4 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/PGInsertTest5.java @@ -0,0 +1,44 @@ +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 PGInsertTest5 extends PGTest { + + public void test_0() throws Exception { + String sql = "WITH upd AS (" + // + " UPDATE employees SET sales_count = sales_count + 1 WHERE id =" + // + " (SELECT sales_person FROM accounts WHERE name = 'Acme Corporation')" + // + " RETURNING *" + // + ")" + // + "INSERT INTO employees_log SELECT *, current_timestamp FROM upd;"; + + 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("distributors"))); + + Assert.assertEquals(2, visitor.getFields().size()); + + Assert.assertTrue(visitor.getFields().contains(new TableStat.Column("distributors", "did"))); + Assert.assertTrue(visitor.getFields().contains(new TableStat.Column("distributors", "dname"))); + } + +}