Skip to content

Commit f3dd22d

Browse files
nkjackzhangjhoeller
authored andcommitted
NamedParameterUtils.parseSqlStatement should parse :{x} style parameter correctly
In my opinion, we should parse ":{x}" style parameter as "x" is parameter using "NamedParameterUtils.parseSqlStatement", so the condition "j - i > 2" is the correct condition, not "j - i > 3", because if "i" is the index of ":" in ":{x}", and "j" is the index of "}" in ":{x}", "j - i == 3" is true. Also add a test case for SPR-16663. (cherry picked from commit 82cb5db)
1 parent 6e4bbac commit f3dd22d

File tree

2 files changed

+25
-15
lines changed

2 files changed

+25
-15
lines changed

spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/NamedParameterUtils.java

+12-14
Original file line numberDiff line numberDiff line change
@@ -41,23 +41,21 @@
4141
public abstract class NamedParameterUtils {
4242

4343
/**
44-
* Set of characters that qualify as parameter separators,
45-
* indicating that a parameter name in a SQL String has ended.
44+
* Set of characters that qualify as comment or quotes starting characters.
4645
*/
47-
private static final char[] PARAMETER_SEPARATORS =
48-
new char[] {'"', '\'', ':', '&', ',', ';', '(', ')', '|', '=', '+', '-', '*', '%', '/', '\\', '<', '>', '^'};
46+
private static final String[] START_SKIP = new String[] {"'", "\"", "--", "/*"};
4947

5048
/**
51-
* Set of characters that qualify as comment or quotes starting characters.
49+
* Set of characters that at are the corresponding comment or quotes ending characters.
5250
*/
53-
private static final String[] START_SKIP =
54-
new String[] {"'", "\"", "--", "/*"};
51+
private static final String[] STOP_SKIP = new String[] {"'", "\"", "\n", "*/"};
5552

5653
/**
57-
* Set of characters that at are the corresponding comment or quotes ending characters.
54+
* Set of characters that qualify as parameter separators,
55+
* indicating that a parameter name in a SQL String has ended.
5856
*/
59-
private static final String[] STOP_SKIP =
60-
new String[] {"'", "\"", "\n", "*/"};
57+
private static final char[] PARAMETER_SEPARATORS =
58+
new char[] {'"', '\'', ':', '&', ',', ';', '(', ')', '|', '=', '+', '-', '*', '%', '/', '\\', '<', '>', '^'};
6159

6260

6361
//-------------------------------------------------------------------------
@@ -109,7 +107,7 @@ public static ParsedSql parseSqlStatement(final String sql) {
109107
String parameter = null;
110108
if (j < statement.length && c == ':' && statement[j] == '{') {
111109
// :{x} style parameter
112-
while (j < statement.length && !('}' == statement[j])) {
110+
while (j < statement.length && '}' != statement[j]) {
113111
j++;
114112
if (':' == statement[j] || '{' == statement[j]) {
115113
throw new InvalidDataAccessApiUsageException("Parameter name contains invalid character '" +
@@ -120,7 +118,7 @@ public static ParsedSql parseSqlStatement(final String sql) {
120118
throw new InvalidDataAccessApiUsageException(
121119
"Non-terminated named parameter declaration at position " + i + " in statement: " + sql);
122120
}
123-
if (j - i > 3) {
121+
if (j - i > 2) {
124122
parameter = sql.substring(i + 2, j);
125123
namedParameterCount = addNewNamedParameter(namedParameters, namedParameterCount, parameter);
126124
totalParameterCount = addNamedParameter(parameterList, totalParameterCount, escapes, i, j + 1, parameter);
@@ -200,7 +198,7 @@ private static int skipCommentsAndQuotes(char[] statement, int position) {
200198
if (statement[position] == START_SKIP[i].charAt(0)) {
201199
boolean match = true;
202200
for (int j = 1; j < START_SKIP[i].length(); j++) {
203-
if (!(statement[position + j] == START_SKIP[i].charAt(j))) {
201+
if (statement[position + j] != START_SKIP[i].charAt(j)) {
204202
match = false;
205203
break;
206204
}
@@ -216,7 +214,7 @@ private static int skipCommentsAndQuotes(char[] statement, int position) {
216214
// last comment not closed properly
217215
return statement.length;
218216
}
219-
if (!(statement[m + n] == STOP_SKIP[i].charAt(n))) {
217+
if (statement[m + n] != STOP_SKIP[i].charAt(n)) {
220218
endMatch = false;
221219
break;
222220
}

spring-jdbc/src/test/java/org/springframework/jdbc/core/namedparam/NamedParameterUtilsTests.java

+13-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2017 the original author or authors.
2+
* Copyright 2002-2018 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.
@@ -253,6 +253,18 @@ public void parseSqlStatementWithEmptyBracketsOrBracketsInQuotes() throws Except
253253
assertEquals(expectedSql2, finalSql2);
254254
}
255255

256+
@Test
257+
public void parseSqlStatementWithSingleLetterInBrackets() {
258+
String expectedSql = "select foo from bar where baz = b?z";
259+
String sql = "select foo from bar where baz = b:{p}z";
260+
261+
ParsedSql parsedSql = NamedParameterUtils.parseSqlStatement(sql);
262+
assertEquals(1, parsedSql.getParameterNames().size());
263+
assertEquals("p", parsedSql.getParameterNames().get(0));
264+
String finalSql = NamedParameterUtils.substituteNamedParameters(parsedSql, null);
265+
assertEquals(expectedSql, finalSql);
266+
}
267+
256268
@Test // SPR-2544
257269
public void parseSqlStatementWithLogicalAnd() {
258270
String expectedSql = "xxx & yyyy";

0 commit comments

Comments
 (0)