Support single quotes nested in double quotes in SQL scripts
Some databases such as Oracle permit double quoted column aliases that contain case-sensitive characters, single quotes, and other special characters; however, prior to this commit, SqlScripts interpreted a single quote nested within double quotes as the start of a string literal resulting in improper parsing. This commit addresses this issue by ensuring that double quoted strings such as column aliases are properly parsed even when containing single quotes. Issue: SPR-13218
This commit is contained in:
parent
de6bbe7797
commit
629bcb6599
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 <a href="https://jira.spring.io/browse/SPR-13218">SPR-13218</a>
|
||||
*/
|
||||
@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<String> statements = new ArrayList<String>();
|
||||
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 <a href="https://jira.spring.io/browse/SPR-11560">SPR-11560</a>
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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');
|
||||
Loading…
Reference in New Issue