improved PageUtils.limit & WallFilter support selectLimit. for issue #1369

This commit is contained in:
wenshao
2017-05-14 02:13:24 +08:00
parent 05a4ac1e1f
commit 23179b0e5c
10 changed files with 376 additions and 118 deletions
@@ -74,57 +74,74 @@ public class PagerUtils {
}
public static String limit(SQLSelect select, String dbType, int offset, int count) {
limit(select, dbType, offset, count, false);
return SQLUtils.toSQLString(select, dbType);
}
public static boolean limit(SQLSelect select, String dbType, int offset, int count, boolean check) {
SQLSelectQuery query = select.getQuery();
if (JdbcConstants.ORACLE.equals(dbType)) {
return limitOracle(select, dbType, offset, count);
return limitOracle(select, dbType, offset, count, check);
}
if (JdbcConstants.DB2.equals(dbType)) {
return limitDB2(select, dbType, offset, count);
return limitDB2(select, dbType, offset, count, check);
}
if (JdbcConstants.SQL_SERVER.equals(dbType) || JdbcUtils.JTDS.equals(dbType)) {
return limitSQLServer(select, dbType, offset, count);
return limitSQLServer(select, dbType, offset, count, check);
}
if (query instanceof SQLSelectQueryBlock) {
return limitQueryBlock(select, dbType, offset, count);
return limitQueryBlock(select, dbType, offset, count, check);
}
throw new UnsupportedOperationException();
}
private static String limitQueryBlock(SQLSelect select, String dbType, int offset, int count) {
private static boolean limitQueryBlock(SQLSelect select, String dbType, int offset, int count, boolean check) {
SQLSelectQueryBlock queryBlock = (SQLSelectQueryBlock) select.getQuery();
if (JdbcConstants.MYSQL.equals(dbType) || //
JdbcConstants.MARIADB.equals(dbType) || //
JdbcConstants.H2.equals(dbType)) {
return limitMySqlQueryBlock((MySqlSelectQueryBlock) queryBlock, dbType, offset, count);
return limitMySqlQueryBlock((MySqlSelectQueryBlock) queryBlock, dbType, offset, count, check);
}
if (JdbcConstants.POSTGRESQL.equals(dbType)) {
return limitPostgreSQLQueryBlock((PGSelectQueryBlock) queryBlock, dbType, offset, count);
return limitPostgreSQLQueryBlock((PGSelectQueryBlock) queryBlock, dbType, offset, count, check);
}
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.");
private static boolean limitPostgreSQLQueryBlock(PGSelectQueryBlock queryBlock, String dbType, int offset, int count, boolean check) {
SQLLimit limit = queryBlock.getLimit();
if (limit != null) {
if (offset > 0) {
limit.setOffset(new SQLIntegerExpr(offset));
}
if (check && limit.getRowCount() instanceof SQLNumericLiteralExpr) {
int rowCount = ((SQLNumericLiteralExpr) limit.getRowCount()).getNumber().intValue();
if (rowCount <= count && offset <= 0) {
return false;
}
}
limit.setRowCount(new SQLIntegerExpr(count));
}
SQLLimit limit = new SQLLimit();
limit = new SQLLimit();
if (offset > 0) {
limit.setOffset(new SQLIntegerExpr(offset));
}
limit.setRowCount(new SQLIntegerExpr(count));
queryBlock.setLimit(limit);
return SQLUtils.toSQLString(queryBlock, dbType);
return true;
}
private static String limitDB2(SQLSelect select, String dbType, int offset, int count) {
private static boolean limitDB2(SQLSelect select, String dbType, int offset, int count, boolean check) {
SQLSelectQuery query = select.getQuery();
SQLBinaryOpExpr gt = new SQLBinaryOpExpr(new SQLIdentifierExpr("ROWNUM"), //
@@ -140,8 +157,15 @@ public class PagerUtils {
if (query instanceof SQLSelectQueryBlock) {
DB2SelectQueryBlock queryBlock = (DB2SelectQueryBlock) query;
if (offset <= 0) {
queryBlock.setFirst(new SQLNumberExpr(count));
return SQLUtils.toSQLString(select, dbType);
SQLExpr first = queryBlock.getFirst();
if (check && first != null && first instanceof SQLNumericLiteralExpr) {
int rowCount = ((SQLNumericLiteralExpr) first).getNumber().intValue();
if (rowCount < count) {
return false;
}
}
queryBlock.setFirst(new SQLIntegerExpr(count));
return true;
}
SQLAggregateExpr aggregateExpr = new SQLAggregateExpr("ROW_NUMBER");
@@ -162,11 +186,13 @@ public class PagerUtils {
DB2SelectQueryBlock countQueryBlock = new DB2SelectQueryBlock();
countQueryBlock.getSelectList().add(new SQLSelectItem(new SQLAllColumnExpr()));
countQueryBlock.setFrom(new SQLSubqueryTableSource(select, "XX"));
countQueryBlock.setFrom(new SQLSubqueryTableSource(select.clone(), "XX"));
countQueryBlock.setWhere(pageCondition);
return SQLUtils.toSQLString(countQueryBlock, dbType);
select.setQuery(countQueryBlock);
return true;
}
DB2SelectQueryBlock countQueryBlock = new DB2SelectQueryBlock();
@@ -177,10 +203,11 @@ public class PagerUtils {
select.setOrderBy(null);
countQueryBlock.getSelectList().add(new SQLSelectItem(aggregateExpr, "ROWNUM"));
countQueryBlock.setFrom(new SQLSubqueryTableSource(select, "XX"));
countQueryBlock.setFrom(new SQLSubqueryTableSource(select.clone(), "XX"));
if (offset <= 0) {
return SQLUtils.toSQLString(countQueryBlock, dbType);
select.setQuery(countQueryBlock);
return true;
}
DB2SelectQueryBlock offsetQueryBlock = new DB2SelectQueryBlock();
@@ -188,10 +215,12 @@ public class PagerUtils {
offsetQueryBlock.setFrom(new SQLSubqueryTableSource(new SQLSelect(countQueryBlock), "XXX"));
offsetQueryBlock.setWhere(pageCondition);
return SQLUtils.toSQLString(offsetQueryBlock, dbType);
select.setQuery(offsetQueryBlock);
return true;
}
private static String limitSQLServer(SQLSelect select, String dbType, int offset, int count) {
private static boolean limitSQLServer(SQLSelect select, String dbType, int offset, int count, boolean check) {
SQLSelectQuery query = select.getQuery();
SQLBinaryOpExpr gt = new SQLBinaryOpExpr(new SQLIdentifierExpr("ROWNUM"), //
@@ -208,8 +237,15 @@ public class PagerUtils {
if (query instanceof SQLSelectQueryBlock) {
SQLServerSelectQueryBlock queryBlock = (SQLServerSelectQueryBlock) query;
if (offset <= 0) {
SQLServerTop top = queryBlock.getTop();
if (check && top != null && !top.isPercent() && top.getExpr() instanceof SQLNumericLiteralExpr) {
int rowCount = ((SQLNumericLiteralExpr) top.getExpr()).getNumber().intValue();
if (rowCount <= count) {
return false;
}
}
queryBlock.setTop(new SQLServerTop(new SQLNumberExpr(count)));
return SQLUtils.toSQLString(select, dbType);
return true;
}
SQLAggregateExpr aggregateExpr = new SQLAggregateExpr("ROW_NUMBER");
@@ -222,21 +258,25 @@ public class PagerUtils {
SQLServerSelectQueryBlock countQueryBlock = new SQLServerSelectQueryBlock();
countQueryBlock.getSelectList().add(new SQLSelectItem(new SQLAllColumnExpr()));
countQueryBlock.setFrom(new SQLSubqueryTableSource(select, "XX"));
countQueryBlock.setFrom(new SQLSubqueryTableSource(select.clone(), "XX"));
countQueryBlock.setWhere(pageCondition);
return SQLUtils.toSQLString(countQueryBlock, dbType);
select.setQuery(countQueryBlock);
return true;
}
SQLServerSelectQueryBlock countQueryBlock = new SQLServerSelectQueryBlock();
countQueryBlock.getSelectList().add(new SQLSelectItem(new SQLPropertyExpr(new SQLIdentifierExpr("XX"), "*")));
countQueryBlock.setFrom(new SQLSubqueryTableSource(select, "XX"));
countQueryBlock.setFrom(new SQLSubqueryTableSource(select.clone(), "XX"));
if (offset <= 0) {
countQueryBlock.setTop(new SQLServerTop(new SQLNumberExpr(count)));
return SQLUtils.toSQLString(countQueryBlock, dbType);
select.setQuery(countQueryBlock);
return true;
}
SQLAggregateExpr aggregateExpr = new SQLAggregateExpr("ROW_NUMBER");
@@ -250,15 +290,34 @@ public class PagerUtils {
offsetQueryBlock.setFrom(new SQLSubqueryTableSource(new SQLSelect(countQueryBlock), "XXX"));
offsetQueryBlock.setWhere(pageCondition);
return SQLUtils.toSQLString(offsetQueryBlock, dbType);
select.setQuery(offsetQueryBlock);
return true;
}
private static String limitOracle(SQLSelect select, String dbType, int offset, int count) {
private static boolean limitOracle(SQLSelect select, String dbType, int offset, int count, boolean check) {
SQLSelectQuery query = select.getQuery();
if (query instanceof SQLSelectQueryBlock) {
OracleSelectQueryBlock queryBlock = (OracleSelectQueryBlock) query;
if (queryBlock.getGroupBy() == null && select.getOrderBy() == null && offset <= 0) {
SQLExpr where = queryBlock.getWhere();
if (check && where instanceof SQLBinaryOpExpr) {
SQLBinaryOpExpr binaryOpWhere = (SQLBinaryOpExpr) where;
if (binaryOpWhere.getOperator() == SQLBinaryOperator.LessThanOrEqual) {
SQLExpr left = binaryOpWhere.getLeft();
SQLExpr right = binaryOpWhere.getRight();
if (left instanceof SQLIdentifierExpr
&& ((SQLIdentifierExpr) left).getName().equalsIgnoreCase("ROWNUM")
&& right instanceof SQLNumericLiteralExpr) {
int rowCount = ((SQLNumericLiteralExpr) right).getNumber().intValue();
if (rowCount <= count) {
return false;
}
}
}
}
SQLExpr condition = new SQLBinaryOpExpr(new SQLIdentifierExpr("ROWNUM"), //
SQLBinaryOperator.LessThanOrEqual, //
new SQLNumberExpr(count), //
@@ -272,7 +331,7 @@ public class PagerUtils {
JdbcConstants.ORACLE));
}
return SQLUtils.toSQLString(select, dbType);
return true;
}
}
@@ -280,13 +339,16 @@ public class PagerUtils {
countQueryBlock.getSelectList().add(new SQLSelectItem(new SQLPropertyExpr(new SQLIdentifierExpr("XX"), "*")));
countQueryBlock.getSelectList().add(new SQLSelectItem(new SQLIdentifierExpr("ROWNUM"), "RN"));
countQueryBlock.setFrom(new SQLSubqueryTableSource(select, "XX"));
countQueryBlock.setFrom(new SQLSubqueryTableSource(select.clone(), "XX"));
countQueryBlock.setWhere(new SQLBinaryOpExpr(new SQLIdentifierExpr("ROWNUM"), //
SQLBinaryOperator.LessThanOrEqual, //
new SQLNumberExpr(count + offset), //
JdbcConstants.ORACLE));
select.setOrderBy(null);
if (offset <= 0) {
return SQLUtils.toSQLString(countQueryBlock, dbType);
select.setQuery(countQueryBlock);
return true;
}
OracleSelectQueryBlock offsetQueryBlock = new OracleSelectQueryBlock();
@@ -297,22 +359,37 @@ public class PagerUtils {
new SQLNumberExpr(offset), //
JdbcConstants.ORACLE));
return SQLUtils.toSQLString(offsetQueryBlock, dbType);
select.setQuery(offsetQueryBlock);
return true;
}
private static String limitMySqlQueryBlock(MySqlSelectQueryBlock queryBlock, String dbType, int offset, int count) {
if (queryBlock.getLimit() != null) {
throw new IllegalArgumentException("limit already exists.");
private static boolean limitMySqlQueryBlock(MySqlSelectQueryBlock queryBlock, String dbType, int offset, int count, boolean check) {
SQLLimit limit = queryBlock.getLimit();
if (limit != null) {
if (offset > 0) {
limit.setOffset(new SQLIntegerExpr(offset));
}
if (check && limit.getRowCount() instanceof SQLNumericLiteralExpr) {
int rowCount = ((SQLNumericLiteralExpr) limit.getRowCount()).getNumber().intValue();
if (rowCount <= count && offset <= 0) {
return false;
}
}
limit.setRowCount(new SQLIntegerExpr(count));
}
SQLLimit limit = new SQLLimit();
if (offset > 0) {
limit.setOffset(new SQLNumberExpr(offset));
if (limit == null) {
limit = new SQLLimit();
if (offset > 0) {
limit.setOffset(new SQLIntegerExpr(offset));
}
limit.setRowCount(new SQLIntegerExpr(count));
queryBlock.setLimit(limit);
}
limit.setRowCount(new SQLNumberExpr(count));
queryBlock.setLimit(limit);
return SQLUtils.toSQLString(queryBlock, dbType);
return true;
}
private static String count(SQLSelect select, String dbType) {