diff --git a/jberet-support/src/main/java/org/jberet/support/_private/SupportMessages.java b/jberet-support/src/main/java/org/jberet/support/_private/SupportMessages.java index 202a50ba5..d4f692fa1 100644 --- a/jberet-support/src/main/java/org/jberet/support/_private/SupportMessages.java +++ b/jberet-support/src/main/java/org/jberet/support/_private/SupportMessages.java @@ -80,4 +80,7 @@ public interface SupportMessages { @Message(id = 60020, value = "Expecting JMS message types: %s, but got %s, %s") BatchRuntimeException unexpectedJmsMessageType(String expectedTypes, String actualType, Object val); + @Message(id = 60021, value = "Failed to determine parameterNames due to a complex SQL was supplied. please specify parameterNames explicitly") + BatchRuntimeException failedToDetermineParameterNames(); + } \ No newline at end of file diff --git a/jberet-support/src/main/java/org/jberet/support/io/JdbcItemWriter.java b/jberet-support/src/main/java/org/jberet/support/io/JdbcItemWriter.java index 4b6fb9799..ae3976031 100644 --- a/jberet-support/src/main/java/org/jberet/support/io/JdbcItemWriter.java +++ b/jberet-support/src/main/java/org/jberet/support/io/JdbcItemWriter.java @@ -123,30 +123,40 @@ public void writeItems(final List items) throws Exception { public void open(final Serializable checkpoint) throws Exception { init(); - if (parameterNames == null) { - final String sqlLowerCase = sql.toLowerCase(); - final int insertPos = sqlLowerCase.indexOf("insert"); - int leftParenthesisPos = sqlLowerCase.indexOf('(', insertPos + 7); - int rightParenthesisPos = sqlLowerCase.indexOf(')', leftParenthesisPos + 1); - final String[] columns = sql.substring(leftParenthesisPos + 1, rightParenthesisPos).split(","); - final int valuesPos = sqlLowerCase.indexOf("values", rightParenthesisPos + 1); - leftParenthesisPos = sqlLowerCase.indexOf('(', valuesPos + 1); - rightParenthesisPos = sqlLowerCase.lastIndexOf(')'); + if (parameterNames == null && beanType != java.util.List.class) { + parameterNames = determineParameterNames(sql); + } + } - if (rightParenthesisPos <= leftParenthesisPos) { - throw SupportMessages.MESSAGES.invalidReaderWriterProperty(null, sql, "sql"); - } + static String[] determineParameterNames(final String sql) { + final String sqlLowerCase = sql.toLowerCase(); + final int insertPos = sqlLowerCase.indexOf("insert"); + int leftParenthesisPos = sqlLowerCase.indexOf('(', insertPos + 7); + int rightParenthesisPos = sqlLowerCase.indexOf(')', leftParenthesisPos + 1); + final String[] columns = sql.substring(leftParenthesisPos + 1, rightParenthesisPos).split(","); + final int valuesPos = sqlLowerCase.indexOf("values", rightParenthesisPos + 1); + leftParenthesisPos = sqlLowerCase.indexOf('(', valuesPos + 1); + rightParenthesisPos = sqlLowerCase.lastIndexOf(')'); - final String[] values = sql.substring(leftParenthesisPos + 1, rightParenthesisPos).split(","); - final List parameterNamesList = new ArrayList(); - for (int i = 0; i < values.length; ++i) { - final String v = values[i].trim(); - if (v.equals("?")) { - parameterNamesList.add(columns[i].trim()); - } + if (rightParenthesisPos <= leftParenthesisPos) { + throw SupportMessages.MESSAGES.invalidReaderWriterProperty(null, sql, "sql"); + } + + final String[] values = sql.substring(leftParenthesisPos + 1, rightParenthesisPos).split(","); + + if (values.length != columns.length) { + throw SupportMessages.MESSAGES.failedToDetermineParameterNames(); + } + + final List parameterNamesList = new ArrayList(); + for (int i = 0; i < values.length; ++i) { + final String v = values[i].trim(); + if (v.equals("?")) { + parameterNamesList.add(columns[i].trim()); } - parameterNames = parameterNamesList.toArray(new String[parameterNamesList.size()]); } + + return parameterNamesList.toArray(new String[parameterNamesList.size()]); } @Override @@ -164,7 +174,7 @@ private void mapParameters(final Object item) throws Exception { final List itemAsList = (List) item; //the item is a list and should contain data of proper types, e.g., String, Integer, Date, etc, //and in the same order as SQL insert statement parameters. - for (int i = 0; i < parameterNames.length; ++i) { + for (int i = 0; i < itemAsList.size(); ++i) { setParameter(i, itemAsList.get(i)); } } else { diff --git a/jberet-support/src/test/java/org/jberet/support/io/JdbcItemWriterTest.java b/jberet-support/src/test/java/org/jberet/support/io/JdbcItemWriterTest.java new file mode 100644 index 000000000..3b8347e2e --- /dev/null +++ b/jberet-support/src/test/java/org/jberet/support/io/JdbcItemWriterTest.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2015 Red Hat, Inc. and/or its affiliates. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + */ +package org.jberet.support.io; + +import org.junit.Test; + +import javax.batch.operations.BatchRuntimeException; + +import static org.junit.Assert.*; +import static org.jberet.support.io.JdbcItemWriter.determineParameterNames; + +@SuppressWarnings("SpellCheckingInspection") +public class JdbcItemWriterTest { + + @Test + public void normal() throws Exception { + final String sql = "INSERT INTO forex (symbol, ts, bid_open, bid_high, bid_low, bid_close, volume) " + + "values ('USDJPY', ?, ?, ?, ?, ?, ?)"; + final String[] actual = determineParameterNames(sql); + final String[] expected = {"ts", "bid_open", "bid_high", "bid_low", "bid_close", "volume"}; + assertArrayEquals(expected, actual); + } + + @Test(expected = BatchRuntimeException.class) + public void canNotDetermine() throws Exception { + final String sql = "INSERT INTO forex (symbol, ts, bid_open, bid_high, bid_low, bid_close, volume) " + + "values ('USDJPY', parsedatetime('yyyyMMdd HHmmss', ?), ?, ?, ?, ?, ?)"; + determineParameterNames(sql); + } +}