From 58174442a438a86d6ca80e380bad7e5de3b550ce Mon Sep 17 00:00:00 2001 From: wenshao Date: Sat, 27 Jul 2013 15:48:06 +0800 Subject: [PATCH] improve PageUtils --- .../com/alibaba/druid/sql/PagerUtils.java | 80 ++++++++++++++----- .../sql/PagerUtilsTest_Limit_SQLServer_1.java | 27 +++++++ .../bvt/sql/PagerUtilsTest_Limit_db2_1.java | 27 +++++++ 3 files changed, 113 insertions(+), 21 deletions(-) create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/PagerUtilsTest_Limit_SQLServer_1.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/PagerUtilsTest_Limit_db2_1.java diff --git a/src/main/java/com/alibaba/druid/sql/PagerUtils.java b/src/main/java/com/alibaba/druid/sql/PagerUtils.java index 89e429c4b8..8aefdb15cf 100644 --- a/src/main/java/com/alibaba/druid/sql/PagerUtils.java +++ b/src/main/java/com/alibaba/druid/sql/PagerUtils.java @@ -92,7 +92,7 @@ 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); } @@ -118,6 +118,14 @@ public class PagerUtils { private static String limitDB2(SQLSelect select, String dbType, int offset, int count) { SQLSelectQuery query = select.getQuery(); + 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); + if (query instanceof SQLSelectQueryBlock) { DB2SelectQueryBlock queryBlock = (DB2SelectQueryBlock) query; if (offset <= 0) { @@ -137,25 +145,44 @@ public class PagerUtils { 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); } - return SQLUtils.toSQLString(select, dbType); + DB2SelectQueryBlock countQueryBlock = new DB2SelectQueryBlock(); + countQueryBlock.getSelectList().add(new SQLSelectItem(new SQLPropertyExpr(new SQLIdentifierExpr("XX"), "*"))); + SQLAggregateExpr aggregateExpr = new SQLAggregateExpr("ROW_NUMBER"); + SQLOrderBy orderBy = select.getOrderBy(); + aggregateExpr.setOver(new SQLOver(orderBy)); + select.setOrderBy(null); + countQueryBlock.getSelectList().add(new SQLSelectItem(aggregateExpr, "ROWNUM")); + + countQueryBlock.setFrom(new SQLSubqueryTableSource(select, "XX")); + + if (offset <= 0) { + return SQLUtils.toSQLString(countQueryBlock, dbType); + } + + DB2SelectQueryBlock offsetQueryBlock = new DB2SelectQueryBlock(); + offsetQueryBlock.getSelectList().add(new SQLSelectItem(new SQLAllColumnExpr())); + offsetQueryBlock.setFrom(new SQLSubqueryTableSource(new SQLSelect(countQueryBlock), "XXX")); + offsetQueryBlock.setWhere(pageCondition); + + return SQLUtils.toSQLString(offsetQueryBlock, dbType); } - + private static String limitSQLServer(SQLSelect select, String dbType, int offset, int count) { SQLSelectQuery query = select.getQuery(); + 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); + if (query instanceof SQLSelectQueryBlock) { SQLServerSelectQueryBlock queryBlock = (SQLServerSelectQueryBlock) query; if (offset <= 0) { @@ -172,25 +199,36 @@ public class PagerUtils { queryBlock.getSelectList().add(new SQLSelectItem(aggregateExpr, "ROWNUM")); - DB2SelectQueryBlock countQueryBlock = new DB2SelectQueryBlock(); + SQLServerSelectQueryBlock countQueryBlock = new SQLServerSelectQueryBlock(); 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); } - return SQLUtils.toSQLString(select, dbType); + SQLServerSelectQueryBlock countQueryBlock = new SQLServerSelectQueryBlock(); + countQueryBlock.getSelectList().add(new SQLSelectItem(new SQLPropertyExpr(new SQLIdentifierExpr("XX"), "*"))); + SQLAggregateExpr aggregateExpr = new SQLAggregateExpr("ROW_NUMBER"); + SQLOrderBy orderBy = select.getOrderBy(); + aggregateExpr.setOver(new SQLOver(orderBy)); + select.setOrderBy(null); + countQueryBlock.getSelectList().add(new SQLSelectItem(aggregateExpr, "ROWNUM")); + + countQueryBlock.setFrom(new SQLSubqueryTableSource(select, "XX")); + + if (offset <= 0) { + return SQLUtils.toSQLString(countQueryBlock, dbType); + } + + SQLServerSelectQueryBlock offsetQueryBlock = new SQLServerSelectQueryBlock(); + offsetQueryBlock.getSelectList().add(new SQLSelectItem(new SQLAllColumnExpr())); + offsetQueryBlock.setFrom(new SQLSubqueryTableSource(new SQLSelect(countQueryBlock), "XXX")); + offsetQueryBlock.setWhere(pageCondition); + + return SQLUtils.toSQLString(offsetQueryBlock, dbType); } private static String limitOracle(SQLSelect select, String dbType, int offset, int count) { diff --git a/src/test/java/com/alibaba/druid/bvt/sql/PagerUtilsTest_Limit_SQLServer_1.java b/src/test/java/com/alibaba/druid/bvt/sql/PagerUtilsTest_Limit_SQLServer_1.java new file mode 100644 index 0000000000..f0c0f59c7b --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/PagerUtilsTest_Limit_SQLServer_1.java @@ -0,0 +1,27 @@ +package com.alibaba.druid.bvt.sql; + +import junit.framework.TestCase; + +import org.junit.Assert; + +import com.alibaba.druid.sql.PagerUtils; +import com.alibaba.druid.util.JdbcConstants; + +public class PagerUtilsTest_Limit_SQLServer_1 extends TestCase { + + public void test_db2_union() throws Exception { + String sql = "select * from t1 union select * from t2"; + String result = PagerUtils.limit(sql, JdbcConstants.SQL_SERVER, 20, 10); + Assert.assertEquals("SELECT *" // + + "\nFROM (SELECT XX.*, ROW_NUMBER() OVER () AS ROWNUM" // + + "\n\tFROM (SELECT *" // + + "\n\t\tFROM t1" // + + "\n\t\tUNION" // + + "\n\t\tSELECT *" // + + "\n\t\tFROM t2" // + + "\n\t\t) XX" // + + "\n\t) XXX" // + + "\nWHERE ROWNUM > 20" // + + "\n\tAND ROWNUM <= 30", result); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/PagerUtilsTest_Limit_db2_1.java b/src/test/java/com/alibaba/druid/bvt/sql/PagerUtilsTest_Limit_db2_1.java new file mode 100644 index 0000000000..48c785bb6e --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/PagerUtilsTest_Limit_db2_1.java @@ -0,0 +1,27 @@ +package com.alibaba.druid.bvt.sql; + +import junit.framework.TestCase; + +import org.junit.Assert; + +import com.alibaba.druid.sql.PagerUtils; +import com.alibaba.druid.util.JdbcConstants; + +public class PagerUtilsTest_Limit_db2_1 extends TestCase { + + public void test_db2_union() throws Exception { + String sql = "select * from t1 union select * from t2"; + String result = PagerUtils.limit(sql, JdbcConstants.DB2, 20, 10); + Assert.assertEquals("SELECT *" // + + "\nFROM (SELECT XX.*, ROW_NUMBER() OVER () AS ROWNUM" // + + "\n\tFROM (SELECT *" // + + "\n\t\tFROM t1" // + + "\n\t\tUNION" // + + "\n\t\tSELECT *" // + + "\n\t\tFROM t2" // + + "\n\t\t) XX" // + + "\n\t) XXX" // + + "\nWHERE ROWNUM > 20" // + + "\n\tAND ROWNUM <= 30", result); + } +}