BATCH-1460: merged changes from trunk

This commit is contained in:
dsyer
2009-12-23 12:27:13 +00:00
parent 4b2f90158d
commit 25504b2a3c
6 changed files with 113 additions and 39 deletions

View File

@@ -39,4 +39,15 @@ public class DerbyPagingQueryProvider extends SqlWindowingPagingQueryProvider {
throw new InvalidDataAccessResourceUsageException("Apache Derby version " + version + " is not supported by this class, Only version 10.4.1.3 or later is supported");
}
}
@Override
protected Object getSubQueryAlias() {
return "AS TMP_SUB ";
}
@Override
protected String getOverClause() {
return "";
}
}

View File

@@ -17,13 +17,14 @@
package org.springframework.batch.item.database.support;
/**
* Oracle implementation of a {@link org.springframework.batch.item.database.PagingQueryProvider} using
* Oracle implementation of a
* {@link org.springframework.batch.item.database.PagingQueryProvider} using
* database specific features.
*
*
* @author Thomas Risberg
* @since 2.0
*/
public class OraclePagingQueryProvider extends SqlWindowingPagingQueryProvider {
public class OraclePagingQueryProvider extends AbstractSqlPagingQueryProvider {
@Override
public String generateFirstPageQuery(int pageSize) {
@@ -36,6 +37,15 @@ public class OraclePagingQueryProvider extends SqlWindowingPagingQueryProvider {
return SqlPagingQueryUtils.generateRowNumSqlQuery(this, true, buildRowNumClause(pageSize));
}
@Override
public String generateJumpToItemQuery(int itemIndex, int pageSize) {
int page = itemIndex / pageSize;
int offset = (page * pageSize);
offset = offset==0 ? 1 : offset;
return SqlPagingQueryUtils.generateRowNumSqlQuery(this, this.getSortKey() + " AS SORT_KEY", false,
"ROWNUM = " + offset);
}
private String buildRowNumClause(int pageSize) {
return new StringBuilder().append("ROWNUM <= ").append(pageSize).toString();
}

View File

@@ -76,15 +76,32 @@ public class SqlPagingQueryUtils {
*
* @param provider {@link AbstractSqlPagingQueryProvider} providing the
* implementation specifics
* @param remainingPageQuery is this query for the ramining pages (true) as
* @param remainingPageQuery is this query for the remaining pages (true) as
* opposed to the first page (false)
* @param rowNumClause the implementation specific row num clause to be used
* @return the generated query
*/
public static String generateRowNumSqlQuery(AbstractSqlPagingQueryProvider provider, boolean remainingPageQuery,
String rowNumClause) {
return generateRowNumSqlQuery(provider, provider.getSelectClause(), remainingPageQuery, rowNumClause);
}
/**
* Generate SQL query string using a ROW_NUM condition
*
* @param provider {@link AbstractSqlPagingQueryProvider} providing the
* implementation specifics
* @param remainingPageQuery is this query for the remaining pages (true) as
* opposed to the first page (false)
* @param rowNumClause the implementation specific row num clause to be used
* @return the generated query
*/
public static String generateRowNumSqlQuery(AbstractSqlPagingQueryProvider provider, String selectClause, boolean remainingPageQuery,
String rowNumClause) {
StringBuilder sql = new StringBuilder();
sql.append("SELECT * FROM (SELECT ").append(provider.getSelectClause());
sql.append("SELECT * FROM (SELECT ").append(selectClause);
sql.append(" FROM ").append(provider.getFromClause());
buildWhereClause(provider, remainingPageQuery, sql);
sql.append(" ORDER BY ").append(provider.getSortKey());

View File

@@ -17,9 +17,10 @@
package org.springframework.batch.item.database.support;
/**
* Generic Paging Query Provider using standard SQL:2003 windowing functions. These features are supported by
* DB2, Oracle, SQL Server 2005, Sybase and Apache Derby version 10.4.1.3
*
* Generic Paging Query Provider using standard SQL:2003 windowing functions.
* These features are supported by DB2, Oracle, SQL Server 2005, Sybase and
* Apache Derby version 10.4.1.3
*
* @author Thomas Risberg
* @since 2.0
*/
@@ -30,22 +31,25 @@ public class SqlWindowingPagingQueryProvider extends AbstractSqlPagingQueryProvi
StringBuilder sql = new StringBuilder();
sql.append("SELECT * FROM ( ");
sql.append("SELECT ").append(getSelectClause()).append(", ");
sql.append("ROW_NUMBER() OVER (ORDER BY ").append(getSortKey());
buildAscendingClause(sql);
sql.append("ROW_NUMBER() OVER (").append(getOverClause());
sql.append(") AS ROW_NUMBER");
sql.append(" FROM ").append(getFromClause()).append(getWhereClause() == null ? "" : " WHERE " + getWhereClause());
sql.append(") WHERE ROW_NUMBER <= ").append(pageSize);
sql.append(" FROM ").append(getFromClause()).append(
getWhereClause() == null ? "" : " WHERE " + getWhereClause());
sql.append(") ").append(getSubQueryAlias()).append("WHERE ROW_NUMBER <= ").append(pageSize);
return sql.toString();
}
protected Object getSubQueryAlias() {
return "";
}
@Override
public String generateRemainingPagesQuery(int pageSize) {
StringBuilder sql = new StringBuilder();
sql.append("SELECT * FROM ( ");
sql.append("SELECT ").append(getSelectClause()).append(", ");
sql.append("ROW_NUMBER() OVER (ORDER BY ").append(getSortKey());
buildAscendingClause(sql);
sql.append("ROW_NUMBER() OVER (").append(getOverClause());
sql.append(") AS ROW_NUMBER");
sql.append(" FROM ").append(getFromClause());
sql.append(" WHERE ");
@@ -61,7 +65,7 @@ public class SqlWindowingPagingQueryProvider extends AbstractSqlPagingQueryProvi
sql.append(" < ");
}
sql.append(getSortKeyPlaceHolder());
sql.append(") WHERE ROW_NUMBER <= ").append(pageSize);
sql.append(") ").append(getSubQueryAlias()).append("WHERE ROW_NUMBER <= ").append(pageSize);
return sql.toString();
}
@@ -70,28 +74,32 @@ public class SqlWindowingPagingQueryProvider extends AbstractSqlPagingQueryProvi
public String generateJumpToItemQuery(int itemIndex, int pageSize) {
int page = itemIndex / pageSize;
int lastRowNum = (page * pageSize);
if (lastRowNum<=0) {
if (lastRowNum <= 0) {
lastRowNum = 1;
}
StringBuilder sql = new StringBuilder();
sql.append("SELECT SORT_KEY FROM ( ");
sql.append("SELECT ").append(getSortKey()).append(" AS SORT_KEY, ");
sql.append("ROW_NUMBER() OVER (ORDER BY ").append(getSortKey());
buildAscendingClause(sql);
sql.append("ROW_NUMBER() OVER (").append(getOverClause());
sql.append(") AS ROW_NUMBER");
sql.append(" FROM ").append(getFromClause()).append(getWhereClause() == null ? "" : " WHERE " + getWhereClause());
sql.append(") WHERE ROW_NUMBER = ").append(lastRowNum);
sql.append(" FROM ").append(getFromClause()).append(
getWhereClause() == null ? "" : " WHERE " + getWhereClause());
sql.append(") ").append(getSubQueryAlias()).append("WHERE ROW_NUMBER = ").append(lastRowNum);
return sql.toString();
}
private void buildAscendingClause(StringBuilder sql) {
protected String getOverClause() {
return "ORDER BY " + getSortKey() + " " + getAscendingClause();
}
private String getAscendingClause() {
if (isAscending()) {
sql.append(" ASC");
return "ASC";
}
else {
sql.append(" DESC");
return "DESC";
}
}

View File

@@ -15,19 +15,21 @@
*/
package org.springframework.batch.item.database.support;
import static org.junit.Assert.fail;
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.fail;
import org.junit.Test;
import org.junit.Assert;
import org.springframework.dao.InvalidDataAccessResourceUsageException;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import javax.sql.DataSource;
import java.sql.DatabaseMetaData;
import java.sql.Connection;
import org.junit.Assert;
import org.junit.Test;
import org.springframework.dao.InvalidDataAccessResourceUsageException;
/**
* @author Thomas Risberg
@@ -69,7 +71,8 @@ public class DerbyPagingQueryProviderTests extends AbstractSqlPagingQueryProvide
try {
pagingQueryProvider.init(ds);
fail();
} catch (InvalidDataAccessResourceUsageException e) {
}
catch (InvalidDataAccessResourceUsageException e) {
// expected
}
verify(ds);
@@ -80,30 +83,55 @@ public class DerbyPagingQueryProviderTests extends AbstractSqlPagingQueryProvide
@Test
@Override
public void testGenerateFirstPageQuery() {
String sql = "SELECT * FROM ( SELECT id, name, age, ROW_NUMBER() OVER (ORDER BY id ASC) AS ROW_NUMBER FROM foo WHERE bar = 1) WHERE ROW_NUMBER <= 100";
String sql = "SELECT * FROM ( SELECT id, name, age, ROW_NUMBER() OVER () AS ROW_NUMBER FROM foo WHERE bar = 1) AS TMP_SUB WHERE ROW_NUMBER <= 100";
String s = pagingQueryProvider.generateFirstPageQuery(pageSize);
Assert.assertEquals("", sql, s);
}
@Test @Override
@Test
@Override
public void testGenerateRemainingPagesQuery() {
String sql = "SELECT * FROM ( SELECT id, name, age, ROW_NUMBER() OVER (ORDER BY id ASC) AS ROW_NUMBER FROM foo WHERE bar = 1 AND id > ?) WHERE ROW_NUMBER <= 100";
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 ROW_NUMBER <= 100";
String s = pagingQueryProvider.generateRemainingPagesQuery(pageSize);
Assert.assertEquals("", sql, s);
}
@Test @Override
@Test
@Override
public void testGenerateJumpToItemQuery() {
String sql = "SELECT SORT_KEY FROM ( SELECT id AS SORT_KEY, ROW_NUMBER() OVER (ORDER BY id ASC) AS ROW_NUMBER FROM foo WHERE bar = 1) WHERE 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) AS TMP_SUB WHERE ROW_NUMBER = 100";
String s = pagingQueryProvider.generateJumpToItemQuery(145, pageSize);
Assert.assertEquals("", sql, s);
}
@Test @Override
@Test
@Override
public void testGenerateJumpToItemQueryForFirstPage() {
String sql = "SELECT SORT_KEY FROM ( SELECT id AS SORT_KEY, ROW_NUMBER() OVER (ORDER BY id ASC) AS ROW_NUMBER FROM foo WHERE bar = 1) WHERE 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) AS TMP_SUB WHERE 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)
*/
@Test
@Override
public void testQueryContainsSortKey() {
String s = pagingQueryProvider.generateFirstPageQuery(pageSize).toLowerCase();
assertFalse("Wrong query: " + s, s.contains("id asc"));
}
/**
* Derby doesn't allow order by in the sub select
*/
@Test
@Override
public void testQueryContainsSortKeyDesc() {
pagingQueryProvider.setAscending(false);
String s = pagingQueryProvider.generateFirstPageQuery(pageSize).toLowerCase();
assertFalse("Wrong query: " + s, s.contains("id desc"));
}
}

View File

@@ -33,14 +33,14 @@ public class OraclePagingQueryProviderTests extends AbstractSqlPagingQueryProvid
@Test @Override
public void testGenerateJumpToItemQuery() {
String sql = "SELECT SORT_KEY FROM ( SELECT id AS SORT_KEY, ROW_NUMBER() OVER (ORDER BY id ASC) AS ROW_NUMBER FROM foo WHERE bar = 1) WHERE ROW_NUMBER = 100";
String sql = "SELECT * FROM (SELECT id AS SORT_KEY FROM foo WHERE bar = 1 ORDER BY id ASC) WHERE ROWNUM = 100";
String s = pagingQueryProvider.generateJumpToItemQuery(145, pageSize);
Assert.assertEquals("", sql, s);
}
@Test @Override
public void testGenerateJumpToItemQueryForFirstPage() {
String sql = "SELECT SORT_KEY FROM ( SELECT id AS SORT_KEY, ROW_NUMBER() OVER (ORDER BY id ASC) AS ROW_NUMBER FROM foo WHERE bar = 1) WHERE ROW_NUMBER = 1";
String sql = "SELECT * FROM (SELECT id AS SORT_KEY FROM foo WHERE bar = 1 ORDER BY id ASC) WHERE ROWNUM = 1";
String s = pagingQueryProvider.generateJumpToItemQuery(45, pageSize);
Assert.assertEquals("", sql, s);
}