Ignore comments when searching for statement delimiter in ScriptUtils

Prior to this commit, the implementations of
ScriptUtils.containsSqlScriptDelimiters() in spring-jdbc and
spring-r2dbc did not ignore comments when searching for the statement
delimiter within an SQL script. This resulted in subtle bugs if a
comment contained a single single-quote or single double-quote, since
the absence of the closing single-quote or double-quote led the
algorithm to believe that it was still "within a text literal". Similar
issues could arise if a comment contained the sought statement
delimiter but the rest of the script did not contain the sought
statement delimiter. In such cases, the algorithms in ScriptUtils could
erroneously choose an incorrect statement delimiter -- for example,
using the fallback statement delimiter instead of the delimiter
specified by the user.

This commit avoids such bugs by ignoring single-line comments and block
comments when searching for the statement delimiter within an SQL
script.

Closes gh-26911
This commit is contained in:
Sam Brannen
2021-05-13 16:17:51 +02:00
parent fae484855b
commit 569ce840cf
6 changed files with 167 additions and 15 deletions

View File

@@ -205,9 +205,25 @@ public class ScriptUtilsUnitTests {
"'select 1\n\n select 2' # '\n\n' # true",
// semicolon with MySQL style escapes '\\'
"'insert into users(first, last)\nvalues(''a\\\\'', ''b;'')' # ; # false",
"'insert into users(first, last)\nvalues(''Charles'', ''d\\''Artagnan''); select 1' # ; # true"
"'insert into users(first, last)\nvalues(''Charles'', ''d\\''Artagnan''); select 1' # ; # true",
// semicolon inside comments
"'-- a;b;c\ninsert into colors(color_num) values(42);' # ; # true",
"'/* a;b;c */\ninsert into colors(color_num) values(42);' # ; # true",
"'-- a;b;c\ninsert into colors(color_num) values(42)' # ; # false",
"'/* a;b;c */\ninsert into colors(color_num) values(42)' # ; # false",
// single quotes inside comments
"'-- What\\''s your favorite color?\ninsert into colors(color_num) values(42);' # ; # true",
"'-- What''s your favorite color?\ninsert into colors(color_num) values(42);' # ; # true",
"'/* What\\''s your favorite color? */\ninsert into colors(color_num) values(42);' # ; # true",
"'/* What''s your favorite color? */\ninsert into colors(color_num) values(42);' # ; # true",
// double quotes inside comments
"'-- double \" quotes\ninsert into colors(color_num) values(42);' # ; # true",
"'-- double \\\" quotes\ninsert into colors(color_num) values(42);' # ; # true",
"'/* double \" quotes */\ninsert into colors(color_num) values(42);' # ; # true",
"'/* double \\\" quotes */\ninsert into colors(color_num) values(42);' # ; # true"
})
public void containsDelimiter(String script, String delimiter, boolean expected) {
public void containsStatementSeparator(String script, String delimiter, boolean expected) {
// Indirectly tests ScriptUtils.containsStatementSeparator(EncodedResource, String, String, String[], String, String).
assertThat(containsSqlScriptDelimiters(script, delimiter)).isEqualTo(expected);
}

View File

@@ -5,16 +5,19 @@
* x, y, z...
*/
-- This is a single line comment containing single (') and double quotes (").
INSERT INTO users(first_name, last_name) VALUES('Juergen', 'Hoeller');
-- This is also a comment.
/*-------------------------------------------
-- A fancy multi-line comments that puts
-- A fancy multi-line comment that puts
-- single line comments inside of a multi-line
-- comment block.
Moreover, the block comment 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.
And here's a line containing single and double quotes (").
-------------------------------------------*/
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