();
private String sqlScriptEncoding;
- private String separator;
+ private String separator = ScriptUtils.DEFAULT_STATEMENT_SEPARATOR;
- private String commentPrefix = DEFAULT_COMMENT_PREFIX;
+ private String commentPrefix = ScriptUtils.DEFAULT_COMMENT_PREFIX;
+
+ private String blockCommentStartDelimiter = ScriptUtils.DEFAULT_BLOCK_COMMENT_START_DELIMITER;
+
+ private String blockCommentEndDelimiter = ScriptUtils.DEFAULT_BLOCK_COMMENT_END_DELIMITER;
private boolean continueOnError = false;
@@ -71,7 +61,7 @@ public class ResourceDatabasePopulator implements DatabasePopulator {
/**
* Add a script to execute to populate the database.
- * @param script the path to a SQL script
+ * @param script the path to an SQL script
*/
public void addScript(Resource script) {
this.scripts.add(script);
@@ -87,8 +77,8 @@ public class ResourceDatabasePopulator implements DatabasePopulator {
/**
* Specify the encoding for SQL scripts, if different from the platform encoding.
- * Note setting this property has no effect on added scripts that are already
- * {@link EncodedResource encoded resources}.
+ * Note that setting this property has no effect on added scripts that are
+ * already {@linkplain EncodedResource encoded resources}.
* @see #addScript(Resource)
*/
public void setSqlScriptEncoding(String sqlScriptEncoding) {
@@ -96,23 +86,46 @@ public class ResourceDatabasePopulator implements DatabasePopulator {
}
/**
- * Specify the statement separator, if a custom one. Default is ";".
+ * Specify the statement separator, if a custom one.
+ *
Default is ";".
*/
public void setSeparator(String separator) {
this.separator = separator;
}
/**
- * Set the line prefix that identifies comments in the SQL script.
- * Default is "--".
+ * Set the prefix that identifies line comments within the SQL scripts.
+ *
Default is "--".
*/
public void setCommentPrefix(String commentPrefix) {
this.commentPrefix = commentPrefix;
}
+ /**
+ * Set the start delimiter that identifies block comments within the SQL
+ * scripts.
+ *
Default is "/*".
+ * @since 4.0.3
+ * @see #setBlockCommentEndDelimiter
+ */
+ public void setBlockCommentStartDelimiter(String blockCommentStartDelimiter) {
+ this.blockCommentStartDelimiter = blockCommentStartDelimiter;
+ }
+
+ /**
+ * Set the end delimiter that identifies block comments within the SQL
+ * scripts.
+ *
Default is "*/".
+ * @since 4.0.3
+ * @see #setBlockCommentStartDelimiter
+ */
+ public void setBlockCommentEndDelimiter(String blockCommentEndDelimiter) {
+ this.blockCommentEndDelimiter = blockCommentEndDelimiter;
+ }
+
/**
* Flag to indicate that all failures in SQL should be logged but not cause a failure.
- * Defaults to false.
+ *
Defaults to {@code false}.
*/
public void setContinueOnError(boolean continueOnError) {
this.continueOnError = continueOnError;
@@ -121,18 +134,20 @@ public class ResourceDatabasePopulator implements DatabasePopulator {
/**
* Flag to indicate that a failed SQL {@code DROP} statement can be ignored.
*
This is useful for non-embedded databases whose SQL dialect does not support an
- * {@code IF EXISTS} clause in a {@code DROP}. The default is false so that if the
- * populator runs accidentally, it will fail fast when the script starts with a {@code DROP}.
+ * {@code IF EXISTS} clause in a {@code DROP} statement.
+ *
The default is {@code false} so that if the populator runs accidentally, it will
+ * fail fast if the script starts with a {@code DROP} statement.
*/
public void setIgnoreFailedDrops(boolean ignoreFailedDrops) {
this.ignoreFailedDrops = ignoreFailedDrops;
}
-
@Override
public void populate(Connection connection) throws SQLException {
for (Resource script : this.scripts) {
- executeSqlScript(connection, applyEncodingIfNecessary(script), this.continueOnError, this.ignoreFailedDrops);
+ ScriptUtils.executeSqlScript(connection, applyEncodingIfNecessary(script), this.continueOnError,
+ this.ignoreFailedDrops, this.commentPrefix, this.separator, this.blockCommentStartDelimiter,
+ this.blockCommentEndDelimiter);
}
}
@@ -144,214 +159,4 @@ public class ResourceDatabasePopulator implements DatabasePopulator {
return new EncodedResource(script, this.sqlScriptEncoding);
}
}
-
- /**
- * Execute the given SQL script.
- *
The script will normally be loaded by classpath. There should be one statement
- * per line. Any {@link #setSeparator(String) statement separators} will be removed.
- *
Do not use this method to execute DDL if you expect rollback.
- * @param connection the JDBC Connection with which to perform JDBC operations
- * @param resource the resource (potentially associated with a specific encoding) to load the SQL script from
- * @param continueOnError whether or not to continue without throwing an exception in the event of an error
- * @param ignoreFailedDrops whether of not to continue in the event of specifically an error on a {@code DROP}
- */
- private void executeSqlScript(Connection connection, EncodedResource resource, boolean continueOnError,
- boolean ignoreFailedDrops) throws SQLException {
-
- if (logger.isInfoEnabled()) {
- logger.info("Executing SQL script from " + resource);
- }
- long startTime = System.currentTimeMillis();
- List statements = new LinkedList();
- String script;
- try {
- script = readScript(resource);
- }
- catch (IOException ex) {
- throw new CannotReadScriptException(resource, ex);
- }
- String delimiter = this.separator;
- if (delimiter == null) {
- delimiter = DEFAULT_STATEMENT_SEPARATOR;
- if (!containsSqlScriptDelimiters(script, delimiter)) {
- delimiter = "\n";
- }
- }
- splitSqlScript(script, delimiter, this.commentPrefix, statements);
- int lineNumber = 0;
- Statement stmt = connection.createStatement();
- try {
- for (String statement : statements) {
- lineNumber++;
- try {
- stmt.execute(statement);
- int rowsAffected = stmt.getUpdateCount();
- if (logger.isDebugEnabled()) {
- logger.debug(rowsAffected + " returned as updateCount for SQL: " + statement);
- }
- }
- catch (SQLException ex) {
- boolean dropStatement = StringUtils.startsWithIgnoreCase(statement.trim(), "drop");
- if (continueOnError || (dropStatement && ignoreFailedDrops)) {
- if (logger.isDebugEnabled()) {
- logger.debug("Failed to execute SQL script statement at line " + lineNumber +
- " of resource " + resource + ": " + statement, ex);
- }
- }
- else {
- throw new ScriptStatementFailedException(statement, lineNumber, resource, ex);
- }
- }
- }
- }
- finally {
- try {
- stmt.close();
- }
- catch (Throwable ex) {
- logger.debug("Could not close JDBC Statement", ex);
- }
- }
- long elapsedTime = System.currentTimeMillis() - startTime;
- if (logger.isInfoEnabled()) {
- logger.info("Done executing SQL script from " + resource + " in " + elapsedTime + " ms.");
- }
- }
-
- /**
- * Read a script from the given resource and build a String containing the lines.
- * @param resource the resource to be read
- * @return {@code String} containing the script lines
- * @throws IOException in case of I/O errors
- */
- private String readScript(EncodedResource resource) throws IOException {
- LineNumberReader lnr = new LineNumberReader(resource.getReader());
- try {
- String currentStatement = lnr.readLine();
- StringBuilder scriptBuilder = new StringBuilder();
- while (currentStatement != null) {
- if (StringUtils.hasText(currentStatement) &&
- (this.commentPrefix != null && !currentStatement.startsWith(this.commentPrefix))) {
- if (scriptBuilder.length() > 0) {
- scriptBuilder.append('\n');
- }
- scriptBuilder.append(currentStatement);
- }
- currentStatement = lnr.readLine();
- }
- maybeAddSeparatorToScript(scriptBuilder);
- return scriptBuilder.toString();
- }
- finally {
- lnr.close();
- }
- }
-
- private void maybeAddSeparatorToScript(StringBuilder scriptBuilder) {
- if (this.separator == null) {
- return;
- }
- String trimmed = this.separator.trim();
- if (trimmed.length() == this.separator.length()) {
- return;
- }
- // separator ends in whitespace, so we might want to see if the script is trying
- // to end the same way
- if (scriptBuilder.lastIndexOf(trimmed) == scriptBuilder.length() - trimmed.length()) {
- scriptBuilder.append(this.separator.substring(trimmed.length()));
- }
- }
-
- /**
- * Does the provided SQL script contain the specified delimiter?
- * @param script the SQL script
- * @param delim character delimiting each statement - typically a ';' character
- */
- private boolean containsSqlScriptDelimiters(String script, String delim) {
- boolean inLiteral = false;
- char[] content = script.toCharArray();
- for (int i = 0; i < script.length(); i++) {
- if (content[i] == '\'') {
- inLiteral = !inLiteral;
- }
- if (!inLiteral && script.startsWith(delim, i)) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Split an SQL script into separate statements delimited by the provided delimiter
- * string. Each individual statement will be added to the provided {@code List}.
- * Within a statement, the provided {@code commentPrefix} will be honored;
- * any text beginning with the comment prefix and extending to the end of the
- * line will be omitted from the statement. In addition, multiple adjacent
- * whitespace characters will be collapsed into a single space.
- * @param script the SQL script
- * @param delim character delimiting each statement (typically a ';' character)
- * @param commentPrefix the prefix that identifies line comments in the SQL script — typically "--"
- * @param statements the List that will contain the individual statements
- */
- private void splitSqlScript(String script, String delim, String commentPrefix, List statements) {
- StringBuilder sb = new StringBuilder();
- boolean inLiteral = false;
- boolean inEscape = false;
- char[] content = script.toCharArray();
- for (int i = 0; i < script.length(); i++) {
- char c = content[i];
- if (inEscape) {
- inEscape = false;
- sb.append(c);
- continue;
- }
- // MySQL style escapes
- if (c == '\\') {
- inEscape = true;
- sb.append(c);
- continue;
- }
- if (c == '\'') {
- inLiteral = !inLiteral;
- }
- if (!inLiteral) {
- if (script.startsWith(delim, i)) {
- // we've reached the end of the current statement
- if (sb.length() > 0) {
- statements.add(sb.toString());
- sb = new StringBuilder();
- }
- i += delim.length() - 1;
- continue;
- }
- else if (script.startsWith(commentPrefix, i)) {
- // skip over any content from the start of the comment to the EOL
- int indexOfNextNewline = script.indexOf("\n", i);
- if (indexOfNextNewline > i) {
- i = indexOfNextNewline;
- continue;
- }
- else {
- // if there's no newline after the comment, we must be at the end
- // of the script, so stop here.
- break;
- }
- }
- else if (c == ' ' || c == '\n' || c == '\t') {
- // avoid multiple adjacent whitespace characters
- if (sb.length() > 0 && sb.charAt(sb.length() - 1) != ' ') {
- c = ' ';
- }
- else {
- continue;
- }
- }
- }
- sb.append(c);
- }
- if (StringUtils.hasText(sb)) {
- statements.add(sb.toString());
- }
- }
-
}
diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/ScriptException.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/ScriptException.java
new file mode 100644
index 0000000000..31c8a9618d
--- /dev/null
+++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/ScriptException.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2002-2014 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.jdbc.datasource.init;
+
+/**
+ * Root of the hierarchy of SQL script exceptions.
+ *
+ * @author Sam Brannen
+ * @since 4.0.3
+ */
+@SuppressWarnings("serial")
+public abstract class ScriptException extends RuntimeException {
+
+ /**
+ * Constructor for {@code ScriptException}.
+ * @param message the detail message
+ */
+ public ScriptException(String message) {
+ super(message);
+ }
+
+ /**
+ * Constructor for {@code ScriptException}.
+ * @param message the detail message
+ * @param cause the root cause
+ */
+ public ScriptException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+}
diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/ScriptParseException.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/ScriptParseException.java
new file mode 100644
index 0000000000..63edc6b03f
--- /dev/null
+++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/ScriptParseException.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2002-2014 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.jdbc.datasource.init;
+
+import org.springframework.core.io.support.EncodedResource;
+
+/**
+ * Thrown by {@link ScriptUtils} if an SQL script cannot be properly parsed.
+ *
+ * @author Sam Brannen
+ * @since 4.0.3
+ */
+@SuppressWarnings("serial")
+public class ScriptParseException extends ScriptException {
+
+ /**
+ * Construct a new {@code ScriptParseException}.
+ * @param message detailed message
+ * @param resource the resource from which the SQL script was read
+ */
+ public ScriptParseException(String message, EncodedResource resource) {
+ super(buildMessage(message, resource));
+ }
+
+ /**
+ * Construct a new {@code ScriptParseException}.
+ * @param message detailed message
+ * @param resource the resource from which the SQL script was read
+ * @param cause the underlying cause of the failure
+ */
+ public ScriptParseException(String message, EncodedResource resource, Throwable cause) {
+ super(buildMessage(message, resource), cause);
+ }
+
+ private static String buildMessage(String message, EncodedResource resource) {
+ return String.format("Failed to parse SQL script from resource [%s]: %s", (resource == null ? ""
+ : resource), message);
+ }
+
+}
diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/ScriptStatementFailedException.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/ScriptStatementFailedException.java
index 016ab1eed9..77c49a1c37 100644
--- a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/ScriptStatementFailedException.java
+++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/ScriptStatementFailedException.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2012 the original author or authors.
+ * Copyright 2002-2014 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,15 +19,15 @@ package org.springframework.jdbc.datasource.init;
import org.springframework.core.io.support.EncodedResource;
/**
- * Thrown by {@link ResourceDatabasePopulator} if a statement in one of its SQL scripts
- * failed when executing it against the target database.
+ * Thrown by {@link ScriptUtils} if a statement in an SQL script failed when
+ * executing it against the target database.
*
* @author Juergen Hoeller
* @author Sam Brannen
* @since 3.0.5
*/
@SuppressWarnings("serial")
-public class ScriptStatementFailedException extends RuntimeException {
+public class ScriptStatementFailedException extends ScriptException {
/**
* Construct a new {@code ScriptStatementFailedException}.
@@ -37,8 +37,8 @@ public class ScriptStatementFailedException extends RuntimeException {
* @param cause the underlying cause of the failure
*/
public ScriptStatementFailedException(String statement, int lineNumber, EncodedResource resource, Throwable cause) {
- super("Failed to execute SQL script statement at line " + lineNumber +
- " of resource " + resource + ": " + statement, cause);
+ super("Failed to execute SQL script statement at line " + lineNumber + " of resource " + resource + ": "
+ + statement, cause);
}
}
diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/ScriptUtils.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/ScriptUtils.java
new file mode 100644
index 0000000000..f43a42304d
--- /dev/null
+++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/ScriptUtils.java
@@ -0,0 +1,397 @@
+/*
+ * Copyright 2002-2014 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.jdbc.datasource.init;
+
+import java.io.IOException;
+import java.io.LineNumberReader;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.core.io.support.EncodedResource;
+import org.springframework.util.Assert;
+import org.springframework.util.StringUtils;
+
+/**
+ * Generic utility methods for working with SQL scripts. Mainly for internal use
+ * within the framework.
+ *
+ * @author Thomas Risberg
+ * @author Sam Brannen
+ * @author Juergen Hoeller
+ * @author Keith Donald
+ * @author Dave Syer
+ * @author Chris Beams
+ * @author Oliver Gierke
+ * @author Chris Baldwin
+ * @since 4.0.3
+ */
+public abstract class ScriptUtils {
+
+ private static final Log logger = LogFactory.getLog(ScriptUtils.class);
+
+ /**
+ * Default statement separator within SQL scripts.
+ */
+ public static final String DEFAULT_STATEMENT_SEPARATOR = ";";
+
+ /**
+ * Default prefix for line comments within SQL scripts.
+ */
+ public static final String DEFAULT_COMMENT_PREFIX = "--";
+
+ /**
+ * Default start delimiter for block comments within SQL scripts.
+ */
+ public static final String DEFAULT_BLOCK_COMMENT_START_DELIMITER = "/*";
+
+ /**
+ * Default end delimiter for block comments within SQL scripts.
+ */
+ public static final String DEFAULT_BLOCK_COMMENT_END_DELIMITER = "*/";
+
+
+ /**
+ * Prevent instantiation of this utility class.
+ */
+ private ScriptUtils() {
+ /* no-op */
+ }
+
+ /**
+ * Split an SQL script into separate statements delimited by the provided
+ * delimiter character. Each individual statement will be added to the
+ * provided {@code List}.
+ * Within the script, {@value #DEFAULT_COMMENT_PREFIX} will be used as the
+ * comment prefix; any text beginning with the comment prefix and extending to
+ * the end of the line will be omitted from the output. Similarly,
+ * {@value #DEFAULT_BLOCK_COMMENT_START_DELIMITER} and
+ * {@value #DEFAULT_BLOCK_COMMENT_END_DELIMITER} will be used as the
+ * start and end block comment delimiters: any text enclosed
+ * in a block comment will be omitted from the output. In addition, multiple
+ * adjacent whitespace characters will be collapsed into a single space.
+ * @param script the SQL script
+ * @param delimiter character delimiting each statement — typically a ';' character
+ * @param statements the list that will contain the individual statements
+ * @see #splitSqlScript(EncodedResource, String, String, String, String, String, List)
+ */
+ public static void splitSqlScript(String script, char delimiter, List statements) throws ScriptException {
+ splitSqlScript(null, script, String.valueOf(delimiter), DEFAULT_COMMENT_PREFIX,
+ DEFAULT_BLOCK_COMMENT_START_DELIMITER, DEFAULT_BLOCK_COMMENT_END_DELIMITER, statements);
+ }
+
+ /**
+ * Split an SQL script into separate statements delimited by the provided
+ * delimiter string. Each individual statement will be added to the provided
+ * {@code List}.
+ * Within the script, the provided {@code commentPrefix} will be honored:
+ * any text beginning with the comment prefix and extending to the end of the
+ * line will be omitted from the output. Similarly, the provided
+ * {@code blockCommentStartDelimiter} and {@code blockCommentEndDelimiter}
+ * delimiters will be honored: any text enclosed in a block comment will be
+ * omitted from the output. In addition, multiple adjacent whitespace characters
+ * will be collapsed into a single space.
+ * @param resource the resource from which the script was read
+ * @param script the SQL script; never {@code null} or empty
+ * @param delimiter text delimiting each statement — typically a ';'
+ * character; never {@code null}
+ * @param commentPrefix the prefix that identifies SQL line comments —
+ * typically "--"; never {@code null} or empty
+ * @param blockCommentStartDelimiter the start block comment delimiter;
+ * never {@code null} or empty
+ * @param blockCommentEndDelimiter the end block comment delimiter;
+ * never {@code null} or empty
+ * @param statements the list that will contain the individual statements
+ */
+ public static void splitSqlScript(EncodedResource resource, String script, String delimiter, String commentPrefix,
+ String blockCommentStartDelimiter, String blockCommentEndDelimiter, List statements)
+ throws ScriptException {
+
+ Assert.hasText(script, "script must not be null or empty");
+ Assert.notNull(delimiter, "delimiter must not be null");
+ Assert.hasText(commentPrefix, "commentPrefix must not be null or empty");
+ Assert.hasText(blockCommentStartDelimiter, "blockCommentStartDelimiter must not be null or empty");
+ Assert.hasText(blockCommentEndDelimiter, "blockCommentEndDelimiter must not be null or empty");
+
+ StringBuilder sb = new StringBuilder();
+ boolean inLiteral = false;
+ boolean inEscape = false;
+ char[] content = script.toCharArray();
+ for (int i = 0; i < script.length(); i++) {
+ char c = content[i];
+ if (inEscape) {
+ inEscape = false;
+ sb.append(c);
+ continue;
+ }
+ // MySQL style escapes
+ if (c == '\\') {
+ inEscape = true;
+ sb.append(c);
+ continue;
+ }
+ if (c == '\'') {
+ inLiteral = !inLiteral;
+ }
+ if (!inLiteral) {
+ if (script.startsWith(delimiter, i)) {
+ // we've reached the end of the current statement
+ if (sb.length() > 0) {
+ statements.add(sb.toString());
+ sb = new StringBuilder();
+ }
+ i += delimiter.length() - 1;
+ continue;
+ }
+ else if (script.startsWith(commentPrefix, i)) {
+ // skip over any content from the start of the comment to the EOL
+ int indexOfNextNewline = script.indexOf("\n", i);
+ if (indexOfNextNewline > i) {
+ i = indexOfNextNewline;
+ continue;
+ }
+ else {
+ // if there's no EOL, we must be at the end
+ // of the script, so stop here.
+ break;
+ }
+ }
+ else if (script.startsWith(blockCommentStartDelimiter, i)) {
+ // skip over any block comments
+ int indexOfCommentEnd = script.indexOf(blockCommentEndDelimiter, i);
+ if (indexOfCommentEnd > i) {
+ i = indexOfCommentEnd + blockCommentEndDelimiter.length() - 1;
+ continue;
+ }
+ else {
+ throw new ScriptParseException(String.format("Missing block comment end delimiter [%s].",
+ blockCommentEndDelimiter), resource);
+ }
+ }
+ else if (c == ' ' || c == '\n' || c == '\t') {
+ // avoid multiple adjacent whitespace characters
+ if (sb.length() > 0 && sb.charAt(sb.length() - 1) != ' ') {
+ c = ' ';
+ }
+ else {
+ continue;
+ }
+ }
+ }
+ sb.append(c);
+ }
+ if (StringUtils.hasText(sb)) {
+ statements.add(sb.toString());
+ }
+ }
+
+ /**
+ * Read a script from the given resource, using "{@code --}" as the comment prefix
+ * and "{@code ;}" as the statement separator, and build a String containing the lines.
+ * @param resource the {@code EncodedResource} to be read
+ * @return {@code String} containing the script lines
+ * @throws IOException in case of I/O errors
+ */
+ static String readScript(EncodedResource resource) throws IOException {
+ return readScript(resource, DEFAULT_COMMENT_PREFIX, DEFAULT_STATEMENT_SEPARATOR);
+ }
+
+ /**
+ * Read a script from the provided resource, using the supplied
+ * comment prefix and statement separator, and build a {@code String} containing
+ * the lines.
+ * Lines beginning with the comment prefix are excluded from the
+ * results; however, line comments anywhere else — for example, within
+ * a statement — will be included in the results.
+ * @param resource the {@code EncodedResource} containing the script
+ * to be processed
+ * @param commentPrefix the prefix that identifies comments in the SQL script —
+ * typically "--"
+ * @param separator the statement separator in the SQL script — typically ";"
+ * @return a {@code String} containing the script lines
+ */
+ private static String readScript(EncodedResource resource, String commentPrefix, String separator)
+ throws IOException {
+ LineNumberReader lnr = new LineNumberReader(resource.getReader());
+ try {
+ return readScript(lnr, commentPrefix, separator);
+ }
+ finally {
+ lnr.close();
+ }
+ }
+
+ /**
+ * Read a script from the provided {@code LineNumberReader}, using the supplied
+ * comment prefix and statement separator, and build a {@code String} containing
+ * the lines.
+ *
Lines beginning with the comment prefix are excluded from the
+ * results; however, line comments anywhere else — for example, within
+ * a statement — will be included in the results.
+ * @param lineNumberReader the {@code LineNumberReader} containing the script
+ * to be processed
+ * @param commentPrefix the prefix that identifies comments in the SQL script —
+ * typically "--"
+ * @param separator the statement separator in the SQL script — typically ";"
+ * @return a {@code String} containing the script lines
+ */
+ public static String readScript(LineNumberReader lineNumberReader, String commentPrefix, String separator)
+ throws IOException {
+ String currentStatement = lineNumberReader.readLine();
+ StringBuilder scriptBuilder = new StringBuilder();
+ while (currentStatement != null) {
+ if (StringUtils.hasText(currentStatement)
+ && (commentPrefix != null && !currentStatement.startsWith(commentPrefix))) {
+ if (scriptBuilder.length() > 0) {
+ scriptBuilder.append('\n');
+ }
+ scriptBuilder.append(currentStatement);
+ }
+ currentStatement = lineNumberReader.readLine();
+ }
+ maybeAddSeparatorToScript(scriptBuilder, separator);
+ return scriptBuilder.toString();
+ }
+
+ private static void maybeAddSeparatorToScript(StringBuilder scriptBuilder, String separator) {
+ if (separator == null) {
+ return;
+ }
+ String trimmed = separator.trim();
+ if (trimmed.length() == separator.length()) {
+ return;
+ }
+ // separator ends in whitespace, so we might want to see if the script is trying
+ // to end the same way
+ if (scriptBuilder.lastIndexOf(trimmed) == scriptBuilder.length() - trimmed.length()) {
+ scriptBuilder.append(separator.substring(trimmed.length()));
+ }
+ }
+
+ /**
+ * Does the provided SQL script contain the specified delimiter?
+ * @param script the SQL script
+ * @param delim String delimiting each statement - typically a ';' character
+ */
+ public static boolean containsSqlScriptDelimiters(String script, String delim) {
+ boolean inLiteral = false;
+ char[] content = script.toCharArray();
+ for (int i = 0; i < script.length(); i++) {
+ if (content[i] == '\'') {
+ inLiteral = !inLiteral;
+ }
+ if (!inLiteral && script.startsWith(delim, i)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Execute the given SQL script.
+ *
Statement separators and comments will be removed before executing
+ * individual statements within the supplied script.
+ *
Do not use this method to execute DDL if you expect rollback.
+ * @param connection the JDBC connection to use to execute the script; already
+ * configured and ready to use
+ * @param resource the resource (potentially associated with a specific encoding)
+ * to load the SQL script from
+ * @param continueOnError whether or not to continue without throwing an exception
+ * in the event of an error
+ * @param ignoreFailedDrops whether or not to continue in the event of specifically
+ * an error on a {@code DROP} statement
+ * @param commentPrefix the prefix that identifies comments in the SQL script —
+ * typically "--"
+ * @param separator the script statement separator; defaults to
+ * {@value #DEFAULT_STATEMENT_SEPARATOR} if not specified
+ * @param blockCommentStartDelimiter the start block comment delimiter; never
+ * {@code null} or empty
+ * @param blockCommentEndDelimiter the end block comment delimiter; never
+ * {@code null} or empty
+ */
+ public static void executeSqlScript(Connection connection, EncodedResource resource, boolean continueOnError,
+ boolean ignoreFailedDrops, String commentPrefix, String separator, String blockCommentStartDelimiter,
+ String blockCommentEndDelimiter) throws SQLException, ScriptException {
+
+ if (logger.isInfoEnabled()) {
+ logger.info("Executing SQL script from " + resource);
+ }
+ long startTime = System.currentTimeMillis();
+ List statements = new LinkedList();
+ String script;
+ try {
+ script = readScript(resource, commentPrefix, separator);
+ }
+ catch (IOException ex) {
+ throw new CannotReadScriptException(resource, ex);
+ }
+
+ if (separator == null) {
+ separator = DEFAULT_STATEMENT_SEPARATOR;
+ if (!containsSqlScriptDelimiters(script, separator)) {
+ separator = "\n";
+ }
+ }
+
+ splitSqlScript(resource, script, separator, commentPrefix, blockCommentStartDelimiter,
+ blockCommentEndDelimiter, statements);
+ int lineNumber = 0;
+ Statement stmt = connection.createStatement();
+ try {
+ for (String statement : statements) {
+ lineNumber++;
+ try {
+ stmt.execute(statement);
+ int rowsAffected = stmt.getUpdateCount();
+ if (logger.isDebugEnabled()) {
+ logger.debug(rowsAffected + " returned as updateCount for SQL: " + statement);
+ }
+ }
+ catch (SQLException ex) {
+ boolean dropStatement = StringUtils.startsWithIgnoreCase(statement.trim(), "drop");
+ if (continueOnError || (dropStatement && ignoreFailedDrops)) {
+ if (logger.isDebugEnabled()) {
+ logger.debug("Failed to execute SQL script statement at line " + lineNumber
+ + " of resource " + resource + ": " + statement, ex);
+ }
+ }
+ else {
+ throw new ScriptStatementFailedException(statement, lineNumber, resource, ex);
+ }
+ }
+ }
+ }
+ finally {
+ try {
+ stmt.close();
+ }
+ catch (Throwable ex) {
+ logger.debug("Could not close JDBC Statement", ex);
+ }
+ }
+
+ long elapsedTime = System.currentTimeMillis() - startTime;
+ if (logger.isInfoEnabled()) {
+ logger.info("Executed SQL script from " + resource + " in " + elapsedTime + " ms.");
+ }
+ }
+
+}
diff --git a/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/init/DatabasePopulatorTests.java b/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/init/DatabasePopulatorTests.java
index 68f33bcf82..73f3629ba5 100644
--- a/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/init/DatabasePopulatorTests.java
+++ b/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/init/DatabasePopulatorTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2013 the original author or authors.
+ * Copyright 2002-2014 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.
@@ -40,9 +40,7 @@ import static org.mockito.BDDMockito.*;
*/
public class DatabasePopulatorTests {
- private final EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
-
- private final EmbeddedDatabase db = builder.build();
+ private final EmbeddedDatabase db = new EmbeddedDatabaseBuilder().build();
private final ResourceDatabasePopulator databasePopulator = new ResourceDatabasePopulator();
diff --git a/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/init/ScriptUtilsTests.java b/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/init/ScriptUtilsTests.java
new file mode 100644
index 0000000000..dff78a50b9
--- /dev/null
+++ b/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/init/ScriptUtilsTests.java
@@ -0,0 +1,196 @@
+/*
+ * Copyright 2002-2014 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.jdbc.datasource.init;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.After;
+import org.junit.Test;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.io.support.EncodedResource;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase;
+import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
+import org.springframework.transaction.support.TransactionSynchronizationManager;
+
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.*;
+
+/**
+ * Unit and integration tests for {@link ScriptUtils}.
+ *
+ * @author Thomas Risberg
+ * @author Sam Brannen
+ * @author Phillip Webb
+ * @author Chris Baldwin
+ */
+public class ScriptUtilsTests {
+
+ private final EmbeddedDatabase db = new EmbeddedDatabaseBuilder().build();
+
+
+ @After
+ public void shutDown() {
+ if (TransactionSynchronizationManager.isSynchronizationActive()) {
+ TransactionSynchronizationManager.clear();
+ TransactionSynchronizationManager.unbindResource(db);
+ }
+ db.shutdown();
+ }
+
+ @Test
+ public void splitSqlScriptDelimitedWithSemicolon() {
+ String rawStatement1 = "insert into customer (id, name)\nvalues (1, 'Rod ; Johnson'), (2, 'Adrian \n Collier')";
+ String cleanedStatement1 = "insert into customer (id, name) values (1, 'Rod ; Johnson'), (2, 'Adrian \n Collier')";
+ String rawStatement2 = "insert into orders(id, order_date, customer_id)\nvalues (1, '2008-01-02', 2)";
+ String cleanedStatement2 = "insert into orders(id, order_date, customer_id) values (1, '2008-01-02', 2)";
+ String rawStatement3 = "insert into orders(id, order_date, customer_id) values (1, '2008-01-02', 2)";
+ String cleanedStatement3 = "insert into orders(id, order_date, customer_id) values (1, '2008-01-02', 2)";
+ char delim = ';';
+ String script = rawStatement1 + delim + rawStatement2 + delim + rawStatement3 + delim;
+ List statements = new ArrayList();
+ ScriptUtils.splitSqlScript(script, delim, statements);
+ assertEquals("wrong number of statements", 3, statements.size());
+ assertEquals("statement 1 not split correctly", cleanedStatement1, statements.get(0));
+ assertEquals("statement 2 not split correctly", cleanedStatement2, statements.get(1));
+ assertEquals("statement 3 not split correctly", cleanedStatement3, statements.get(2));
+ }
+
+ @Test
+ public void splitSqlScriptDelimitedWithNewLine() {
+ String statement1 = "insert into customer (id, name) values (1, 'Rod ; Johnson'), (2, 'Adrian \n Collier')";
+ String statement2 = "insert into orders(id, order_date, customer_id) values (1, '2008-01-02', 2)";
+ String statement3 = "insert into orders(id, order_date, customer_id) values (1, '2008-01-02', 2)";
+ char delim = '\n';
+ String script = statement1 + delim + statement2 + delim + statement3 + delim;
+ List statements = new ArrayList();
+ ScriptUtils.splitSqlScript(script, delim, statements);
+ assertEquals("wrong number of statements", 3, statements.size());
+ assertEquals("statement 1 not split correctly", statement1, statements.get(0));
+ assertEquals("statement 2 not split correctly", statement2, statements.get(1));
+ assertEquals("statement 3 not split correctly", statement3, statements.get(2));
+ }
+
+ @Test
+ public void readAndSplitScriptContainingComments() throws Exception {
+ EncodedResource resource = new EncodedResource(new ClassPathResource("test-data-with-comments.sql", getClass()));
+
+ String script = ScriptUtils.readScript(resource);
+
+ char delim = ';';
+ List statements = new ArrayList();
+ ScriptUtils.splitSqlScript(script, delim, statements);
+
+ String statement1 = "insert into customer (id, name) values (1, 'Rod; Johnson'), (2, 'Adrian Collier')";
+ String statement2 = "insert into orders(id, order_date, customer_id) values (1, '2008-01-02', 2)";
+ String statement3 = "insert into orders(id, order_date, customer_id) values (1, '2008-01-02', 2)";
+ // Statement 4 addresses the error described in SPR-9982.
+ String statement4 = "INSERT INTO persons( person_id , name) VALUES( 1 , 'Name' )";
+
+ assertEquals("wrong number of statements", 4, statements.size());
+ assertEquals("statement 1 not split correctly", statement1, statements.get(0));
+ assertEquals("statement 2 not split correctly", statement2, statements.get(1));
+ assertEquals("statement 3 not split correctly", statement3, statements.get(2));
+ assertEquals("statement 4 not split correctly", statement4, statements.get(3));
+ }
+
+ /**
+ * See SPR-10330
+ */
+ @Test
+ public void readAndSplitScriptContainingCommentsWithLeadingTabs() throws Exception {
+ EncodedResource resource = new EncodedResource(new ClassPathResource(
+ "test-data-with-comments-and-leading-tabs.sql", getClass()));
+
+ String script = ScriptUtils.readScript(resource);
+
+ char delim = ';';
+ List statements = new ArrayList();
+ ScriptUtils.splitSqlScript(script, delim, statements);
+
+ String statement1 = "insert into customer (id, name) values (1, 'Sam Brannen')";
+ String statement2 = "insert into orders(id, order_date, customer_id) values (1, '2013-06-08', 1)";
+ String statement3 = "insert into orders(id, order_date, customer_id) values (2, '2013-06-08', 1)";
+
+ assertEquals("wrong number of statements", 3, statements.size());
+ assertEquals("statement 1 not split correctly", statement1, statements.get(0));
+ assertEquals("statement 2 not split correctly", statement2, statements.get(1));
+ assertEquals("statement 3 not split correctly", statement3, statements.get(2));
+ }
+
+ /**
+ * See SPR-9531
+ */
+ @Test
+ public void readAndSplitScriptContainingMuliLineComments() throws Exception {
+ EncodedResource resource = new EncodedResource(new ClassPathResource("test-data-with-multi-line-comments.sql",
+ getClass()));
+
+ String script = ScriptUtils.readScript(resource);
+
+ char delim = ';';
+ List statements = new ArrayList();
+ ScriptUtils.splitSqlScript(script, delim, statements);
+
+ String statement1 = "INSERT INTO users(first_name, last_name) VALUES('Juergen', 'Hoeller')";
+ String statement2 = "INSERT INTO users(first_name, last_name) VALUES( 'Sam' , 'Brannen' )";
+
+ assertEquals("wrong number of statements", 2, statements.size());
+ assertEquals("statement 1 not split correctly", statement1, statements.get(0));
+ assertEquals("statement 2 not split correctly", statement2, statements.get(1));
+ }
+
+ @Test
+ public void containsDelimiters() {
+ assertTrue("test with ';' is wrong", !ScriptUtils.containsSqlScriptDelimiters("select 1\n select ';'", ";"));
+ assertTrue("test with delimiter ; is wrong", ScriptUtils.containsSqlScriptDelimiters("select 1; select 2", ";"));
+ assertTrue("test with '\\n' is wrong",
+ !ScriptUtils.containsSqlScriptDelimiters("select 1; select '\\n\n';", "\n"));
+ assertTrue("test with delimiter \\n is wrong",
+ ScriptUtils.containsSqlScriptDelimiters("select 1\n select 2", "\n"));
+ }
+
+ @Test
+ public void executeSqlScript() throws SQLException {
+ EncodedResource schemaResource = new EncodedResource(new ClassPathResource("users-schema.sql", getClass()));
+ EncodedResource commentResource = new EncodedResource(new ClassPathResource(
+ "test-data-with-multi-line-comments.sql", getClass()));
+ Connection connection = db.getConnection();
+
+ ScriptUtils.executeSqlScript(connection, schemaResource, false, false, ScriptUtils.DEFAULT_COMMENT_PREFIX,
+ ScriptUtils.DEFAULT_STATEMENT_SEPARATOR, ScriptUtils.DEFAULT_BLOCK_COMMENT_START_DELIMITER,
+ ScriptUtils.DEFAULT_BLOCK_COMMENT_END_DELIMITER);
+ ScriptUtils.executeSqlScript(connection, commentResource, false, false, ScriptUtils.DEFAULT_COMMENT_PREFIX,
+ ScriptUtils.DEFAULT_STATEMENT_SEPARATOR, ScriptUtils.DEFAULT_BLOCK_COMMENT_START_DELIMITER,
+ ScriptUtils.DEFAULT_BLOCK_COMMENT_END_DELIMITER);
+
+ assertUsersDatabaseCreated("Hoeller", "Brannen");
+ }
+
+ private void assertUsersDatabaseCreated(String... lastNames) {
+ final JdbcTemplate jdbcTemplate = new JdbcTemplate(db);
+ for (String lastName : lastNames) {
+ assertThat("Did not find user with last name [" + lastName + "].",
+ jdbcTemplate.queryForObject("select count(0) from users where last_name = ?", Integer.class, lastName),
+ equalTo(1));
+ }
+ }
+
+}
diff --git a/spring-test/src/test/resources/org/springframework/test/jdbc/test-data-with-comments-and-leading-tabs.sql b/spring-jdbc/src/test/resources/org/springframework/jdbc/datasource/init/test-data-with-comments-and-leading-tabs.sql
similarity index 100%
rename from spring-test/src/test/resources/org/springframework/test/jdbc/test-data-with-comments-and-leading-tabs.sql
rename to spring-jdbc/src/test/resources/org/springframework/jdbc/datasource/init/test-data-with-comments-and-leading-tabs.sql
diff --git a/spring-test/src/test/resources/org/springframework/test/jdbc/test-data-with-comments.sql b/spring-jdbc/src/test/resources/org/springframework/jdbc/datasource/init/test-data-with-comments.sql
similarity index 100%
rename from spring-test/src/test/resources/org/springframework/test/jdbc/test-data-with-comments.sql
rename to spring-jdbc/src/test/resources/org/springframework/jdbc/datasource/init/test-data-with-comments.sql
diff --git a/spring-jdbc/src/test/resources/org/springframework/jdbc/datasource/init/test-data-with-multi-line-comments.sql b/spring-jdbc/src/test/resources/org/springframework/jdbc/datasource/init/test-data-with-multi-line-comments.sql
new file mode 100644
index 0000000000..5886bd002e
--- /dev/null
+++ b/spring-jdbc/src/test/resources/org/springframework/jdbc/datasource/init/test-data-with-multi-line-comments.sql
@@ -0,0 +1,17 @@
+/* This is a multi line comment
+ * The next comment line has no text
+
+ * The next comment line starts with a space.
+ * x, y, z...
+ */
+
+INSERT INTO users(first_name, last_name) VALUES('Juergen', 'Hoeller');
+-- This is also a comment.
+/*
+ * Let's add another comment
+ * that covers multiple lines
+ */INSERT INTO
+users(first_name, last_name)
+VALUES( 'Sam' -- first_name
+ , 'Brannen' -- last_name
+);--
\ No newline at end of file
diff --git a/spring-test/src/main/java/org/springframework/test/context/junit4/AbstractTransactionalJUnit4SpringContextTests.java b/spring-test/src/main/java/org/springframework/test/context/junit4/AbstractTransactionalJUnit4SpringContextTests.java
index c1494050a2..2bc4582716 100644
--- a/spring-test/src/main/java/org/springframework/test/context/junit4/AbstractTransactionalJUnit4SpringContextTests.java
+++ b/spring-test/src/main/java/org/springframework/test/context/junit4/AbstractTransactionalJUnit4SpringContextTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2013 the original author or authors.
+ * Copyright 2002-2014 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.
@@ -21,9 +21,10 @@ import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.core.io.Resource;
-import org.springframework.core.io.support.EncodedResource;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.datasource.init.DatabasePopulatorUtils;
+import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestExecutionListeners;
import org.springframework.test.context.transaction.TransactionalTestExecutionListener;
@@ -171,21 +172,24 @@ public abstract class AbstractTransactionalJUnit4SpringContextTests extends Abst
/**
* Execute the given SQL script.
* Use with caution outside of a transaction!
- *
The script will normally be loaded by classpath. There should be one
- * statement per line. Any semicolons will be removed. Do not use this
- * method to execute DDL if you expect rollback.
+ *
The script will normally be loaded by classpath.
+ *
Do not use this method to execute DDL if you expect rollback.
* @param sqlResourcePath the Spring resource path for the SQL script
* @param continueOnError whether or not to continue without throwing an
* exception in the event of an error
* @throws DataAccessException if there is an error executing a statement
- * and continueOnError was {@code false}
- * @see JdbcTestUtils#executeSqlScript(JdbcTemplate, EncodedResource, boolean)
+ * @see ResourceDatabasePopulator
+ * @see DatabasePopulatorUtils
* @see #setSqlScriptEncoding
*/
protected void executeSqlScript(String sqlResourcePath, boolean continueOnError) throws DataAccessException {
Resource resource = this.applicationContext.getResource(sqlResourcePath);
- JdbcTestUtils.executeSqlScript(this.jdbcTemplate, new EncodedResource(resource, this.sqlScriptEncoding),
- continueOnError);
+ ResourceDatabasePopulator databasePopulator = new ResourceDatabasePopulator();
+ databasePopulator.setContinueOnError(continueOnError);
+ databasePopulator.addScript(resource);
+ databasePopulator.setSqlScriptEncoding(this.sqlScriptEncoding);
+
+ DatabasePopulatorUtils.execute(databasePopulator, jdbcTemplate.getDataSource());
}
}
diff --git a/spring-test/src/main/java/org/springframework/test/context/testng/AbstractTransactionalTestNGSpringContextTests.java b/spring-test/src/main/java/org/springframework/test/context/testng/AbstractTransactionalTestNGSpringContextTests.java
index e71b82d529..3d99d31c71 100644
--- a/spring-test/src/main/java/org/springframework/test/context/testng/AbstractTransactionalTestNGSpringContextTests.java
+++ b/spring-test/src/main/java/org/springframework/test/context/testng/AbstractTransactionalTestNGSpringContextTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2013 the original author or authors.
+ * Copyright 2002-2014 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.
@@ -21,9 +21,10 @@ import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.core.io.Resource;
-import org.springframework.core.io.support.EncodedResource;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.datasource.init.DatabasePopulatorUtils;
+import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
import org.springframework.test.context.TestExecutionListeners;
import org.springframework.test.context.transaction.TransactionalTestExecutionListener;
import org.springframework.test.jdbc.JdbcTestUtils;
@@ -162,21 +163,24 @@ public abstract class AbstractTransactionalTestNGSpringContextTests extends Abst
/**
* Execute the given SQL script.
*
Use with caution outside of a transaction!
- *
The script will normally be loaded by classpath. There should be one
- * statement per line. Any semicolons will be removed. Do not use this
- * method to execute DDL if you expect rollback.
+ *
The script will normally be loaded by classpath.
+ *
Do not use this method to execute DDL if you expect rollback.
* @param sqlResourcePath the Spring resource path for the SQL script
* @param continueOnError whether or not to continue without throwing an
* exception in the event of an error
* @throws DataAccessException if there is an error executing a statement
- * and continueOnError was {@code false}
- * @see JdbcTestUtils#executeSqlScript(JdbcTemplate, EncodedResource, boolean)
+ * @see ResourceDatabasePopulator
+ * @see DatabasePopulatorUtils
* @see #setSqlScriptEncoding
*/
protected void executeSqlScript(String sqlResourcePath, boolean continueOnError) throws DataAccessException {
Resource resource = this.applicationContext.getResource(sqlResourcePath);
- JdbcTestUtils.executeSqlScript(this.jdbcTemplate, new EncodedResource(resource, this.sqlScriptEncoding),
- continueOnError);
+ ResourceDatabasePopulator databasePopulator = new ResourceDatabasePopulator();
+ databasePopulator.setContinueOnError(continueOnError);
+ databasePopulator.addScript(resource);
+ databasePopulator.setSqlScriptEncoding(this.sqlScriptEncoding);
+
+ DatabasePopulatorUtils.execute(databasePopulator, jdbcTemplate.getDataSource());
}
}
diff --git a/spring-test/src/main/java/org/springframework/test/jdbc/JdbcTestUtils.java b/spring-test/src/main/java/org/springframework/test/jdbc/JdbcTestUtils.java
index 27d14b82ac..dd74f449f6 100644
--- a/spring-test/src/main/java/org/springframework/test/jdbc/JdbcTestUtils.java
+++ b/spring-test/src/main/java/org/springframework/test/jdbc/JdbcTestUtils.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2013 the original author or authors.
+ * Copyright 2002-2014 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.
@@ -18,19 +18,20 @@ package org.springframework.test.jdbc;
import java.io.IOException;
import java.io.LineNumberReader;
-import java.util.LinkedList;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.support.EncodedResource;
import org.springframework.dao.DataAccessException;
-import org.springframework.dao.DataAccessResourceFailureException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.SqlParameterValue;
+import org.springframework.jdbc.datasource.init.DatabasePopulatorUtils;
import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
+import org.springframework.jdbc.datasource.init.ScriptUtils;
import org.springframework.util.StringUtils;
/**
@@ -41,16 +42,13 @@ import org.springframework.util.StringUtils;
* @author Sam Brannen
* @author Juergen Hoeller
* @author Phillip Webb
+ * @author Chris Baldwin
* @since 2.5.4
*/
public class JdbcTestUtils {
private static final Log logger = LogFactory.getLog(JdbcTestUtils.class);
- private static final String DEFAULT_COMMENT_PREFIX = "--";
-
- private static final char DEFAULT_STATEMENT_SEPARATOR = ';';
-
/**
* Count the rows in the given table.
@@ -121,14 +119,13 @@ public class JdbcTestUtils {
* optionally the scale.
* @return the number of rows deleted from the table
*/
- public static int deleteFromTableWhere(JdbcTemplate jdbcTemplate, String tableName,
- String whereClause, Object... args) {
+ public static int deleteFromTableWhere(JdbcTemplate jdbcTemplate, String tableName, String whereClause,
+ Object... args) {
String sql = "DELETE FROM " + tableName;
if (StringUtils.hasText(whereClause)) {
sql += " WHERE " + whereClause;
}
- int rowCount = (args != null && args.length > 0 ? jdbcTemplate.update(sql, args)
- : jdbcTemplate.update(sql));
+ int rowCount = (args != null && args.length > 0 ? jdbcTemplate.update(sql, args) : jdbcTemplate.update(sql));
if (logger.isInfoEnabled()) {
logger.info("Deleted " + rowCount + " rows from table " + tableName);
}
@@ -162,8 +159,13 @@ public class JdbcTestUtils {
* @throws DataAccessException if there is an error executing a statement
* and {@code continueOnError} is {@code false}
* @see ResourceDatabasePopulator
+ * @see DatabasePopulatorUtils
* @see #executeSqlScript(JdbcTemplate, Resource, boolean)
+ * @deprecated as of Spring 4.0.3, in favor of using
+ * {@link org.springframework.jdbc.datasource.init.ScriptUtils#executeSqlScript}
+ * or {@link org.springframework.jdbc.datasource.init.ResourceDatabasePopulator}.
*/
+ @Deprecated
public static void executeSqlScript(JdbcTemplate jdbcTemplate, ResourceLoader resourceLoader,
String sqlResourcePath, boolean continueOnError) throws DataAccessException {
Resource resource = resourceLoader.getResource(sqlResourcePath);
@@ -185,8 +187,13 @@ public class JdbcTestUtils {
* @throws DataAccessException if there is an error executing a statement
* and {@code continueOnError} is {@code false}
* @see ResourceDatabasePopulator
+ * @see DatabasePopulatorUtils
* @see #executeSqlScript(JdbcTemplate, EncodedResource, boolean)
+ * @deprecated as of Spring 4.0.3, in favor of using
+ * {@link org.springframework.jdbc.datasource.init.ScriptUtils#executeSqlScript}
+ * or {@link org.springframework.jdbc.datasource.init.ResourceDatabasePopulator}.
*/
+ @Deprecated
public static void executeSqlScript(JdbcTemplate jdbcTemplate, Resource resource, boolean continueOnError)
throws DataAccessException {
executeSqlScript(jdbcTemplate, new EncodedResource(resource), continueOnError);
@@ -205,63 +212,20 @@ public class JdbcTestUtils {
* @throws DataAccessException if there is an error executing a statement
* and {@code continueOnError} is {@code false}
* @see ResourceDatabasePopulator
+ * @see DatabasePopulatorUtils
+ * @deprecated as of Spring 4.0.3, in favor of using
+ * {@link org.springframework.jdbc.datasource.init.ScriptUtils#executeSqlScript}
+ * or {@link org.springframework.jdbc.datasource.init.ResourceDatabasePopulator}.
*/
+ @Deprecated
public static void executeSqlScript(JdbcTemplate jdbcTemplate, EncodedResource resource, boolean continueOnError)
throws DataAccessException {
+ ResourceDatabasePopulator databasePopulator = new ResourceDatabasePopulator();
+ databasePopulator.setContinueOnError(continueOnError);
+ databasePopulator.addScript(resource.getResource());
+ databasePopulator.setSqlScriptEncoding(resource.getEncoding());
- if (logger.isInfoEnabled()) {
- logger.info("Executing SQL script from " + resource);
- }
- long startTime = System.currentTimeMillis();
- List statements = new LinkedList();
- LineNumberReader reader = null;
- try {
- reader = new LineNumberReader(resource.getReader());
- String script = readScript(reader);
- char delimiter = DEFAULT_STATEMENT_SEPARATOR;
- if (!containsSqlScriptDelimiters(script, delimiter)) {
- delimiter = '\n';
- }
- splitSqlScript(script, delimiter, statements);
- int lineNumber = 0;
- for (String statement : statements) {
- lineNumber++;
- try {
- int rowsAffected = jdbcTemplate.update(statement);
- if (logger.isDebugEnabled()) {
- logger.debug(rowsAffected + " rows affected by SQL: " + statement);
- }
- }
- catch (DataAccessException ex) {
- if (continueOnError) {
- if (logger.isWarnEnabled()) {
- logger.warn("Failed to execute SQL script statement at line " + lineNumber
- + " of resource " + resource + ": " + statement, ex);
- }
- }
- else {
- throw ex;
- }
- }
- }
- long elapsedTime = System.currentTimeMillis() - startTime;
- if (logger.isInfoEnabled()) {
- logger.info(String.format("Executed SQL script from %s in %s ms.", resource, elapsedTime));
- }
- }
- catch (IOException ex) {
- throw new DataAccessResourceFailureException("Failed to open SQL script from " + resource, ex);
- }
- finally {
- try {
- if (reader != null) {
- reader.close();
- }
- }
- catch (IOException ex) {
- // ignore
- }
- }
+ DatabasePopulatorUtils.execute(databasePopulator, jdbcTemplate.getDataSource());
}
/**
@@ -272,9 +236,12 @@ public class JdbcTestUtils {
* to be processed
* @return a {@code String} containing the script lines
* @see #readScript(LineNumberReader, String)
+ * @deprecated as of Spring 4.0.3, in favor of using
+ * {@link org.springframework.jdbc.datasource.init.ScriptUtils#readScript(LineNumberReader, String, String)}
*/
+ @Deprecated
public static String readScript(LineNumberReader lineNumberReader) throws IOException {
- return readScript(lineNumberReader, DEFAULT_COMMENT_PREFIX);
+ return readScript(lineNumberReader, ScriptUtils.DEFAULT_COMMENT_PREFIX);
}
/**
@@ -287,21 +254,12 @@ public class JdbcTestUtils {
* to be processed
* @param commentPrefix the prefix that identifies comments in the SQL script — typically "--"
* @return a {@code String} containing the script lines
+ * @deprecated as of Spring 4.0.3, in favor of using
+ * {@link org.springframework.jdbc.datasource.init.ScriptUtils#readScript(LineNumberReader, String, String)}
*/
+ @Deprecated
public static String readScript(LineNumberReader lineNumberReader, String commentPrefix) throws IOException {
- String currentStatement = lineNumberReader.readLine();
- StringBuilder scriptBuilder = new StringBuilder();
- while (currentStatement != null) {
- if (StringUtils.hasText(currentStatement)
- && (commentPrefix != null && !currentStatement.startsWith(commentPrefix))) {
- if (scriptBuilder.length() > 0) {
- scriptBuilder.append('\n');
- }
- scriptBuilder.append(currentStatement);
- }
- currentStatement = lineNumberReader.readLine();
- }
- return scriptBuilder.toString();
+ return ScriptUtils.readScript(lineNumberReader, commentPrefix, ScriptUtils.DEFAULT_STATEMENT_SEPARATOR);
}
/**
@@ -309,19 +267,12 @@ public class JdbcTestUtils {
* @param script the SQL script
* @param delim character delimiting each statement — typically a ';' character
* @return {@code true} if the script contains the delimiter; {@code false} otherwise
+ * @deprecated as of Spring 4.0.3, in favor of using
+ * {@link org.springframework.jdbc.datasource.init.ScriptUtils#containsSqlScriptDelimiters}
*/
+ @Deprecated
public static boolean containsSqlScriptDelimiters(String script, char delim) {
- boolean inLiteral = false;
- char[] content = script.toCharArray();
- for (int i = 0; i < script.length(); i++) {
- if (content[i] == '\'') {
- inLiteral = !inLiteral;
- }
- if (content[i] == delim && !inLiteral) {
- return true;
- }
- }
- return false;
+ return ScriptUtils.containsSqlScriptDelimiters(script, String.valueOf(delim));
}
/**
@@ -335,83 +286,11 @@ public class JdbcTestUtils {
* @param script the SQL script
* @param delim character delimiting each statement — typically a ';' character
* @param statements the list that will contain the individual statements
+ * @deprecated as of Spring 4.0.3, in favor of using
+ * {@link org.springframework.jdbc.datasource.init.ScriptUtils#splitSqlScript(String, char, List)}
*/
+ @Deprecated
public static void splitSqlScript(String script, char delim, List statements) {
- splitSqlScript(script, "" + delim, DEFAULT_COMMENT_PREFIX, statements);
+ ScriptUtils.splitSqlScript(script, delim, statements);
}
-
- /**
- * Split an SQL script into separate statements delimited by the provided
- * delimiter string. Each individual statement will be added to the provided
- * {@code List}.
- * Within a statement, the provided {@code commentPrefix} will be honored;
- * any text beginning with the comment prefix and extending to the end of the
- * line will be omitted from the statement. In addition, multiple adjacent
- * whitespace characters will be collapsed into a single space.
- * @param script the SQL script
- * @param delim character delimiting each statement — typically a ';' character
- * @param commentPrefix the prefix that identifies line comments in the SQL script — typically "--"
- * @param statements the List that will contain the individual statements
- */
- private static void splitSqlScript(String script, String delim, String commentPrefix, List statements) {
- StringBuilder sb = new StringBuilder();
- boolean inLiteral = false;
- boolean inEscape = false;
- char[] content = script.toCharArray();
- for (int i = 0; i < script.length(); i++) {
- char c = content[i];
- if (inEscape) {
- inEscape = false;
- sb.append(c);
- continue;
- }
- // MySQL style escapes
- if (c == '\\') {
- inEscape = true;
- sb.append(c);
- continue;
- }
- if (c == '\'') {
- inLiteral = !inLiteral;
- }
- if (!inLiteral) {
- if (script.startsWith(delim, i)) {
- // we've reached the end of the current statement
- if (sb.length() > 0) {
- statements.add(sb.toString());
- sb = new StringBuilder();
- }
- i += delim.length() - 1;
- continue;
- }
- else if (script.startsWith(commentPrefix, i)) {
- // skip over any content from the start of the comment to the EOL
- int indexOfNextNewline = script.indexOf("\n", i);
- if (indexOfNextNewline > i) {
- i = indexOfNextNewline;
- continue;
- }
- else {
- // if there's no newline after the comment, we must be at the end
- // of the script, so stop here.
- break;
- }
- }
- else if (c == ' ' || c == '\n' || c == '\t') {
- // avoid multiple adjacent whitespace characters
- if (sb.length() > 0 && sb.charAt(sb.length() - 1) != ' ') {
- c = ' ';
- }
- else {
- continue;
- }
- }
- }
- sb.append(c);
- }
- if (StringUtils.hasText(sb)) {
- statements.add(sb.toString());
- }
- }
-
}
diff --git a/spring-test/src/test/java/org/springframework/test/jdbc/JdbcTestUtilsIntegrationTests.java b/spring-test/src/test/java/org/springframework/test/jdbc/JdbcTestUtilsIntegrationTests.java
new file mode 100644
index 0000000000..5f9897e5bc
--- /dev/null
+++ b/spring-test/src/test/java/org/springframework/test/jdbc/JdbcTestUtilsIntegrationTests.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2002-2014 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.test.jdbc;
+
+import java.util.Arrays;
+
+import org.junit.After;
+import org.junit.Test;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.support.EncodedResource;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase;
+import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
+
+import static org.junit.Assert.*;
+
+/**
+ * Integration tests for {@link JdbcTestUtils}.
+ *
+ * @author Sam Brannen
+ * @since 4.0.3
+ * @see JdbcTestUtilsTests
+ */
+public class JdbcTestUtilsIntegrationTests {
+
+ private final EmbeddedDatabase db = new EmbeddedDatabaseBuilder().build();
+
+ private JdbcTemplate jdbcTemplate = new JdbcTemplate(db);
+
+
+ @After
+ public void shutdown() {
+ db.shutdown();
+ }
+
+ @Test
+ @SuppressWarnings("deprecation")
+ public void executeSqlScriptsAndcountRowsInTableWhere() throws Exception {
+
+ for (String script : Arrays.asList("schema.sql", "data.sql")) {
+ Resource resource = new ClassPathResource(script, getClass());
+ JdbcTestUtils.executeSqlScript(this.jdbcTemplate, new EncodedResource(resource), false);
+ }
+
+ assertEquals(1, JdbcTestUtils.countRowsInTableWhere(jdbcTemplate, "person", "name = 'bob'"));
+ }
+
+}
diff --git a/spring-test/src/test/java/org/springframework/test/jdbc/JdbcTestUtilsTests.java b/spring-test/src/test/java/org/springframework/test/jdbc/JdbcTestUtilsTests.java
index a67697165c..1c9452d034 100644
--- a/spring-test/src/test/java/org/springframework/test/jdbc/JdbcTestUtilsTests.java
+++ b/spring-test/src/test/java/org/springframework/test/jdbc/JdbcTestUtilsTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2013 the original author or authors.
+ * Copyright 2002-2014 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,31 +16,22 @@
package org.springframework.test.jdbc;
-import static org.hamcrest.Matchers.equalTo;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.BDDMockito.given;
-
-import java.io.LineNumberReader;
-import java.util.ArrayList;
-import java.util.List;
-
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
-import org.springframework.core.io.ClassPathResource;
-import org.springframework.core.io.support.EncodedResource;
import org.springframework.jdbc.core.JdbcTemplate;
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.*;
+import static org.mockito.BDDMockito.*;
+
/**
* Unit tests for {@link JdbcTestUtils}.
*
- * @author Thomas Risberg
- * @author Sam Brannen
* @author Phillip Webb
* @since 2.5.4
+ * @see JdbcTestUtilsIntegrationTests
*/
@RunWith(MockitoJUnitRunner.class)
public class JdbcTestUtilsTests {
@@ -49,102 +40,6 @@ public class JdbcTestUtilsTests {
private JdbcTemplate jdbcTemplate;
- @Test
- public void containsDelimiters() {
- assertTrue("test with ';' is wrong", !JdbcTestUtils.containsSqlScriptDelimiters("select 1\n select ';'", ';'));
- assertTrue("test with delimiter ; is wrong",
- JdbcTestUtils.containsSqlScriptDelimiters("select 1; select 2", ';'));
- assertTrue("test with '\\n' is wrong",
- !JdbcTestUtils.containsSqlScriptDelimiters("select 1; select '\\n\n';", '\n'));
- assertTrue("test with delimiter \\n is wrong",
- JdbcTestUtils.containsSqlScriptDelimiters("select 1\n select 2", '\n'));
- }
-
- @Test
- public void splitSqlScriptDelimitedWithSemicolon() {
- String rawStatement1 = "insert into customer (id, name)\nvalues (1, 'Rod ; Johnson'), (2, 'Adrian \n Collier')";
- String cleanedStatement1 = "insert into customer (id, name) values (1, 'Rod ; Johnson'), (2, 'Adrian \n Collier')";
- String rawStatement2 = "insert into orders(id, order_date, customer_id)\nvalues (1, '2008-01-02', 2)";
- String cleanedStatement2 = "insert into orders(id, order_date, customer_id) values (1, '2008-01-02', 2)";
- String rawStatement3 = "insert into orders(id, order_date, customer_id) values (1, '2008-01-02', 2)";
- String cleanedStatement3 = "insert into orders(id, order_date, customer_id) values (1, '2008-01-02', 2)";
- char delim = ';';
- String script = rawStatement1 + delim + rawStatement2 + delim + rawStatement3 + delim;
- List statements = new ArrayList();
- JdbcTestUtils.splitSqlScript(script, delim, statements);
- assertEquals("wrong number of statements", 3, statements.size());
- assertEquals("statement 1 not split correctly", cleanedStatement1, statements.get(0));
- assertEquals("statement 2 not split correctly", cleanedStatement2, statements.get(1));
- assertEquals("statement 3 not split correctly", cleanedStatement3, statements.get(2));
- }
-
- @Test
- public void splitSqlScriptDelimitedWithNewLine() {
- String statement1 = "insert into customer (id, name) values (1, 'Rod ; Johnson'), (2, 'Adrian \n Collier')";
- String statement2 = "insert into orders(id, order_date, customer_id) values (1, '2008-01-02', 2)";
- String statement3 = "insert into orders(id, order_date, customer_id) values (1, '2008-01-02', 2)";
- char delim = '\n';
- String script = statement1 + delim + statement2 + delim + statement3 + delim;
- List statements = new ArrayList();
- JdbcTestUtils.splitSqlScript(script, delim, statements);
- assertEquals("wrong number of statements", 3, statements.size());
- assertEquals("statement 1 not split correctly", statement1, statements.get(0));
- assertEquals("statement 2 not split correctly", statement2, statements.get(1));
- assertEquals("statement 3 not split correctly", statement3, statements.get(2));
- }
-
- @Test
- public void readAndSplitScriptContainingComments() throws Exception {
-
- EncodedResource resource = new EncodedResource(new ClassPathResource("test-data-with-comments.sql", getClass()));
- LineNumberReader lineNumberReader = new LineNumberReader(resource.getReader());
-
- String script = JdbcTestUtils.readScript(lineNumberReader);
-
- char delim = ';';
- List statements = new ArrayList();
- JdbcTestUtils.splitSqlScript(script, delim, statements);
-
- String statement1 = "insert into customer (id, name) values (1, 'Rod; Johnson'), (2, 'Adrian Collier')";
- String statement2 = "insert into orders(id, order_date, customer_id) values (1, '2008-01-02', 2)";
- String statement3 = "insert into orders(id, order_date, customer_id) values (1, '2008-01-02', 2)";
- // Statement 4 addresses the error described in SPR-9982.
- String statement4 = "INSERT INTO persons( person_id , name) VALUES( 1 , 'Name' )";
-
- assertEquals("wrong number of statements", 4, statements.size());
- assertEquals("statement 1 not split correctly", statement1, statements.get(0));
- assertEquals("statement 2 not split correctly", statement2, statements.get(1));
- assertEquals("statement 3 not split correctly", statement3, statements.get(2));
- assertEquals("statement 4 not split correctly", statement4, statements.get(3));
- }
-
- /**
- * See SPR-10330
- * @since 4.0
- */
- @Test
- public void readAndSplitScriptContainingCommentsWithLeadingTabs() throws Exception {
-
- EncodedResource resource = new EncodedResource(new ClassPathResource(
- "test-data-with-comments-and-leading-tabs.sql", getClass()));
- LineNumberReader lineNumberReader = new LineNumberReader(resource.getReader());
-
- String script = JdbcTestUtils.readScript(lineNumberReader);
-
- char delim = ';';
- List statements = new ArrayList();
- JdbcTestUtils.splitSqlScript(script, delim, statements);
-
- String statement1 = "insert into customer (id, name) values (1, 'Sam Brannen')";
- String statement2 = "insert into orders(id, order_date, customer_id) values (1, '2013-06-08', 1)";
- String statement3 = "insert into orders(id, order_date, customer_id) values (2, '2013-06-08', 1)";
-
- assertEquals("wrong number of statements", 3, statements.size());
- assertEquals("statement 1 not split correctly", statement1, statements.get(0));
- assertEquals("statement 2 not split correctly", statement2, statements.get(1));
- assertEquals("statement 3 not split correctly", statement3, statements.get(2));
- }
-
@Test
public void deleteWithoutWhereClause() throws Exception {
given(jdbcTemplate.update("DELETE FROM person")).willReturn(10);
diff --git a/spring-test/src/test/resources/org/springframework/test/jdbc/data.sql b/spring-test/src/test/resources/org/springframework/test/jdbc/data.sql
new file mode 100644
index 0000000000..10d02a9c91
--- /dev/null
+++ b/spring-test/src/test/resources/org/springframework/test/jdbc/data.sql
@@ -0,0 +1 @@
+INSERT INTO person VALUES('bob');
\ No newline at end of file
diff --git a/spring-test/src/test/resources/org/springframework/test/jdbc/schema.sql b/spring-test/src/test/resources/org/springframework/test/jdbc/schema.sql
new file mode 100644
index 0000000000..d5bacef4fb
--- /dev/null
+++ b/spring-test/src/test/resources/org/springframework/test/jdbc/schema.sql
@@ -0,0 +1,4 @@
+CREATE TABLE person (
+ name VARCHAR(20) NOT NULL,
+ PRIMARY KEY(name)
+);
\ No newline at end of file