BATCH-1571: fix paging queries for Postgres
This commit is contained in:
@@ -241,6 +241,13 @@
|
||||
<optional>true</optional>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
<version>8.3-603.jdbc3</version>
|
||||
<optional>true</optional>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<pluginManagement>
|
||||
|
||||
@@ -75,6 +75,7 @@ public class IbatisPagingItemReaderAsyncTests {
|
||||
int max = 10;
|
||||
for (int i = 0; i < max; i++) {
|
||||
try {
|
||||
logger.info("Testing asynch reader, iteration="+i);
|
||||
doTest();
|
||||
}
|
||||
catch (Throwable e) {
|
||||
@@ -136,7 +137,11 @@ public class IbatisPagingItemReaderAsyncTests {
|
||||
SqlMapClient sqlMapClient = createSqlMapClient();
|
||||
|
||||
IbatisPagingItemReader<Foo> reader = new IbatisPagingItemReader<Foo>();
|
||||
reader.setQueryId("getPagedFoos");
|
||||
if ("postgres".equals(System.getProperty("ENVIRONMENT"))) {
|
||||
reader.setQueryId("getPagedFoosPostgres");
|
||||
} else {
|
||||
reader.setQueryId("getPagedFoos");
|
||||
}
|
||||
reader.setPageSize(2);
|
||||
reader.setSqlMapClient(sqlMapClient);
|
||||
reader.setSaveState(true);
|
||||
|
||||
@@ -115,14 +115,20 @@ public class JdbcPagingQueryIntegrationTests {
|
||||
public void testJumpToItem() throws Exception {
|
||||
|
||||
PagingQueryProvider queryProvider = getPagingQueryProvider();
|
||||
|
||||
int minId = jdbcTemplate.queryForInt("SELECT MIN(ID) FROM T_FOOS");
|
||||
|
||||
List<Map<String, Object>> list = jdbcTemplate.queryForList(queryProvider.generateJumpToItemQuery(pageSize,
|
||||
pageSize));
|
||||
logger.debug("Jump to page result: " + list);
|
||||
assertEquals(1, list.size());
|
||||
String expected = "[{sort_key="+(minId+pageSize-1);
|
||||
assertEquals(expected, list.toString().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().substring(0, expected.length()));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ public class DataSourceInitializer implements InitializingBean, DisposableBean {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
if (destroyScript!=null) {
|
||||
if (destroyScript != null) {
|
||||
doExecuteScript(destroyScript);
|
||||
initialized = false;
|
||||
}
|
||||
@@ -78,7 +78,7 @@ public class DataSourceInitializer implements InitializingBean, DisposableBean {
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.notNull(dataSource);
|
||||
logger.info("Initializing with scripts: "+Arrays.asList(initScripts));
|
||||
logger.info("Initializing with scripts: " + Arrays.asList(initScripts));
|
||||
if (!initialized && initialize) {
|
||||
try {
|
||||
doExecuteScript(destroyScript);
|
||||
@@ -89,7 +89,7 @@ public class DataSourceInitializer implements InitializingBean, DisposableBean {
|
||||
if (initScripts != null) {
|
||||
for (int i = 0; i < initScripts.length; i++) {
|
||||
Resource initScript = initScripts[i];
|
||||
logger.info("Executing init script: "+initScript);
|
||||
logger.info("Executing init script: " + initScript);
|
||||
doExecuteScript(initScript);
|
||||
}
|
||||
}
|
||||
@@ -100,36 +100,39 @@ public class DataSourceInitializer implements InitializingBean, DisposableBean {
|
||||
private void doExecuteScript(final Resource scriptResource) {
|
||||
if (scriptResource == null || !scriptResource.exists())
|
||||
return;
|
||||
TransactionTemplate transactionTemplate = new TransactionTemplate(new DataSourceTransactionManager(dataSource));
|
||||
transactionTemplate.execute(new TransactionCallback() {
|
||||
|
||||
final JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
|
||||
String[] scripts;
|
||||
try {
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
|
||||
String[] scripts;
|
||||
try {
|
||||
scripts = StringUtils.delimitedListToStringArray(stripComments(IOUtils.readLines(scriptResource
|
||||
.getInputStream())), ";");
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new BeanInitializationException("Cannot load script from [" + scriptResource + "]", e);
|
||||
}
|
||||
for (int i = 0; i < scripts.length; i++) {
|
||||
String script = scripts[i].trim();
|
||||
String[] list = StringUtils.delimitedListToStringArray(stripComments(IOUtils.readLines(scriptResource
|
||||
.getInputStream())), ";");
|
||||
scripts = list;
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new BeanInitializationException("Cannot load script from [" + scriptResource + "]", e);
|
||||
}
|
||||
for (int i = 0; i < scripts.length; i++) {
|
||||
final String script = scripts[i].trim();
|
||||
TransactionTemplate transactionTemplate = new TransactionTemplate(new DataSourceTransactionManager(
|
||||
dataSource));
|
||||
transactionTemplate.execute(new TransactionCallback() {
|
||||
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
if (StringUtils.hasText(script)) {
|
||||
try {
|
||||
jdbcTemplate.execute(scripts[i]);
|
||||
} catch (DataAccessException e) {
|
||||
jdbcTemplate.execute(script);
|
||||
}
|
||||
catch (DataAccessException e) {
|
||||
if (!script.toUpperCase().startsWith("DROP")) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
# Placeholders batch.*
|
||||
# for Oracle:
|
||||
batch.jdbc.driver=org.postgresql.Driver
|
||||
batch.jdbc.url=jdbc:postgresql://localhost:9432/test
|
||||
batch.jdbc.user=test
|
||||
batch.jdbc.password=test
|
||||
batch.jdbc.testWhileIdle=false
|
||||
batch.jdbc.validationQuery=
|
||||
batch.schema.script=classpath:org/springframework/batch/item/database/init-foo-schema-postgres.sql
|
||||
batch.business.schema.script=classpath:/org/springframework/batch/jms/init.sql
|
||||
batch.data.source.init=true
|
||||
batch.database.incrementer.class=org.springframework.jdbc.support.incrementer.PostgreSQLSequenceMaxValueIncrementer
|
||||
batch.database.incrementer.parent=sequenceIncrementerParent
|
||||
batch.verify.cursor.position=true
|
||||
@@ -7,6 +7,7 @@ log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %t %c{1}:%L - %m
|
||||
log4j.category.org.apache.activemq=ERROR
|
||||
# log4j.category.org.springframework=DEBUG
|
||||
log4j.category.org.springframework.jdbc=DEBUG
|
||||
log4j.category.org.springframework.jdbc.datasource=INFO
|
||||
# log4j.category.org.springframework.jms=DEBUG
|
||||
# log4j.category.org.springframework.batch=DEBUG
|
||||
log4j.category.org.springframework.batch.support=INFO
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<property name="initialize" value="${batch.data.source.init}"/>
|
||||
<property name="initScripts">
|
||||
<list>
|
||||
<value>classpath:org/springframework/batch/item/database/init-foo-schema-hsqldb.sql</value>
|
||||
<value>${batch.schema.script}</value>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
@@ -26,12 +26,8 @@
|
||||
select LIMIT #_skiprows# #_pagesize# ID, NAME, VALUE from T_FOOS order by ID
|
||||
</select>
|
||||
|
||||
<select id="getPagedFoos3AndUp" resultMap="fooResult">
|
||||
select LIMIT #_skiprows# #_pagesize# ID, NAME, VALUE from T_FOOS where VALUE >= #limit# order by ID
|
||||
</select>
|
||||
|
||||
<select id="getFoos3AndUp" resultMap="fooResult">
|
||||
select ID, NAME, VALUE from T_FOOS where VALUE >= #limit#
|
||||
<select id="getPagedFoosPostgres" resultMap="fooResult">
|
||||
select ID, NAME, VALUE from T_FOOS order by ID LIMIT #_pagesize# OFFSET #_skiprows#
|
||||
</select>
|
||||
|
||||
<select id="getAllFooIdsRestart" resultClass="int">
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
DROP TABLE T_FOOS;
|
||||
DROP TABLE T_WRITE_FOOS;
|
||||
|
||||
CREATE TABLE T_FOOS (
|
||||
ID BIGINT NOT NULL,
|
||||
NAME VARCHAR(45),
|
||||
VALUE BIGINT
|
||||
);
|
||||
|
||||
ALTER TABLE T_FOOS ADD PRIMARY KEY (ID);
|
||||
|
||||
INSERT INTO t_foos (id, name, VALUE) VALUES (1, 'bar1', 1);
|
||||
INSERT INTO t_foos (id, name, VALUE) VALUES (2, 'bar2', 2);
|
||||
INSERT INTO t_foos (id, name, VALUE) VALUES (3, 'bar3', 3);
|
||||
INSERT INTO t_foos (id, name, VALUE) VALUES (4, 'bar4', 4);
|
||||
INSERT INTO t_foos (id, name, VALUE) VALUES (5, 'bar5', 5);
|
||||
|
||||
CREATE TABLE T_WRITE_FOOS (
|
||||
ID BIGINT NOT NULL,
|
||||
NAME VARCHAR(45),
|
||||
VALUE BIGINT
|
||||
);
|
||||
|
||||
ALTER TABLE T_WRITE_FOOS ADD PRIMARY KEY (ID);
|
||||
@@ -43,8 +43,7 @@ public class PostgresPagingQueryProvider extends AbstractSqlPagingQueryProvider
|
||||
int page = itemIndex / pageSize;
|
||||
int offset = (page * pageSize) - 1;
|
||||
offset = offset<0 ? 0 : offset;
|
||||
|
||||
String limitClause = new StringBuilder().append("LIMIT ").append(offset).append(" 1").toString();
|
||||
String limitClause = new StringBuilder().append("LIMIT 1 OFFSET ").append(offset).toString();
|
||||
return SqlPagingQueryUtils.generateLimitJumpToQuery(this, limitClause);
|
||||
}
|
||||
|
||||
|
||||
@@ -29,16 +29,16 @@ public class PostgresPagingQueryProviderTests extends AbstractSqlPagingQueryProv
|
||||
|
||||
@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 AS SORT_KEY FROM foo WHERE bar = 1 ORDER BY id ASC LIMIT 1 OFFSET 99";
|
||||
String s = pagingQueryProvider.generateJumpToItemQuery(145, pageSize);
|
||||
Assert.assertEquals("", sql, s);
|
||||
Assert.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 0 1";
|
||||
String sql = "SELECT id AS SORT_KEY FROM foo WHERE bar = 1 ORDER BY id ASC LIMIT 1 OFFSET 0";
|
||||
String s = pagingQueryProvider.generateJumpToItemQuery(45, pageSize);
|
||||
Assert.assertEquals("", sql, s);
|
||||
Assert.assertEquals("Wrong SQL for first page", sql, s);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user