BATCH-1860: Use sub query for Derby for JdbcPagingItemReader

Order the results before the ROW_NUM restriction is applied (and make related infrastructure tests more robust)
This commit is contained in:
David Thexton
2012-06-07 16:00:53 +01:00
committed by Dave Syer
parent 1c843e2ded
commit 8c445bcb08
13 changed files with 68 additions and 57 deletions

View File

@@ -5,7 +5,7 @@
* 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
* 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,
@@ -26,7 +26,11 @@ import javax.sql.DataSource;
* Derby implementation of a {@link PagingQueryProvider} using standard SQL:2003 windowing functions.
* These features are supported starting with Apache Derby version 10.4.1.3.
*
* As the OVER() function does not support the ORDER BY clause a sub query is instead used to order the results
* before the ROW_NUM restriction is applied
*
* @author Thomas Risberg
* @author David Thexton
* @since 2.0
*/
public class DerbyPagingQueryProvider extends SqlWindowingPagingQueryProvider {
@@ -42,23 +46,17 @@ public class DerbyPagingQueryProvider extends SqlWindowingPagingQueryProvider {
}
}
@Override
protected Object getSubQueryAlias() {
return "AS TMP_SUB ";
}
@Override
protected String getOverClause() {
return "";
}
@Override
protected String getAfterWhereClause() {
if (version!=null && "10.6.1".compareTo(version) > 0) {
// Old behaviour retained, even though it is broken
return "";
}
return " " + super.getOverClause();
protected String getOverSubstituteClauseStart() {
return " FROM (SELECT " + getSelectClause();
}
protected String getOverSubstituteClauseEnd() {
return " " + super.getOverClause() + ") AS TMP_ORDERED";
}
}

View File

@@ -35,16 +35,21 @@ public class SqlWindowingPagingQueryProvider extends AbstractSqlPagingQueryProvi
sql.append("SELECT ").append(getSelectClause()).append(", ");
sql.append("ROW_NUMBER() OVER (").append(getOverClause());
sql.append(") AS ROW_NUMBER");
sql.append(getOverSubstituteClauseStart());
sql.append(" FROM ").append(getFromClause()).append(
getWhereClause() == null ? "" : " WHERE " + getWhereClause());
sql.append(getAfterWhereClause());
String alias = extractTableAlias();
sql.append(") ").append(getSubQueryAlias()).append("WHERE " + alias + "ROW_NUMBER <= ").append(pageSize);
sql.append(getOverSubstituteClauseEnd());
sql.append(") ").append(getSubQueryAlias()).append("WHERE ").append(extractTableAlias()).append(
"ROW_NUMBER <= ").append(pageSize);
return sql.toString();
}
private String extractTableAlias() {
protected Object getSubQueryAlias() {
return "AS TMP_SUB ";
}
protected Object extractTableAlias() {
String alias = "" + getSubQueryAlias();
if (StringUtils.hasText(alias) && alias.toUpperCase().startsWith("AS")) {
alias = alias.substring(3).trim() + ".";
@@ -52,10 +57,6 @@ public class SqlWindowingPagingQueryProvider extends AbstractSqlPagingQueryProvi
return alias;
}
protected Object getSubQueryAlias() {
return "";
}
@Override
public String generateRemainingPagesQuery(int pageSize) {
StringBuilder sql = new StringBuilder();
@@ -63,6 +64,7 @@ public class SqlWindowingPagingQueryProvider extends AbstractSqlPagingQueryProvi
sql.append("SELECT ").append(getSelectClause()).append(", ");
sql.append("ROW_NUMBER() OVER (").append(getOverClause());
sql.append(") AS ROW_NUMBER");
sql.append(getOverSubstituteClauseStart());
sql.append(" FROM ").append(getFromClause());
sql.append(" WHERE ");
if (getWhereClause() != null) {
@@ -77,17 +79,13 @@ public class SqlWindowingPagingQueryProvider extends AbstractSqlPagingQueryProvi
sql.append(" < ");
}
sql.append(getSortKeyPlaceHolder());
sql.append(getAfterWhereClause());
String alias = extractTableAlias();
sql.append(") ").append(getSubQueryAlias()).append("WHERE " + alias + "ROW_NUMBER <= ").append(pageSize);
sql.append(getOverSubstituteClauseEnd());
sql.append(") ").append(getSubQueryAlias()).append("WHERE ").append(extractTableAlias()).append(
"ROW_NUMBER <= ").append(pageSize);
return sql.toString();
}
protected String getAfterWhereClause() {
return "";
}
@Override
public String generateJumpToItemQuery(int itemIndex, int pageSize) {
int page = itemIndex / pageSize;
@@ -101,11 +99,12 @@ public class SqlWindowingPagingQueryProvider extends AbstractSqlPagingQueryProvi
sql.append("SELECT ").append(getSortKey()).append(" AS SORT_KEY, ");
sql.append("ROW_NUMBER() OVER (").append(getOverClause());
sql.append(") AS ROW_NUMBER");
sql.append(" FROM ").append(getFromClause()).append(
getWhereClause() == null ? "" : " WHERE " + getWhereClause());
sql.append(getAfterWhereClause());
String alias = extractTableAlias();
sql.append(") ").append(getSubQueryAlias()).append("WHERE " + alias + "ROW_NUMBER = ").append(lastRowNum);
sql.append(getOverSubstituteClauseStart());
sql.append(" FROM ").append(getFromClause());
sql.append(getWhereClause() == null ? "" : " WHERE " + getWhereClause());
sql.append(getOverSubstituteClauseEnd());
sql.append(") ").append(getSubQueryAlias()).append("WHERE ").append(extractTableAlias()).append(
"ROW_NUMBER = ").append(lastRowNum);
return sql.toString();
}
@@ -114,6 +113,14 @@ public class SqlWindowingPagingQueryProvider extends AbstractSqlPagingQueryProvi
return "ORDER BY " + getSortKey() + " " + getAscendingClause();
}
protected String getOverSubstituteClauseStart() {
return "";
}
protected String getOverSubstituteClauseEnd() {
return "";
}
private String getAscendingClause() {
if (isAscending()) {
return "ASC";

View File

@@ -37,6 +37,11 @@ public class SybasePagingQueryProvider extends SqlWindowingPagingQueryProvider {
return SqlPagingQueryUtils.generateTopSqlQuery(this, true, buildTopClause(pageSize));
}
@Override
protected Object getSubQueryAlias() {
return "";
}
private String buildTopClause(int pageSize) {
return new StringBuilder().append("TOP ").append(pageSize).toString();
}