Skip to content

Commit 649d145

Browse files
committed
Merge pull request #835 from ndebeiss/master
* ndebeiss-master: Support single quotes nested in double quotes in SQL scripts
2 parents de6bbe7 + 629bcb6 commit 649d145

File tree

4 files changed

+51
-9
lines changed

4 files changed

+51
-9
lines changed

spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/ScriptUtils.java

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
* @author Chris Beams
4646
* @author Oliver Gierke
4747
* @author Chris Baldwin
48+
* @author Nicolas Debeissat
4849
* @since 4.0.3
4950
*/
5051
public abstract class ScriptUtils {
@@ -173,7 +174,8 @@ public static void splitSqlScript(EncodedResource resource, String script, Strin
173174
Assert.hasText(blockCommentEndDelimiter, "blockCommentEndDelimiter must not be null or empty");
174175

175176
StringBuilder sb = new StringBuilder();
176-
boolean inLiteral = false;
177+
boolean inSingleQuote = false;
178+
boolean inDoubleQuote = false;
177179
boolean inEscape = false;
178180
char[] content = script.toCharArray();
179181
for (int i = 0; i < script.length(); i++) {
@@ -189,10 +191,13 @@ public static void splitSqlScript(EncodedResource resource, String script, Strin
189191
sb.append(c);
190192
continue;
191193
}
192-
if (c == '\'') {
193-
inLiteral = !inLiteral;
194+
if (!inDoubleQuote && (c == '\'')) {
195+
inSingleQuote = !inSingleQuote;
196+
}
197+
else if (!inSingleQuote && (c == '"')) {
198+
inDoubleQuote = !inDoubleQuote;
194199
}
195-
if (!inLiteral) {
200+
if (!inSingleQuote && !inDoubleQuote) {
196201
if (script.startsWith(separator, i)) {
197202
// we've reached the end of the current statement
198203
if (sb.length() > 0) {

spring-jdbc/src/test/java/org/springframework/jdbc/datasource/init/ScriptUtilsIntegrationTests.java

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2014 the original author or authors.
2+
* Copyright 2002-2015 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@
1818

1919
import java.sql.SQLException;
2020

21+
import org.junit.Before;
2122
import org.junit.Test;
2223

2324
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
@@ -28,20 +29,32 @@
2829
* Integration tests for {@link ScriptUtils}.
2930
*
3031
* @author Sam Brannen
31-
* @see ScriptUtilsUnitTests
3232
* @since 4.0.3
33+
* @see ScriptUtilsUnitTests
3334
*/
3435
public class ScriptUtilsIntegrationTests extends AbstractDatabaseInitializationTests {
3536

3637
protected EmbeddedDatabaseType getEmbeddedDatabaseType() {
3738
return EmbeddedDatabaseType.HSQL;
3839
}
3940

41+
@Before
42+
public void setUpSchema() throws SQLException {
43+
executeSqlScript(db.getConnection(), usersSchema());
44+
}
45+
4046
@Test
4147
public void executeSqlScriptContainingMuliLineComments() throws SQLException {
42-
executeSqlScript(db.getConnection(), usersSchema());
4348
executeSqlScript(db.getConnection(), resource("test-data-with-multi-line-comments.sql"));
49+
assertUsersDatabaseCreated("Hoeller", "Brannen");
50+
}
4451

52+
/**
53+
* @since 4.2
54+
*/
55+
@Test
56+
public void executeSqlScriptContainingSingleQuotesNestedInsideDoubleQuotes() throws SQLException {
57+
executeSqlScript(db.getConnection(), resource("users-data-with-single-quotes-nested-in-double-quotes.sql"));
4558
assertUsersDatabaseCreated("Hoeller", "Brannen");
4659
}
4760

spring-jdbc/src/test/java/org/springframework/jdbc/datasource/init/ScriptUtilsUnitTests.java

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2014 the original author or authors.
2+
* Copyright 2002-2015 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -34,8 +34,9 @@
3434
* @author Sam Brannen
3535
* @author Phillip Webb
3636
* @author Chris Baldwin
37-
* @see ScriptUtilsIntegrationTests
37+
* @author Nicolas Debeissat
3838
* @since 4.0.3
39+
* @see ScriptUtilsIntegrationTests
3940
*/
4041
public class ScriptUtilsUnitTests {
4142

@@ -85,6 +86,22 @@ public void splitSqlScriptDelimitedWithNewLineButDefaultDelimiterSpecified() {
8586
statements.get(0));
8687
}
8788

89+
/**
90+
* See <a href="https://jira.spring.io/browse/SPR-13218">SPR-13218</a>
91+
*/
92+
@Test
93+
public void splitScriptWithSingleQuotesNestedInsideDoubleQuotes() throws Exception {
94+
String statement1 = "select '1' as \"Dogbert's owner's\" from dual";
95+
String statement2 = "select '2' as \"Dilbert's\" from dual";
96+
char delim = ';';
97+
String script = statement1 + delim + statement2 + delim;
98+
List<String> statements = new ArrayList<String>();
99+
splitSqlScript(script, ';', statements);
100+
assertEquals("wrong number of statements", 2, statements.size());
101+
assertEquals("statement 1 not split correctly", statement1, statements.get(0));
102+
assertEquals("statement 2 not split correctly", statement2, statements.get(1));
103+
}
104+
88105
/**
89106
* See <a href="https://jira.spring.io/browse/SPR-11560">SPR-11560</a>
90107
*/
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
INSERT INTO users(first_name, last_name) VALUES('Juergen', 'Hoeller');
2+
3+
-- The following is not actually used; we just want to ensure that it does not
4+
-- result in a parsing exception due to the nested single quote.
5+
SELECT last_name AS "Juergen's Last Name" FROM users WHERE last_name='Hoeller';
6+
7+
INSERT INTO users(first_name, last_name) values('Sam', 'Brannen');

0 commit comments

Comments
 (0)