From a2d8db21022a2cd8f6f3bcd3e46576ad356182ec Mon Sep 17 00:00:00 2001 From: wenshao Date: Sat, 6 Jun 2015 02:30:08 +0800 Subject: [PATCH] bug fixed for pg sqlparser --- .../ast/stmt/PGSelectQueryBlock.java | 54 ++++++++---------- .../postgresql/parser/PGSelectParser.java | 19 +++++-- .../postgresql/visitor/PGOutputVisitor.java | 14 ++--- .../bvt/sql/postgresql/PGSelectTest23.java | 55 +++++++++++++++++++ 4 files changed, 99 insertions(+), 43 deletions(-) create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/postgresql/PGSelectTest23.java diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGSelectQueryBlock.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGSelectQueryBlock.java index 04ea681237..6e837cabca 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGSelectQueryBlock.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGSelectQueryBlock.java @@ -22,18 +22,17 @@ import com.alibaba.druid.sql.ast.SQLExpr; import com.alibaba.druid.sql.ast.SQLObjectImpl; import com.alibaba.druid.sql.ast.SQLOrderBy; import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock; +import com.alibaba.druid.sql.dialect.postgresql.ast.PGSQLObject; 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.dialect.postgresql.visitor.PGOutputVisitor; import com.alibaba.druid.sql.visitor.SQLASTVisitor; public class PGSelectQueryBlock extends SQLSelectQueryBlock { private PGWithClause with; private List distinctOn = new ArrayList(2); - private SQLExpr limit; - private SQLExpr offset; + private PGLimit limit; private WindowClause window; private SQLOrderBy orderBy; @@ -70,7 +69,6 @@ public class PGSelectQueryBlock extends SQLSelectQueryBlock { acceptChild(visitor, this.window); acceptChild(visitor, this.orderBy); acceptChild(visitor, this.limit); - acceptChild(visitor, this.offset); acceptChild(visitor, this.fetch); acceptChild(visitor, this.forClause); } @@ -109,11 +107,11 @@ public class PGSelectQueryBlock extends SQLSelectQueryBlock { this.with = with; } - public SQLExpr getLimit() { + public PGLimit getLimit() { return limit; } - public void setLimit(SQLExpr limit) { + public void setLimit(PGLimit limit) { this.limit = limit; } @@ -126,11 +124,18 @@ public class PGSelectQueryBlock extends SQLSelectQueryBlock { } public SQLExpr getOffset() { - return offset; + if (limit != null) { + return limit.offset; + } + return null; } public void setOffset(SQLExpr offset) { - this.offset = offset; + if (limit == null) { + limit = new PGLimit(); + limit.setParent(this); + } + limit.setOffset(offset); } public List getDistinctOn() { @@ -249,7 +254,8 @@ public class PGSelectQueryBlock extends SQLSelectQueryBlock { visitor.endVisit(this); } } - public static class PGLimit extends SQLObjectImpl implements SQLExpr { + + public static class PGLimit extends SQLObjectImpl implements SQLExpr, PGSQLObject { public PGLimit(){ @@ -279,31 +285,19 @@ public class PGSelectQueryBlock extends SQLSelectQueryBlock { } this.offset = offset; } - + @Override protected void accept0(SQLASTVisitor visitor) { - if (visitor instanceof PGASTVisitor) { - PGASTVisitor pgVisitor = (PGASTVisitor) visitor; + accept0((PGASTVisitor) visitor); + } - if (pgVisitor.visit(this)) { - if (pgVisitor instanceof PGOutputVisitor) - { - PGOutputVisitor pgv = (PGOutputVisitor) pgVisitor; - pgv.print(this.rowCount.toString()); - if (this.offset != null) - { - pgv.print(" OFFSET "); - pgv.print(this.offset.toString()); - } - } - else - { - acceptChild(visitor, offset); - acceptChild(visitor, rowCount); - } - } - pgVisitor.endVisit(this); + @Override + public void accept0(PGASTVisitor visitor) { + if (visitor.visit(this)) { + acceptChild(visitor, offset); + acceptChild(visitor, rowCount); } + visitor.endVisit(this); } } 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 d3abbba30d..145d0676a7 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 @@ -27,8 +27,9 @@ import com.alibaba.druid.sql.ast.statement.SQLTableSource; import com.alibaba.druid.sql.dialect.postgresql.ast.expr.PGParameter; import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGFunctionTableSource; import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock; -import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGValuesQuery; import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock.IntoOption; +import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock.PGLimit; +import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGValuesQuery; import com.alibaba.druid.sql.parser.ParserException; import com.alibaba.druid.sql.parser.SQLExprParser; import com.alibaba.druid.sql.parser.SQLSelectParser; @@ -158,18 +159,26 @@ public class PGSelectParser extends SQLSelectParser { for (;;) { if (lexer.token() == Token.LIMIT) { + PGLimit limit = new PGLimit(); + lexer.nextToken(); if (lexer.token() == Token.ALL) { - queryBlock.setLimit(new SQLIdentifierExpr("ALL")); + limit.setRowCount(new SQLIdentifierExpr("ALL")); lexer.nextToken(); } else { - SQLExpr limit = expr(); + limit.setRowCount(expr()); + } + + queryBlock.setLimit(limit); + } else if (lexer.token() == Token.OFFSET) { + PGLimit limit = queryBlock.getLimit(); + if (limit == null) { + limit = new PGLimit(); queryBlock.setLimit(limit); } - } else if (lexer.token() == Token.OFFSET) { lexer.nextToken(); SQLExpr offset = expr(); - queryBlock.setOffset(offset); + limit.setOffset(offset); if (lexer.token() == Token.ROW || lexer.token() == Token.ROWS) { lexer.nextToken(); 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 d8ee5334ae..b218f860a2 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 @@ -234,13 +234,6 @@ public class PGOutputVisitor extends SQLASTOutputVisitor implements PGASTVisitor x.getLimit().accept(this); } - if (x.getOffset() != null) { - println(); - print("OFFSET "); - x.getOffset().accept(this); - print(" ROWS"); - } - if (x.getFetch() != null) { println(); x.getFetch().accept(this); @@ -491,7 +484,12 @@ public class PGOutputVisitor extends SQLASTOutputVisitor implements PGASTVisitor @Override public boolean visit(PGLimit x) { - return true; + x.getRowCount().accept(this); + if (x.getOffset() != null) { + print(" OFFSET "); + x.getOffset().accept(this); + } + return false; } @Override diff --git a/src/test/java/com/alibaba/druid/bvt/sql/postgresql/PGSelectTest23.java b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/PGSelectTest23.java new file mode 100644 index 0000000000..20ff3c3ccc --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/PGSelectTest23.java @@ -0,0 +1,55 @@ +/* + * 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 PGSelectTest23 extends PGTest { + + public void test_0() throws Exception { + String sql = "select id, login_name, name, password, salt, roles, register_date from user WHERE ( name like ? ) limit ? offset ?"; + + PGSQLStatementParser parser = new PGSQLStatementParser(sql); + List statementList = parser.parseStatementList(); + SQLStatement statemen = statementList.get(0); + print(statementList); + + Assert.assertEquals("SELECT id, login_name, name, password, salt" + + "\n\t, roles, register_date" + + "\nFROM user" + + "\nWHERE name LIKE ?" + + "\nLIMIT ? OFFSET ?", 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(7, visitor.getColumns().size()); + Assert.assertEquals(1, visitor.getTables().size()); + } +}