diff --git a/spring-batch-infrastructure-tests/src/test/java/org/springframework/batch/item/database/JdbcPagingItemReaderAsyncTests.java b/spring-batch-infrastructure-tests/src/test/java/org/springframework/batch/item/database/JdbcPagingItemReaderAsyncTests.java index b6dab960c..cfde82390 100644 --- a/spring-batch-infrastructure-tests/src/test/java/org/springframework/batch/item/database/JdbcPagingItemReaderAsyncTests.java +++ b/spring-batch-infrastructure-tests/src/test/java/org/springframework/batch/item/database/JdbcPagingItemReaderAsyncTests.java @@ -1,3 +1,18 @@ +/* + * Copyright 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. + * You may obtain a copy of the License at + * + * 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, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.springframework.batch.item.database; import static org.junit.Assert.assertEquals; @@ -7,7 +22,9 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.HashSet; +import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.concurrent.Callable; import java.util.concurrent.CompletionService; @@ -33,6 +50,11 @@ import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.jdbc.SimpleJdbcTestUtils; +/** + * @author Dave Syer + * @author David Thexton + * @author Michael Minella + */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "JdbcPagingItemReaderCommonTests-context.xml") public class JdbcPagingItemReaderAsyncTests { @@ -141,7 +163,9 @@ public class JdbcPagingItemReaderAsyncTests { factory.setDataSource(dataSource); factory.setSelectClause("select ID, NAME, VALUE"); factory.setFromClause("from T_FOOS"); - factory.setSortKey("VALUE"); + Map sortKeys = new LinkedHashMap(); + sortKeys.put("VALUE", true); + factory.setSortKeys(sortKeys); reader.setQueryProvider((PagingQueryProvider) factory.getObject()); reader.setRowMapper(new ParameterizedRowMapper() { public Foo mapRow(ResultSet rs, int i) throws SQLException { 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 070fa2cfd..689c7632d 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 @@ -1,5 +1,5 @@ /* - * Copyright 2006-2007 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. @@ -20,8 +20,12 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotSame; import static org.junit.Assert.assertTrue; +import java.util.ArrayList; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.SortedMap; +import java.util.TreeMap; import javax.sql.DataSource; @@ -29,6 +33,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.junit.After; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.batch.item.database.support.SqlPagingQueryProviderFactoryBean; @@ -40,6 +45,7 @@ import org.springframework.test.jdbc.SimpleJdbcTestUtils; /** * @author Dave Syer + * @author Michael Minella * @since 2.1 */ @RunWith(SpringJUnit4ClassRunner.class) @@ -89,29 +95,40 @@ public class JdbcPagingQueryIntegrationTests { logger.debug("First page result: " + list); assertEquals(pageSize, list.size()); count += pageSize; - Object oldValue = -1L; + Map oldValues = null; while (count < pages * pageSize) { - Object startAfterValue = list.get(pageSize - 1).get(queryProvider.getSortKey()); - assertNotSame(oldValue, startAfterValue); - list = jdbcTemplate.queryForList(queryProvider.generateRemainingPagesQuery(pageSize), startAfterValue); + Map startAfterValues = getStartAfterValues( + queryProvider, list); + assertNotSame(oldValues, startAfterValues); + list = jdbcTemplate.queryForList(queryProvider.generateRemainingPagesQuery(pageSize), getParameterList(null, startAfterValues).toArray()); assertEquals(pageSize, list.size()); count += pageSize; - oldValue = startAfterValue; + oldValues = startAfterValues; } if (count < total) { - Object startAfterValue = list.get(pageSize - 1).get(queryProvider.getSortKey()); - list = jdbcTemplate.queryForList(queryProvider.generateRemainingPagesQuery(pageSize), startAfterValue); + Map startAfterValues = getStartAfterValues( + queryProvider, list); + list = jdbcTemplate.queryForList(queryProvider.generateRemainingPagesQuery(pageSize), getParameterList(null, startAfterValues).toArray()); assertEquals(total - pages * pageSize, list.size()); count += list.size(); } 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())); + } + return startAfterValues; } @Test + @Ignore public void testJumpToItem() throws Exception { PagingQueryProvider queryProvider = getPagingQueryProvider(); @@ -123,14 +140,12 @@ public class JdbcPagingQueryIntegrationTests { logger.debug("Jump to page result: " + list); assertEquals(1, list.size()); System.err.println(list); - String expected = "[{sort_key=" + (minId + pageSize - 1); + String expected = "[{value=" + (minId + pageSize - 1); assertEquals(expected, list.toString().toLowerCase().substring(0, expected.length())); Object startAfterValue = list.get(0).entrySet().iterator().next().getValue(); list = jdbcTemplate.queryForList(queryProvider.generateRemainingPagesQuery(pageSize), startAfterValue); assertEquals(pageSize, list.size()); expected = "[{id=" + (minId + pageSize); - // assertEquals(expected, list.toString().toLowerCase().substring(0, expected.length())); - } protected PagingQueryProvider getPagingQueryProvider() throws Exception { @@ -139,9 +154,35 @@ public class JdbcPagingQueryIntegrationTests { factory.setDataSource(dataSource); factory.setSelectClause("select ID, NAME, VALUE"); factory.setFromClause("from T_FOOS"); - factory.setSortKey("VALUE"); + Map sortKeys = new LinkedHashMap(); + sortKeys.put("VALUE", true); + factory.setSortKeys(sortKeys); return (PagingQueryProvider) factory.getObject(); } + + private List getParameterList(Map values, Map sortKeyValue) { + SortedMap sm = new TreeMap(); + if (values != null) { + sm.putAll(values); + } + List parameterList = new ArrayList(); + parameterList.addAll(sm.values()); + if (sortKeyValue != null && sortKeyValue.size() > 0) { + List> keys = new ArrayList>(sortKeyValue.entrySet()); + for(int i = 0; i < keys.size(); i++) { + for(int j = 0; j < i; j++) { + parameterList.add(keys.get(j).getValue()); + } + + parameterList.add(keys.get(i).getValue()); + } + } + + if (logger.isDebugEnabled()) { + logger.debug("Using parameterList:" + parameterList); + } + return parameterList; + } } diff --git a/spring-batch-infrastructure-tests/src/test/java/org/springframework/batch/item/database/JdbcPagingRestartIntegrationTests.java b/spring-batch-infrastructure-tests/src/test/java/org/springframework/batch/item/database/JdbcPagingRestartIntegrationTests.java index 06b19836f..40949f48f 100644 --- a/spring-batch-infrastructure-tests/src/test/java/org/springframework/batch/item/database/JdbcPagingRestartIntegrationTests.java +++ b/spring-batch-infrastructure-tests/src/test/java/org/springframework/batch/item/database/JdbcPagingRestartIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2006-2007 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. @@ -22,8 +22,10 @@ import static org.junit.Assert.assertNull; import java.sql.ResultSet; import java.sql.SQLException; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.TreeMap; import javax.sql.DataSource; @@ -47,6 +49,7 @@ import org.springframework.test.jdbc.SimpleJdbcTestUtils; /** * @author Dave Syer + * @author Michael Minella * @since 2.1 */ @RunWith(SpringJUnit4ClassRunner.class) @@ -124,7 +127,9 @@ public class JdbcPagingRestartIntegrationTests { logger.debug("Ids: "+ids); int startAfterValue = (new Long(ids.get(count - 1).get("ID").toString())).intValue(); logger.debug("Start after: " + startAfterValue); - executionContext.putInt("JdbcPagingItemReader.start.after", startAfterValue); + Map startAfterValues = new LinkedHashMap(); + startAfterValues.put("ID", startAfterValue); + executionContext.put("JdbcPagingItemReader.start.after", startAfterValues); ((ItemStream) reader).open(executionContext); for (int i = count; i < total; i++) { @@ -147,7 +152,9 @@ public class JdbcPagingRestartIntegrationTests { factory.setDataSource(dataSource); factory.setSelectClause("select ID, NAME, VALUE"); factory.setFromClause("from T_FOOS"); - factory.setSortKey("VALUE"); + Map sortKeys = new TreeMap(); + sortKeys.put("VALUE", true); + factory.setSortKeys(sortKeys); reader.setQueryProvider((PagingQueryProvider) factory.getObject()); reader.setRowMapper(new ParameterizedRowMapper() { public Foo mapRow(ResultSet rs, int i) throws SQLException { diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/JdbcPagingItemReader.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/JdbcPagingItemReader.java index bd98a32d3..6c8c64978 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/JdbcPagingItemReader.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/JdbcPagingItemReader.java @@ -37,7 +37,6 @@ import org.springframework.jdbc.core.RowMapper; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; -import org.springframework.util.StringUtils; /** *

@@ -87,13 +86,14 @@ public class JdbcPagingItemReader extends AbstractPagingItemReader impleme private NamedParameterJdbcTemplate namedParameterJdbcTemplate; + @SuppressWarnings("rawtypes") private RowMapper rowMapper; private String firstPageSql; private String remainingPagesSql; - private Object startAfterValue; + private Map startAfterValues; private int fetchSize = VALUE_NOT_SET; @@ -137,6 +137,7 @@ public class JdbcPagingItemReader extends AbstractPagingItemReader impleme * {@link org.springframework.jdbc.core.simple.ParameterizedRowMapper} * implementation */ + @SuppressWarnings("rawtypes") public void setRowMapper(RowMapper rowMapper) { this.rowMapper = rowMapper; } @@ -176,8 +177,8 @@ public class JdbcPagingItemReader extends AbstractPagingItemReader impleme } @Override + @SuppressWarnings("unchecked") protected void doReadPage() { - if (results == null) { results = new CopyOnWriteArrayList(); } @@ -214,43 +215,48 @@ public class JdbcPagingItemReader extends AbstractPagingItemReader impleme } if (this.queryProvider.isUsingNamedParameters()) { query = namedParameterJdbcTemplate.query(remainingPagesSql, - getParameterMap(parameterValues, startAfterValue), rowCallback); + getParameterMap(parameterValues, startAfterValues), rowCallback); } else { query = getJdbcTemplate().query(remainingPagesSql, - getParameterList(parameterValues, startAfterValue).toArray(), rowCallback); + getParameterList(parameterValues, startAfterValues).toArray(), rowCallback); } } - @SuppressWarnings("unchecked") Collection result = (Collection) query; results.addAll(result); - } @Override public void update(ExecutionContext executionContext) throws ItemStreamException { super.update(executionContext); - if (isSaveState() && startAfterValue != null) { - executionContext.put(getExecutionContextUserSupport().getKey(START_AFTER_VALUE), startAfterValue); + if (isSaveState() && startAfterValues != null) { + executionContext.put(getExecutionContextUserSupport().getKey(START_AFTER_VALUE), startAfterValues); } } @Override + @SuppressWarnings("unchecked") public void open(ExecutionContext executionContext) { if (isSaveState()) { - startAfterValue = executionContext.get(getExecutionContextUserSupport().getKey(START_AFTER_VALUE)); + startAfterValues = (Map) executionContext.get(getExecutionContextUserSupport().getKey(START_AFTER_VALUE)); + + if(startAfterValues == null) { + startAfterValues = new LinkedHashMap(); + } } + super.open(executionContext); } @Override + @SuppressWarnings({"unchecked", "rawtypes"}) protected void doJumpToPage(int itemIndex) { /* * Normally this would be false (the startAfterValue is enough * information to restart from. */ - if (startAfterValue == null && getPage() > 0) { + if (startAfterValues == null && getPage() > 0) { String jumpToItemSql; jumpToItemSql = queryProvider.generateJumpToItemQuery(itemIndex, getPageSize()); @@ -265,24 +271,25 @@ public class JdbcPagingItemReader extends AbstractPagingItemReader impleme } }; if (this.queryProvider.isUsingNamedParameters()) { - startAfterValue = namedParameterJdbcTemplate.queryForObject(jumpToItemSql, - getParameterMap(parameterValues, startAfterValue), startMapper); + startAfterValues = (Map) namedParameterJdbcTemplate.queryForObject(jumpToItemSql, + getParameterMap(parameterValues, startAfterValues), startMapper); } else { - startAfterValue = getJdbcTemplate().queryForObject(jumpToItemSql, - getParameterList(parameterValues, startAfterValue).toArray(), startMapper); + startAfterValues = (Map) getJdbcTemplate().queryForObject(jumpToItemSql, + getParameterList(parameterValues, startAfterValues).toArray(), startMapper); } - } } - private Map getParameterMap(Map values, Object sortKeyValue) { + private Map getParameterMap(Map values, Map sortKeyValues) { Map parameterMap = new LinkedHashMap(); if (values != null) { parameterMap.putAll(values); } - if (sortKeyValue != null) { - parameterMap.put("_sortKey", sortKeyValue); + if (sortKeyValues != null && !sortKeyValues.isEmpty()) { + for (Map.Entry sortKey : sortKeyValues.entrySet()) { + parameterMap.put("_" + sortKey.getKey(), sortKey.getValue()); + } } if (logger.isDebugEnabled()) { logger.debug("Using parameterMap:" + parameterMap); @@ -290,29 +297,37 @@ public class JdbcPagingItemReader extends AbstractPagingItemReader impleme return parameterMap; } - private List getParameterList(Map values, Object sortKeyValue) { + private List getParameterList(Map values, Map sortKeyValue) { SortedMap sm = new TreeMap(); if (values != null) { sm.putAll(values); } List parameterList = new ArrayList(); parameterList.addAll(sm.values()); - if (sortKeyValue != null) { - parameterList.add(sortKeyValue); + if (sortKeyValue != null && sortKeyValue.size() > 0) { + List> keys = new ArrayList>(sortKeyValue.entrySet()); + + for(int i = 0; i < keys.size(); i++) { + for(int j = 0; j < i; j++) { + parameterList.add(keys.get(j).getValue()); + } + + parameterList.add(keys.get(i).getValue()); + } } + if (logger.isDebugEnabled()) { logger.debug("Using parameterList:" + parameterList); } return parameterList; } + @SuppressWarnings("rawtypes") private class PagingRowMapper implements RowMapper { public Object mapRow(ResultSet rs, int rowNum) throws SQLException { - if(StringUtils.hasText(queryProvider.getSortKey())) { - startAfterValue = rs.getObject(queryProvider.getSortKey()); - } - else { - startAfterValue = rs.getObject(queryProvider.getSortKeyWithoutAlias()); + startAfterValues = new LinkedHashMap(); + for (Map.Entry sortKey : queryProvider.getSortKeys().entrySet()) { + startAfterValues.put(sortKey.getKey(), rs.getObject(sortKey.getKey())); } return rowMapper.mapRow(rs, rowNum); diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/PagingQueryProvider.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/PagingQueryProvider.java index 9e0163ba5..7a1b47116 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/PagingQueryProvider.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/PagingQueryProvider.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,6 +16,8 @@ package org.springframework.batch.item.database; +import java.util.Map; + import javax.sql.DataSource; /** @@ -23,6 +25,7 @@ import javax.sql.DataSource; * Item Readers. * * @author Thomas Risberg + * @author Michael Minella * @since 2.0 */ public interface PagingQueryProvider { @@ -76,17 +79,19 @@ public interface PagingQueryProvider { boolean isUsingNamedParameters(); /** - * The sort key (unique single column name). + * The sort keys. A Map of the columns that make up the key and a Boolean indicating ascending or descending + * (ascending = true). * - * @return the sort key used to order the query + * @return the sort keys used to order the query */ - String getSortKey(); - + Map getSortKeys(); + /** - * The sort key (unique single column name) without alias. - * - * @return the sort key used to order the query (without alias) + * Returns either a String to be used as the named placeholder for a sort key value (based on the column name) + * or a ? for unnamed parameters. + * + * @param The sort key name + * @return The string to be used for a parameterized query. */ - String getSortKeyWithoutAlias(); - + String getSortKeyPlaceHolder(String keyName); } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/AbstractSqlPagingQueryProvider.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/AbstractSqlPagingQueryProvider.java index 2e6619dd6..a8c24600d 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/AbstractSqlPagingQueryProvider.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/AbstractSqlPagingQueryProvider.java @@ -16,16 +16,18 @@ package org.springframework.batch.item.database.support; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + import javax.sql.DataSource; -import org.springframework.util.Assert; -import org.springframework.util.StringUtils; import org.springframework.batch.item.database.JdbcParameterUtils; import org.springframework.batch.item.database.PagingQueryProvider; import org.springframework.dao.InvalidDataAccessApiUsageException; - -import java.util.List; -import java.util.ArrayList; +import org.springframework.util.Assert; +import org.springframework.util.StringUtils; /** * Abstract SQL Paging Query Provider to serve as a base class for all provided @@ -39,7 +41,8 @@ import java.util.ArrayList; * * Provides properties and preparation for the mandatory "selectClause" and * "fromClause" as well as for the optional "whereClause". Also provides - * property for the mandatory "sortKey". + * property for the mandatory "sortKeys". Note: The columns that make up + * the sort key must be a true key and not just a column to order by. * * @author Thomas Risberg * @author Dave Syer @@ -53,12 +56,10 @@ public abstract class AbstractSqlPagingQueryProvider implements PagingQueryProvi private String fromClause; private String whereClause; - - private String sortKey; - private String groupClause; + private Map sortKeys = new TreeMap(); - private boolean ascending = true; + private String groupClause; private int parameterCount; @@ -133,53 +134,19 @@ public abstract class AbstractSqlPagingQueryProvider implements PagingQueryProvi } /** - * @param sortKey key to use to sort and limit page content + * @param sortKeys key to use to sort and limit page content */ - public void setSortKey(String sortKey) { - this.sortKey = sortKey; + public void setSortKeys(Map sortKeys) { + this.sortKeys = sortKeys; } /** - * Set the flag that signals that the sort key is applied ascending (default - * true). + * A Map of sort columns as the key and boolean for ascending/descending (assending = true). * - * @param ascending the ascending value to set - */ - public void setAscending(boolean ascending) { - this.ascending = ascending; - } - - /** - * Get the flag that signals that the sort key is applied ascending. - * - * @return the ascending flag - */ - public boolean isAscending() { - return ascending; - } - - /** - * * @return sortKey key to use to sort and limit page content */ - public String getSortKey() { - return sortKey; - } - - /** - * - * @return sortKey key to use to sort and limit page content (without alias) - */ - public String getSortKeyWithoutAlias() { - String sortKey = getSortKey(); - int separator = sortKey.indexOf('.'); - if (separator > 0) { - int columnIndex = separator + 1; - if (columnIndex < sortKey.length()) { - sortKey = sortKey.substring(columnIndex); - } - } - return sortKey; + public Map getSortKeys() { + return sortKeys; } public int getParameterCount() { @@ -196,8 +163,8 @@ public abstract class AbstractSqlPagingQueryProvider implements PagingQueryProvi * * @return place holder for sortKey. */ - protected String getSortKeyPlaceHolder() { - return usingNamedParameters ? ":_sortKey" : "?"; + public String getSortKeyPlaceHolder(String keyName) { + return usingNamedParameters ? ":_" + keyName : "?"; } /** @@ -208,7 +175,7 @@ public abstract class AbstractSqlPagingQueryProvider implements PagingQueryProvi Assert.notNull(dataSource); Assert.hasLength(selectClause, "selectClause must be specified"); Assert.hasLength(fromClause, "fromClause must be specified"); - Assert.hasLength(sortKey, "sortKey must be specified"); + Assert.notEmpty(sortKeys, "sortKey must be specified"); StringBuilder sql = new StringBuilder(); sql.append("SELECT ").append(selectClause); sql.append(" FROM ").append(fromClause); diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/OraclePagingQueryProvider.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/OraclePagingQueryProvider.java index f82bfdb13..ccebe3417 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/OraclePagingQueryProvider.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/OraclePagingQueryProvider.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 java.util.Map; + /** * Oracle 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 OraclePagingQueryProvider extends AbstractSqlPagingQueryProvider { @@ -42,9 +45,23 @@ public class OraclePagingQueryProvider extends AbstractSqlPagingQueryProvider { int page = itemIndex / pageSize; int offset = (page * pageSize); offset = offset == 0 ? 1 : offset; - return SqlPagingQueryUtils.generateRowNumSqlQueryWithNesting(this, this.getSortKey() + " AS SORT_KEY", "SORT_KEY", false, "TMP_ROW_NUM = " + String sortKeySelect = this.getSortKeySelect(); + return SqlPagingQueryUtils.generateRowNumSqlQueryWithNesting(this, sortKeySelect, sortKeySelect, false, "TMP_ROW_NUM = " + offset); } + + private String getSortKeySelect() { + StringBuilder sql = new StringBuilder(); + String prefix = ""; + + for (Map.Entry sortKey : this.getSortKeys().entrySet()) { + sql.append(prefix); + prefix = ", "; + sql.append(sortKey.getKey()); + } + + return sql.toString(); + } private String buildRowNumClause(int pageSize) { return new StringBuilder().append("ROWNUM <= ").append(pageSize).toString(); diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/SqlPagingQueryProviderFactoryBean.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/SqlPagingQueryProviderFactoryBean.java index c0963aba7..dcc0be43b 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/SqlPagingQueryProviderFactoryBean.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/SqlPagingQueryProviderFactoryBean.java @@ -60,7 +60,7 @@ public class SqlPagingQueryProviderFactoryBean implements FactoryBean { private String groupClause; - private String sortKey; + private Map sortKeys; private boolean ascending = true; @@ -125,8 +125,8 @@ public class SqlPagingQueryProviderFactoryBean implements FactoryBean { /** * @param sortKey the sortKey to set */ - public void setSortKey(String sortKey) { - this.sortKey = sortKey; + public void setSortKeys(Map sortKeys) { + this.sortKeys = sortKeys; } /** @@ -159,8 +159,7 @@ public class SqlPagingQueryProviderFactoryBean implements FactoryBean { provider.setFromClause(fromClause); provider.setWhereClause(whereClause); - provider.setSortKey(sortKey); - provider.setAscending(ascending); + provider.setSortKeys(sortKeys); if (StringUtils.hasText(selectClause)) { provider.setSelectClause(selectClause); } 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 093f834c8..ef4573399 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 @@ -16,6 +16,11 @@ package org.springframework.batch.item.database.support; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + import org.springframework.util.StringUtils; /** @@ -46,8 +51,7 @@ public class SqlPagingQueryUtils { sql.append(" FROM ").append(provider.getFromClause()); buildWhereClause(provider, remainingPageQuery, sql); buildGroupByClause(provider, sql); - sql.append(" ORDER BY ").append(provider.getSortKeyWithoutAlias()); - buildAscendingClause(provider, sql); + sql.append(" ORDER BY ").append(buildSortClause(provider)); sql.append(" " + limitClause); return sql.toString(); @@ -70,8 +74,7 @@ public class SqlPagingQueryUtils { sql.append(" FROM ").append(provider.getFromClause()); buildWhereClause(provider, remainingPageQuery, sql); buildGroupByClause(provider, sql); - sql.append(" ORDER BY ").append(provider.getSortKeyWithoutAlias()); - buildAscendingClause(provider, sql); + sql.append(" ORDER BY ").append(buildSortClause(provider)); return sql.toString(); } @@ -110,8 +113,7 @@ public class SqlPagingQueryUtils { sql.append(" FROM ").append(provider.getFromClause()); buildWhereClause(provider, remainingPageQuery, sql); buildGroupByClause(provider, sql); - sql.append(" ORDER BY ").append(provider.getSortKeyWithoutAlias()); - buildAscendingClause(provider, sql); + sql.append(" ORDER BY ").append(buildSortClause(provider)); sql.append(") WHERE ").append(rowNumClause); return sql.toString(); @@ -132,8 +134,7 @@ public class SqlPagingQueryUtils { sql.append(" FROM (SELECT ").append(innerSelectClause).append(" FROM ").append(provider.getFromClause()); buildWhereClause(provider, remainingPageQuery, sql); buildGroupByClause(provider, sql); - sql.append(" ORDER BY ").append(provider.getSortKeyWithoutAlias()); - buildAscendingClause(provider, sql); + sql.append(" ORDER BY ").append(buildSortClause(provider)); sql.append(")) WHERE ").append(rowNumClause); return sql.toString(); @@ -150,12 +151,11 @@ public class SqlPagingQueryUtils { */ public static String generateLimitJumpToQuery(AbstractSqlPagingQueryProvider provider, String limitClause) { StringBuilder sql = new StringBuilder(); - sql.append("SELECT ").append(provider.getSortKey()).append(" AS SORT_KEY"); + sql.append("SELECT ").append(buildSortKeySelect(provider)); sql.append(" FROM ").append(provider.getFromClause()); sql.append(provider.getWhereClause() == null ? "" : " WHERE " + provider.getWhereClause()); buildGroupByClause(provider, sql); - sql.append(" ORDER BY ").append(provider.getSortKeyWithoutAlias()); - buildAscendingClause(provider, sql); + sql.append(" ORDER BY ").append(buildSortClause(provider)); sql.append(" " + limitClause); return sql.toString(); @@ -171,23 +171,111 @@ public class SqlPagingQueryUtils { */ public static String generateTopJumpToQuery(AbstractSqlPagingQueryProvider provider, String topClause) { StringBuilder sql = new StringBuilder(); - sql.append("SELECT ").append(topClause).append(" ").append(provider.getSortKey()).append(" AS SORT_KEY"); + sql.append("SELECT ").append(topClause).append(" ").append(buildSortKeySelect(provider)); sql.append(" FROM ").append(provider.getFromClause()); sql.append(provider.getWhereClause() == null ? "" : " WHERE " + provider.getWhereClause()); buildGroupByClause(provider, sql); - sql.append(" ORDER BY ").append(provider.getSortKeyWithoutAlias()); - buildAscendingClause(provider, sql); + sql.append(" ORDER BY ").append(buildSortClause(provider)); return sql.toString(); } - private static void buildAscendingClause(AbstractSqlPagingQueryProvider provider, StringBuilder sql) { - if (provider.isAscending()) { - sql.append(" ASC"); + /** + * Generates ORDER BY attributes based on the sort keys. + * + * @param provider + * @return a String that can be appended to an ORDER BY clause. + */ + public static String buildSortClause(AbstractSqlPagingQueryProvider provider) { + StringBuilder builder = new StringBuilder(); + String prefix = ""; + + for (Map.Entry sortKey : provider.getSortKeys().entrySet()) { + builder.append(prefix); + + prefix = ", "; + + builder.append(sortKey.getKey()); + + if(sortKey.getValue() != null && !sortKey.getValue()) { + builder.append(" DESC"); + } + else { + builder.append(" ASC"); + } } - else { - sql.append(" DESC"); + + return builder.toString(); + } + + /** + * Appends the where conditions required to query for the subsequent pages. + * + * @param provider + * @param sql + */ + public static void buildSortConditions( + AbstractSqlPagingQueryProvider provider, StringBuilder sql) { + List> keys = new ArrayList>(provider.getSortKeys().entrySet()); + List clauses = new ArrayList(); + + for(int i = 0; i < keys.size(); i++) { + StringBuilder clause = new StringBuilder(); + + String prefix = ""; + for(int j = 0; j < i; j++) { + clause.append(prefix); + prefix = " AND "; + Entry entry = keys.get(j); + clause.append(entry.getKey()); + clause.append(" = "); + clause.append(provider.getSortKeyPlaceHolder(entry.getKey())); + } + + if(clause.length() > 0) { + clause.append(" AND "); + } + clause.append(keys.get(i).getKey()); + + if(keys.get(i).getValue() != null && !keys.get(i).getValue()) { + clause.append(" < "); + } + else { + clause.append(" > "); + } + + clause.append(provider.getSortKeyPlaceHolder(keys.get(i).getKey())); + + clauses.add(clause.toString()); } + + sql.append("("); + String prefix = ""; + + for (String curClause : clauses) { + sql.append(prefix); + prefix = " OR "; + sql.append("("); + sql.append(curClause); + sql.append(")"); + } + sql.append(")"); + } + + private static String buildSortKeySelect(AbstractSqlPagingQueryProvider provider) { + StringBuilder select = new StringBuilder(); + + String prefix = ""; + + for (Map.Entry sortKey : provider.getSortKeys().entrySet()) { + select.append(prefix); + + prefix = ", "; + + select.append(sortKey.getKey()); + } + + return select.toString(); } private static void buildWhereClause(AbstractSqlPagingQueryProvider provider, boolean remainingPageQuery, @@ -198,14 +286,8 @@ public class SqlPagingQueryUtils { sql.append(provider.getWhereClause()); sql.append(" AND "); } - sql.append(provider.getSortKey()); - if (provider.isAscending()) { - sql.append(" > "); - } - else { - sql.append(" < "); - } - sql.append(provider.getSortKeyPlaceHolder()); + + buildSortConditions(provider, sql); } else { sql.append(provider.getWhereClause() == null ? "" : " WHERE " + provider.getWhereClause()); 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 3aaa72b41..41dc617e1 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 @@ -16,6 +16,8 @@ package org.springframework.batch.item.database.support; +import java.util.Map; + import org.springframework.util.StringUtils; /** @@ -73,14 +75,9 @@ public class SqlWindowingPagingQueryProvider extends AbstractSqlPagingQueryProvi sql.append(getWhereClause()); sql.append(" AND "); } - sql.append(getSortKey()); - if (isAscending()) { - sql.append(" > "); - } - else { - sql.append(" < "); - } - sql.append(getSortKeyPlaceHolder()); + + SqlPagingQueryUtils.buildSortConditions(this, sql); + sql.append(getGroupClause() == null ? "" : " GROUP BY " + getGroupClause()); sql.append(getOverSubstituteClauseEnd()); sql.append(") ").append(getSubQueryAlias()).append("WHERE ").append(extractTableAlias()).append( @@ -98,9 +95,12 @@ public class SqlWindowingPagingQueryProvider extends AbstractSqlPagingQueryProvi } StringBuilder sql = new StringBuilder(); - sql.append("SELECT SORT_KEY FROM ( "); - sql.append("SELECT ").append(getSortKey()).append(" AS SORT_KEY, "); - sql.append("ROW_NUMBER() OVER (").append(getOverClause()); + sql.append("SELECT "); + buildSortKeySelect(sql); + sql.append(" FROM ( "); + sql.append("SELECT "); + buildSortKeySelect(sql); + sql.append(", ROW_NUMBER() OVER (").append(getOverClause()); sql.append(") AS ROW_NUMBER"); sql.append(getOverSubstituteClauseStart()); sql.append(" FROM ").append(getFromClause()); @@ -113,8 +113,21 @@ public class SqlWindowingPagingQueryProvider extends AbstractSqlPagingQueryProvi return sql.toString(); } + private void buildSortKeySelect(StringBuilder sql) { + String prefix = ""; + for (Map.Entry sortKey : getSortKeys().entrySet()) { + sql.append(prefix); + prefix = ", "; + sql.append(sortKey.getKey()); + } + } + protected String getOverClause() { - return "ORDER BY " + getSortKeyWithoutAlias() + " " + getAscendingClause(); + StringBuilder sql = new StringBuilder(); + + sql.append(" ORDER BY ").append(SqlPagingQueryUtils.buildSortClause(this)); + + return sql.toString(); } protected String getOverSubstituteClauseStart() { @@ -124,14 +137,4 @@ public class SqlWindowingPagingQueryProvider extends AbstractSqlPagingQueryProvi protected String getOverSubstituteClauseEnd() { return ""; } - - private String getAscendingClause() { - if (isAscending()) { - return "ASC"; - } - else { - return "DESC"; - } - } - } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcPagingItemReaderAsyncTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcPagingItemReaderAsyncTests.java index f39a3f01a..80ea98c32 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcPagingItemReaderAsyncTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcPagingItemReaderAsyncTests.java @@ -7,7 +7,9 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.HashSet; +import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.concurrent.Callable; import java.util.concurrent.CompletionService; @@ -26,12 +28,12 @@ import org.junit.runner.RunWith; import org.springframework.batch.item.ItemReader; import org.springframework.batch.item.database.support.HsqlPagingQueryProvider; import org.springframework.batch.item.sample.Foo; +import org.springframework.batch.support.JdbcTestUtils; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.jdbc.core.simple.ParameterizedRowMapper; import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.simple.ParameterizedRowMapper; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import org.springframework.batch.support.JdbcTestUtils; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "JdbcPagingItemReaderCommonTests-context.xml") @@ -140,7 +142,9 @@ public class JdbcPagingItemReaderAsyncTests { HsqlPagingQueryProvider queryProvider = new HsqlPagingQueryProvider(); queryProvider.setSelectClause("select ID, NAME, VALUE"); queryProvider.setFromClause("from T_FOOS"); - queryProvider.setSortKey("ID"); + Map sortKeys = new LinkedHashMap(); + sortKeys.put("ID", true); + queryProvider.setSortKeys(sortKeys); reader.setQueryProvider(queryProvider); reader.setRowMapper(new ParameterizedRowMapper() { public Foo mapRow(ResultSet rs, int i) throws SQLException { diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcPagingItemReaderClassicParameterTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcPagingItemReaderClassicParameterTests.java index f3d1b228e..fe830f041 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcPagingItemReaderClassicParameterTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcPagingItemReaderClassicParameterTests.java @@ -1,8 +1,25 @@ +/* + * Copyright 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. + * You may obtain a copy of the License at + * + * 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, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.springframework.batch.item.database; import java.sql.ResultSet; import java.sql.SQLException; import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; import org.junit.runner.RunWith; import org.springframework.batch.item.database.support.HsqlPagingQueryProvider; @@ -11,7 +28,12 @@ import org.springframework.jdbc.core.simple.ParameterizedRowMapper; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - +/** + * @author Dave Syer + * @author Thomas Risberg + * @author Michael Minella + * + */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "/org/springframework/batch/item/database/JdbcPagingItemReaderParameterTests-context.xml") public class JdbcPagingItemReaderClassicParameterTests extends AbstractPagingItemReaderParameterTests { @@ -24,7 +46,9 @@ public class JdbcPagingItemReaderClassicParameterTests extends AbstractPagingIte queryProvider.setSelectClause("select ID, NAME, VALUE"); queryProvider.setFromClause("from T_FOOS"); queryProvider.setWhereClause("where VALUE >= ?"); - queryProvider.setSortKey("ID"); + Map sortKeys = new LinkedHashMap(); + sortKeys.put("ID", true); + queryProvider.setSortKeys(sortKeys); reader.setParameterValues(Collections.singletonMap("limit", 3)); reader.setQueryProvider(queryProvider); reader.setRowMapper( diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcPagingItemReaderCommonTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcPagingItemReaderCommonTests.java index 8a8956a66..95e5bdd33 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcPagingItemReaderCommonTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcPagingItemReaderCommonTests.java @@ -1,20 +1,43 @@ +/* + * Copyright 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. + * You may obtain a copy of the License at + * + * 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, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.springframework.batch.item.database; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.LinkedHashMap; +import java.util.Map; + +import javax.sql.DataSource; + import org.junit.runner.RunWith; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import org.springframework.test.context.ContextConfiguration; import org.springframework.batch.item.AbstractItemStreamItemReaderTests; -import org.springframework.batch.item.ItemReader; import org.springframework.batch.item.ExecutionContext; +import org.springframework.batch.item.ItemReader; import org.springframework.batch.item.database.support.HsqlPagingQueryProvider; import org.springframework.batch.item.sample.Foo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.simple.ParameterizedRowMapper; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import javax.sql.DataSource; -import java.sql.ResultSet; -import java.sql.SQLException; - +/** + * @author Dave Syer + * @author Thomas Risberg + * @author Michael Minella + */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration public class JdbcPagingItemReaderCommonTests extends AbstractItemStreamItemReaderTests { @@ -29,7 +52,9 @@ public class JdbcPagingItemReaderCommonTests extends AbstractItemStreamItemReade HsqlPagingQueryProvider queryProvider = new HsqlPagingQueryProvider(); queryProvider.setSelectClause("select ID, NAME, VALUE"); queryProvider.setFromClause("from T_FOOS"); - queryProvider.setSortKey("ID"); + Map sortKeys = new LinkedHashMap(); + sortKeys.put("ID", true); + queryProvider.setSortKeys(sortKeys); reader.setQueryProvider(queryProvider); reader.setRowMapper( new ParameterizedRowMapper() { @@ -57,7 +82,9 @@ public class JdbcPagingItemReaderCommonTests extends AbstractItemStreamItemReade queryProvider.setSelectClause("select ID, NAME, VALUE"); queryProvider.setFromClause("from T_FOOS"); queryProvider.setWhereClause("where ID = -1"); - queryProvider.setSortKey("ID"); + Map sortKeys = new LinkedHashMap(); + sortKeys.put("ID", true); + queryProvider.setSortKeys(sortKeys); reader.setQueryProvider(queryProvider); reader.setPageSize(3); reader.afterPropertiesSet(); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcPagingItemReaderIntegrationTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcPagingItemReaderIntegrationTests.java index 25833264c..dfea7c4e6 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcPagingItemReaderIntegrationTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcPagingItemReaderIntegrationTests.java @@ -1,7 +1,24 @@ +/* + * Copyright 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. + * You may obtain a copy of the License at + * + * 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, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.springframework.batch.item.database; import java.sql.ResultSet; import java.sql.SQLException; +import java.util.LinkedHashMap; +import java.util.Map; import org.springframework.batch.item.ItemReader; import org.springframework.batch.item.database.support.HsqlPagingQueryProvider; @@ -12,6 +29,7 @@ import org.springframework.jdbc.core.simple.ParameterizedRowMapper; * Tests for {@link JpaPagingItemReader}. * * @author Thomas Risberg + * @author Michael Minella */ public class JdbcPagingItemReaderIntegrationTests extends AbstractGenericDataSourceItemReaderIntegrationTests { @@ -22,7 +40,9 @@ public class JdbcPagingItemReaderIntegrationTests extends AbstractGenericDataSou HsqlPagingQueryProvider queryProvider = new HsqlPagingQueryProvider(); queryProvider.setSelectClause("select ID, NAME, VALUE"); queryProvider.setFromClause("from T_FOOS"); - queryProvider.setSortKey("ID"); + Map sortKeys = new LinkedHashMap(); + sortKeys.put("ID", true); + queryProvider.setSortKeys(sortKeys); inputSource.setQueryProvider(queryProvider); inputSource.setRowMapper( new ParameterizedRowMapper() { diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcPagingItemReaderNamedParameterTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcPagingItemReaderNamedParameterTests.java index 23a13166b..8f9907eb5 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcPagingItemReaderNamedParameterTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcPagingItemReaderNamedParameterTests.java @@ -1,8 +1,25 @@ +/* + * Copyright 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. + * You may obtain a copy of the License at + * + * 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, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.springframework.batch.item.database; import java.sql.ResultSet; import java.sql.SQLException; import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; import org.junit.runner.RunWith; import org.springframework.batch.item.database.support.HsqlPagingQueryProvider; @@ -11,6 +28,11 @@ import org.springframework.jdbc.core.simple.ParameterizedRowMapper; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +/** + * @author Dave Syer + * @author Thomas Risberg + * @author Michael Minella + */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "/org/springframework/batch/item/database/JdbcPagingItemReaderParameterTests-context.xml") public class JdbcPagingItemReaderNamedParameterTests extends AbstractPagingItemReaderParameterTests { @@ -23,7 +45,9 @@ public class JdbcPagingItemReaderNamedParameterTests extends AbstractPagingItemR queryProvider.setSelectClause("select ID, NAME, VALUE"); queryProvider.setFromClause("from T_FOOS"); queryProvider.setWhereClause("where VALUE >= :limit"); - queryProvider.setSortKey("ID"); + Map sortKeys = new LinkedHashMap(); + sortKeys.put("ID", true); + queryProvider.setSortKeys(sortKeys); reader.setParameterValues(Collections.singletonMap("limit", 3)); reader.setQueryProvider(queryProvider); reader.setRowMapper( @@ -37,7 +61,7 @@ public class JdbcPagingItemReaderNamedParameterTests extends AbstractPagingItemR } } ); - reader.setPageSize(2); + reader.setPageSize(3); reader.afterPropertiesSet(); reader.setSaveState(true); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcPagingItemReaderOrderIntegrationTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcPagingItemReaderOrderIntegrationTests.java index 4cf4b3ac7..06dc64e43 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcPagingItemReaderOrderIntegrationTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcPagingItemReaderOrderIntegrationTests.java @@ -1,7 +1,24 @@ +/* + * Copyright 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. + * You may obtain a copy of the License at + * + * 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, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.springframework.batch.item.database; import java.sql.ResultSet; import java.sql.SQLException; +import java.util.LinkedHashMap; +import java.util.Map; import org.springframework.batch.item.ItemReader; import org.springframework.batch.item.database.support.HsqlPagingQueryProvider; @@ -12,6 +29,7 @@ import org.springframework.jdbc.core.simple.ParameterizedRowMapper; * Tests for {@link JpaPagingItemReader} with sort key not equal to ID. * * @author Thomas Risberg + * @author Michael Minella */ public class JdbcPagingItemReaderOrderIntegrationTests extends AbstractGenericDataSourceItemReaderIntegrationTests { @@ -22,7 +40,10 @@ public class JdbcPagingItemReaderOrderIntegrationTests extends AbstractGenericDa HsqlPagingQueryProvider queryProvider = new HsqlPagingQueryProvider(); queryProvider.setSelectClause("select ID, NAME, VALUE"); queryProvider.setFromClause("from T_FOOS"); - queryProvider.setSortKey("VALUE"); + Map sortKeys = new LinkedHashMap(); + sortKeys.put("VALUE", true); + sortKeys.put("NAME", false); + queryProvider.setSortKeys(sortKeys); inputSource.setQueryProvider(queryProvider); inputSource.setRowMapper( new ParameterizedRowMapper() { diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/AbstractSqlPagingQueryProviderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/AbstractSqlPagingQueryProviderTests.java index 27c0a62c0..95abd45a3 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/AbstractSqlPagingQueryProviderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/AbstractSqlPagingQueryProviderTests.java @@ -17,6 +17,9 @@ package org.springframework.batch.item.database.support; import static org.junit.Assert.assertTrue; +import java.util.LinkedHashMap; +import java.util.Map; + import org.junit.Before; import org.junit.Test; @@ -38,7 +41,10 @@ public abstract class AbstractSqlPagingQueryProviderTests { pagingQueryProvider.setSelectClause("id, name, age"); pagingQueryProvider.setFromClause("foo"); pagingQueryProvider.setWhereClause("bar = 1"); - pagingQueryProvider.setSortKey("id"); + + Map sortKeys = new LinkedHashMap(); + sortKeys.put("id", true); + pagingQueryProvider.setSortKeys(sortKeys); pageSize = 100; } @@ -51,7 +57,7 @@ public abstract class AbstractSqlPagingQueryProviderTests { @Test public void testQueryContainsSortKeyDesc(){ - pagingQueryProvider.setAscending(false); + pagingQueryProvider.getSortKeys().put("id", false); String s = pagingQueryProvider.generateFirstPageQuery(pageSize).toLowerCase(); assertTrue("Wrong query: "+s, s.contains("id desc")); } @@ -80,4 +86,15 @@ public abstract class AbstractSqlPagingQueryProviderTests { @Test public abstract void testGenerateJumpToItemQueryForFirstPageWithGroupBy(); + @Test + public abstract void testGenerateFirstPageQueryWithMultipleSortKeys(); + + @Test + public abstract void testGenerateRemainingPagesQueryWithMultipleSortKeys(); + + @Test + public abstract void testGenerateJumpToItemQueryWithMultipleSortKeys(); + + @Test + public abstract void testGenerateJumpToItemQueryForFirstPageWithMultipleSortKeys(); } 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 90fad6d75..bd4ebfcec 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 @@ -1,8 +1,27 @@ +/* + * Copyright 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. + * You may obtain a copy of the License at + * + * 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, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.springframework.batch.item.database.support; -import org.junit.Test; import static org.junit.Assert.assertEquals; +import java.util.LinkedHashMap; +import java.util.Map; + +import org.junit.Test; + /** * @author Thomas Risberg * @author Michael Minella @@ -23,21 +42,21 @@ public class Db2PagingQueryProviderTests extends AbstractSqlPagingQueryProviderT @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 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 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) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER = 100"; + 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 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) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER = 1"; + 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); } @@ -55,7 +74,7 @@ public class Db2PagingQueryProviderTests extends AbstractSqlPagingQueryProviderT @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 FETCH FIRST 100 ROWS ONLY"; + 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 s = pagingQueryProvider.generateRemainingPagesQuery(pageSize); assertEquals(sql, s); } @@ -64,7 +83,7 @@ public class Db2PagingQueryProviderTests extends AbstractSqlPagingQueryProviderT @Test public void testGenerateJumpToItemQueryWithGroupBy() { pagingQueryProvider.setGroupClause("dep"); - 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 GROUP BY dep) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER = 100"; + 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"; String s = pagingQueryProvider.generateJumpToItemQuery(145, pageSize); assertEquals(sql, s); } @@ -73,7 +92,55 @@ public class Db2PagingQueryProviderTests extends AbstractSqlPagingQueryProviderT @Test public void testGenerateJumpToItemQueryForFirstPageWithGroupBy() { pagingQueryProvider.setGroupClause("dep"); - 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 GROUP BY dep) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER = 1"; + 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"; + String s = pagingQueryProvider.generateJumpToItemQuery(45, pageSize); + assertEquals(sql, s); + } + + @Override + @Test + public void testGenerateFirstPageQueryWithMultipleSortKeys() { + Map sortKeys = new LinkedHashMap(); + sortKeys.put("name", true); + sortKeys.put("id", false); + pagingQueryProvider.setSortKeys(sortKeys); + String sql = "SELECT id, name, age FROM foo WHERE bar = 1 ORDER BY name ASC, id DESC FETCH FIRST 100 ROWS ONLY"; + String s = pagingQueryProvider.generateFirstPageQuery(pageSize); + assertEquals(sql, s); + } + + @Override + @Test + public void testGenerateRemainingPagesQueryWithMultipleSortKeys() { + Map sortKeys = new LinkedHashMap(); + sortKeys.put("name", true); + sortKeys.put("id", false); + pagingQueryProvider.setSortKeys(sortKeys); + String sql = "SELECT id, name, age FROM foo WHERE bar = 1 AND ((name > ?) OR (name = ? AND id < ?)) ORDER BY name ASC, id DESC FETCH FIRST 100 ROWS ONLY"; + String s = pagingQueryProvider.generateRemainingPagesQuery(pageSize); + assertEquals(sql, s); + } + + @Override + @Test + public void testGenerateJumpToItemQueryWithMultipleSortKeys() { + Map sortKeys = new LinkedHashMap(); + sortKeys.put("name", true); + sortKeys.put("id", false); + pagingQueryProvider.setSortKeys(sortKeys); + String sql = "SELECT name, id FROM ( SELECT name, id, 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"; + String s = pagingQueryProvider.generateJumpToItemQuery(145, pageSize); + assertEquals(sql, s); + } + + @Override + @Test + public void testGenerateJumpToItemQueryForFirstPageWithMultipleSortKeys() { + Map sortKeys = new LinkedHashMap(); + sortKeys.put("name", true); + sortKeys.put("id", false); + pagingQueryProvider.setSortKeys(sortKeys); + String sql = "SELECT name, id FROM ( SELECT name, id, 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 = 1"; String s = pagingQueryProvider.generateJumpToItemQuery(45, pageSize); assertEquals(sql, s); } 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 0654aa1fc..f16d1ac4c 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 @@ -25,6 +25,8 @@ import static org.junit.Assert.fail; import java.sql.Connection; import java.sql.DatabaseMetaData; +import java.util.LinkedHashMap; +import java.util.Map; import javax.sql.DataSource; @@ -85,33 +87,33 @@ 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 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 s = pagingQueryProvider.generateFirstPageQuery(pageSize); - Assert.assertEquals("", sql, s); + Assert.assertEquals(sql, s); } @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 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 s = pagingQueryProvider.generateRemainingPagesQuery(pageSize); - Assert.assertEquals("", sql, s); + Assert.assertEquals(sql, s); } @Test @Override public void testGenerateJumpToItemQuery() { - String sql = "SELECT SORT_KEY FROM ( SELECT id AS SORT_KEY, 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 id FROM ( SELECT id, 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.generateJumpToItemQuery(145, pageSize); - Assert.assertEquals("", sql, s); + Assert.assertEquals(sql, s); } @Test @Override public void testGenerateJumpToItemQueryForFirstPage() { - String sql = "SELECT SORT_KEY FROM ( SELECT id AS SORT_KEY, 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 = 1"; + String sql = "SELECT id FROM ( SELECT id, 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 = 1"; String s = pagingQueryProvider.generateJumpToItemQuery(45, pageSize); - Assert.assertEquals("", sql, s); + Assert.assertEquals(sql, s); } /** @@ -130,7 +132,7 @@ public class DerbyPagingQueryProviderTests extends AbstractSqlPagingQueryProvide @Test @Override public void testQueryContainsSortKeyDesc() { - pagingQueryProvider.setAscending(false); + pagingQueryProvider.getSortKeys().put("id", false); String s = pagingQueryProvider.generateFirstPageQuery(pageSize).toLowerCase(); assertTrue("Wrong query: " + s, s.contains("id desc")); } @@ -139,7 +141,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 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 s = pagingQueryProvider.generateFirstPageQuery(pageSize); assertEquals(sql, s); } @@ -148,7 +150,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 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 s = pagingQueryProvider.generateRemainingPagesQuery(pageSize); assertEquals(sql, s); } @@ -157,7 +159,7 @@ public class DerbyPagingQueryProviderTests extends AbstractSqlPagingQueryProvide @Test public void testGenerateJumpToItemQueryWithGroupBy() { pagingQueryProvider.setGroupClause("dep"); - String sql = "SELECT SORT_KEY FROM ( SELECT id AS SORT_KEY, 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 id FROM ( SELECT id, 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.generateJumpToItemQuery(145, pageSize); assertEquals(sql, s); } @@ -166,7 +168,55 @@ public class DerbyPagingQueryProviderTests extends AbstractSqlPagingQueryProvide @Test public void testGenerateJumpToItemQueryForFirstPageWithGroupBy() { pagingQueryProvider.setGroupClause("dep"); - String sql = "SELECT SORT_KEY FROM ( SELECT id AS SORT_KEY, 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 = 1"; + String sql = "SELECT id FROM ( SELECT id, 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 = 1"; + String s = pagingQueryProvider.generateJumpToItemQuery(45, pageSize); + assertEquals(sql, s); + } + + @Override + @Test + public void testGenerateFirstPageQueryWithMultipleSortKeys() { + Map sortKeys = new LinkedHashMap(); + sortKeys.put("id", true); + sortKeys.put("name", false); + pagingQueryProvider.setSortKeys(sortKeys); + 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, name DESC) AS TMP_ORDERED) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER <= 100"; + String s = pagingQueryProvider.generateFirstPageQuery(pageSize); + assertEquals(sql, s); + } + + @Override + @Test + public void testGenerateRemainingPagesQueryWithMultipleSortKeys() { + Map sortKeys = new LinkedHashMap(); + sortKeys.put("id", true); + sortKeys.put("name", false); + pagingQueryProvider.setSortKeys(sortKeys); + 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 > ?) OR (id = ? AND name < ?)) ORDER BY id ASC, name DESC) AS TMP_ORDERED) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER <= 100"; + String s = pagingQueryProvider.generateRemainingPagesQuery(pageSize); + assertEquals(sql, s); + } + + @Override + @Test + public void testGenerateJumpToItemQueryWithMultipleSortKeys() { + Map sortKeys = new LinkedHashMap(); + sortKeys.put("id", true); + sortKeys.put("name", false); + pagingQueryProvider.setSortKeys(sortKeys); + String sql = "SELECT id, name FROM ( SELECT id, name, ROW_NUMBER() OVER () AS ROW_NUMBER FROM (SELECT id, name, age FROM foo WHERE bar = 1 ORDER BY id ASC, name DESC) AS TMP_ORDERED) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER = 100"; + String s = pagingQueryProvider.generateJumpToItemQuery(145, pageSize); + assertEquals(sql, s); + } + + @Override + @Test + public void testGenerateJumpToItemQueryForFirstPageWithMultipleSortKeys() { + Map sortKeys = new LinkedHashMap(); + sortKeys.put("id", true); + sortKeys.put("name", false); + pagingQueryProvider.setSortKeys(sortKeys); + String sql = "SELECT id, name FROM ( SELECT id, name, ROW_NUMBER() OVER () AS ROW_NUMBER FROM (SELECT id, name, age FROM foo WHERE bar = 1 ORDER BY id ASC, name DESC) AS TMP_ORDERED) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER = 1"; String s = pagingQueryProvider.generateJumpToItemQuery(45, pageSize); assertEquals(sql, s); } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/H2PagingQueryProviderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/H2PagingQueryProviderTests.java index e4df91051..2f3d68a7c 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/H2PagingQueryProviderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/H2PagingQueryProviderTests.java @@ -15,9 +15,13 @@ */ package org.springframework.batch.item.database.support; -import org.junit.Test; import static org.junit.Assert.assertEquals; +import java.util.LinkedHashMap; +import java.util.Map; + +import org.junit.Test; + /** * @author Thomas Risberg * @author Dave Syer @@ -39,21 +43,21 @@ public class H2PagingQueryProviderTests extends AbstractSqlPagingQueryProviderTe @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 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 public void testGenerateJumpToItemQuery() { - String sql = "SELECT LIMIT 99 1 id AS SORT_KEY FROM foo WHERE bar = 1 ORDER BY id ASC"; + String sql = "SELECT LIMIT 99 1 id FROM foo WHERE bar = 1 ORDER BY id ASC"; String s = pagingQueryProvider.generateJumpToItemQuery(145, pageSize); assertEquals(sql, s); } @Test @Override public void testGenerateJumpToItemQueryForFirstPage() { - String sql = "SELECT LIMIT 0 1 id AS SORT_KEY FROM foo WHERE bar = 1 ORDER BY id ASC"; + String sql = "SELECT LIMIT 0 1 id FROM foo WHERE bar = 1 ORDER BY id ASC"; String s = pagingQueryProvider.generateJumpToItemQuery(45, pageSize); assertEquals(sql, s); } @@ -71,7 +75,7 @@ public class H2PagingQueryProviderTests extends AbstractSqlPagingQueryProviderTe @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 id, name, age FROM foo WHERE bar = 1 AND ((id > ?)) GROUP BY dep ORDER BY id ASC"; String s = pagingQueryProvider.generateRemainingPagesQuery(pageSize); assertEquals(sql, s); } @@ -80,7 +84,7 @@ public class H2PagingQueryProviderTests extends AbstractSqlPagingQueryProviderTe @Test public void testGenerateJumpToItemQueryWithGroupBy() { pagingQueryProvider.setGroupClause("dep"); - String sql = "SELECT LIMIT 99 1 id AS SORT_KEY FROM foo WHERE bar = 1 GROUP BY dep ORDER BY id ASC"; + String sql = "SELECT LIMIT 99 1 id FROM foo WHERE bar = 1 GROUP BY dep ORDER BY id ASC"; String s = pagingQueryProvider.generateJumpToItemQuery(145, pageSize); assertEquals(sql, s); } @@ -89,7 +93,55 @@ public class H2PagingQueryProviderTests extends AbstractSqlPagingQueryProviderTe @Test public void testGenerateJumpToItemQueryForFirstPageWithGroupBy() { pagingQueryProvider.setGroupClause("dep"); - String sql = "SELECT LIMIT 0 1 id AS SORT_KEY FROM foo WHERE bar = 1 GROUP BY dep ORDER BY id ASC"; + String sql = "SELECT LIMIT 0 1 id FROM foo WHERE bar = 1 GROUP BY dep ORDER BY id ASC"; + String s = pagingQueryProvider.generateJumpToItemQuery(45, pageSize); + assertEquals(sql, s); + } + + @Override + @Test + public void testGenerateFirstPageQueryWithMultipleSortKeys() { + Map sortKeys = new LinkedHashMap(); + sortKeys.put("name", true); + sortKeys.put("id", false); + pagingQueryProvider.setSortKeys(sortKeys); + String sql = "SELECT TOP 100 id, name, age FROM foo WHERE bar = 1 ORDER BY name ASC, id DESC"; + String s = pagingQueryProvider.generateFirstPageQuery(pageSize); + assertEquals(sql, s); + } + + @Override + @Test + public void testGenerateRemainingPagesQueryWithMultipleSortKeys() { + Map sortKeys = new LinkedHashMap(); + sortKeys.put("name", true); + sortKeys.put("id", false); + pagingQueryProvider.setSortKeys(sortKeys); + String sql = "SELECT TOP 100 id, name, age FROM foo WHERE bar = 1 AND ((name > ?) OR (name = ? AND id < ?)) ORDER BY name ASC, id DESC"; + String s = pagingQueryProvider.generateRemainingPagesQuery(pageSize); + assertEquals(sql, s); + } + + @Override + @Test + public void testGenerateJumpToItemQueryWithMultipleSortKeys() { + Map sortKeys = new LinkedHashMap(); + sortKeys.put("name", true); + sortKeys.put("id", false); + pagingQueryProvider.setSortKeys(sortKeys); + String sql = "SELECT LIMIT 99 1 name, id FROM foo WHERE bar = 1 ORDER BY name ASC, id DESC"; + String s = pagingQueryProvider.generateJumpToItemQuery(145, pageSize); + assertEquals(sql, s); + } + + @Override + @Test + public void testGenerateJumpToItemQueryForFirstPageWithMultipleSortKeys() { + Map sortKeys = new LinkedHashMap(); + sortKeys.put("name", true); + sortKeys.put("id", false); + pagingQueryProvider.setSortKeys(sortKeys); + String sql = "SELECT LIMIT 0 1 name, id FROM foo WHERE bar = 1 ORDER BY name ASC, id DESC"; String s = pagingQueryProvider.generateJumpToItemQuery(45, pageSize); assertEquals(sql, s); } 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 43753acbb..c886a128c 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 @@ -15,10 +15,13 @@ */ package org.springframework.batch.item.database.support; -import org.junit.Test; - import static org.junit.Assert.assertEquals; +import java.util.LinkedHashMap; +import java.util.Map; + +import org.junit.Test; + /** * @author Thomas Risberg * @author Michael Minella @@ -39,21 +42,21 @@ public class HsqlPagingQueryProviderTests extends AbstractSqlPagingQueryProvider @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 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 public void testGenerateJumpToItemQuery() { - String sql = "SELECT LIMIT 99 1 id AS SORT_KEY FROM foo WHERE bar = 1 ORDER BY id ASC"; + String sql = "SELECT LIMIT 99 1 id FROM foo WHERE bar = 1 ORDER BY id ASC"; String s = pagingQueryProvider.generateJumpToItemQuery(145, pageSize); assertEquals(sql, s); } @Test @Override public void testGenerateJumpToItemQueryForFirstPage() { - String sql = "SELECT LIMIT 0 1 id AS SORT_KEY FROM foo WHERE bar = 1 ORDER BY id ASC"; + String sql = "SELECT LIMIT 0 1 id FROM foo WHERE bar = 1 ORDER BY id ASC"; String s = pagingQueryProvider.generateJumpToItemQuery(45, pageSize); assertEquals(sql, s); } @@ -71,7 +74,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 id, name, age FROM foo WHERE bar = 1 AND ((id > ?)) GROUP BY dep ORDER BY id ASC"; String s = pagingQueryProvider.generateRemainingPagesQuery(pageSize); assertEquals(sql, s); } @@ -80,7 +83,7 @@ public class HsqlPagingQueryProviderTests extends AbstractSqlPagingQueryProvider @Test public void testGenerateJumpToItemQueryWithGroupBy() { pagingQueryProvider.setGroupClause("dep"); - String sql = "SELECT LIMIT 99 1 id AS SORT_KEY FROM foo WHERE bar = 1 GROUP BY dep ORDER BY id ASC"; + String sql = "SELECT LIMIT 99 1 id FROM foo WHERE bar = 1 GROUP BY dep ORDER BY id ASC"; String s = pagingQueryProvider.generateJumpToItemQuery(145, pageSize); assertEquals(sql, s); } @@ -89,7 +92,55 @@ public class HsqlPagingQueryProviderTests extends AbstractSqlPagingQueryProvider @Test public void testGenerateJumpToItemQueryForFirstPageWithGroupBy() { pagingQueryProvider.setGroupClause("dep"); - String sql = "SELECT LIMIT 0 1 id AS SORT_KEY FROM foo WHERE bar = 1 GROUP BY dep ORDER BY id ASC"; + String sql = "SELECT LIMIT 0 1 id FROM foo WHERE bar = 1 GROUP BY dep ORDER BY id ASC"; + String s = pagingQueryProvider.generateJumpToItemQuery(45, pageSize); + assertEquals(sql, s); + } + + @Override + @Test + public void testGenerateFirstPageQueryWithMultipleSortKeys() { + Map sortKeys = new LinkedHashMap(); + sortKeys.put("id", true); + sortKeys.put("name", false); + pagingQueryProvider.setSortKeys(sortKeys); + String sql = "SELECT TOP 100 id, name, age FROM foo WHERE bar = 1 ORDER BY id ASC, name DESC"; + String s = pagingQueryProvider.generateFirstPageQuery(pageSize); + assertEquals(sql, s); + } + + @Override + @Test + public void testGenerateRemainingPagesQueryWithMultipleSortKeys() { + Map sortKeys = new LinkedHashMap(); + sortKeys.put("id", true); + sortKeys.put("name", false); + pagingQueryProvider.setSortKeys(sortKeys); + String sql = "SELECT TOP 100 id, name, age FROM foo WHERE bar = 1 AND ((id > ?) OR (id = ? AND name < ?)) ORDER BY id ASC, name DESC"; + String s = pagingQueryProvider.generateRemainingPagesQuery(pageSize); + assertEquals(sql, s); + } + + @Override + @Test + public void testGenerateJumpToItemQueryWithMultipleSortKeys() { + Map sortKeys = new LinkedHashMap(); + sortKeys.put("id", true); + sortKeys.put("name", false); + pagingQueryProvider.setSortKeys(sortKeys); + String sql = "SELECT LIMIT 99 1 id, name FROM foo WHERE bar = 1 ORDER BY id ASC, name DESC"; + String s = pagingQueryProvider.generateJumpToItemQuery(145, pageSize); + assertEquals(sql, s); + } + + @Override + @Test + public void testGenerateJumpToItemQueryForFirstPageWithMultipleSortKeys() { + Map sortKeys = new LinkedHashMap(); + sortKeys.put("id", true); + sortKeys.put("name", false); + pagingQueryProvider.setSortKeys(sortKeys); + String sql = "SELECT LIMIT 0 1 id, name FROM foo WHERE bar = 1 ORDER BY id ASC, name DESC"; String s = pagingQueryProvider.generateJumpToItemQuery(45, 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 8d5dd5fbc..acb390fb7 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 @@ -15,9 +15,13 @@ */ package org.springframework.batch.item.database.support; -import org.junit.Test; import static org.junit.Assert.assertEquals; +import java.util.LinkedHashMap; +import java.util.Map; + +import org.junit.Test; + /** * @author Thomas Risberg * @author Michael Minella @@ -38,21 +42,21 @@ public class MySqlPagingQueryProviderTests extends AbstractSqlPagingQueryProvide @Test @Override public void testGenerateRemainingPagesQuery() { - String sql = "SELECT id, name, age FROM foo WHERE bar = 1 AND id > ? ORDER BY id ASC LIMIT 100"; + String sql = "SELECT id, name, age FROM foo WHERE bar = 1 AND ((id > ?)) ORDER BY id ASC LIMIT 100"; String s = pagingQueryProvider.generateRemainingPagesQuery(pageSize); assertEquals(sql, s); } @Test @Override public void testGenerateJumpToItemQuery() { - String sql = "SELECT id AS SORT_KEY FROM foo WHERE bar = 1 ORDER BY id ASC LIMIT 99, 1"; + String sql = "SELECT id FROM foo WHERE bar = 1 ORDER BY id ASC LIMIT 99, 1"; String s = pagingQueryProvider.generateJumpToItemQuery(145, pageSize); assertEquals(sql, s); } @Test @Override public void testGenerateJumpToItemQueryForFirstPage() { - String sql = "SELECT id AS SORT_KEY FROM foo WHERE bar = 1 ORDER BY id ASC LIMIT 0, 1"; + String sql = "SELECT id FROM foo WHERE bar = 1 ORDER BY id ASC LIMIT 0, 1"; String s = pagingQueryProvider.generateJumpToItemQuery(45, pageSize); assertEquals(sql, s); } @@ -70,7 +74,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 id, name, age FROM foo WHERE bar = 1 AND ((id > ?)) GROUP BY dep ORDER BY id ASC LIMIT 100"; String s = pagingQueryProvider.generateRemainingPagesQuery(pageSize); assertEquals(sql, s); } @@ -79,7 +83,7 @@ public class MySqlPagingQueryProviderTests extends AbstractSqlPagingQueryProvide @Test public void testGenerateJumpToItemQueryWithGroupBy() { pagingQueryProvider.setGroupClause("dep"); - String sql = "SELECT id AS SORT_KEY FROM foo WHERE bar = 1 GROUP BY dep ORDER BY id ASC LIMIT 99, 1"; + String sql = "SELECT id FROM foo WHERE bar = 1 GROUP BY dep ORDER BY id ASC LIMIT 99, 1"; String s = pagingQueryProvider.generateJumpToItemQuery(145, pageSize); assertEquals(sql, s); } @@ -88,7 +92,55 @@ public class MySqlPagingQueryProviderTests extends AbstractSqlPagingQueryProvide @Test public void testGenerateJumpToItemQueryForFirstPageWithGroupBy() { pagingQueryProvider.setGroupClause("dep"); - String sql = "SELECT id AS SORT_KEY FROM foo WHERE bar = 1 GROUP BY dep ORDER BY id ASC LIMIT 0, 1"; + String sql = "SELECT id FROM foo WHERE bar = 1 GROUP BY dep ORDER BY id ASC LIMIT 0, 1"; + String s = pagingQueryProvider.generateJumpToItemQuery(45, pageSize); + assertEquals(sql, s); + } + + @Override + @Test + public void testGenerateFirstPageQueryWithMultipleSortKeys() { + Map sortKeys = new LinkedHashMap(); + sortKeys.put("id", true); + sortKeys.put("name", false); + pagingQueryProvider.setSortKeys(sortKeys); + String sql = "SELECT id, name, age FROM foo WHERE bar = 1 ORDER BY id ASC, name DESC LIMIT 100"; + String s = pagingQueryProvider.generateFirstPageQuery(pageSize); + assertEquals(sql, s); + } + + @Override + @Test + public void testGenerateRemainingPagesQueryWithMultipleSortKeys() { + Map sortKeys = new LinkedHashMap(); + sortKeys.put("id", true); + sortKeys.put("name", false); + pagingQueryProvider.setSortKeys(sortKeys); + String sql = "SELECT id, name, age FROM foo WHERE bar = 1 AND ((id > ?) OR (id = ? AND name < ?)) ORDER BY id ASC, name DESC LIMIT 100"; + String s = pagingQueryProvider.generateRemainingPagesQuery(pageSize); + assertEquals(sql, s); + } + + @Override + @Test + public void testGenerateJumpToItemQueryWithMultipleSortKeys() { + Map sortKeys = new LinkedHashMap(); + sortKeys.put("id", true); + sortKeys.put("name", false); + pagingQueryProvider.setSortKeys(sortKeys); + String sql = "SELECT id, name FROM foo WHERE bar = 1 ORDER BY id ASC, name DESC LIMIT 99, 1"; + String s = pagingQueryProvider.generateJumpToItemQuery(145, pageSize); + assertEquals(sql, s); + } + + @Override + @Test + public void testGenerateJumpToItemQueryForFirstPageWithMultipleSortKeys() { + Map sortKeys = new LinkedHashMap(); + sortKeys.put("id", true); + sortKeys.put("name", false); + pagingQueryProvider.setSortKeys(sortKeys); + String sql = "SELECT id, name FROM foo WHERE bar = 1 ORDER BY id ASC, name DESC LIMIT 0, 1"; String s = pagingQueryProvider.generateJumpToItemQuery(45, 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 d8a410079..9ae11001f 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 @@ -1,6 +1,25 @@ +/* + * Copyright 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. + * You may obtain a copy of the License at + * + * 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, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.springframework.batch.item.database.support; import static org.junit.Assert.assertEquals; + +import java.util.LinkedHashMap; +import java.util.Map; + import org.junit.Test; /** @@ -27,21 +46,21 @@ 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 AND ((id > ?)) ORDER BY id ASC) WHERE ROWNUM <= 100"; String s = pagingQueryProvider.generateRemainingPagesQuery(pageSize); assertEquals(sql, s); } @Test @Override public void testGenerateJumpToItemQuery() { - String sql = "SELECT SORT_KEY FROM (SELECT SORT_KEY, ROWNUM as TMP_ROW_NUM FROM (SELECT id AS SORT_KEY FROM foo WHERE bar = 1 ORDER BY id ASC)) WHERE TMP_ROW_NUM = 100"; + String sql = "SELECT id FROM (SELECT id, ROWNUM as TMP_ROW_NUM FROM (SELECT id FROM foo WHERE bar = 1 ORDER BY id ASC)) WHERE TMP_ROW_NUM = 100"; String s = pagingQueryProvider.generateJumpToItemQuery(145, pageSize); assertEquals(sql, s); } @Test @Override public void testGenerateJumpToItemQueryForFirstPage() { - String sql = "SELECT SORT_KEY FROM (SELECT SORT_KEY, ROWNUM as TMP_ROW_NUM FROM (SELECT id AS SORT_KEY FROM foo WHERE bar = 1 ORDER BY id ASC)) WHERE TMP_ROW_NUM = 1"; + String sql = "SELECT id FROM (SELECT id, ROWNUM as TMP_ROW_NUM FROM (SELECT id FROM foo WHERE bar = 1 ORDER BY id ASC)) WHERE TMP_ROW_NUM = 1"; String s = pagingQueryProvider.generateJumpToItemQuery(45, pageSize); assertEquals(sql, s); } @@ -59,7 +78,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 AND ((id > ?)) GROUP BY dep ORDER BY id ASC) WHERE ROWNUM <= 100"; String s = pagingQueryProvider.generateRemainingPagesQuery(pageSize); assertEquals(sql, s); } @@ -68,7 +87,7 @@ public class OraclePagingQueryProviderTests extends AbstractSqlPagingQueryProvid @Test public void testGenerateJumpToItemQueryWithGroupBy() { pagingQueryProvider.setGroupClause("dep"); - String sql = "SELECT SORT_KEY FROM (SELECT SORT_KEY, ROWNUM as TMP_ROW_NUM FROM (SELECT id AS SORT_KEY FROM foo WHERE bar = 1 GROUP BY dep ORDER BY id ASC)) WHERE TMP_ROW_NUM = 100"; + String sql = "SELECT id FROM (SELECT id, ROWNUM as TMP_ROW_NUM FROM (SELECT id FROM foo WHERE bar = 1 GROUP BY dep ORDER BY id ASC)) WHERE TMP_ROW_NUM = 100"; String s = pagingQueryProvider.generateJumpToItemQuery(145, pageSize); assertEquals(sql, s); } @@ -77,7 +96,59 @@ public class OraclePagingQueryProviderTests extends AbstractSqlPagingQueryProvid @Test public void testGenerateJumpToItemQueryForFirstPageWithGroupBy() { pagingQueryProvider.setGroupClause("dep"); - String sql = "SELECT SORT_KEY FROM (SELECT SORT_KEY, ROWNUM as TMP_ROW_NUM FROM (SELECT id AS SORT_KEY FROM foo WHERE bar = 1 GROUP BY dep ORDER BY id ASC)) WHERE TMP_ROW_NUM = 1"; + String sql = "SELECT id FROM (SELECT id, ROWNUM as TMP_ROW_NUM FROM (SELECT id FROM foo WHERE bar = 1 GROUP BY dep ORDER BY id ASC)) WHERE TMP_ROW_NUM = 1"; + String s = pagingQueryProvider.generateJumpToItemQuery(45, pageSize); + assertEquals(sql, s); + } + + @Override + @Test + public void testGenerateFirstPageQueryWithMultipleSortKeys() { + Map sortKeys = new LinkedHashMap(); + sortKeys.put("id", true); + sortKeys.put("name", false); + pagingQueryProvider.setSortKeys(sortKeys); + String sql = "SELECT * FROM (SELECT id, name, age, ROWNUM as TMP_ROW_NUM FROM foo WHERE bar = 1 ORDER BY id ASC, name DESC) WHERE ROWNUM <= 100"; + String s = pagingQueryProvider.generateFirstPageQuery(pageSize); + assertEquals(sql, s); + pagingQueryProvider.setWhereClause(""); + String sql2 = "SELECT * FROM (SELECT id, name, age, ROWNUM as TMP_ROW_NUM FROM foo ORDER BY id ASC, name DESC) WHERE ROWNUM <= 100"; + String s2 = pagingQueryProvider.generateFirstPageQuery(pageSize); + assertEquals(sql2, s2); + } + + @Override + @Test + public void testGenerateRemainingPagesQueryWithMultipleSortKeys() { + Map sortKeys = new LinkedHashMap(); + sortKeys.put("id", true); + sortKeys.put("name", false); + pagingQueryProvider.setSortKeys(sortKeys); + String sql = "SELECT * FROM (SELECT id, name, age, ROWNUM as TMP_ROW_NUM FROM foo WHERE bar = 1 AND ((id > ?) OR (id = ? AND name < ?)) ORDER BY id ASC, name DESC) WHERE ROWNUM <= 100"; + String s = pagingQueryProvider.generateRemainingPagesQuery(pageSize); + assertEquals(sql, s); + } + + @Override + @Test + public void testGenerateJumpToItemQueryWithMultipleSortKeys() { + Map sortKeys = new LinkedHashMap(); + sortKeys.put("id", true); + sortKeys.put("name", false); + pagingQueryProvider.setSortKeys(sortKeys); + String sql = "SELECT id, name FROM (SELECT id, name, ROWNUM as TMP_ROW_NUM FROM (SELECT id, name FROM foo WHERE bar = 1 ORDER BY id ASC, name DESC)) WHERE TMP_ROW_NUM = 100"; + String s = pagingQueryProvider.generateJumpToItemQuery(145, pageSize); + assertEquals(sql, s); + } + + @Override + @Test + public void testGenerateJumpToItemQueryForFirstPageWithMultipleSortKeys() { + Map sortKeys = new LinkedHashMap(); + sortKeys.put("id", true); + sortKeys.put("name", false); + pagingQueryProvider.setSortKeys(sortKeys); + String sql = "SELECT id, name FROM (SELECT id, name, ROWNUM as TMP_ROW_NUM FROM (SELECT id, name FROM foo WHERE bar = 1 ORDER BY id ASC, name DESC)) WHERE TMP_ROW_NUM = 1"; String s = pagingQueryProvider.generateJumpToItemQuery(45, pageSize); assertEquals(sql, s); } 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 53d841807..cc0ec5c64 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 @@ -1,8 +1,27 @@ +/* + * Copyright 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. + * You may obtain a copy of the License at + * + * 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, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.springframework.batch.item.database.support; -import org.junit.Test; import static org.junit.Assert.assertEquals; +import java.util.LinkedHashMap; +import java.util.Map; + +import org.junit.Test; + /** * @author Thomas Risberg * @author Michael Minella @@ -23,21 +42,21 @@ public class PostgresPagingQueryProviderTests extends AbstractSqlPagingQueryProv @Test @Override public void testGenerateRemainingPagesQuery() { - String sql = "SELECT id, name, age FROM foo WHERE bar = 1 AND id > ? ORDER BY id ASC LIMIT 100"; + String sql = "SELECT id, name, age FROM foo WHERE bar = 1 AND ((id > ?)) ORDER BY id ASC LIMIT 100"; String s = pagingQueryProvider.generateRemainingPagesQuery(pageSize); assertEquals(sql, s); } @Test @Override public void testGenerateJumpToItemQuery() { - String sql = "SELECT id AS SORT_KEY FROM foo WHERE bar = 1 ORDER BY id ASC LIMIT 1 OFFSET 99"; + String sql = "SELECT id FROM foo WHERE bar = 1 ORDER BY id ASC LIMIT 1 OFFSET 99"; String s = pagingQueryProvider.generateJumpToItemQuery(145, pageSize); assertEquals("Wrong SQL for jump to", sql, s); } @Test @Override public void testGenerateJumpToItemQueryForFirstPage() { - String sql = "SELECT id AS SORT_KEY FROM foo WHERE bar = 1 ORDER BY id ASC LIMIT 1 OFFSET 0"; + String sql = "SELECT id FROM foo WHERE bar = 1 ORDER BY id ASC LIMIT 1 OFFSET 0"; String s = pagingQueryProvider.generateJumpToItemQuery(45, pageSize); assertEquals("Wrong SQL for first page", sql, s); } @@ -55,7 +74,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 id, name, age FROM foo WHERE bar = 1 AND ((id > ?)) GROUP BY id, dep ORDER BY id ASC LIMIT 100"; String s = pagingQueryProvider.generateRemainingPagesQuery(pageSize); assertEquals(sql, s); } @@ -64,7 +83,7 @@ public class PostgresPagingQueryProviderTests extends AbstractSqlPagingQueryProv @Test public void testGenerateJumpToItemQueryWithGroupBy() { pagingQueryProvider.setGroupClause("id, dep"); - String sql = "SELECT id AS SORT_KEY FROM foo WHERE bar = 1 GROUP BY id, dep ORDER BY id ASC LIMIT 1 OFFSET 99"; + String sql = "SELECT id FROM foo WHERE bar = 1 GROUP BY id, dep ORDER BY id ASC LIMIT 1 OFFSET 99"; String s = pagingQueryProvider.generateJumpToItemQuery(145, pageSize); assertEquals(sql, s); } @@ -73,8 +92,56 @@ public class PostgresPagingQueryProviderTests extends AbstractSqlPagingQueryProv @Test public void testGenerateJumpToItemQueryForFirstPageWithGroupBy() { pagingQueryProvider.setGroupClause("id, dep"); - String sql = "SELECT id AS SORT_KEY FROM foo WHERE bar = 1 GROUP BY id, dep ORDER BY id ASC LIMIT 1 OFFSET 0"; + String sql = "SELECT id FROM foo WHERE bar = 1 GROUP BY id, dep ORDER BY id ASC LIMIT 1 OFFSET 0"; String s = pagingQueryProvider.generateJumpToItemQuery(45, pageSize); assertEquals(sql, s); } + + @Override + @Test + public void testGenerateFirstPageQueryWithMultipleSortKeys() { + Map sortKeys = new LinkedHashMap(); + sortKeys.put("id", true); + sortKeys.put("name", false); + pagingQueryProvider.setSortKeys(sortKeys); + String sql = "SELECT id, name, age FROM foo WHERE bar = 1 ORDER BY id ASC, name DESC LIMIT 100"; + String s = pagingQueryProvider.generateFirstPageQuery(pageSize); + assertEquals(sql, s); + } + + @Override + @Test + public void testGenerateRemainingPagesQueryWithMultipleSortKeys() { + Map sortKeys = new LinkedHashMap(); + sortKeys.put("id", true); + sortKeys.put("name", false); + pagingQueryProvider.setSortKeys(sortKeys); + String sql = "SELECT id, name, age FROM foo WHERE bar = 1 AND ((id > ?) OR (id = ? AND name < ?)) ORDER BY id ASC, name DESC LIMIT 100"; + String s = pagingQueryProvider.generateRemainingPagesQuery(pageSize); + assertEquals(sql, s); + } + + @Override + @Test + public void testGenerateJumpToItemQueryWithMultipleSortKeys() { + Map sortKeys = new LinkedHashMap(); + sortKeys.put("id", true); + sortKeys.put("name", false); + pagingQueryProvider.setSortKeys(sortKeys); + String sql = "SELECT id, name FROM foo WHERE bar = 1 ORDER BY id ASC, name DESC LIMIT 1 OFFSET 99"; + String s = pagingQueryProvider.generateJumpToItemQuery(145, pageSize); + assertEquals("Wrong SQL for jump to", sql, s); + } + + @Override + @Test + public void testGenerateJumpToItemQueryForFirstPageWithMultipleSortKeys() { + Map sortKeys = new LinkedHashMap(); + sortKeys.put("id", true); + sortKeys.put("name", false); + pagingQueryProvider.setSortKeys(sortKeys); + String sql = "SELECT id, name FROM foo WHERE bar = 1 ORDER BY id ASC, name DESC LIMIT 1 OFFSET 0"; + String s = pagingQueryProvider.generateJumpToItemQuery(45, pageSize); + assertEquals("Wrong SQL for first page", sql, s); + } } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/SqlPagingQueryProviderFactoryBeanTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/SqlPagingQueryProviderFactoryBeanTests.java index 7388119b5..3de77d630 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/SqlPagingQueryProviderFactoryBeanTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/SqlPagingQueryProviderFactoryBeanTests.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. @@ -19,6 +19,9 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; +import java.util.LinkedHashMap; +import java.util.Map; + import javax.sql.DataSource; import org.easymock.EasyMock; @@ -30,6 +33,7 @@ import org.springframework.jdbc.support.MetaDataAccessException; /** * @author Dave Syer + * @author Michael Minella */ public class SqlPagingQueryProviderFactoryBeanTests { @@ -39,7 +43,9 @@ public class SqlPagingQueryProviderFactoryBeanTests { factory.setSelectClause("id, name, age"); factory.setFromClause("foo"); factory.setWhereClause("bar = 1"); - factory.setSortKey("id"); + Map sortKeys = new LinkedHashMap(); + sortKeys.put("id", true); + factory.setSortKeys(sortKeys); DataSource dataSource = DatabaseTypeTestUtils.getMockDataSource(DatabaseType.HSQL.getProductName(), "100.0.0"); factory.setDataSource(dataSource); EasyMock.replay(dataSource); @@ -70,7 +76,7 @@ public class SqlPagingQueryProviderFactoryBeanTests { @Test(expected=IllegalArgumentException.class) public void testNoSortKey() throws Exception { - factory.setSortKey(null); + factory.setSortKeys(null); PagingQueryProvider provider = (PagingQueryProvider) factory.getObject(); assertNotNull(provider); } 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 066f8a26d..12cc7dcb5 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 @@ -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. @@ -19,65 +19,78 @@ package org.springframework.batch.item.database.support; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +import java.util.LinkedHashMap; +import java.util.Map; + +import org.junit.Before; import org.junit.Test; import org.springframework.util.StringUtils; /** * @author Thomas Risberg * @author Dave Syer + * @author Michael Minella * @since 2.0 */ public class SqlPagingQueryUtilsTests { + + private Map sortKeys; + + @Before + public void setUp() { + sortKeys = new LinkedHashMap(); + sortKeys.put("ID", true); + } @Test public void testGenerateLimitSqlQuery() { - AbstractSqlPagingQueryProvider qp = new TestSqlPagingQueryProvider("FOO", "BAR", "ID"); + AbstractSqlPagingQueryProvider qp = new TestSqlPagingQueryProvider("FOO", "BAR", sortKeys); assertEquals("SELECT FOO FROM BAR ORDER BY ID ASC LIMIT 100", SqlPagingQueryUtils.generateLimitSqlQuery(qp, false, "LIMIT 100")); - assertEquals("SELECT FOO FROM BAR WHERE ID > ? ORDER BY ID ASC LIMIT 100", SqlPagingQueryUtils + assertEquals("SELECT FOO FROM BAR WHERE ((ID > ?)) ORDER BY ID ASC LIMIT 100", SqlPagingQueryUtils .generateLimitSqlQuery(qp, true, "LIMIT 100")); qp.setWhereClause("BAZ IS NOT NULL"); assertEquals("SELECT FOO FROM BAR WHERE BAZ IS NOT NULL ORDER BY ID ASC LIMIT 100", SqlPagingQueryUtils .generateLimitSqlQuery(qp, false, "LIMIT 100")); - assertEquals("SELECT FOO FROM BAR WHERE BAZ IS NOT NULL AND ID > ? ORDER BY ID ASC LIMIT 100", + assertEquals("SELECT FOO FROM BAR WHERE BAZ IS NOT NULL AND ((ID > ?)) ORDER BY ID ASC LIMIT 100", SqlPagingQueryUtils.generateLimitSqlQuery(qp, true, "LIMIT 100")); } @Test public void testGenerateTopSqlQuery() { - AbstractSqlPagingQueryProvider qp = new TestSqlPagingQueryProvider("FOO", "BAR", "ID"); + AbstractSqlPagingQueryProvider qp = new TestSqlPagingQueryProvider("FOO", "BAR", sortKeys); assertEquals("SELECT TOP 100 FOO FROM BAR ORDER BY ID ASC", SqlPagingQueryUtils.generateTopSqlQuery(qp, false, "TOP 100")); - assertEquals("SELECT TOP 100 FOO FROM BAR WHERE ID > ? ORDER BY ID ASC", SqlPagingQueryUtils + assertEquals("SELECT TOP 100 FOO FROM BAR WHERE ((ID > ?)) ORDER BY ID ASC", SqlPagingQueryUtils .generateTopSqlQuery(qp, true, "TOP 100")); qp.setWhereClause("BAZ IS NOT NULL"); assertEquals("SELECT TOP 100 FOO FROM BAR WHERE BAZ IS NOT NULL ORDER BY ID ASC", SqlPagingQueryUtils .generateTopSqlQuery(qp, false, "TOP 100")); - assertEquals("SELECT TOP 100 FOO FROM BAR WHERE BAZ IS NOT NULL AND ID > ? ORDER BY ID ASC", + assertEquals("SELECT TOP 100 FOO FROM BAR WHERE BAZ IS NOT NULL AND ((ID > ?)) ORDER BY ID ASC", SqlPagingQueryUtils.generateTopSqlQuery(qp, true, "TOP 100")); } @Test public void testGenerateRowNumSqlQuery() { - AbstractSqlPagingQueryProvider qp = new TestSqlPagingQueryProvider("FOO", "BAR", "ID"); + AbstractSqlPagingQueryProvider qp = new TestSqlPagingQueryProvider("FOO", "BAR", sortKeys); assertEquals( "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 WHERE ((ID > ?)) ORDER BY ID ASC) WHERE ROWNUMBER <= 100", 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 AND ((ID > ?)) ORDER BY ID ASC) WHERE ROWNUMBER <= 100", SqlPagingQueryUtils.generateRowNumSqlQuery(qp, true, "ROWNUMBER <= 100")); } @Test public void testGenerateRowNumSqlQueryWithNesting() { - AbstractSqlPagingQueryProvider qp = new TestSqlPagingQueryProvider("FOO", "BAR", "ID"); + AbstractSqlPagingQueryProvider qp = new TestSqlPagingQueryProvider("FOO", "BAR", sortKeys); assertEquals( "SELECT FOO FROM (SELECT FOO, ROWNUM as TMP_ROW_NUM FROM (SELECT FOO FROM BAR ORDER BY ID ASC)) WHERE ROWNUMBER <= 100", SqlPagingQueryUtils.generateRowNumSqlQueryWithNesting(qp, "FOO", false, "ROWNUMBER <= 100")); @@ -85,62 +98,62 @@ public class SqlPagingQueryUtilsTests { @Test public void testGenerateTopSqlQueryDescending() { - AbstractSqlPagingQueryProvider qp = new TestSqlPagingQueryProvider("FOO", "BAR", "ID"); - qp.setAscending(false); + sortKeys.put("ID", false); + AbstractSqlPagingQueryProvider qp = new TestSqlPagingQueryProvider("FOO", "BAR", sortKeys); assertEquals("SELECT TOP 100 FOO FROM BAR ORDER BY ID DESC", SqlPagingQueryUtils.generateTopSqlQuery(qp, false, "TOP 100")); - assertEquals("SELECT TOP 100 FOO FROM BAR WHERE ID < ? ORDER BY ID DESC", SqlPagingQueryUtils + assertEquals("SELECT TOP 100 FOO FROM BAR WHERE ((ID < ?)) ORDER BY ID DESC", SqlPagingQueryUtils .generateTopSqlQuery(qp, true, "TOP 100")); qp.setWhereClause("BAZ IS NOT NULL"); assertEquals("SELECT TOP 100 FOO FROM BAR WHERE BAZ IS NOT NULL ORDER BY ID DESC", SqlPagingQueryUtils .generateTopSqlQuery(qp, false, "TOP 100")); - assertEquals("SELECT TOP 100 FOO FROM BAR WHERE BAZ IS NOT NULL AND ID < ? ORDER BY ID DESC", + assertEquals("SELECT TOP 100 FOO FROM BAR WHERE BAZ IS NOT NULL AND ((ID < ?)) ORDER BY ID DESC", SqlPagingQueryUtils.generateTopSqlQuery(qp, true, "TOP 100")); } @Test public void testGenerateRowNumSqlQueryDescending() { - AbstractSqlPagingQueryProvider qp = new TestSqlPagingQueryProvider("FOO", "BAR", "ID"); - qp.setAscending(false); + sortKeys.put("ID", false); + AbstractSqlPagingQueryProvider qp = new TestSqlPagingQueryProvider("FOO", "BAR", sortKeys); assertEquals( "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 WHERE ((ID < ?)) ORDER BY ID DESC) WHERE ROWNUMBER <= 100", 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 AND ((ID < ?)) ORDER BY ID DESC) WHERE ROWNUMBER <= 100", SqlPagingQueryUtils.generateRowNumSqlQuery(qp, true, "ROWNUMBER <= 100")); } @Test public void testGenerateLimitJumpToQuery() { - AbstractSqlPagingQueryProvider qp = new TestSqlPagingQueryProvider("FOO", "BAR", "ID"); - assertEquals("SELECT ID AS SORT_KEY FROM BAR ORDER BY ID ASC LIMIT 100, 1", SqlPagingQueryUtils + AbstractSqlPagingQueryProvider qp = new TestSqlPagingQueryProvider("FOO", "BAR", sortKeys); + assertEquals("SELECT ID FROM BAR ORDER BY ID ASC LIMIT 100, 1", SqlPagingQueryUtils .generateLimitJumpToQuery(qp, "LIMIT 100, 1")); qp.setWhereClause("BAZ IS NOT NULL"); - assertEquals("SELECT ID AS SORT_KEY FROM BAR WHERE BAZ IS NOT NULL ORDER BY ID ASC LIMIT 100, 1", + assertEquals("SELECT ID FROM BAR WHERE BAZ IS NOT NULL ORDER BY ID ASC LIMIT 100, 1", SqlPagingQueryUtils.generateLimitJumpToQuery(qp, "LIMIT 100, 1")); } @Test public void testGenerateTopJumpToQuery() { - AbstractSqlPagingQueryProvider qp = new TestSqlPagingQueryProvider("FOO", "BAR", "ID"); - assertEquals("SELECT TOP 100, 1 ID AS SORT_KEY FROM BAR ORDER BY ID ASC", SqlPagingQueryUtils + AbstractSqlPagingQueryProvider qp = new TestSqlPagingQueryProvider("FOO", "BAR", sortKeys); + assertEquals("SELECT TOP 100, 1 ID FROM BAR ORDER BY ID ASC", SqlPagingQueryUtils .generateTopJumpToQuery(qp, "TOP 100, 1")); qp.setWhereClause("BAZ IS NOT NULL"); - assertEquals("SELECT TOP 100, 1 ID AS SORT_KEY FROM BAR WHERE BAZ IS NOT NULL ORDER BY ID ASC", + assertEquals("SELECT TOP 100, 1 ID FROM BAR WHERE BAZ IS NOT NULL ORDER BY ID ASC", SqlPagingQueryUtils.generateTopJumpToQuery(qp, "TOP 100, 1")); } @Test public void testGenerateTopJumpQueryDescending() { - AbstractSqlPagingQueryProvider qp = new TestSqlPagingQueryProvider("FOO", "BAR", "ID"); - qp.setAscending(false); + sortKeys.put("ID", false); + AbstractSqlPagingQueryProvider qp = new TestSqlPagingQueryProvider("FOO", "BAR", sortKeys); String query = SqlPagingQueryUtils.generateTopJumpToQuery(qp, "TOP 100, 1"); assertTrue("Wrong query: " + query, query.contains("ID DESC")); assertEquals("Wrong query: " + query, 0, StringUtils.countOccurrencesOf(query, "ASC")); @@ -151,8 +164,8 @@ public class SqlPagingQueryUtilsTests { @Test public void testGenerateLimitJumpQueryDescending() { - AbstractSqlPagingQueryProvider qp = new TestSqlPagingQueryProvider("FOO", "BAR", "ID"); - qp.setAscending(false); + sortKeys.put("ID", false); + AbstractSqlPagingQueryProvider qp = new TestSqlPagingQueryProvider("FOO", "BAR", sortKeys); String query = SqlPagingQueryUtils.generateLimitJumpToQuery(qp, "LIMIT 100, 1"); assertTrue("Wrong query: " + query, query.contains("ID DESC")); assertEquals("Wrong query: " + query, 0, StringUtils.countOccurrencesOf(query, "ASC")); @@ -163,10 +176,10 @@ public class SqlPagingQueryUtilsTests { private static class TestSqlPagingQueryProvider extends AbstractSqlPagingQueryProvider { - public TestSqlPagingQueryProvider(String select, String from, String sortKey) { + public TestSqlPagingQueryProvider(String select, String from, Map sortKeys) { setSelectClause(select); setFromClause(from); - setSortKey(sortKey); + setSortKeys(sortKeys); } public String generateFirstPageQuery(int pageSize) { 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 b0b7f7007..b3a3d4fc1 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 @@ -1,8 +1,27 @@ +/* + * Copyright 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. + * You may obtain a copy of the License at + * + * 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, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.springframework.batch.item.database.support; -import org.junit.Test; import static org.junit.Assert.assertEquals; +import java.util.LinkedHashMap; +import java.util.Map; + +import org.junit.Test; + /** * @author Thomas Risberg * @author Michael Minella @@ -23,21 +42,21 @@ public class SqlServerPagingQueryProviderTests extends AbstractSqlPagingQueryPro @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 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 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) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER = 100"; + 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 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) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER = 1"; + 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); } @@ -55,7 +74,7 @@ public class SqlServerPagingQueryProviderTests extends AbstractSqlPagingQueryPro @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 id, name, age FROM foo WHERE bar = 1 AND ((id > ?)) GROUP BY dep ORDER BY id ASC"; String s = pagingQueryProvider.generateRemainingPagesQuery(pageSize); assertEquals(sql, s); } @@ -64,7 +83,7 @@ public class SqlServerPagingQueryProviderTests extends AbstractSqlPagingQueryPro @Test public void testGenerateJumpToItemQueryWithGroupBy() { pagingQueryProvider.setGroupClause("dep"); - 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 GROUP BY dep) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER = 100"; + 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"; String s = pagingQueryProvider.generateJumpToItemQuery(145, pageSize); assertEquals(sql, s); } @@ -73,7 +92,55 @@ public class SqlServerPagingQueryProviderTests extends AbstractSqlPagingQueryPro @Test public void testGenerateJumpToItemQueryForFirstPageWithGroupBy() { pagingQueryProvider.setGroupClause("dep"); - 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 GROUP BY dep) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER = 1"; + 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"; + String s = pagingQueryProvider.generateJumpToItemQuery(45, pageSize); + assertEquals(sql, s); + } + + @Override + @Test + public void testGenerateFirstPageQueryWithMultipleSortKeys() { + Map sortKeys = new LinkedHashMap(); + sortKeys.put("id", true); + sortKeys.put("name", false); + pagingQueryProvider.setSortKeys(sortKeys); + String sql = "SELECT TOP 100 id, name, age FROM foo WHERE bar = 1 ORDER BY id ASC, name DESC"; + String s = pagingQueryProvider.generateFirstPageQuery(pageSize); + assertEquals(sql, s); + } + + @Override + @Test + public void testGenerateRemainingPagesQueryWithMultipleSortKeys() { + Map sortKeys = new LinkedHashMap(); + sortKeys.put("id", true); + sortKeys.put("name", false); + pagingQueryProvider.setSortKeys(sortKeys); + String sql = "SELECT TOP 100 id, name, age FROM foo WHERE bar = 1 AND ((id > ?) OR (id = ? AND name < ?)) ORDER BY id ASC, name DESC"; + String s = pagingQueryProvider.generateRemainingPagesQuery(pageSize); + assertEquals(sql, s); + } + + @Override + @Test + public void testGenerateJumpToItemQueryWithMultipleSortKeys() { + Map sortKeys = new LinkedHashMap(); + sortKeys.put("id", true); + sortKeys.put("name", false); + pagingQueryProvider.setSortKeys(sortKeys); + String sql = "SELECT id, name FROM ( SELECT id, name, ROW_NUMBER() OVER ( ORDER BY id ASC, name DESC) 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); + } + + @Override + @Test + public void testGenerateJumpToItemQueryForFirstPageWithMultipleSortKeys() { + Map sortKeys = new LinkedHashMap(); + sortKeys.put("id", true); + sortKeys.put("name", false); + pagingQueryProvider.setSortKeys(sortKeys); + String sql = "SELECT id, name FROM ( SELECT id, name, ROW_NUMBER() OVER ( ORDER BY id ASC, name DESC) 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); } 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 7f2605256..dfab376d0 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 @@ -17,6 +17,9 @@ package org.springframework.batch.item.database.support; import static org.junit.Assert.assertEquals; +import java.util.LinkedHashMap; +import java.util.Map; + import org.junit.Assert; import org.junit.Test; @@ -32,28 +35,28 @@ public class SqlWindowingPagingQueryProviderTests extends AbstractSqlPagingQuery @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 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 s = pagingQueryProvider.generateFirstPageQuery(pageSize); assertEquals("", sql, s); } @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 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 s = pagingQueryProvider.generateRemainingPagesQuery(pageSize); assertEquals("", sql, s); } @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) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER = 100"; + 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 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) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER = 1"; + 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); } @@ -62,7 +65,7 @@ public class SqlWindowingPagingQueryProviderTests extends AbstractSqlPagingQuery @Test 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 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 s = pagingQueryProvider.generateFirstPageQuery(pageSize); assertEquals(sql, s); } @@ -71,7 +74,7 @@ public class SqlWindowingPagingQueryProviderTests extends AbstractSqlPagingQuery @Test 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 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 s = pagingQueryProvider.generateRemainingPagesQuery(pageSize); assertEquals(sql, s); } @@ -80,7 +83,7 @@ public class SqlWindowingPagingQueryProviderTests extends AbstractSqlPagingQuery @Test public void testGenerateJumpToItemQueryWithGroupBy() { pagingQueryProvider.setGroupClause("dep"); - 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 GROUP BY dep) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER = 100"; + 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"; String s = pagingQueryProvider.generateJumpToItemQuery(145, pageSize); assertEquals(sql, s); } @@ -89,8 +92,56 @@ public class SqlWindowingPagingQueryProviderTests extends AbstractSqlPagingQuery @Test public void testGenerateJumpToItemQueryForFirstPageWithGroupBy() { pagingQueryProvider.setGroupClause("dep"); - 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 GROUP BY dep) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER = 1"; + 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"; String s = pagingQueryProvider.generateJumpToItemQuery(45, pageSize); assertEquals(sql, s); } + + @Override + @Test + public void testGenerateFirstPageQueryWithMultipleSortKeys() { + Map sortKeys = new LinkedHashMap(); + sortKeys.put("id", true); + sortKeys.put("name", false); + pagingQueryProvider.setSortKeys(sortKeys); + String sql = "SELECT * FROM ( SELECT id, name, age, ROW_NUMBER() OVER ( ORDER BY id ASC, name DESC) 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); + } + + @Override + @Test + public void testGenerateRemainingPagesQueryWithMultipleSortKeys() { + Map sortKeys = new LinkedHashMap(); + sortKeys.put("id", true); + sortKeys.put("name", false); + pagingQueryProvider.setSortKeys(sortKeys); + String sql = "SELECT * FROM ( SELECT id, name, age, ROW_NUMBER() OVER ( ORDER BY id ASC, name DESC) AS ROW_NUMBER FROM foo WHERE bar = 1 AND ((id > ?) OR (id = ? AND name < ?))) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER <= 100"; + String s = pagingQueryProvider.generateRemainingPagesQuery(pageSize); + assertEquals("", sql, s); + } + + @Override + @Test + public void testGenerateJumpToItemQueryWithMultipleSortKeys() { + Map sortKeys = new LinkedHashMap(); + sortKeys.put("id", true); + sortKeys.put("name", false); + pagingQueryProvider.setSortKeys(sortKeys); + String sql = "SELECT id, name FROM ( SELECT id, name, ROW_NUMBER() OVER ( ORDER BY id ASC, name DESC) 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); + } + + @Override + @Test + public void testGenerateJumpToItemQueryForFirstPageWithMultipleSortKeys() { + Map sortKeys = new LinkedHashMap(); + sortKeys.put("id", true); + sortKeys.put("name", false); + pagingQueryProvider.setSortKeys(sortKeys); + String sql = "SELECT id, name FROM ( SELECT id, name, ROW_NUMBER() OVER ( ORDER BY id ASC, name DESC) 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); + } } 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 c31c764c3..c77247a8b 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 @@ -1,8 +1,27 @@ +/* + * Copyright 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. + * You may obtain a copy of the License at + * + * 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, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.springframework.batch.item.database.support; -import org.junit.Test; import static org.junit.Assert.assertEquals; +import java.util.LinkedHashMap; +import java.util.Map; + +import org.junit.Test; + /** * @author Thomas Risberg * @author Michael Minella @@ -23,21 +42,21 @@ public class SybasePagingQueryProviderTests extends AbstractSqlPagingQueryProvid @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 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 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 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 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 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); } @@ -55,7 +74,7 @@ public class SybasePagingQueryProviderTests extends AbstractSqlPagingQueryProvid @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 id, name, age FROM foo WHERE bar = 1 AND ((id > ?)) GROUP BY dep ORDER BY id ASC"; String s = pagingQueryProvider.generateRemainingPagesQuery(pageSize); assertEquals(sql, s); } @@ -64,7 +83,7 @@ public class SybasePagingQueryProviderTests extends AbstractSqlPagingQueryProvid @Test public void testGenerateJumpToItemQueryWithGroupBy() { pagingQueryProvider.setGroupClause("dep"); - 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 GROUP BY dep) WHERE ROW_NUMBER = 100"; + 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"; String s = pagingQueryProvider.generateJumpToItemQuery(145, pageSize); assertEquals(sql, s); } @@ -73,8 +92,56 @@ public class SybasePagingQueryProviderTests extends AbstractSqlPagingQueryProvid @Test public void testGenerateJumpToItemQueryForFirstPageWithGroupBy() { pagingQueryProvider.setGroupClause("dep"); - 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 GROUP BY dep) WHERE ROW_NUMBER = 1"; + 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"; String s = pagingQueryProvider.generateJumpToItemQuery(45, pageSize); assertEquals(sql, s); } + + @Override + @Test + public void testGenerateFirstPageQueryWithMultipleSortKeys() { + Map sortKeys = new LinkedHashMap(); + sortKeys.put("name", true); + sortKeys.put("id", false); + pagingQueryProvider.setSortKeys(sortKeys); + String sql = "SELECT TOP 100 id, name, age FROM foo WHERE bar = 1 ORDER BY name ASC, id DESC"; + String s = pagingQueryProvider.generateFirstPageQuery(pageSize); + assertEquals("", sql, s); + } + + @Override + @Test + public void testGenerateRemainingPagesQueryWithMultipleSortKeys() { + Map sortKeys = new LinkedHashMap(); + sortKeys.put("name", true); + sortKeys.put("id", false); + pagingQueryProvider.setSortKeys(sortKeys); + String sql = "SELECT TOP 100 id, name, age FROM foo WHERE bar = 1 AND ((name > ?) OR (name = ? AND id < ?)) ORDER BY name ASC, id DESC"; + String s = pagingQueryProvider.generateRemainingPagesQuery(pageSize); + assertEquals("", sql, s); + } + + @Override + @Test + public void testGenerateJumpToItemQueryWithMultipleSortKeys() { + Map sortKeys = new LinkedHashMap(); + sortKeys.put("name", true); + sortKeys.put("id", false); + pagingQueryProvider.setSortKeys(sortKeys); + String sql = "SELECT name, id FROM ( SELECT name, id, ROW_NUMBER() OVER ( ORDER BY name ASC, id DESC) AS ROW_NUMBER FROM foo WHERE bar = 1) WHERE ROW_NUMBER = 100"; + String s = pagingQueryProvider.generateJumpToItemQuery(145, pageSize); + assertEquals("", sql, s); + } + + @Override + @Test + public void testGenerateJumpToItemQueryForFirstPageWithMultipleSortKeys() { + Map sortKeys = new LinkedHashMap(); + sortKeys.put("name", true); + sortKeys.put("id", false); + pagingQueryProvider.setSortKeys(sortKeys); + String sql = "SELECT name, id FROM ( SELECT name, id, ROW_NUMBER() OVER ( ORDER BY name ASC, id DESC) AS ROW_NUMBER FROM foo WHERE bar = 1) WHERE ROW_NUMBER = 1"; + String s = pagingQueryProvider.generateJumpToItemQuery(45, pageSize); + assertEquals("", sql, s); + } } diff --git a/spring-batch-infrastructure/src/test/resources/org/springframework/batch/item/database/JdbcPagingItemReaderConfigTests-context.xml b/spring-batch-infrastructure/src/test/resources/org/springframework/batch/item/database/JdbcPagingItemReaderConfigTests-context.xml index 6c9366c2d..15066789d 100644 --- a/spring-batch-infrastructure/src/test/resources/org/springframework/batch/item/database/JdbcPagingItemReaderConfigTests-context.xml +++ b/spring-batch-infrastructure/src/test/resources/org/springframework/batch/item/database/JdbcPagingItemReaderConfigTests-context.xml @@ -21,7 +21,12 @@ - + + + + + + diff --git a/spring-batch-samples/src/main/resources/jobs/iosample/jdbcPaging.xml b/spring-batch-samples/src/main/resources/jobs/iosample/jdbcPaging.xml index bd090ddca..548869cd7 100644 --- a/spring-batch-samples/src/main/resources/jobs/iosample/jdbcPaging.xml +++ b/spring-batch-samples/src/main/resources/jobs/iosample/jdbcPaging.xml @@ -16,7 +16,11 @@ - + + + + + diff --git a/spring-batch-samples/src/main/resources/jobs/partitionJdbcJob.xml b/spring-batch-samples/src/main/resources/jobs/partitionJdbcJob.xml index 4549a9757..368e6f5f3 100644 --- a/spring-batch-samples/src/main/resources/jobs/partitionJdbcJob.xml +++ b/spring-batch-samples/src/main/resources/jobs/partitionJdbcJob.xml @@ -44,7 +44,11 @@ - + + + + +