BATCH-1691: Implemented group by functionality not impacted by paging

This commit is contained in:
Michael Minella
2012-11-06 16:41:31 -06:00
parent 920d0e5f7f
commit ea4fdfdf15
24 changed files with 254 additions and 83 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2006-2008 the original author or authors.
* Copyright 2006-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,12 +17,14 @@
package org.springframework.batch.item.database.support;
import org.springframework.batch.item.database.PagingQueryProvider;
import org.springframework.util.StringUtils;
/**
* DB2 implementation of a {@link PagingQueryProvider} using
* database specific features.
*
* @author Thomas Risberg
* @author Michael Minella
* @since 2.0
*/
public class Db2PagingQueryProvider extends SqlWindowingPagingQueryProvider {
@@ -34,7 +36,12 @@ public class Db2PagingQueryProvider extends SqlWindowingPagingQueryProvider {
@Override
public String generateRemainingPagesQuery(int pageSize) {
return SqlPagingQueryUtils.generateLimitSqlQuery(this, true, buildLimitClause(pageSize));
if(StringUtils.hasText(getGroupClause())) {
return SqlPagingQueryUtils.generateLimitGroupedSqlQuery(this, true, buildLimitClause(pageSize));
}
else {
return SqlPagingQueryUtils.generateLimitSqlQuery(this, true, buildLimitClause(pageSize));
}
}
@Override

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2006-2008 the original author or authors.
* Copyright 2006-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,11 +16,11 @@
package org.springframework.batch.item.database.support;
import org.springframework.jdbc.support.JdbcUtils;
import javax.sql.DataSource;
import org.springframework.batch.item.database.PagingQueryProvider;
import org.springframework.dao.InvalidDataAccessResourceUsageException;
import javax.sql.DataSource;
import org.springframework.jdbc.support.JdbcUtils;
/**
* Derby implementation of a {@link PagingQueryProvider} using standard SQL:2003 windowing functions.
@@ -31,6 +31,7 @@ import javax.sql.DataSource;
*
* @author Thomas Risberg
* @author David Thexton
* @author Michael Minella
* @since 2.0
*/
public class DerbyPagingQueryProvider extends SqlWindowingPagingQueryProvider {
@@ -46,6 +47,11 @@ public class DerbyPagingQueryProvider extends SqlWindowingPagingQueryProvider {
}
}
@Override
protected String getOrderedQueryAlias() {
return "TMP_ORDERED";
}
@Override
protected String getOverClause() {
return "";
@@ -56,7 +62,7 @@ public class DerbyPagingQueryProvider extends SqlWindowingPagingQueryProvider {
}
protected String getOverSubstituteClauseEnd() {
return " " + super.getOverClause() + ") AS TMP_ORDERED";
return " " + super.getOverClause() + ") AS " + getOrderedQueryAlias();
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2006-2008 the original author or authors.
* Copyright 2006-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,10 +16,13 @@
package org.springframework.batch.item.database.support;
import org.springframework.util.StringUtils;
/**
* HSQLDB implementation of a {@link org.springframework.batch.item.database.PagingQueryProvider} using database specific features.
*
* @author Thomas Risberg
* @author Michael Minella
* @since 2.0
*/
public class HsqlPagingQueryProvider extends AbstractSqlPagingQueryProvider {
@@ -31,7 +34,12 @@ public class HsqlPagingQueryProvider extends AbstractSqlPagingQueryProvider {
@Override
public String generateRemainingPagesQuery(int pageSize) {
return SqlPagingQueryUtils.generateTopSqlQuery(this, true, buildTopClause(pageSize));
if(StringUtils.hasText(getGroupClause())) {
return SqlPagingQueryUtils.generateGroupedTopSqlQuery(this, true, buildTopClause(pageSize));
}
else {
return SqlPagingQueryUtils.generateTopSqlQuery(this, true, buildTopClause(pageSize));
}
}
private String buildTopClause(int pageSize) {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2006-2008 the original author or authors.
* Copyright 2006-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,11 +17,13 @@
package org.springframework.batch.item.database.support;
import org.springframework.batch.item.database.PagingQueryProvider;
import org.springframework.util.StringUtils;
/**
* MySQL implementation of a {@link PagingQueryProvider} using database specific features.
*
* @author Thomas Risberg
* @author Michael Minella
* @since 2.0
*/
public class MySqlPagingQueryProvider extends AbstractSqlPagingQueryProvider {
@@ -33,7 +35,12 @@ public class MySqlPagingQueryProvider extends AbstractSqlPagingQueryProvider {
@Override
public String generateRemainingPagesQuery(int pageSize) {
return SqlPagingQueryUtils.generateLimitSqlQuery(this, true, buildLimitClause(pageSize));
if(StringUtils.hasText(getGroupClause())) {
return SqlPagingQueryUtils.generateLimitGroupedSqlQuery(this, true, buildLimitClause(pageSize));
}
else {
return SqlPagingQueryUtils.generateLimitSqlQuery(this, true, buildLimitClause(pageSize));
}
}
private String buildLimitClause(int pageSize) {

View File

@@ -16,6 +16,8 @@
package org.springframework.batch.item.database.support;
import org.springframework.util.StringUtils;
/**
* Postgres implementation of a {@link org.springframework.batch.item.database.PagingQueryProvider} using database specific features.
*
@@ -35,7 +37,12 @@ public class PostgresPagingQueryProvider extends AbstractSqlPagingQueryProvider
@Override
public String generateRemainingPagesQuery(int pageSize) {
return SqlPagingQueryUtils.generateLimitSqlQuery(this, true, buildLimitClause(pageSize));
if(StringUtils.hasText(getGroupClause())) {
return SqlPagingQueryUtils.generateLimitGroupedSqlQuery(this, true, buildLimitClause(pageSize));
}
else {
return SqlPagingQueryUtils.generateLimitSqlQuery(this, true, buildLimitClause(pageSize));
}
}
private String buildLimitClause(int pageSize) {

View File

@@ -57,6 +57,34 @@ public class SqlPagingQueryUtils {
return sql.toString();
}
/**
* Generate SQL query string using a LIMIT clause
*
* @param provider {@link AbstractSqlPagingQueryProvider} providing the
* implementation specifics
* @param remainingPageQuery is this query for the ramining pages (true) as
* opposed to the first page (false)
* @param limitClause the implementation specific limit clause to be used
* @return the generated query
*/
public static String generateLimitGroupedSqlQuery(AbstractSqlPagingQueryProvider provider, boolean remainingPageQuery,
String limitClause) {
StringBuilder sql = new StringBuilder();
sql.append("SELECT * ");
sql.append(" FROM (");
sql.append("SELECT ").append(provider.getSelectClause());
sql.append(" FROM ").append(provider.getFromClause());
sql.append(provider.getWhereClause() == null ? "" : " WHERE " + provider.getWhereClause());
buildGroupByClause(provider, sql);
sql.append(" ORDER BY ").append(buildSortClause(provider));
sql.append(") AS MAIN_QRY ");
sql.append("WHERE ");
buildSortConditions(provider, sql);
sql.append(" " + limitClause);
return sql.toString();
}
/**
* Generate SQL query string using a TOP clause
*
@@ -79,6 +107,32 @@ public class SqlPagingQueryUtils {
return sql.toString();
}
/**
* Generate SQL query string using a TOP clause
*
* @param provider {@link AbstractSqlPagingQueryProvider} providing the
* implementation specifics
* @param remainingPageQuery is this query for the ramining pages (true) as
* opposed to the first page (false)
* @param topClause the implementation specific top clause to be used
* @return the generated query
*/
public static String generateGroupedTopSqlQuery(AbstractSqlPagingQueryProvider provider, boolean remainingPageQuery,
String topClause) {
StringBuilder sql = new StringBuilder();
sql.append("SELECT ").append(topClause).append(" * FROM (");
sql.append("SELECT ").append(provider.getSelectClause());
sql.append(" FROM ").append(provider.getFromClause());
sql.append(provider.getWhereClause() == null ? "" : " WHERE " + provider.getWhereClause());
buildGroupByClause(provider, sql);
sql.append(" ORDER BY ").append(buildSortClause(provider));
sql.append(") AS MAIN_QRY ");
sql.append("WHERE ");
buildSortConditions(provider, sql);
return sql.toString();
}
/**
* Generate SQL query string using a ROW_NUM condition
*
@@ -111,10 +165,14 @@ public class SqlPagingQueryUtils {
StringBuilder sql = new StringBuilder();
sql.append("SELECT * FROM (SELECT ").append(selectClause).append(", ROWNUM as TMP_ROW_NUM");
sql.append(" FROM ").append(provider.getFromClause());
buildWhereClause(provider, remainingPageQuery, sql);
sql.append(provider.getWhereClause() == null ? "" : " WHERE " + provider.getWhereClause());
buildGroupByClause(provider, sql);
sql.append(" ORDER BY ").append(buildSortClause(provider));
sql.append(") WHERE ").append(rowNumClause);
if(remainingPageQuery) {
sql.append(" AND ");
buildSortConditions(provider, sql);
}
return sql.toString();

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2006-2008 the original author or authors.
* Copyright 2006-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,12 +16,15 @@
package org.springframework.batch.item.database.support;
import org.springframework.util.StringUtils;
/**
* Sql Server implementation of a
* {@link org.springframework.batch.item.database.PagingQueryProvider} using
* database specific features.
*
* @author Thomas Risberg
* @author Michael Minella
* @since 2.0
*/
public class SqlServerPagingQueryProvider extends SqlWindowingPagingQueryProvider {
@@ -33,7 +36,12 @@ public class SqlServerPagingQueryProvider extends SqlWindowingPagingQueryProvide
@Override
public String generateRemainingPagesQuery(int pageSize) {
return SqlPagingQueryUtils.generateTopSqlQuery(this, true, buildTopClause(pageSize));
if(StringUtils.hasText(getGroupClause())) {
return SqlPagingQueryUtils.generateGroupedTopSqlQuery(this, true, buildTopClause(pageSize));
}
else {
return SqlPagingQueryUtils.generateTopSqlQuery(this, true, buildTopClause(pageSize));
}
}
@Override

View File

@@ -35,7 +35,7 @@ public class SqlWindowingPagingQueryProvider extends AbstractSqlPagingQueryProvi
public String generateFirstPageQuery(int pageSize) {
StringBuilder sql = new StringBuilder();
sql.append("SELECT * FROM ( ");
sql.append("SELECT ").append(getSelectClause()).append(", ");
sql.append("SELECT ").append(StringUtils.hasText(getOrderedQueryAlias()) ? getOrderedQueryAlias() + ".*, " : "*, ");
sql.append("ROW_NUMBER() OVER (").append(getOverClause());
sql.append(") AS ROW_NUMBER");
sql.append(getOverSubstituteClauseStart());
@@ -49,6 +49,10 @@ public class SqlWindowingPagingQueryProvider extends AbstractSqlPagingQueryProvi
return sql.toString();
}
protected String getOrderedQueryAlias() {
return "";
}
protected Object getSubQueryAlias() {
return "AS TMP_SUB ";
}
@@ -65,23 +69,22 @@ public class SqlWindowingPagingQueryProvider extends AbstractSqlPagingQueryProvi
public String generateRemainingPagesQuery(int pageSize) {
StringBuilder sql = new StringBuilder();
sql.append("SELECT * FROM ( ");
sql.append("SELECT ").append(getSelectClause()).append(", ");
sql.append("SELECT ").append(StringUtils.hasText(getOrderedQueryAlias()) ? getOrderedQueryAlias() + ".*, " : "*, ");
sql.append("ROW_NUMBER() OVER (").append(getOverClause());
sql.append(") AS ROW_NUMBER");
sql.append(getOverSubstituteClauseStart());
sql.append(" FROM ").append(getFromClause());
sql.append(" WHERE ");
if (getWhereClause() != null) {
sql.append(" WHERE ");
sql.append(getWhereClause());
sql.append(" AND ");
}
SqlPagingQueryUtils.buildSortConditions(this, sql);
sql.append(getGroupClause() == null ? "" : " GROUP BY " + getGroupClause());
sql.append(getOverSubstituteClauseEnd());
sql.append(") ").append(getSubQueryAlias()).append("WHERE ").append(extractTableAlias()).append(
"ROW_NUMBER <= ").append(pageSize);
sql.append(" AND ");
SqlPagingQueryUtils.buildSortConditions(this, sql);
return sql.toString();
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2006-2008 the original author or authors.
* Copyright 2006-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,12 +17,14 @@
package org.springframework.batch.item.database.support;
import org.springframework.batch.item.database.PagingQueryProvider;
import org.springframework.util.StringUtils;
/**
* Sybase implementation of a {@link PagingQueryProvider} using
* database specific features.
*
* @author Thomas Risberg
* @author Michael Minella
* @since 2.0
*/
public class SybasePagingQueryProvider extends SqlWindowingPagingQueryProvider {
@@ -34,7 +36,12 @@ public class SybasePagingQueryProvider extends SqlWindowingPagingQueryProvider {
@Override
public String generateRemainingPagesQuery(int pageSize) {
return SqlPagingQueryUtils.generateTopSqlQuery(this, true, buildTopClause(pageSize));
if(StringUtils.hasText(getGroupClause())) {
return SqlPagingQueryUtils.generateGroupedTopSqlQuery(this, true, buildTopClause(pageSize));
}
else {
return SqlPagingQueryUtils.generateTopSqlQuery(this, true, buildTopClause(pageSize));
}
}
@Override