diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/DerbyPagingQueryProvider.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/DerbyPagingQueryProvider.java
index 1878032a6..c078e602b 100644
--- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/DerbyPagingQueryProvider.java
+++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/DerbyPagingQueryProvider.java
@@ -31,10 +31,12 @@ import javax.sql.DataSource;
*/
public class DerbyPagingQueryProvider extends SqlWindowingPagingQueryProvider {
+ private String version;
+
@Override
public void init(DataSource dataSource) throws Exception {
super.init(dataSource);
- String version = JdbcUtils.extractDatabaseMetaData(dataSource, "getDatabaseProductVersion").toString();
+ version = JdbcUtils.extractDatabaseMetaData(dataSource, "getDatabaseProductVersion").toString();
if ("10.4.1.3".compareTo(version) > 0) {
throw new InvalidDataAccessResourceUsageException("Apache Derby version " + version + " is not supported by this class, Only version 10.4.1.3 or later is supported");
}
@@ -49,5 +51,14 @@ public class DerbyPagingQueryProvider extends SqlWindowingPagingQueryProvider {
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();
+ }
}
diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/SqlWindowingPagingQueryProvider.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/SqlWindowingPagingQueryProvider.java
index 7c3f6a8b5..e62d8ad00 100644
--- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/SqlWindowingPagingQueryProvider.java
+++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/SqlWindowingPagingQueryProvider.java
@@ -37,6 +37,7 @@ public class SqlWindowingPagingQueryProvider extends AbstractSqlPagingQueryProvi
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(pageSize);
@@ -76,12 +77,17 @@ 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);
return sql.toString();
}
+ protected String getAfterWhereClause() {
+ return "";
+ }
+
@Override
public String generateJumpToItemQuery(int itemIndex, int pageSize) {
int page = itemIndex / pageSize;
@@ -97,6 +103,7 @@ public class SqlWindowingPagingQueryProvider extends AbstractSqlPagingQueryProvi
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);
diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/DerbyPagingQueryProviderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/DerbyPagingQueryProviderTests.java
index 5643ca2e0..92af44284 100644
--- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/DerbyPagingQueryProviderTests.java
+++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/DerbyPagingQueryProviderTests.java
@@ -19,7 +19,7 @@ import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
-import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.sql.Connection;
@@ -83,7 +83,7 @@ public class DerbyPagingQueryProviderTests extends AbstractSqlPagingQueryProvide
@Test
@Override
public void testGenerateFirstPageQuery() {
- String sql = "SELECT * FROM ( SELECT id, name, age, ROW_NUMBER() OVER () AS ROW_NUMBER FROM foo WHERE bar = 1) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER <= 100";
+ String sql = "SELECT * FROM ( SELECT id, name, age, ROW_NUMBER() OVER () AS ROW_NUMBER FROM foo WHERE bar = 1 ORDER BY id ASC) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER <= 100";
String s = pagingQueryProvider.generateFirstPageQuery(pageSize);
Assert.assertEquals("", sql, s);
}
@@ -91,7 +91,7 @@ public class DerbyPagingQueryProviderTests extends AbstractSqlPagingQueryProvide
@Test
@Override
public void testGenerateRemainingPagesQuery() {
- String sql = "SELECT * FROM ( SELECT id, name, age, ROW_NUMBER() OVER () AS ROW_NUMBER FROM foo WHERE bar = 1 AND id > ?) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER <= 100";
+ String sql = "SELECT * FROM ( SELECT id, name, age, ROW_NUMBER() OVER () AS ROW_NUMBER FROM foo WHERE bar = 1 AND id > ? ORDER BY id ASC) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER <= 100";
String s = pagingQueryProvider.generateRemainingPagesQuery(pageSize);
Assert.assertEquals("", sql, s);
}
@@ -99,7 +99,7 @@ public class DerbyPagingQueryProviderTests extends AbstractSqlPagingQueryProvide
@Test
@Override
public void testGenerateJumpToItemQuery() {
- String sql = "SELECT SORT_KEY FROM ( SELECT id AS SORT_KEY, ROW_NUMBER() OVER () AS ROW_NUMBER FROM foo WHERE bar = 1) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER = 100";
+ String sql = "SELECT SORT_KEY FROM ( SELECT id AS SORT_KEY, ROW_NUMBER() OVER () AS ROW_NUMBER FROM foo WHERE bar = 1 ORDER BY id ASC) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER = 100";
String s = pagingQueryProvider.generateJumpToItemQuery(145, pageSize);
Assert.assertEquals("", sql, s);
}
@@ -107,31 +107,30 @@ public class DerbyPagingQueryProviderTests extends AbstractSqlPagingQueryProvide
@Test
@Override
public void testGenerateJumpToItemQueryForFirstPage() {
- String sql = "SELECT SORT_KEY FROM ( SELECT id AS SORT_KEY, ROW_NUMBER() OVER () AS ROW_NUMBER FROM foo WHERE bar = 1) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER = 1";
+ String sql = "SELECT SORT_KEY FROM ( SELECT id AS SORT_KEY, ROW_NUMBER() OVER () AS ROW_NUMBER FROM foo WHERE bar = 1 ORDER BY id ASC) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER = 1";
String s = pagingQueryProvider.generateJumpToItemQuery(45, pageSize);
Assert.assertEquals("", sql, s);
}
/**
- * Derby doesn't allow order by in the sub select (so it's pretty useless in
- * general for paging)
+ * Older versions of Derby don't allow order by in the sub select. This should work with 10.6.1 and above.
*/
@Test
@Override
public void testQueryContainsSortKey() {
String s = pagingQueryProvider.generateFirstPageQuery(pageSize).toLowerCase();
- assertFalse("Wrong query: " + s, s.contains("id asc"));
+ assertTrue("Wrong query: " + s, s.contains("id asc"));
}
/**
- * Derby doesn't allow order by in the sub select
+ * Older versions of Derby don't allow order by in the sub select. This should work with 10.6.1 and above.
*/
@Test
@Override
public void testQueryContainsSortKeyDesc() {
pagingQueryProvider.setAscending(false);
String s = pagingQueryProvider.generateFirstPageQuery(pageSize).toLowerCase();
- assertFalse("Wrong query: " + s, s.contains("id desc"));
+ assertTrue("Wrong query: " + s, s.contains("id desc"));
}
}
diff --git a/spring-batch-parent/pom.xml b/spring-batch-parent/pom.xml
index 23adfae03..20b4a817c 100644
--- a/spring-batch-parent/pom.xml
+++ b/spring-batch-parent/pom.xml
@@ -426,7 +426,7 @@
org.apache.derby
derby
- 10.4.2.0
+ 10.6.2.1
test