diff --git a/src/main/java/com/alibaba/druid/sql/PagerUtils.java b/src/main/java/com/alibaba/druid/sql/PagerUtils.java index 3e441c5429..5205ce6190 100644 --- a/src/main/java/com/alibaba/druid/sql/PagerUtils.java +++ b/src/main/java/com/alibaba/druid/sql/PagerUtils.java @@ -42,6 +42,7 @@ import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleAggregateExpr; 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.sqlserver.ast.SQLServerSelectQueryBlock; +import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerTop; import com.alibaba.druid.util.JdbcConstants; public class PagerUtils { @@ -91,6 +92,10 @@ public class PagerUtils { if (JdbcConstants.DB2.equals(dbType)) { return limitDB2(select, dbType, offset, count); } + + if (JdbcConstants.SQL_SERVER.equals(dbType)) { + return limitSQLServer(select, dbType, offset, count); + } if (query instanceof SQLSelectQueryBlock) { return limitQueryBlock(select, dbType, offset, count); @@ -144,12 +149,45 @@ public class PagerUtils { countQueryBlock.setWhere(pageCondition); - // DB2SelectQueryBlock offsetQueryBlock = new DB2SelectQueryBlock(); - // offsetQueryBlock.getSelectList().add(new SQLSelectItem(new SQLAllColumnExpr())); - // offsetQueryBlock.setFrom(new SQLSubqueryTableSource(new SQLSelect(countQueryBlock), "XXX")); - // offsetQueryBlock.setWhere(new SQLBinaryOpExpr(new SQLIdentifierExpr("RN"), // - // SQLBinaryOperator.GreaterThan, // - // new SQLNumberExpr(offset))); + return SQLUtils.toSQLString(countQueryBlock, dbType); + } + + return SQLUtils.toSQLString(select, dbType); + } + + private static String limitSQLServer(SQLSelect select, String dbType, int offset, int count) { + SQLSelectQuery query = select.getQuery(); + + if (query instanceof SQLSelectQueryBlock) { + SQLServerSelectQueryBlock queryBlock = (SQLServerSelectQueryBlock) query; + if (offset <= 0) { + queryBlock.setTop(new SQLServerTop(new SQLNumberExpr(count))); + return SQLUtils.toSQLString(select, dbType); + } + + SQLAggregateExpr aggregateExpr = new SQLAggregateExpr("ROW_NUMBER"); + SQLOrderBy orderBy = select.getOrderBy(); + if (orderBy != null) { + aggregateExpr.setOver(new SQLOver(orderBy)); + select.setOrderBy(null); + } + + queryBlock.getSelectList().add(new SQLSelectItem(aggregateExpr, "ROWNUM")); + + DB2SelectQueryBlock countQueryBlock = new DB2SelectQueryBlock(); + countQueryBlock.getSelectList().add(new SQLSelectItem(new SQLAllColumnExpr())); + + countQueryBlock.setFrom(new SQLSubqueryTableSource(select, "XX")); + + SQLBinaryOpExpr gt = new SQLBinaryOpExpr(new SQLIdentifierExpr("ROWNUM"), // + SQLBinaryOperator.GreaterThan, // + new SQLNumberExpr(offset)); + SQLBinaryOpExpr lteq = new SQLBinaryOpExpr(new SQLIdentifierExpr("ROWNUM"), // + SQLBinaryOperator.LessThanOrEqual, // + new SQLNumberExpr(count + offset)); + SQLBinaryOpExpr pageCondition = new SQLBinaryOpExpr(gt, SQLBinaryOperator.BooleanAnd, lteq); + + countQueryBlock.setWhere(pageCondition); return SQLUtils.toSQLString(countQueryBlock, dbType); } diff --git a/src/main/java/com/alibaba/druid/sql/ast/SQLOrderBy.java b/src/main/java/com/alibaba/druid/sql/ast/SQLOrderBy.java index 0221bc22dd..1ca107481a 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/SQLOrderBy.java +++ b/src/main/java/com/alibaba/druid/sql/ast/SQLOrderBy.java @@ -29,6 +29,12 @@ public class SQLOrderBy extends SQLObjectImpl { public SQLOrderBy(){ } + + public SQLOrderBy(SQLExpr expr) { + SQLSelectOrderByItem item = new SQLSelectOrderByItem(expr); + item.setParent(this); + this.items.add(item); + } public List getItems() { return this.items; diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectOrderByItem.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectOrderByItem.java index 663bd1ee57..a566b95bac 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectOrderByItem.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectOrderByItem.java @@ -31,12 +31,19 @@ public class SQLSelectOrderByItem extends SQLObjectImpl { public SQLSelectOrderByItem(){ } + + public SQLSelectOrderByItem(SQLExpr expr){ + this.setExpr(expr); + } public SQLExpr getExpr() { return this.expr; } public void setExpr(SQLExpr expr) { + if (expr != null) { + expr.setParent(this); + } this.expr = expr; } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/SQLServerSelectQueryBlock.java b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/SQLServerSelectQueryBlock.java index 35eb7d4b99..86fe529395 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/SQLServerSelectQueryBlock.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/SQLServerSelectQueryBlock.java @@ -33,6 +33,9 @@ public class SQLServerSelectQueryBlock extends SQLSelectQueryBlock { } public void setTop(SQLServerTop top) { + if (top != null) { + top.setParent(this); + } this.top = top; } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/SQLServerTop.java b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/SQLServerTop.java index c5dd0d6b70..e887e75d3f 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/SQLServerTop.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/SQLServerTop.java @@ -28,12 +28,23 @@ public class SQLServerTop extends SQLServerObjectImpl { private SQLExpr expr; private boolean percent; private boolean withTies; + + public SQLServerTop() { + + } + + public SQLServerTop(SQLExpr expr) { + this.setExpr(expr); + } public SQLExpr getExpr() { return expr; } public void setExpr(SQLExpr expr) { + if (expr != null) { + expr.setParent(this); + } this.expr = expr; }