From 21b8a41f4f3da5c0c9c9f628f0af06152bb3b508 Mon Sep 17 00:00:00 2001 From: wenshao Date: Sat, 2 Feb 2013 13:48:48 +0800 Subject: [PATCH] add PagerUtils --- .../com/alibaba/druid/sql/PagerUtils.java | 106 +++++++++++++++--- src/test/java/PagerUtils/PagerUtilsTest0.java | 12 +- .../PagerUtils/PagerUtilsTestLimit_0.java | 44 ++++++++ 3 files changed, 145 insertions(+), 17 deletions(-) create mode 100644 src/test/java/PagerUtils/PagerUtilsTestLimit_0.java diff --git a/src/main/java/com/alibaba/druid/sql/PagerUtils.java b/src/main/java/com/alibaba/druid/sql/PagerUtils.java index f576a30b37..4f75c76399 100644 --- a/src/main/java/com/alibaba/druid/sql/PagerUtils.java +++ b/src/main/java/com/alibaba/druid/sql/PagerUtils.java @@ -1,3 +1,18 @@ +/* + * 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.sql; import java.util.List; @@ -5,6 +20,7 @@ import java.util.List; import com.alibaba.druid.sql.ast.SQLStatement; import com.alibaba.druid.sql.ast.expr.SQLAggregateExpr; import com.alibaba.druid.sql.ast.expr.SQLAllColumnExpr; +import com.alibaba.druid.sql.ast.expr.SQLNumberExpr; import com.alibaba.druid.sql.ast.statement.SQLSelect; import com.alibaba.druid.sql.ast.statement.SQLSelectItem; import com.alibaba.druid.sql.ast.statement.SQLSelectQuery; @@ -13,6 +29,7 @@ import com.alibaba.druid.sql.ast.statement.SQLSelectStatement; import com.alibaba.druid.sql.ast.statement.SQLSubqueryTableSource; import com.alibaba.druid.sql.ast.statement.SQLUnionQuery; 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.expr.OracleAggregateExpr; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectQueryBlock; import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock; @@ -35,15 +52,63 @@ public class PagerUtils { } SQLSelectStatement selectStmt = (SQLSelectStatement) stmt; - - return count(selectStmt, dbType); + return count(selectStmt.getSelect(), dbType); } + + public static String limit(String sql, String dbType, int offset, int count) { + List stmtList = SQLUtils.parseStatements(sql, dbType); - private static String count(SQLSelectStatement stmt, String dbType) { - SQLSelect select = stmt.getSelect(); + if (stmtList.size() != 1) { + throw new IllegalArgumentException("sql not support count : " + sql); + } + + SQLStatement stmt = stmtList.get(0); + + if (!(stmt instanceof SQLSelectStatement)) { + throw new IllegalArgumentException("sql not support count : " + sql); + } + + SQLSelectStatement selectStmt = (SQLSelectStatement) stmt; + + return limit(selectStmt.getSelect(), dbType, offset, count); + } + + public static String limit(SQLSelect select, String dbType, int offset, int count) { + SQLSelectQuery query = select.getQuery(); + + if (query instanceof SQLSelectQueryBlock) { + return limit((SQLSelectQueryBlock) query, dbType, offset, count); + } + throw new UnsupportedOperationException(); + } + + public static String limit(SQLSelectQueryBlock queryBlock, String dbType, int offset, int count) { + if (JdbcConstants.MYSQL.equals(dbType)) { + return limitMySql((MySqlSelectQueryBlock) queryBlock, dbType, offset, count); + } + throw new UnsupportedOperationException(); + } + + public static String limitMySql(MySqlSelectQueryBlock queryBlock, String dbType, int offset, int count) { + if (queryBlock.getLimit() != null) { + throw new IllegalArgumentException("limit already exists."); + } + + Limit limit = new Limit(); + if (offset > 0) { + limit.setOffset(new SQLNumberExpr(offset)); + } + limit.setRowCount(new SQLNumberExpr(count)); + queryBlock.setLimit(limit); + + return SQLUtils.toSQLString(queryBlock, dbType); + } + + private static String count(SQLSelect select, String dbType) { if (select.getOrderBy() != null) { select.setOrderBy(null); } + SQLSelectQuery query = select.getQuery(); clearOrderBy(query); @@ -51,26 +116,35 @@ public class PagerUtils { SQLSelectItem countItem = createCountItem(dbType); SQLSelectQueryBlock queryBlock = (SQLSelectQueryBlock) query; + + if (queryBlock.getGroupBy() != null && queryBlock.getGroupBy().getItems().size() > 0) { + return createCountUseSubQuery(select, dbType); + } + queryBlock.getSelectList().clear(); queryBlock.getSelectList().add(countItem); - return SQLUtils.toSQLString(stmt, dbType); + return SQLUtils.toSQLString(select, dbType); } else if (query instanceof SQLUnionQuery) { - SQLSelectQueryBlock countSelectQuery = createQueryBlock(dbType); - - SQLSelectItem countItem = createCountItem(dbType); - countSelectQuery.getSelectList().add(countItem); - - countSelectQuery.setFrom(new SQLSubqueryTableSource(select)); - - SQLSelect countSelect = new SQLSelect(countSelectQuery); - SQLSelectStatement countStmt = new SQLSelectStatement(countSelect); - - return SQLUtils.toSQLString(countStmt, dbType); + return createCountUseSubQuery(select, dbType); } throw new IllegalStateException(); } + private static String createCountUseSubQuery(SQLSelect select, String dbType) { + SQLSelectQueryBlock countSelectQuery = createQueryBlock(dbType); + + SQLSelectItem countItem = createCountItem(dbType); + countSelectQuery.getSelectList().add(countItem); + + countSelectQuery.setFrom(new SQLSubqueryTableSource(select)); + + SQLSelect countSelect = new SQLSelect(countSelectQuery); + SQLSelectStatement countStmt = new SQLSelectStatement(countSelect); + + return SQLUtils.toSQLString(countStmt, dbType); + } + private static SQLSelectQueryBlock createQueryBlock(String dbType) { if (JdbcConstants.MYSQL.equals(dbType)) { return new MySqlSelectQueryBlock(); diff --git a/src/test/java/PagerUtils/PagerUtilsTest0.java b/src/test/java/PagerUtils/PagerUtilsTest0.java index 0cff3af24a..b9508d8e79 100644 --- a/src/test/java/PagerUtils/PagerUtilsTest0.java +++ b/src/test/java/PagerUtils/PagerUtilsTest0.java @@ -30,7 +30,17 @@ public class PagerUtilsTest0 extends TestCase { "FROM t", result); } - public void test_mysql_3() throws Exception { + public void test_mysql_group_0() throws Exception { + String sql = "select type, count(*) from t group by type"; + String result = PagerUtils.count(sql, JdbcConstants.MYSQL); + Assert.assertEquals("SELECT COUNT(*)" + // + "\nFROM (SELECT type, COUNT(*)" + // + "\n\tFROM t" + // + "\n\tGROUP BY type" + // + "\n\t)", result); + } + + public void test_mysql_union_0() throws Exception { String sql = "select id, name from t1 union select id, name from t2 order by id"; String result = PagerUtils.count(sql, JdbcConstants.MYSQL); Assert.assertEquals("SELECT COUNT(*)\n" + // diff --git a/src/test/java/PagerUtils/PagerUtilsTestLimit_0.java b/src/test/java/PagerUtils/PagerUtilsTestLimit_0.java new file mode 100644 index 0000000000..86058a7766 --- /dev/null +++ b/src/test/java/PagerUtils/PagerUtilsTestLimit_0.java @@ -0,0 +1,44 @@ +package PagerUtils; + +import junit.framework.TestCase; + +import org.junit.Assert; + +import com.alibaba.druid.sql.PagerUtils; +import com.alibaba.druid.util.JdbcConstants; + +public class PagerUtilsTestLimit_0 extends TestCase { + + public void test_mysql_0() throws Exception { + String sql = "select * from t"; + String result = PagerUtils.limit(sql, JdbcConstants.MYSQL, 0, 10); + Assert.assertEquals("SELECT *" + // + "\nFROM t" + // + "\nLIMIT 10", result); + } + + public void test_mysql_1() throws Exception { + String sql = "select * from t"; + String result = PagerUtils.limit(sql, JdbcConstants.MYSQL, 10, 10); + Assert.assertEquals("SELECT *" + // + "\nFROM t" + // + "\nLIMIT 10, 10", result); + } + + public void test_mysql_2() throws Exception { + String sql = "select * from t"; + String result = PagerUtils.limit(sql, JdbcConstants.MYSQL, 20, 10); + Assert.assertEquals("SELECT *" + // + "\nFROM t" + // + "\nLIMIT 20, 10", result); + } + + public void test_mysql_3() throws Exception { + String sql = "select id, name, salary from t order by id, name"; + String result = PagerUtils.limit(sql, JdbcConstants.MYSQL, 20, 10); + Assert.assertEquals("SELECT id, name, salary" + // + "\nFROM t" + // + "\nORDER BY id, name" + // + "\nLIMIT 20, 10", result); + } +}