diff --git a/src/main/java/com/alibaba/druid/sql/PagerUtils.java b/src/main/java/com/alibaba/druid/sql/PagerUtils.java index 24067727ff..b8fe5524c6 100644 --- a/src/main/java/com/alibaba/druid/sql/PagerUtils.java +++ b/src/main/java/com/alibaba/druid/sql/PagerUtils.java @@ -40,6 +40,7 @@ import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock.Limit; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectQueryBlock; import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock; +import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock.PGLimit; import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerSelectQueryBlock; import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerTop; import com.alibaba.druid.util.JdbcConstants; @@ -112,9 +113,30 @@ public class PagerUtils { return limitMySqlQueryBlock((MySqlSelectQueryBlock) queryBlock, dbType, offset, count); } + if (JdbcConstants.POSTGRESQL.equals(dbType)) + { + return limitPostgreSQLQueryBlock((PGSelectQueryBlock) queryBlock, dbType, offset, count); + } throw new UnsupportedOperationException(); } + private static String limitPostgreSQLQueryBlock(PGSelectQueryBlock queryBlock, String dbType, + int offset, int count) { + if (queryBlock.getLimit() != null) + { + throw new IllegalArgumentException("limit already exists."); + } + + PGLimit limit = new PGLimit(); + if (offset > 0) + { + limit.setOffset(new SQLNumberExpr(offset)); + } + limit.setRowCount(new SQLNumberExpr(count)); + queryBlock.setLimit(limit); + + return SQLUtils.toSQLString(queryBlock, dbType); + } private static String limitDB2(SQLSelect select, String dbType, int offset, int count) { SQLSelectQuery query = select.getQuery(); 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 6e58c6893c..04ea681237 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 @@ -19,11 +19,13 @@ import java.util.ArrayList; import java.util.List; 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.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 { @@ -247,5 +249,63 @@ public class PGSelectQueryBlock extends SQLSelectQueryBlock { visitor.endVisit(this); } } + public static class PGLimit extends SQLObjectImpl implements SQLExpr { + + public PGLimit(){ + + } + + private SQLExpr rowCount; + private SQLExpr offset; + + public SQLExpr getRowCount() { + return rowCount; + } + + public void setRowCount(SQLExpr rowCount) { + if (rowCount != null) { + rowCount.setParent(this); + } + this.rowCount = rowCount; + } + + public SQLExpr getOffset() { + return offset; + } + + public void setOffset(SQLExpr offset) { + if (offset != null) { + offset.setParent(this); + } + this.offset = offset; + } + + @Override + protected void accept0(SQLASTVisitor visitor) { + if (visitor instanceof PGASTVisitor) { + PGASTVisitor pgVisitor = (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); + } + } + + } } 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 ddb49757d9..4e6cd95db8 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 @@ -27,6 +27,10 @@ import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGUpdateStatement; import com.alibaba.druid.sql.visitor.SQLASTVisitor; public interface PGASTVisitor extends SQLASTVisitor { + + boolean visit(PGSelectQueryBlock.PGLimit x); + + void endVisit(PGSelectQueryBlock.PGLimit x); void endVisit(PGSelectQueryBlock 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 045375e505..a5e7a2570a 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 @@ -24,6 +24,7 @@ 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.PGSelectQueryBlock.FetchClause; import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock.ForClause; +import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock.PGLimit; import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock.WindowClause; import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectStatement; import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGUpdateStatement; @@ -156,4 +157,14 @@ public class PGASTVisitorAdapter extends SQLASTVisitorAdapter implements PGASTVi return true; } + @Override + public boolean visit(PGLimit x) { + return true; + } + + @Override + public void endVisit(PGLimit x) { + + } + } 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 2bb1b00c3d..a9641597b6 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 @@ -27,6 +27,7 @@ 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.PGSelectQueryBlock.FetchClause; import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock.ForClause; +import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock.PGLimit; import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock.WindowClause; import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectStatement; import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGUpdateStatement; @@ -470,4 +471,14 @@ public class PGOutputVisitor extends SQLASTOutputVisitor implements PGASTVisitor } + @Override + public boolean visit(PGLimit x) { + return true; + } + + @Override + public void endVisit(PGLimit x) { + + } + } diff --git a/src/test/java/com/alibaba/druid/postgresql/PGLimitTest.java b/src/test/java/com/alibaba/druid/postgresql/PGLimitTest.java new file mode 100644 index 0000000000..c5838d355b --- /dev/null +++ b/src/test/java/com/alibaba/druid/postgresql/PGLimitTest.java @@ -0,0 +1,27 @@ +package com.alibaba.druid.postgresql; + +import com.alibaba.druid.util.JdbcConstants; + +/** + * + * @author lizongbo + * + */ +public class PGLimitTest { + + /** + * @param args + */ + public static void main(String[] args) { + String dbType = JdbcConstants.POSTGRESQL;// "postgresql"; + // dbType = "mysql"; + String sql = " select * from brandinfo where 1=1 and brandid > 100 order by brandid asc"; + String sqlLimit = com.alibaba.druid.sql.PagerUtils.limit(sql, dbType, + 2499, 100); + System.out.println("sqlLimit == " + sqlLimit); + String sqlCount = com.alibaba.druid.sql.PagerUtils.count(sql, dbType); + System.out.println("sqlCount == " + sqlCount); + + } + +}