From ea4fdfdf15b92482d5a41f0733de4e62e09e18b6 Mon Sep 17 00:00:00 2001 From: Michael Minella Date: Tue, 6 Nov 2012 16:41:31 -0600 Subject: [PATCH] BATCH-1691: Implemented group by functionality not impacted by paging --- .../JdbcPagingQueryIntegrationTests.java | 55 +++++++++++++++-- .../item/database/init-foo-schema-derby.sql | 1 + .../item/database/init-foo-schema-hsqldb.sql | 1 + .../item/database/init-foo-schema-oracle.sql | 1 + .../database/init-foo-schema-postgres.sql | 1 + .../support/Db2PagingQueryProvider.java | 11 +++- .../support/DerbyPagingQueryProvider.java | 16 +++-- .../support/HsqlPagingQueryProvider.java | 12 +++- .../support/MySqlPagingQueryProvider.java | 11 +++- .../support/PostgresPagingQueryProvider.java | 9 ++- .../database/support/SqlPagingQueryUtils.java | 60 ++++++++++++++++++- .../support/SqlServerPagingQueryProvider.java | 12 +++- .../SqlWindowingPagingQueryProvider.java | 15 +++-- .../support/SybasePagingQueryProvider.java | 11 +++- .../support/Db2PagingQueryProviderTests.java | 19 +++--- .../DerbyPagingQueryProviderTests.java | 12 ++-- .../support/HsqlPagingQueryProviderTests.java | 2 +- .../MySqlPagingQueryProviderTests.java | 2 +- .../OraclePagingQueryProviderTests.java | 6 +- .../PostgresPagingQueryProviderTests.java | 2 +- .../support/SqlPagingQueryUtilsTests.java | 8 +-- .../SqlServerPagingQueryProviderTests.java | 19 +++--- .../SqlWindowingPagingQueryProviderTests.java | 32 +++++----- .../SybasePagingQueryProviderTests.java | 19 +++--- 24 files changed, 254 insertions(+), 83 deletions(-) diff --git a/spring-batch-infrastructure-tests/src/test/java/org/springframework/batch/item/database/JdbcPagingQueryIntegrationTests.java b/spring-batch-infrastructure-tests/src/test/java/org/springframework/batch/item/database/JdbcPagingQueryIntegrationTests.java index 0d0e8dade..b1eddb365 100644 --- a/spring-batch-infrastructure-tests/src/test/java/org/springframework/batch/item/database/JdbcPagingQueryIntegrationTests.java +++ b/spring-batch-infrastructure-tests/src/test/java/org/springframework/batch/item/database/JdbcPagingQueryIntegrationTests.java @@ -36,6 +36,7 @@ import org.junit.Before; import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; +import org.springframework.batch.item.database.support.AbstractSqlPagingQueryProvider; import org.springframework.batch.item.database.support.Order; import org.springframework.batch.item.database.support.SqlPagingQueryProviderFactoryBean; import org.springframework.beans.factory.annotation.Autowired; @@ -65,13 +66,16 @@ public class JdbcPagingQueryIntegrationTests { private int itemCount = 9; private int pageSize = 2; - + @Before - public void init() { + public void testInit() { jdbcTemplate = new SimpleJdbcTemplate(dataSource); - maxId = jdbcTemplate.queryForInt("SELECT MAX(ID) from T_FOOS"); - for (int i = itemCount; i > maxId; i--) { - jdbcTemplate.update("INSERT into T_FOOS (ID,NAME,VALUE) values (?, ?, ?)", i, "foo" + i, i); + String[] names = {"Foo", "Bar", "Baz", "Foo", "Bar", "Baz", "Foo", "Bar", "Baz"}; + String[] codes = {"A", "B", "A", "B", "B", "B", "A", "B", "A"}; + jdbcTemplate.update("DELETE from T_FOOS"); + for(int i = 0; i < names.length; i++) { + jdbcTemplate.update("INSERT into T_FOOS (ID,NAME, CODE, VALUE) values (?, ?, ?, ?)", maxId, names[i], codes[i], i); + maxId++; } assertEquals(itemCount, SimpleJdbcTestUtils.countRowsInTable(jdbcTemplate, "T_FOOS")); } @@ -118,12 +122,51 @@ public class JdbcPagingQueryIntegrationTests { assertEquals(total, count); } + + @Test + public void testQueryFromStartWithGroupBy() throws Exception { + AbstractSqlPagingQueryProvider queryProvider = (AbstractSqlPagingQueryProvider) getPagingQueryProvider(); + Map sortKeys = new LinkedHashMap(); + sortKeys.put("NAME", Order.ASCENDING); + sortKeys.put("CODE", Order.DESCENDING); + queryProvider.setSortKeys(sortKeys); + queryProvider.setSelectClause("select NAME, CODE, sum(VALUE)"); + queryProvider.setGroupClause("NAME, CODE"); + + int pages = 3; + int count = 0; + int total = 5; + + List> list = jdbcTemplate.queryForList(queryProvider.generateFirstPageQuery(pageSize)); + logger.debug("First page result: " + list); + assertEquals(pageSize, list.size()); + count += pageSize; + Map oldValues = null; + + while (count < total) { + Map startAfterValues = getStartAfterValues( + queryProvider, list); + assertNotSame(oldValues, startAfterValues); + list = jdbcTemplate.queryForList(queryProvider.generateRemainingPagesQuery(pageSize), getParameterList(null, startAfterValues).toArray()); + count += list.size(); + + if(list.size() < pageSize) { + assertEquals(1, list.size()); + } + else { + assertEquals(pageSize, list.size()); + } + oldValues = startAfterValues; + } + + assertEquals(total, count); + } private Map getStartAfterValues( PagingQueryProvider queryProvider, List> list) { Map startAfterValues = new LinkedHashMap(); for (Map.Entry sortKey : queryProvider.getSortKeys().entrySet()) { - startAfterValues.put(sortKey.getKey(), list.get(pageSize - 1).get(sortKey.getKey())); + startAfterValues.put(sortKey.getKey(), list.get(list.size() - 1).get(sortKey.getKey())); } return startAfterValues; } diff --git a/spring-batch-infrastructure-tests/src/test/resources/org/springframework/batch/item/database/init-foo-schema-derby.sql b/spring-batch-infrastructure-tests/src/test/resources/org/springframework/batch/item/database/init-foo-schema-derby.sql index d4e9e150b..5f3a58fcf 100644 --- a/spring-batch-infrastructure-tests/src/test/resources/org/springframework/batch/item/database/init-foo-schema-derby.sql +++ b/spring-batch-infrastructure-tests/src/test/resources/org/springframework/batch/item/database/init-foo-schema-derby.sql @@ -4,6 +4,7 @@ DROP TABLE T_WRITE_FOOS; CREATE TABLE T_FOOS ( ID BIGINT NOT NULL, NAME VARCHAR(45), + CODE VARCHAR(10), VALUE INTEGER ); diff --git a/spring-batch-infrastructure-tests/src/test/resources/org/springframework/batch/item/database/init-foo-schema-hsqldb.sql b/spring-batch-infrastructure-tests/src/test/resources/org/springframework/batch/item/database/init-foo-schema-hsqldb.sql index 0d89dc86a..6248723a0 100644 --- a/spring-batch-infrastructure-tests/src/test/resources/org/springframework/batch/item/database/init-foo-schema-hsqldb.sql +++ b/spring-batch-infrastructure-tests/src/test/resources/org/springframework/batch/item/database/init-foo-schema-hsqldb.sql @@ -4,6 +4,7 @@ DROP TABLE T_WRITE_FOOS if exists; CREATE TABLE T_FOOS ( ID BIGINT NOT NULL, NAME VARCHAR(45), + CODE VARCHAR(10), VALUE INTEGER ); diff --git a/spring-batch-infrastructure-tests/src/test/resources/org/springframework/batch/item/database/init-foo-schema-oracle.sql b/spring-batch-infrastructure-tests/src/test/resources/org/springframework/batch/item/database/init-foo-schema-oracle.sql index b7067fb57..aa496106d 100644 --- a/spring-batch-infrastructure-tests/src/test/resources/org/springframework/batch/item/database/init-foo-schema-oracle.sql +++ b/spring-batch-infrastructure-tests/src/test/resources/org/springframework/batch/item/database/init-foo-schema-oracle.sql @@ -4,6 +4,7 @@ DROP TABLE T_WRITE_FOOS; CREATE TABLE T_FOOS ( ID NUMBER(19) NOT NULL, NAME VARCHAR(45), + CODE VARCHAR(10), VALUE NUMBER(19) ); diff --git a/spring-batch-infrastructure-tests/src/test/resources/org/springframework/batch/item/database/init-foo-schema-postgres.sql b/spring-batch-infrastructure-tests/src/test/resources/org/springframework/batch/item/database/init-foo-schema-postgres.sql index ef97a6c6d..3055172fe 100644 --- a/spring-batch-infrastructure-tests/src/test/resources/org/springframework/batch/item/database/init-foo-schema-postgres.sql +++ b/spring-batch-infrastructure-tests/src/test/resources/org/springframework/batch/item/database/init-foo-schema-postgres.sql @@ -4,6 +4,7 @@ DROP TABLE T_WRITE_FOOS; CREATE TABLE T_FOOS ( ID BIGINT NOT NULL, NAME VARCHAR(45), + CODE VARCHAR(10), VALUE BIGINT ); diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/Db2PagingQueryProvider.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/Db2PagingQueryProvider.java index 78c46000c..a2c46f73a 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/Db2PagingQueryProvider.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/Db2PagingQueryProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2006-2008 the original author or authors. + * Copyright 2006-2012 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,12 +17,14 @@ package org.springframework.batch.item.database.support; import org.springframework.batch.item.database.PagingQueryProvider; +import org.springframework.util.StringUtils; /** * DB2 implementation of a {@link PagingQueryProvider} using * database specific features. * * @author Thomas Risberg + * @author Michael Minella * @since 2.0 */ public class Db2PagingQueryProvider extends SqlWindowingPagingQueryProvider { @@ -34,7 +36,12 @@ public class Db2PagingQueryProvider extends SqlWindowingPagingQueryProvider { @Override public String generateRemainingPagesQuery(int pageSize) { - return SqlPagingQueryUtils.generateLimitSqlQuery(this, true, buildLimitClause(pageSize)); + if(StringUtils.hasText(getGroupClause())) { + return SqlPagingQueryUtils.generateLimitGroupedSqlQuery(this, true, buildLimitClause(pageSize)); + } + else { + return SqlPagingQueryUtils.generateLimitSqlQuery(this, true, buildLimitClause(pageSize)); + } } @Override 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 501cecbec..482f65773 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 @@ -1,5 +1,5 @@ /* - * Copyright 2006-2008 the original author or authors. + * Copyright 2006-2012 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,11 +16,11 @@ package org.springframework.batch.item.database.support; -import org.springframework.jdbc.support.JdbcUtils; +import javax.sql.DataSource; + import org.springframework.batch.item.database.PagingQueryProvider; import org.springframework.dao.InvalidDataAccessResourceUsageException; - -import javax.sql.DataSource; +import org.springframework.jdbc.support.JdbcUtils; /** * Derby implementation of a {@link PagingQueryProvider} using standard SQL:2003 windowing functions. @@ -31,6 +31,7 @@ import javax.sql.DataSource; * * @author Thomas Risberg * @author David Thexton + * @author Michael Minella * @since 2.0 */ public class DerbyPagingQueryProvider extends SqlWindowingPagingQueryProvider { @@ -46,6 +47,11 @@ public class DerbyPagingQueryProvider extends SqlWindowingPagingQueryProvider { } } + @Override + protected String getOrderedQueryAlias() { + return "TMP_ORDERED"; + } + @Override protected String getOverClause() { return ""; @@ -56,7 +62,7 @@ public class DerbyPagingQueryProvider extends SqlWindowingPagingQueryProvider { } protected String getOverSubstituteClauseEnd() { - return " " + super.getOverClause() + ") AS TMP_ORDERED"; + return " " + super.getOverClause() + ") AS " + getOrderedQueryAlias(); } } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/HsqlPagingQueryProvider.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/HsqlPagingQueryProvider.java index 0d0a25f81..198651b21 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/HsqlPagingQueryProvider.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/HsqlPagingQueryProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2006-2008 the original author or authors. + * Copyright 2006-2012 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,10 +16,13 @@ package org.springframework.batch.item.database.support; +import org.springframework.util.StringUtils; + /** * HSQLDB implementation of a {@link org.springframework.batch.item.database.PagingQueryProvider} using database specific features. * * @author Thomas Risberg + * @author Michael Minella * @since 2.0 */ public class HsqlPagingQueryProvider extends AbstractSqlPagingQueryProvider { @@ -31,7 +34,12 @@ public class HsqlPagingQueryProvider extends AbstractSqlPagingQueryProvider { @Override public String generateRemainingPagesQuery(int pageSize) { - return SqlPagingQueryUtils.generateTopSqlQuery(this, true, buildTopClause(pageSize)); + if(StringUtils.hasText(getGroupClause())) { + return SqlPagingQueryUtils.generateGroupedTopSqlQuery(this, true, buildTopClause(pageSize)); + } + else { + return SqlPagingQueryUtils.generateTopSqlQuery(this, true, buildTopClause(pageSize)); + } } private String buildTopClause(int pageSize) { diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/MySqlPagingQueryProvider.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/MySqlPagingQueryProvider.java index d7897633b..5714e3df4 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/MySqlPagingQueryProvider.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/MySqlPagingQueryProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2006-2008 the original author or authors. + * Copyright 2006-2012 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,11 +17,13 @@ package org.springframework.batch.item.database.support; import org.springframework.batch.item.database.PagingQueryProvider; +import org.springframework.util.StringUtils; /** * MySQL implementation of a {@link PagingQueryProvider} using database specific features. * * @author Thomas Risberg + * @author Michael Minella * @since 2.0 */ public class MySqlPagingQueryProvider extends AbstractSqlPagingQueryProvider { @@ -33,7 +35,12 @@ public class MySqlPagingQueryProvider extends AbstractSqlPagingQueryProvider { @Override public String generateRemainingPagesQuery(int pageSize) { - return SqlPagingQueryUtils.generateLimitSqlQuery(this, true, buildLimitClause(pageSize)); + if(StringUtils.hasText(getGroupClause())) { + return SqlPagingQueryUtils.generateLimitGroupedSqlQuery(this, true, buildLimitClause(pageSize)); + } + else { + return SqlPagingQueryUtils.generateLimitSqlQuery(this, true, buildLimitClause(pageSize)); + } } private String buildLimitClause(int pageSize) { diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/PostgresPagingQueryProvider.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/PostgresPagingQueryProvider.java index b92603575..326b897e0 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/PostgresPagingQueryProvider.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/PostgresPagingQueryProvider.java @@ -16,6 +16,8 @@ package org.springframework.batch.item.database.support; +import org.springframework.util.StringUtils; + /** * Postgres implementation of a {@link org.springframework.batch.item.database.PagingQueryProvider} using database specific features. * @@ -35,7 +37,12 @@ public class PostgresPagingQueryProvider extends AbstractSqlPagingQueryProvider @Override public String generateRemainingPagesQuery(int pageSize) { - return SqlPagingQueryUtils.generateLimitSqlQuery(this, true, buildLimitClause(pageSize)); + if(StringUtils.hasText(getGroupClause())) { + return SqlPagingQueryUtils.generateLimitGroupedSqlQuery(this, true, buildLimitClause(pageSize)); + } + else { + return SqlPagingQueryUtils.generateLimitSqlQuery(this, true, buildLimitClause(pageSize)); + } } private String buildLimitClause(int pageSize) { diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/SqlPagingQueryUtils.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/SqlPagingQueryUtils.java index f13eb0ba9..fc4280979 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/SqlPagingQueryUtils.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/SqlPagingQueryUtils.java @@ -57,6 +57,34 @@ public class SqlPagingQueryUtils { return sql.toString(); } + /** + * Generate SQL query string using a LIMIT clause + * + * @param provider {@link AbstractSqlPagingQueryProvider} providing the + * implementation specifics + * @param remainingPageQuery is this query for the ramining pages (true) as + * opposed to the first page (false) + * @param limitClause the implementation specific limit clause to be used + * @return the generated query + */ + public static String generateLimitGroupedSqlQuery(AbstractSqlPagingQueryProvider provider, boolean remainingPageQuery, + String limitClause) { + StringBuilder sql = new StringBuilder(); + sql.append("SELECT * "); + sql.append(" FROM ("); + sql.append("SELECT ").append(provider.getSelectClause()); + sql.append(" FROM ").append(provider.getFromClause()); + sql.append(provider.getWhereClause() == null ? "" : " WHERE " + provider.getWhereClause()); + buildGroupByClause(provider, sql); + sql.append(" ORDER BY ").append(buildSortClause(provider)); + sql.append(") AS MAIN_QRY "); + sql.append("WHERE "); + buildSortConditions(provider, sql); + sql.append(" " + limitClause); + + return sql.toString(); + } + /** * Generate SQL query string using a TOP clause * @@ -79,6 +107,32 @@ public class SqlPagingQueryUtils { return sql.toString(); } + /** + * Generate SQL query string using a TOP clause + * + * @param provider {@link AbstractSqlPagingQueryProvider} providing the + * implementation specifics + * @param remainingPageQuery is this query for the ramining pages (true) as + * opposed to the first page (false) + * @param topClause the implementation specific top clause to be used + * @return the generated query + */ + public static String generateGroupedTopSqlQuery(AbstractSqlPagingQueryProvider provider, boolean remainingPageQuery, + String topClause) { + StringBuilder sql = new StringBuilder(); + sql.append("SELECT ").append(topClause).append(" * FROM ("); + sql.append("SELECT ").append(provider.getSelectClause()); + sql.append(" FROM ").append(provider.getFromClause()); + sql.append(provider.getWhereClause() == null ? "" : " WHERE " + provider.getWhereClause()); + buildGroupByClause(provider, sql); + sql.append(" ORDER BY ").append(buildSortClause(provider)); + sql.append(") AS MAIN_QRY "); + sql.append("WHERE "); + buildSortConditions(provider, sql); + + return sql.toString(); + } + /** * Generate SQL query string using a ROW_NUM condition * @@ -111,10 +165,14 @@ public class SqlPagingQueryUtils { StringBuilder sql = new StringBuilder(); sql.append("SELECT * FROM (SELECT ").append(selectClause).append(", ROWNUM as TMP_ROW_NUM"); sql.append(" FROM ").append(provider.getFromClause()); - buildWhereClause(provider, remainingPageQuery, sql); + sql.append(provider.getWhereClause() == null ? "" : " WHERE " + provider.getWhereClause()); buildGroupByClause(provider, sql); sql.append(" ORDER BY ").append(buildSortClause(provider)); sql.append(") WHERE ").append(rowNumClause); + if(remainingPageQuery) { + sql.append(" AND "); + buildSortConditions(provider, sql); + } return sql.toString(); diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/SqlServerPagingQueryProvider.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/SqlServerPagingQueryProvider.java index 918604d65..f3cbec586 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/SqlServerPagingQueryProvider.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/SqlServerPagingQueryProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2006-2008 the original author or authors. + * Copyright 2006-2012 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,12 +16,15 @@ package org.springframework.batch.item.database.support; +import org.springframework.util.StringUtils; + /** * Sql Server implementation of a * {@link org.springframework.batch.item.database.PagingQueryProvider} using * database specific features. * * @author Thomas Risberg + * @author Michael Minella * @since 2.0 */ public class SqlServerPagingQueryProvider extends SqlWindowingPagingQueryProvider { @@ -33,7 +36,12 @@ public class SqlServerPagingQueryProvider extends SqlWindowingPagingQueryProvide @Override public String generateRemainingPagesQuery(int pageSize) { - return SqlPagingQueryUtils.generateTopSqlQuery(this, true, buildTopClause(pageSize)); + if(StringUtils.hasText(getGroupClause())) { + return SqlPagingQueryUtils.generateGroupedTopSqlQuery(this, true, buildTopClause(pageSize)); + } + else { + return SqlPagingQueryUtils.generateTopSqlQuery(this, true, buildTopClause(pageSize)); + } } @Override 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 d9533d0a5..ae1731b45 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 @@ -35,7 +35,7 @@ public class SqlWindowingPagingQueryProvider extends AbstractSqlPagingQueryProvi public String generateFirstPageQuery(int pageSize) { StringBuilder sql = new StringBuilder(); sql.append("SELECT * FROM ( "); - sql.append("SELECT ").append(getSelectClause()).append(", "); + sql.append("SELECT ").append(StringUtils.hasText(getOrderedQueryAlias()) ? getOrderedQueryAlias() + ".*, " : "*, "); sql.append("ROW_NUMBER() OVER (").append(getOverClause()); sql.append(") AS ROW_NUMBER"); sql.append(getOverSubstituteClauseStart()); @@ -49,6 +49,10 @@ public class SqlWindowingPagingQueryProvider extends AbstractSqlPagingQueryProvi return sql.toString(); } + protected String getOrderedQueryAlias() { + return ""; + } + protected Object getSubQueryAlias() { return "AS TMP_SUB "; } @@ -65,23 +69,22 @@ public class SqlWindowingPagingQueryProvider extends AbstractSqlPagingQueryProvi public String generateRemainingPagesQuery(int pageSize) { StringBuilder sql = new StringBuilder(); sql.append("SELECT * FROM ( "); - sql.append("SELECT ").append(getSelectClause()).append(", "); + sql.append("SELECT ").append(StringUtils.hasText(getOrderedQueryAlias()) ? getOrderedQueryAlias() + ".*, " : "*, "); 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) { + sql.append(" WHERE "); sql.append(getWhereClause()); - sql.append(" AND "); } - SqlPagingQueryUtils.buildSortConditions(this, sql); - sql.append(getGroupClause() == null ? "" : " GROUP BY " + getGroupClause()); sql.append(getOverSubstituteClauseEnd()); sql.append(") ").append(getSubQueryAlias()).append("WHERE ").append(extractTableAlias()).append( "ROW_NUMBER <= ").append(pageSize); + sql.append(" AND "); + SqlPagingQueryUtils.buildSortConditions(this, sql); return sql.toString(); } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/SybasePagingQueryProvider.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/SybasePagingQueryProvider.java index 91b3e7ca0..0615e5c86 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/SybasePagingQueryProvider.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/SybasePagingQueryProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2006-2008 the original author or authors. + * Copyright 2006-2012 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,12 +17,14 @@ package org.springframework.batch.item.database.support; import org.springframework.batch.item.database.PagingQueryProvider; +import org.springframework.util.StringUtils; /** * Sybase implementation of a {@link PagingQueryProvider} using * database specific features. * * @author Thomas Risberg + * @author Michael Minella * @since 2.0 */ public class SybasePagingQueryProvider extends SqlWindowingPagingQueryProvider { @@ -34,7 +36,12 @@ public class SybasePagingQueryProvider extends SqlWindowingPagingQueryProvider { @Override public String generateRemainingPagesQuery(int pageSize) { - return SqlPagingQueryUtils.generateTopSqlQuery(this, true, buildTopClause(pageSize)); + if(StringUtils.hasText(getGroupClause())) { + return SqlPagingQueryUtils.generateGroupedTopSqlQuery(this, true, buildTopClause(pageSize)); + } + else { + return SqlPagingQueryUtils.generateTopSqlQuery(this, true, buildTopClause(pageSize)); + } } @Override diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/Db2PagingQueryProviderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/Db2PagingQueryProviderTests.java index bc4ea9438..bba59a06d 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/Db2PagingQueryProviderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/Db2PagingQueryProviderTests.java @@ -37,29 +37,32 @@ public class Db2PagingQueryProviderTests extends AbstractSqlPagingQueryProviderT assertEquals(sql, s); } - @Test @Override + @Test + @Override public void testGenerateRemainingPagesQuery() { String sql = "SELECT id, name, age FROM foo WHERE bar = 1 AND ((id > ?)) ORDER BY id ASC FETCH FIRST 100 ROWS ONLY"; String s = pagingQueryProvider.generateRemainingPagesQuery(pageSize); assertEquals(sql, s); } - @Test @Override + @Test + @Override public void testGenerateJumpToItemQuery() { String sql = "SELECT id FROM ( SELECT id, ROW_NUMBER() OVER ( ORDER BY id ASC) AS ROW_NUMBER FROM foo WHERE bar = 1) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER = 100"; String s = pagingQueryProvider.generateJumpToItemQuery(145, pageSize); assertEquals(sql, s); } - @Test @Override + @Test + @Override public void testGenerateJumpToItemQueryForFirstPage() { String sql = "SELECT id FROM ( SELECT id, ROW_NUMBER() OVER ( ORDER BY id ASC) AS ROW_NUMBER FROM foo WHERE bar = 1) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER = 1"; String s = pagingQueryProvider.generateJumpToItemQuery(45, pageSize); assertEquals(sql, s); } - @Override @Test + @Override public void testGenerateFirstPageQueryWithGroupBy() { pagingQueryProvider.setGroupClause("dep"); String sql = "SELECT id, name, age FROM foo WHERE bar = 1 GROUP BY dep ORDER BY id ASC FETCH FIRST 100 ROWS ONLY"; @@ -67,17 +70,17 @@ public class Db2PagingQueryProviderTests extends AbstractSqlPagingQueryProviderT assertEquals(sql, s); } - @Override @Test + @Override public void testGenerateRemainingPagesQueryWithGroupBy() { pagingQueryProvider.setGroupClause("dep"); - String sql = "SELECT id, name, age FROM foo WHERE bar = 1 AND ((id > ?)) GROUP BY dep ORDER BY id ASC FETCH FIRST 100 ROWS ONLY"; + String sql = "SELECT * FROM (SELECT id, name, age FROM foo WHERE bar = 1 GROUP BY dep ORDER BY id ASC) AS MAIN_QRY WHERE ((id > ?)) FETCH FIRST 100 ROWS ONLY"; String s = pagingQueryProvider.generateRemainingPagesQuery(pageSize); assertEquals(sql, s); } - @Override @Test + @Override public void testGenerateJumpToItemQueryWithGroupBy() { pagingQueryProvider.setGroupClause("dep"); String sql = "SELECT id FROM ( SELECT id, ROW_NUMBER() OVER ( ORDER BY id ASC) AS ROW_NUMBER FROM foo WHERE bar = 1 GROUP BY dep) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER = 100"; @@ -85,8 +88,8 @@ public class Db2PagingQueryProviderTests extends AbstractSqlPagingQueryProviderT assertEquals(sql, s); } - @Override @Test + @Override public void testGenerateJumpToItemQueryForFirstPageWithGroupBy() { pagingQueryProvider.setGroupClause("dep"); String sql = "SELECT id FROM ( SELECT id, ROW_NUMBER() OVER ( ORDER BY id ASC) AS ROW_NUMBER FROM foo WHERE bar = 1 GROUP BY dep) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER = 1"; 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 314f2dc52..6b22ec2e6 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 @@ -85,7 +85,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 (SELECT id, name, age FROM foo WHERE bar = 1 ORDER BY id ASC) AS TMP_ORDERED) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER <= 100"; + String sql = "SELECT * FROM ( SELECT TMP_ORDERED.*, ROW_NUMBER() OVER () AS ROW_NUMBER FROM (SELECT id, name, age FROM foo WHERE bar = 1 ORDER BY id ASC) AS TMP_ORDERED) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER <= 100"; String s = pagingQueryProvider.generateFirstPageQuery(pageSize); Assert.assertEquals(sql, s); } @@ -93,7 +93,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 (SELECT id, name, age FROM foo WHERE bar = 1 AND ((id > ?)) ORDER BY id ASC) AS TMP_ORDERED) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER <= 100"; + String sql = "SELECT * FROM ( SELECT TMP_ORDERED.*, ROW_NUMBER() OVER () AS ROW_NUMBER FROM (SELECT id, name, age FROM foo WHERE bar = 1 ORDER BY id ASC) AS TMP_ORDERED) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER <= 100 AND ((id > ?))"; String s = pagingQueryProvider.generateRemainingPagesQuery(pageSize); Assert.assertEquals(sql, s); } @@ -139,7 +139,7 @@ public class DerbyPagingQueryProviderTests extends AbstractSqlPagingQueryProvide @Test public void testGenerateFirstPageQueryWithGroupBy() { pagingQueryProvider.setGroupClause("dep"); - String sql = "SELECT * FROM ( SELECT id, name, age, ROW_NUMBER() OVER () AS ROW_NUMBER FROM (SELECT id, name, age FROM foo WHERE bar = 1 GROUP BY dep ORDER BY id ASC) AS TMP_ORDERED) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER <= 100"; + String sql = "SELECT * FROM ( SELECT TMP_ORDERED.*, ROW_NUMBER() OVER () AS ROW_NUMBER FROM (SELECT id, name, age FROM foo WHERE bar = 1 GROUP BY dep ORDER BY id ASC) AS TMP_ORDERED) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER <= 100"; String s = pagingQueryProvider.generateFirstPageQuery(pageSize); assertEquals(sql, s); } @@ -148,7 +148,7 @@ public class DerbyPagingQueryProviderTests extends AbstractSqlPagingQueryProvide @Test public void testGenerateRemainingPagesQueryWithGroupBy() { pagingQueryProvider.setGroupClause("dep"); - String sql = "SELECT * FROM ( SELECT id, name, age, ROW_NUMBER() OVER () AS ROW_NUMBER FROM (SELECT id, name, age FROM foo WHERE bar = 1 AND ((id > ?)) GROUP BY dep ORDER BY id ASC) AS TMP_ORDERED) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER <= 100"; + String sql = "SELECT * FROM ( SELECT TMP_ORDERED.*, ROW_NUMBER() OVER () AS ROW_NUMBER FROM (SELECT id, name, age FROM foo WHERE bar = 1 GROUP BY dep ORDER BY id ASC) AS TMP_ORDERED) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER <= 100 AND ((id > ?))"; String s = pagingQueryProvider.generateRemainingPagesQuery(pageSize); assertEquals(sql, s); } @@ -173,12 +173,12 @@ public class DerbyPagingQueryProviderTests extends AbstractSqlPagingQueryProvide @Override public String getFirstPageSqlWithMultipleSortKeys() { - return "SELECT * FROM ( SELECT id, name, age, ROW_NUMBER() OVER () AS ROW_NUMBER FROM (SELECT id, name, age FROM foo WHERE bar = 1 ORDER BY name ASC, id DESC) AS TMP_ORDERED) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER <= 100"; + return "SELECT * FROM ( SELECT TMP_ORDERED.*, ROW_NUMBER() OVER () AS ROW_NUMBER FROM (SELECT id, name, age FROM foo WHERE bar = 1 ORDER BY name ASC, id DESC) AS TMP_ORDERED) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER <= 100"; } @Override public String getRemainingSqlWithMultipleSortKeys() { - return "SELECT * FROM ( SELECT id, name, age, ROW_NUMBER() OVER () AS ROW_NUMBER FROM (SELECT id, name, age FROM foo WHERE bar = 1 AND ((name > ?) OR (name = ? AND id < ?)) ORDER BY name ASC, id DESC) AS TMP_ORDERED) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER <= 100"; + return "SELECT * FROM ( SELECT TMP_ORDERED.*, ROW_NUMBER() OVER () AS ROW_NUMBER FROM (SELECT id, name, age FROM foo WHERE bar = 1 ORDER BY name ASC, id DESC) AS TMP_ORDERED) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER <= 100 AND ((name > ?) OR (name = ? AND id < ?))"; } @Override diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/HsqlPagingQueryProviderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/HsqlPagingQueryProviderTests.java index 262bd6411..8289b020c 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/HsqlPagingQueryProviderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/HsqlPagingQueryProviderTests.java @@ -71,7 +71,7 @@ public class HsqlPagingQueryProviderTests extends AbstractSqlPagingQueryProvider @Test public void testGenerateRemainingPagesQueryWithGroupBy() { pagingQueryProvider.setGroupClause("dep"); - String sql = "SELECT TOP 100 id, name, age FROM foo WHERE bar = 1 AND ((id > ?)) GROUP BY dep ORDER BY id ASC"; + String sql = "SELECT TOP 100 * FROM (SELECT id, name, age FROM foo WHERE bar = 1 GROUP BY dep ORDER BY id ASC) AS MAIN_QRY WHERE ((id > ?))"; String s = pagingQueryProvider.generateRemainingPagesQuery(pageSize); assertEquals(sql, s); } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/MySqlPagingQueryProviderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/MySqlPagingQueryProviderTests.java index 9a0c051a2..34daa0d96 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/MySqlPagingQueryProviderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/MySqlPagingQueryProviderTests.java @@ -71,7 +71,7 @@ public class MySqlPagingQueryProviderTests extends AbstractSqlPagingQueryProvide @Test public void testGenerateRemainingPagesQueryWithGroupBy() { pagingQueryProvider.setGroupClause("dep"); - String sql = "SELECT id, name, age FROM foo WHERE bar = 1 AND ((id > ?)) GROUP BY dep ORDER BY id ASC LIMIT 100"; + String sql = "SELECT * FROM (SELECT id, name, age FROM foo WHERE bar = 1 GROUP BY dep ORDER BY id ASC) AS MAIN_QRY WHERE ((id > ?)) LIMIT 100"; String s = pagingQueryProvider.generateRemainingPagesQuery(pageSize); assertEquals(sql, s); } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/OraclePagingQueryProviderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/OraclePagingQueryProviderTests.java index 69d08bbf3..d7f7d5977 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/OraclePagingQueryProviderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/OraclePagingQueryProviderTests.java @@ -43,7 +43,7 @@ public class OraclePagingQueryProviderTests extends AbstractSqlPagingQueryProvid @Test @Override public void testGenerateRemainingPagesQuery() { - String sql = "SELECT * FROM (SELECT id, name, age, ROWNUM as TMP_ROW_NUM FROM foo WHERE bar = 1 AND ((id > ?)) ORDER BY id ASC) WHERE ROWNUM <= 100"; + String sql = "SELECT * FROM (SELECT id, name, age, ROWNUM as TMP_ROW_NUM FROM foo WHERE bar = 1 ORDER BY id ASC) WHERE ROWNUM <= 100 AND ((id > ?))"; String s = pagingQueryProvider.generateRemainingPagesQuery(pageSize); assertEquals(sql, s); } @@ -75,7 +75,7 @@ public class OraclePagingQueryProviderTests extends AbstractSqlPagingQueryProvid @Test public void testGenerateRemainingPagesQueryWithGroupBy() { pagingQueryProvider.setGroupClause("dep"); - String sql = "SELECT * FROM (SELECT id, name, age, ROWNUM as TMP_ROW_NUM FROM foo WHERE bar = 1 AND ((id > ?)) GROUP BY dep ORDER BY id ASC) WHERE ROWNUM <= 100"; + String sql = "SELECT * FROM (SELECT id, name, age, ROWNUM as TMP_ROW_NUM FROM foo WHERE bar = 1 GROUP BY dep ORDER BY id ASC) WHERE ROWNUM <= 100 AND ((id > ?))"; String s = pagingQueryProvider.generateRemainingPagesQuery(pageSize); assertEquals(sql, s); } @@ -105,7 +105,7 @@ public class OraclePagingQueryProviderTests extends AbstractSqlPagingQueryProvid @Override public String getRemainingSqlWithMultipleSortKeys() { - return "SELECT * FROM (SELECT id, name, age, ROWNUM as TMP_ROW_NUM FROM foo WHERE bar = 1 AND ((name > ?) OR (name = ? AND id < ?)) ORDER BY name ASC, id DESC) WHERE ROWNUM <= 100"; + return "SELECT * FROM (SELECT id, name, age, ROWNUM as TMP_ROW_NUM FROM foo WHERE bar = 1 ORDER BY name ASC, id DESC) WHERE ROWNUM <= 100 AND ((name > ?) OR (name = ? AND id < ?))"; } @Override diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/PostgresPagingQueryProviderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/PostgresPagingQueryProviderTests.java index 43b9bbc96..6b8743176 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/PostgresPagingQueryProviderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/PostgresPagingQueryProviderTests.java @@ -71,7 +71,7 @@ public class PostgresPagingQueryProviderTests extends AbstractSqlPagingQueryProv @Test public void testGenerateRemainingPagesQueryWithGroupBy() { pagingQueryProvider.setGroupClause("id, dep"); - String sql = "SELECT id, name, age FROM foo WHERE bar = 1 AND ((id > ?)) GROUP BY id, dep ORDER BY id ASC LIMIT 100"; + String sql = "SELECT * FROM (SELECT id, name, age FROM foo WHERE bar = 1 GROUP BY id, dep ORDER BY id ASC) AS MAIN_QRY WHERE ((id > ?)) LIMIT 100"; String s = pagingQueryProvider.generateRemainingPagesQuery(pageSize); assertEquals(sql, s); } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/SqlPagingQueryUtilsTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/SqlPagingQueryUtilsTests.java index 69ac9c317..95148546f 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/SqlPagingQueryUtilsTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/SqlPagingQueryUtilsTests.java @@ -77,14 +77,14 @@ public class SqlPagingQueryUtilsTests { "SELECT * FROM (SELECT FOO, ROWNUM as TMP_ROW_NUM FROM BAR ORDER BY ID ASC) WHERE ROWNUMBER <= 100", SqlPagingQueryUtils.generateRowNumSqlQuery(qp, false, "ROWNUMBER <= 100")); assertEquals( - "SELECT * FROM (SELECT FOO, ROWNUM as TMP_ROW_NUM FROM BAR WHERE ((ID > ?)) ORDER BY ID ASC) WHERE ROWNUMBER <= 100", + "SELECT * FROM (SELECT FOO, ROWNUM as TMP_ROW_NUM FROM BAR ORDER BY ID ASC) WHERE ROWNUMBER <= 100 AND ((ID > ?))", SqlPagingQueryUtils.generateRowNumSqlQuery(qp, true, "ROWNUMBER <= 100")); qp.setWhereClause("BAZ IS NOT NULL"); assertEquals( "SELECT * FROM (SELECT FOO, ROWNUM as TMP_ROW_NUM FROM BAR WHERE BAZ IS NOT NULL ORDER BY ID ASC) WHERE ROWNUMBER <= 100", SqlPagingQueryUtils.generateRowNumSqlQuery(qp, false, "ROWNUMBER <= 100")); assertEquals( - "SELECT * FROM (SELECT FOO, ROWNUM as TMP_ROW_NUM FROM BAR WHERE BAZ IS NOT NULL AND ((ID > ?)) ORDER BY ID ASC) WHERE ROWNUMBER <= 100", + "SELECT * FROM (SELECT FOO, ROWNUM as TMP_ROW_NUM FROM BAR WHERE BAZ IS NOT NULL ORDER BY ID ASC) WHERE ROWNUMBER <= 100 AND ((ID > ?))", SqlPagingQueryUtils.generateRowNumSqlQuery(qp, true, "ROWNUMBER <= 100")); } @@ -119,14 +119,14 @@ public class SqlPagingQueryUtilsTests { "SELECT * FROM (SELECT FOO, ROWNUM as TMP_ROW_NUM FROM BAR ORDER BY ID DESC) WHERE ROWNUMBER <= 100", SqlPagingQueryUtils.generateRowNumSqlQuery(qp, false, "ROWNUMBER <= 100")); assertEquals( - "SELECT * FROM (SELECT FOO, ROWNUM as TMP_ROW_NUM FROM BAR WHERE ((ID < ?)) ORDER BY ID DESC) WHERE ROWNUMBER <= 100", + "SELECT * FROM (SELECT FOO, ROWNUM as TMP_ROW_NUM FROM BAR ORDER BY ID DESC) WHERE ROWNUMBER <= 100 AND ((ID < ?))", SqlPagingQueryUtils.generateRowNumSqlQuery(qp, true, "ROWNUMBER <= 100")); qp.setWhereClause("BAZ IS NOT NULL"); assertEquals( "SELECT * FROM (SELECT FOO, ROWNUM as TMP_ROW_NUM FROM BAR WHERE BAZ IS NOT NULL ORDER BY ID DESC) WHERE ROWNUMBER <= 100", SqlPagingQueryUtils.generateRowNumSqlQuery(qp, false, "ROWNUMBER <= 100")); assertEquals( - "SELECT * FROM (SELECT FOO, ROWNUM as TMP_ROW_NUM FROM BAR WHERE BAZ IS NOT NULL AND ((ID < ?)) ORDER BY ID DESC) WHERE ROWNUMBER <= 100", + "SELECT * FROM (SELECT FOO, ROWNUM as TMP_ROW_NUM FROM BAR WHERE BAZ IS NOT NULL ORDER BY ID DESC) WHERE ROWNUMBER <= 100 AND ((ID < ?))", SqlPagingQueryUtils.generateRowNumSqlQuery(qp, true, "ROWNUMBER <= 100")); } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/SqlServerPagingQueryProviderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/SqlServerPagingQueryProviderTests.java index 12690894a..3ee943e71 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/SqlServerPagingQueryProviderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/SqlServerPagingQueryProviderTests.java @@ -37,29 +37,32 @@ public class SqlServerPagingQueryProviderTests extends AbstractSqlPagingQueryPro assertEquals(sql, s); } - @Test @Override + @Test + @Override public void testGenerateRemainingPagesQuery() { String sql = "SELECT TOP 100 id, name, age FROM foo WHERE bar = 1 AND ((id > ?)) ORDER BY id ASC"; String s = pagingQueryProvider.generateRemainingPagesQuery(pageSize); assertEquals(sql, s); } - @Test @Override + @Test + @Override public void testGenerateJumpToItemQuery() { String sql = "SELECT id FROM ( SELECT id, ROW_NUMBER() OVER ( ORDER BY id ASC) AS ROW_NUMBER FROM foo WHERE bar = 1) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER = 100"; String s = pagingQueryProvider.generateJumpToItemQuery(145, pageSize); assertEquals(sql, s); } - @Test @Override + @Test + @Override public void testGenerateJumpToItemQueryForFirstPage() { String sql = "SELECT id FROM ( SELECT id, ROW_NUMBER() OVER ( ORDER BY id ASC) AS ROW_NUMBER FROM foo WHERE bar = 1) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER = 1"; String s = pagingQueryProvider.generateJumpToItemQuery(45, pageSize); assertEquals(sql, s); } - @Override @Test + @Override public void testGenerateFirstPageQueryWithGroupBy() { pagingQueryProvider.setGroupClause("dep"); String sql = "SELECT TOP 100 id, name, age FROM foo WHERE bar = 1 GROUP BY dep ORDER BY id ASC"; @@ -67,17 +70,17 @@ public class SqlServerPagingQueryProviderTests extends AbstractSqlPagingQueryPro assertEquals(sql, s); } - @Override @Test + @Override public void testGenerateRemainingPagesQueryWithGroupBy() { pagingQueryProvider.setGroupClause("dep"); - String sql = "SELECT TOP 100 id, name, age FROM foo WHERE bar = 1 AND ((id > ?)) GROUP BY dep ORDER BY id ASC"; + String sql = "SELECT TOP 100 * FROM (SELECT id, name, age FROM foo WHERE bar = 1 GROUP BY dep ORDER BY id ASC) AS MAIN_QRY WHERE ((id > ?))"; String s = pagingQueryProvider.generateRemainingPagesQuery(pageSize); assertEquals(sql, s); } - @Override @Test + @Override public void testGenerateJumpToItemQueryWithGroupBy() { pagingQueryProvider.setGroupClause("dep"); String sql = "SELECT id FROM ( SELECT id, ROW_NUMBER() OVER ( ORDER BY id ASC) AS ROW_NUMBER FROM foo WHERE bar = 1 GROUP BY dep) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER = 100"; @@ -85,8 +88,8 @@ public class SqlServerPagingQueryProviderTests extends AbstractSqlPagingQueryPro assertEquals(sql, s); } - @Override @Test + @Override public void testGenerateJumpToItemQueryForFirstPageWithGroupBy() { pagingQueryProvider.setGroupClause("dep"); String sql = "SELECT id FROM ( SELECT id, ROW_NUMBER() OVER ( ORDER BY id ASC) AS ROW_NUMBER FROM foo WHERE bar = 1 GROUP BY dep) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER = 1"; diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/SqlWindowingPagingQueryProviderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/SqlWindowingPagingQueryProviderTests.java index f8bfc36a9..57e8caa89 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/SqlWindowingPagingQueryProviderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/SqlWindowingPagingQueryProviderTests.java @@ -30,54 +30,58 @@ public class SqlWindowingPagingQueryProviderTests extends AbstractSqlPagingQuery pagingQueryProvider = new SqlWindowingPagingQueryProvider(); } - @Test @Override + @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) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER <= 100"; + String sql = "SELECT * FROM ( SELECT *, ROW_NUMBER() OVER ( ORDER BY id ASC) AS ROW_NUMBER FROM foo WHERE bar = 1) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER <= 100"; String s = pagingQueryProvider.generateFirstPageQuery(pageSize); 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 > ?))) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER <= 100"; + String sql = "SELECT * FROM ( SELECT *, ROW_NUMBER() OVER ( ORDER BY id ASC) AS ROW_NUMBER FROM foo WHERE bar = 1) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER <= 100 AND ((id > ?))"; String s = pagingQueryProvider.generateRemainingPagesQuery(pageSize); assertEquals("", sql, s); } - @Test @Override + @Test + @Override public void testGenerateJumpToItemQuery() { String sql = "SELECT id FROM ( SELECT id, ROW_NUMBER() OVER ( ORDER BY id ASC) AS ROW_NUMBER FROM foo WHERE bar = 1) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER = 100"; String s = pagingQueryProvider.generateJumpToItemQuery(145, pageSize); assertEquals("", sql, s); } - @Test @Override + @Test + @Override public void testGenerateJumpToItemQueryForFirstPage() { String sql = "SELECT id FROM ( SELECT id, ROW_NUMBER() OVER ( ORDER BY id ASC) AS ROW_NUMBER FROM foo WHERE bar = 1) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER = 1"; String s = pagingQueryProvider.generateJumpToItemQuery(45, pageSize); Assert.assertEquals("", sql, s); } - @Override @Test + @Override public void testGenerateFirstPageQueryWithGroupBy() { pagingQueryProvider.setGroupClause("dep"); - String sql = "SELECT * FROM ( SELECT id, name, age, ROW_NUMBER() OVER ( ORDER BY id ASC) AS ROW_NUMBER FROM foo WHERE bar = 1 GROUP BY dep) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER <= 100"; + String sql = "SELECT * FROM ( SELECT *, ROW_NUMBER() OVER ( ORDER BY id ASC) AS ROW_NUMBER FROM foo WHERE bar = 1 GROUP BY dep) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER <= 100"; String s = pagingQueryProvider.generateFirstPageQuery(pageSize); assertEquals(sql, s); } - @Override @Test + @Override public void testGenerateRemainingPagesQueryWithGroupBy() { pagingQueryProvider.setGroupClause("dep"); - 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 > ?)) GROUP BY dep) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER <= 100"; + String sql = "SELECT * FROM ( SELECT *, ROW_NUMBER() OVER ( ORDER BY id ASC) AS ROW_NUMBER FROM foo WHERE bar = 1 GROUP BY dep) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER <= 100 AND ((id > ?))"; String s = pagingQueryProvider.generateRemainingPagesQuery(pageSize); assertEquals(sql, s); } - @Override @Test + @Override public void testGenerateJumpToItemQueryWithGroupBy() { pagingQueryProvider.setGroupClause("dep"); String sql = "SELECT id FROM ( SELECT id, ROW_NUMBER() OVER ( ORDER BY id ASC) AS ROW_NUMBER FROM foo WHERE bar = 1 GROUP BY dep) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER = 100"; @@ -85,8 +89,8 @@ public class SqlWindowingPagingQueryProviderTests extends AbstractSqlPagingQuery assertEquals(sql, s); } - @Override @Test + @Override public void testGenerateJumpToItemQueryForFirstPageWithGroupBy() { pagingQueryProvider.setGroupClause("dep"); String sql = "SELECT id FROM ( SELECT id, ROW_NUMBER() OVER ( ORDER BY id ASC) AS ROW_NUMBER FROM foo WHERE bar = 1 GROUP BY dep) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER = 1"; @@ -96,12 +100,12 @@ public class SqlWindowingPagingQueryProviderTests extends AbstractSqlPagingQuery @Override public String getFirstPageSqlWithMultipleSortKeys() { - return "SELECT * FROM ( SELECT id, name, age, ROW_NUMBER() OVER ( ORDER BY name ASC, id DESC) AS ROW_NUMBER FROM foo WHERE bar = 1) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER <= 100"; + return "SELECT * FROM ( SELECT *, ROW_NUMBER() OVER ( ORDER BY name ASC, id DESC) AS ROW_NUMBER FROM foo WHERE bar = 1) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER <= 100"; } @Override public String getRemainingSqlWithMultipleSortKeys() { - return "SELECT * FROM ( SELECT id, name, age, ROW_NUMBER() OVER ( ORDER BY name ASC, id DESC) AS ROW_NUMBER FROM foo WHERE bar = 1 AND ((name > ?) OR (name = ? AND id < ?))) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER <= 100"; + return "SELECT * FROM ( SELECT *, ROW_NUMBER() OVER ( ORDER BY name ASC, id DESC) AS ROW_NUMBER FROM foo WHERE bar = 1) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER <= 100 AND ((name > ?) OR (name = ? AND id < ?))"; } @Override diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/SybasePagingQueryProviderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/SybasePagingQueryProviderTests.java index 7937875c1..aeb34bb32 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/SybasePagingQueryProviderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/SybasePagingQueryProviderTests.java @@ -37,29 +37,32 @@ public class SybasePagingQueryProviderTests extends AbstractSqlPagingQueryProvid assertEquals("", sql, s); } - @Test @Override + @Test + @Override public void testGenerateRemainingPagesQuery() { String sql = "SELECT TOP 100 id, name, age FROM foo WHERE bar = 1 AND ((id > ?)) ORDER BY id ASC"; String s = pagingQueryProvider.generateRemainingPagesQuery(pageSize); assertEquals("", sql, s); } - @Test @Override + @Test + @Override public void testGenerateJumpToItemQuery() { String sql = "SELECT id FROM ( SELECT id, ROW_NUMBER() OVER ( ORDER BY id ASC) AS ROW_NUMBER FROM foo WHERE bar = 1) WHERE ROW_NUMBER = 100"; String s = pagingQueryProvider.generateJumpToItemQuery(145, pageSize); assertEquals("", sql, s); } - @Test @Override + @Test + @Override public void testGenerateJumpToItemQueryForFirstPage() { String sql = "SELECT id FROM ( SELECT id, ROW_NUMBER() OVER ( ORDER BY id ASC) AS ROW_NUMBER FROM foo WHERE bar = 1) WHERE ROW_NUMBER = 1"; String s = pagingQueryProvider.generateJumpToItemQuery(45, pageSize); assertEquals("", sql, s); } - @Override @Test + @Override public void testGenerateFirstPageQueryWithGroupBy() { pagingQueryProvider.setGroupClause("dep"); String sql = "SELECT TOP 100 id, name, age FROM foo WHERE bar = 1 GROUP BY dep ORDER BY id ASC"; @@ -67,17 +70,17 @@ public class SybasePagingQueryProviderTests extends AbstractSqlPagingQueryProvid assertEquals(sql, s); } - @Override @Test + @Override public void testGenerateRemainingPagesQueryWithGroupBy() { pagingQueryProvider.setGroupClause("dep"); - String sql = "SELECT TOP 100 id, name, age FROM foo WHERE bar = 1 AND ((id > ?)) GROUP BY dep ORDER BY id ASC"; + String sql = "SELECT TOP 100 * FROM (SELECT id, name, age FROM foo WHERE bar = 1 GROUP BY dep ORDER BY id ASC) AS MAIN_QRY WHERE ((id > ?))"; String s = pagingQueryProvider.generateRemainingPagesQuery(pageSize); assertEquals(sql, s); } - @Override @Test + @Override public void testGenerateJumpToItemQueryWithGroupBy() { pagingQueryProvider.setGroupClause("dep"); String sql = "SELECT id FROM ( SELECT id, ROW_NUMBER() OVER ( ORDER BY id ASC) AS ROW_NUMBER FROM foo WHERE bar = 1 GROUP BY dep) WHERE ROW_NUMBER = 100"; @@ -85,8 +88,8 @@ public class SybasePagingQueryProviderTests extends AbstractSqlPagingQueryProvid assertEquals(sql, s); } - @Override @Test + @Override public void testGenerateJumpToItemQueryForFirstPageWithGroupBy() { pagingQueryProvider.setGroupClause("dep"); String sql = "SELECT id FROM ( SELECT id, ROW_NUMBER() OVER ( ORDER BY id ASC) AS ROW_NUMBER FROM foo WHERE bar = 1 GROUP BY dep) WHERE ROW_NUMBER = 1";