BATCH-1571: fix paging queries for Postgres

This commit is contained in:
dsyer
2010-05-19 07:55:23 +00:00
parent a7c1a1e07b
commit 90c63f71dc
11 changed files with 92 additions and 37 deletions

View File

@@ -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>

View File

@@ -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);

View File

@@ -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()));
}

View File

@@ -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;
}
});
});
}
}

View File

@@ -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

View File

@@ -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

View File

@@ -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>

View File

@@ -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">

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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);
}
}