Skip to content

Commit 82dbde1

Browse files
mmustaquimjhoeller
authored andcommitted
Fix for ScriptUtils failure when '--' occurs inside a multi-line comment on the same line as '*/' (#22392)
* Test for multi-line comment block where the comment end delimiter occurs on a line starting with the single-line comment prefix * ScriptUtils successfully parses a SQL script containing a multi-line comment block where the comment-end delimiter occurs on a line starting with the single-line comment prefix.
1 parent a698adf commit 82dbde1

File tree

3 files changed

+48
-8
lines changed

3 files changed

+48
-8
lines changed

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

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ else if (c == ' ' || c == '\n' || c == '\t') {
259259
* @throws IOException in case of I/O errors
260260
*/
261261
static String readScript(EncodedResource resource) throws IOException {
262-
return readScript(resource, DEFAULT_COMMENT_PREFIX, DEFAULT_STATEMENT_SEPARATOR);
262+
return readScript(resource, DEFAULT_COMMENT_PREFIX, DEFAULT_STATEMENT_SEPARATOR, DEFAULT_BLOCK_COMMENT_END_DELIMITER);
263263
}
264264

265265
/**
@@ -273,15 +273,16 @@ static String readScript(EncodedResource resource) throws IOException {
273273
* @param commentPrefix the prefix that identifies comments in the SQL script —
274274
* typically "--"
275275
* @param separator the statement separator in the SQL script — typically ";"
276+
* @param blockCommentEndDelimiter the <em>end</em> block comment delimiter
276277
* @return a {@code String} containing the script lines
277278
* @throws IOException in case of I/O errors
278279
*/
279280
private static String readScript(EncodedResource resource, @Nullable String commentPrefix,
280-
@Nullable String separator) throws IOException {
281+
@Nullable String separator, @Nullable String blockCommentEndDelimiter) throws IOException {
281282

282283
LineNumberReader lnr = new LineNumberReader(resource.getReader());
283284
try {
284-
return readScript(lnr, commentPrefix, separator);
285+
return readScript(lnr, commentPrefix, separator, blockCommentEndDelimiter);
285286
}
286287
finally {
287288
lnr.close();
@@ -297,19 +298,21 @@ private static String readScript(EncodedResource resource, @Nullable String comm
297298
* a statement &mdash; will be included in the results.
298299
* @param lineNumberReader the {@code LineNumberReader} containing the script
299300
* to be processed
300-
* @param commentPrefix the prefix that identifies comments in the SQL script &mdash;
301+
* @param lineCommentPrefix the prefix that identifies comments in the SQL script &mdash;
301302
* typically "--"
302303
* @param separator the statement separator in the SQL script &mdash; typically ";"
304+
* @param blockCommentEndDelimiter the <em>end</em> block comment delimiter
303305
* @return a {@code String} containing the script lines
304306
* @throws IOException in case of I/O errors
305307
*/
306-
public static String readScript(LineNumberReader lineNumberReader, @Nullable String commentPrefix,
307-
@Nullable String separator) throws IOException {
308+
public static String readScript(LineNumberReader lineNumberReader, @Nullable String lineCommentPrefix,
309+
@Nullable String separator, @Nullable String blockCommentEndDelimiter) throws IOException {
308310

309311
String currentStatement = lineNumberReader.readLine();
310312
StringBuilder scriptBuilder = new StringBuilder();
311313
while (currentStatement != null) {
312-
if (commentPrefix != null && !currentStatement.startsWith(commentPrefix)) {
314+
if ((blockCommentEndDelimiter != null && currentStatement.contains(blockCommentEndDelimiter)) ||
315+
(lineCommentPrefix != null && !currentStatement.startsWith(lineCommentPrefix))) {
313316
if (scriptBuilder.length() > 0) {
314317
scriptBuilder.append('\n');
315318
}
@@ -460,7 +463,7 @@ public static void executeSqlScript(Connection connection, EncodedResource resou
460463

461464
String script;
462465
try {
463-
script = readScript(resource, commentPrefix, separator);
466+
script = readScript(resource, commentPrefix, separator, blockCommentEndDelimiter);
464467
}
465468
catch (IOException ex) {
466469
throw new CannotReadScriptException(resource, ex);

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,20 @@ public void readAndSplitScriptContainingMultiLineComments() throws Exception {
162162
assertEquals("statement 2 not split correctly", statement2, statements.get(1));
163163
}
164164

165+
@Test
166+
public void readAndSplitScriptContainingMultiLineNestedComments() throws Exception {
167+
String script = readScript("test-data-with-multi-line-nested-comments.sql");
168+
List<String> statements = new ArrayList<>();
169+
splitSqlScript(script, ';', statements);
170+
171+
String statement1 = "INSERT INTO users(first_name, last_name) VALUES('Juergen', 'Hoeller')";
172+
String statement2 = "INSERT INTO users(first_name, last_name) VALUES( 'Sam' , 'Brannen' )";
173+
174+
assertEquals("wrong number of statements", 2, statements.size());
175+
assertEquals("statement 1 not split correctly", statement1, statements.get(0));
176+
assertEquals("statement 2 not split correctly", statement2, statements.get(1));
177+
}
178+
165179
@Test
166180
public void containsDelimiters() {
167181
assertFalse(containsSqlScriptDelimiters("select 1\n select ';'", ";"));
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/* This is a multi line comment
2+
* The next comment line has no text
3+
4+
* The next comment line starts with a space.
5+
* x, y, z...
6+
*/
7+
8+
INSERT INTO users(first_name, last_name) VALUES('Juergen', 'Hoeller');
9+
-- This is also a comment.
10+
/*-------------------------------------------
11+
-- A fancy multi-line comments that puts
12+
-- single line comments inside of a multi-line
13+
-- comment block.
14+
Moreover, the block commend end delimiter
15+
appears on a line that can potentially also
16+
be a single-line comment if we weren't
17+
already inside a multi-line comment run.
18+
-------------------------------------------*/
19+
INSERT INTO
20+
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
21+
VALUES( 'Sam' -- first_name
22+
, 'Brannen' -- last_name
23+
);--

0 commit comments

Comments
 (0)