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 863280ede0..d9f3167d84 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 @@ -259,7 +259,7 @@ public abstract class ScriptUtils { * @throws IOException in case of I/O errors */ static String readScript(EncodedResource resource) throws IOException { - return readScript(resource, DEFAULT_COMMENT_PREFIX, DEFAULT_STATEMENT_SEPARATOR); + return readScript(resource, DEFAULT_COMMENT_PREFIX, DEFAULT_STATEMENT_SEPARATOR, DEFAULT_BLOCK_COMMENT_END_DELIMITER); } /** @@ -273,15 +273,16 @@ public abstract class ScriptUtils { * @param commentPrefix the prefix that identifies comments in the SQL script — * typically "--" * @param separator the statement separator in the SQL script — typically ";" + * @param blockCommentEndDelimiter the end block comment delimiter * @return a {@code String} containing the script lines * @throws IOException in case of I/O errors */ private static String readScript(EncodedResource resource, @Nullable String commentPrefix, - @Nullable String separator) throws IOException { + @Nullable String separator, @Nullable String blockCommentEndDelimiter) throws IOException { LineNumberReader lnr = new LineNumberReader(resource.getReader()); try { - return readScript(lnr, commentPrefix, separator); + return readScript(lnr, commentPrefix, separator, blockCommentEndDelimiter); } finally { lnr.close(); @@ -297,19 +298,21 @@ public abstract class ScriptUtils { * 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 — + * @param lineCommentPrefix the prefix that identifies comments in the SQL script — * typically "--" * @param separator the statement separator in the SQL script — typically ";" + * @param blockCommentEndDelimiter the end block comment delimiter * @return a {@code String} containing the script lines * @throws IOException in case of I/O errors */ - public static String readScript(LineNumberReader lineNumberReader, @Nullable String commentPrefix, - @Nullable String separator) throws IOException { + public static String readScript(LineNumberReader lineNumberReader, @Nullable String lineCommentPrefix, + @Nullable String separator, @Nullable String blockCommentEndDelimiter) throws IOException { String currentStatement = lineNumberReader.readLine(); StringBuilder scriptBuilder = new StringBuilder(); while (currentStatement != null) { - if (commentPrefix != null && !currentStatement.startsWith(commentPrefix)) { + if ((blockCommentEndDelimiter != null && currentStatement.contains(blockCommentEndDelimiter)) || + (lineCommentPrefix != null && !currentStatement.startsWith(lineCommentPrefix))) { if (scriptBuilder.length() > 0) { scriptBuilder.append('\n'); } @@ -460,7 +463,7 @@ public abstract class ScriptUtils { String script; try { - script = readScript(resource, commentPrefix, separator); + script = readScript(resource, commentPrefix, separator, blockCommentEndDelimiter); } catch (IOException ex) { throw new CannotReadScriptException(resource, ex); 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 80f44ff57f..b55ab14302 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 @@ -162,6 +162,20 @@ public class ScriptUtilsUnitTests { assertEquals("statement 2 not split correctly", statement2, statements.get(1)); } + @Test + public void readAndSplitScriptContainingMultiLineNestedComments() throws Exception { + String script = readScript("test-data-with-multi-line-nested-comments.sql"); + List statements = new ArrayList<>(); + splitSqlScript(script, ';', 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() { assertFalse(containsSqlScriptDelimiters("select 1\n select ';'", ";")); diff --git a/spring-jdbc/src/test/resources/org/springframework/jdbc/datasource/init/test-data-with-multi-line-nested-comments.sql b/spring-jdbc/src/test/resources/org/springframework/jdbc/datasource/init/test-data-with-multi-line-nested-comments.sql new file mode 100644 index 0000000000..8c1e1174b7 --- /dev/null +++ b/spring-jdbc/src/test/resources/org/springframework/jdbc/datasource/init/test-data-with-multi-line-nested-comments.sql @@ -0,0 +1,23 @@ +/* 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. +/*------------------------------------------- +-- A fancy multi-line comments that puts +-- single line comments inside of a multi-line +-- comment block. +Moreover, the block commend end delimiter +appears on a line that can potentially also +be a single-line comment if we weren't +already inside a multi-line comment run. +-------------------------------------------*/ + INSERT INTO +users(first_name, last_name) -- This is a single line comment containing the block-end-comment sequence here */ but it's still a single-line comment +VALUES( 'Sam' -- first_name + , 'Brannen' -- last_name +);-- \ No newline at end of file