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
index 21bbe07076c..6aaaec04054 100644
--- 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
@@ -45,6 +45,7 @@ import org.springframework.util.StringUtils;
* @author Chris Beams
* @author Oliver Gierke
* @author Chris Baldwin
+ * @author Nicolas Debeissat
* @since 4.0.3
*/
public abstract class ScriptUtils {
@@ -173,7 +174,8 @@ public abstract class ScriptUtils {
Assert.hasText(blockCommentEndDelimiter, "blockCommentEndDelimiter must not be null or empty");
StringBuilder sb = new StringBuilder();
- boolean inLiteral = false;
+ boolean inSingleQuote = false;
+ boolean inDoubleQuote = false;
boolean inEscape = false;
char[] content = script.toCharArray();
for (int i = 0; i < script.length(); i++) {
@@ -189,10 +191,13 @@ public abstract class ScriptUtils {
sb.append(c);
continue;
}
- if (c == '\'') {
- inLiteral = !inLiteral;
+ if (!inDoubleQuote && (c == '\'')) {
+ inSingleQuote = !inSingleQuote;
}
- if (!inLiteral) {
+ else if (!inSingleQuote && (c == '"')) {
+ inDoubleQuote = !inDoubleQuote;
+ }
+ if (!inSingleQuote && !inDoubleQuote) {
if (script.startsWith(separator, i)) {
// we've reached the end of the current statement
if (sb.length() > 0) {
diff --git a/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/init/ScriptUtilsIntegrationTests.java b/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/init/ScriptUtilsIntegrationTests.java
index 7a34a9db8ab..7bd998b1337 100644
--- a/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/init/ScriptUtilsIntegrationTests.java
+++ b/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/init/ScriptUtilsIntegrationTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2014 the original author or authors.
+ * Copyright 2002-2015 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,6 +18,7 @@ package org.springframework.jdbc.datasource.init;
import java.sql.SQLException;
+import org.junit.Before;
import org.junit.Test;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
@@ -28,8 +29,8 @@ import static org.springframework.jdbc.datasource.init.ScriptUtils.*;
* Integration tests for {@link ScriptUtils}.
*
* @author Sam Brannen
- * @see ScriptUtilsUnitTests
* @since 4.0.3
+ * @see ScriptUtilsUnitTests
*/
public class ScriptUtilsIntegrationTests extends AbstractDatabaseInitializationTests {
@@ -37,11 +38,23 @@ public class ScriptUtilsIntegrationTests extends AbstractDatabaseInitializationT
return EmbeddedDatabaseType.HSQL;
}
+ @Before
+ public void setUpSchema() throws SQLException {
+ executeSqlScript(db.getConnection(), usersSchema());
+ }
+
@Test
public void executeSqlScriptContainingMuliLineComments() throws SQLException {
- executeSqlScript(db.getConnection(), usersSchema());
executeSqlScript(db.getConnection(), resource("test-data-with-multi-line-comments.sql"));
+ assertUsersDatabaseCreated("Hoeller", "Brannen");
+ }
+ /**
+ * @since 4.2
+ */
+ @Test
+ public void executeSqlScriptContainingSingleQuotesNestedInsideDoubleQuotes() throws SQLException {
+ executeSqlScript(db.getConnection(), resource("users-data-with-single-quotes-nested-in-double-quotes.sql"));
assertUsersDatabaseCreated("Hoeller", "Brannen");
}
diff --git a/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/init/ScriptUtilsUnitTests.java b/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/init/ScriptUtilsUnitTests.java
index 224a22b75c7..ab9a5a5eb92 100644
--- a/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/init/ScriptUtilsUnitTests.java
+++ b/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/init/ScriptUtilsUnitTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2014 the original author or authors.
+ * Copyright 2002-2015 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.
@@ -34,8 +34,9 @@ import static org.springframework.jdbc.datasource.init.ScriptUtils.*;
* @author Sam Brannen
* @author Phillip Webb
* @author Chris Baldwin
- * @see ScriptUtilsIntegrationTests
+ * @author Nicolas Debeissat
* @since 4.0.3
+ * @see ScriptUtilsIntegrationTests
*/
public class ScriptUtilsUnitTests {
@@ -85,6 +86,22 @@ public class ScriptUtilsUnitTests {
statements.get(0));
}
+ /**
+ * See SPR-13218
+ */
+ @Test
+ public void splitScriptWithSingleQuotesNestedInsideDoubleQuotes() throws Exception {
+ String statement1 = "select '1' as \"Dogbert's owner's\" from dual";
+ String statement2 = "select '2' as \"Dilbert's\" from dual";
+ char delim = ';';
+ String script = statement1 + delim + statement2 + delim;
+ List statements = new ArrayList();
+ splitSqlScript(script, ';', statements);
+ 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));
+ }
+
/**
* See SPR-11560
*/
diff --git a/spring-jdbc/src/test/resources/org/springframework/jdbc/datasource/init/users-data-with-single-quotes-nested-in-double-quotes.sql b/spring-jdbc/src/test/resources/org/springframework/jdbc/datasource/init/users-data-with-single-quotes-nested-in-double-quotes.sql
new file mode 100644
index 00000000000..1f5e3e08882
--- /dev/null
+++ b/spring-jdbc/src/test/resources/org/springframework/jdbc/datasource/init/users-data-with-single-quotes-nested-in-double-quotes.sql
@@ -0,0 +1,7 @@
+INSERT INTO users(first_name, last_name) VALUES('Juergen', 'Hoeller');
+
+-- The following is not actually used; we just want to ensure that it does not
+-- result in a parsing exception due to the nested single quote.
+SELECT last_name AS "Juergen's Last Name" FROM users WHERE last_name='Hoeller';
+
+INSERT INTO users(first_name, last_name) values('Sam', 'Brannen');
\ No newline at end of file