Skip to content

Commit 64b6bee

Browse files
committed
Consistent support for square brackets around named parameter
See gh-27716
1 parent 86eda27 commit 64b6bee

File tree

4 files changed

+16
-38
lines changed

4 files changed

+16
-38
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ public abstract class NamedParameterUtils {
5555
* Set of characters that qualify as parameter separators,
5656
* indicating that a parameter name in an SQL String has ended.
5757
*/
58-
private static final String PARAMETER_SEPARATORS = "\"':&,;()|=+-*%/\\<>^";
58+
private static final String PARAMETER_SEPARATORS = "\"':&,;()|=+-*%/\\<>^[]";
5959

6060
/**
6161
* An index with separator flags per character code.

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,4 +319,12 @@ public void parseSqlStatementWithQuotesAndCommentAfter() {
319319
assertThat(psql2.getParameterNames().get(0)).isEqualTo("xxx");
320320
}
321321

322+
@Test // gh-27716
323+
public void parseSqlStatementWithSquareBracket() {
324+
String sql = "SELECT ARRAY[:ext]";
325+
ParsedSql psql = NamedParameterUtils.parseSqlStatement(sql);
326+
assertThat(psql.getNamedParameterCount()).isEqualTo(1);
327+
assertThat(psql.getParameterNames()).containsExactly("ext");
328+
}
329+
322330
}

spring-r2dbc/src/main/java/org/springframework/r2dbc/core/NamedParameterUtils.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2020 the original author or authors.
2+
* Copyright 2002-2021 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.
@@ -37,8 +37,7 @@
3737
/**
3838
* Helper methods for named parameter parsing.
3939
*
40-
* <p>Only intended for internal use within Spring's R2DBC
41-
* framework.
40+
* <p>Only intended for internal use within Spring's R2DBC framework.
4241
*
4342
* <p>References to the same parameter name are substituted with
4443
* the same bind marker placeholder if a {@link BindMarkersFactory} uses

spring-r2dbc/src/test/java/org/springframework/r2dbc/core/NamedParameterUtilsUnitTests.java

Lines changed: 5 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2020 the original author or authors.
2+
* Copyright 2002-2021 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.
@@ -44,6 +44,7 @@ public class NamedParameterUtilsUnitTests {
4444

4545
private final BindMarkersFactory BIND_MARKERS = BindMarkersFactory.indexed("$", 1);
4646

47+
4748
@Test
4849
public void shouldParseSql() {
4950
String sql = "xxx :a yyyy :b :c :a zzzzz";
@@ -146,7 +147,6 @@ public void parseSqlStatementWithPostgresContainedOperator() {
146147
String sql = "select 'first name' from artists where info->'stat'->'albums' = ?? :album and '[\"1\",\"2\",\"3\"]'::jsonb ?? '4'";
147148

148149
ParsedSql parsedSql = NamedParameterUtils.parseSqlStatement(sql);
149-
150150
assertThat(parsedSql.getTotalParameterCount()).isEqualTo(1);
151151
assertThat(expand(parsedSql)).isEqualTo(expectedSql);
152152
}
@@ -157,7 +157,6 @@ public void parseSqlStatementWithPostgresAnyArrayStringsExistsOperator() {
157157
String sql = "select '[\"3\", \"11\"]'::jsonb ?| '{1,3,11,12,17}'::text[]";
158158

159159
ParsedSql parsedSql = NamedParameterUtils.parseSqlStatement(sql);
160-
161160
assertThat(parsedSql.getTotalParameterCount()).isEqualTo(0);
162161
assertThat(expand(parsedSql)).isEqualTo(expectedSql);
163162
}
@@ -178,7 +177,6 @@ public void parseSqlStatementWithEscapedColon() {
178177
String sql = "select '0\\:0' as a, foo from bar where baz < DATE(:p1 23\\:59\\:59) and baz = :p2";
179178

180179
ParsedSql parsedSql = NamedParameterUtils.parseSqlStatement(sql);
181-
182180
assertThat(parsedSql.getParameterNames()).containsExactly("p1", "p2");
183181
assertThat(expand(parsedSql)).isEqualTo(expectedSql);
184182
}
@@ -199,7 +197,6 @@ public void parseSqlStatementWithEmptyBracketsOrBracketsInQuotes() {
199197
String sql = "select foo from bar where baz = b:{}z";
200198

201199
ParsedSql parsedSql = NamedParameterUtils.parseSqlStatement(sql);
202-
203200
assertThat(parsedSql.getParameterNames()).isEmpty();
204201
assertThat(expand(parsedSql)).isEqualTo(expectedSql);
205202

@@ -226,13 +223,11 @@ public void parseSqlStatementWithLogicalAnd() {
226223
String expectedSql = "xxx & yyyy";
227224

228225
ParsedSql parsedSql = NamedParameterUtils.parseSqlStatement(expectedSql);
229-
230226
assertThat(expand(parsedSql)).isEqualTo(expectedSql);
231227
}
232228

233229
@Test
234230
public void substituteNamedParametersWithLogicalAnd() {
235-
236231
String expectedSql = "xxx & yyyy";
237232

238233
assertThat(expand(expectedSql)).isEqualTo(expectedSql);
@@ -250,7 +245,6 @@ public void parseSqlStatementWithQuotedSingleQuote() {
250245
String sql = "SELECT ':foo'':doo', :xxx FROM DUAL";
251246

252247
ParsedSql psql = NamedParameterUtils.parseSqlStatement(sql);
253-
254248
assertThat(psql.getTotalParameterCount()).isEqualTo(1);
255249
assertThat(psql.getParameterNames()).containsExactly("xxx");
256250
}
@@ -260,7 +254,6 @@ public void parseSqlStatementWithQuotesAndCommentBefore() {
260254
String sql = "SELECT /*:doo*/':foo', :xxx FROM DUAL";
261255

262256
ParsedSql psql = NamedParameterUtils.parseSqlStatement(sql);
263-
264257
assertThat(psql.getTotalParameterCount()).isEqualTo(1);
265258
assertThat(psql.getParameterNames()).containsExactly("xxx");
266259
}
@@ -270,30 +263,24 @@ public void parseSqlStatementWithQuotesAndCommentAfter() {
270263
String sql2 = "SELECT ':foo'/*:doo*/, :xxx FROM DUAL";
271264

272265
ParsedSql psql2 = NamedParameterUtils.parseSqlStatement(sql2);
273-
274266
assertThat(psql2.getTotalParameterCount()).isEqualTo(1);
275267
assertThat(psql2.getParameterNames()).containsExactly("xxx");
276268
}
277269

278-
@Test public void parseSqlStatementWithSquareBracket() {
279-
// given
270+
@Test // gh-27716
271+
public void parseSqlStatementWithSquareBracket() {
280272
String sql = "SELECT ARRAY[:ext]";
281273

282-
// when
283274
ParsedSql psql = NamedParameterUtils.parseSqlStatement(sql);
284-
285-
//then
286275
assertThat(psql.getNamedParameterCount()).isEqualTo(1);
287276
assertThat(psql.getParameterNames()).containsExactly("ext");
288277
}
289278

290279
@Test
291280
public void shouldAllowParsingMultipleUseOfParameter() {
292-
293281
String sql = "SELECT * FROM person where name = :id or lastname = :id";
294282

295283
ParsedSql parsed = NamedParameterUtils.parseSqlStatement(sql);
296-
297284
assertThat(parsed.getTotalParameterCount()).isEqualTo(2);
298285
assertThat(parsed.getNamedParameterCount()).isEqualTo(1);
299286
assertThat(parsed.getParameterNames()).containsExactly("id", "id");
@@ -313,23 +300,19 @@ sql, factory, new MapBindParameterSource(
313300
"SELECT * FROM person where name = $0 or lastname = $0");
314301

315302
operation.bindTo(new BindTarget() {
316-
317303
@Override
318304
public void bind(String identifier, Object value) {
319305
throw new UnsupportedOperationException();
320306
}
321-
322307
@Override
323308
public void bind(int index, Object value) {
324309
assertThat(index).isEqualTo(0);
325310
assertThat(value).isEqualTo("foo");
326311
}
327-
328312
@Override
329313
public void bindNull(String identifier, Class<?> type) {
330314
throw new UnsupportedOperationException();
331315
}
332-
333316
@Override
334317
public void bindNull(int index, Class<?> type) {
335318
throw new UnsupportedOperationException();
@@ -353,25 +336,20 @@ sql, factory, new MapBindParameterSource(Collections.singletonMap("ids",
353336
"SELECT * FROM person where name IN ($0, $1, $2) or lastname IN ($0, $1, $2)");
354337

355338
operation.bindTo(new BindTarget() {
356-
357339
@Override
358340
public void bind(String identifier, Object value) {
359341
throw new UnsupportedOperationException();
360342
}
361-
362343
@Override
363344
public void bind(int index, Object value) {
364345
assertThat(index).isIn(0, 1, 2);
365346
assertThat(value).isIn("foo", "bar", "baz");
366-
367347
bindings.add(index, value);
368348
}
369-
370349
@Override
371350
public void bindNull(String identifier, Class<?> type) {
372351
throw new UnsupportedOperationException();
373352
}
374-
375353
@Override
376354
public void bindNull(int index, Class<?> type) {
377355
throw new UnsupportedOperationException();
@@ -399,22 +377,18 @@ sql, factory, new MapBindParameterSource(
399377
Map<Integer, Object> bindValues = new LinkedHashMap<>();
400378

401379
operation.bindTo(new BindTarget() {
402-
403380
@Override
404381
public void bind(String identifier, Object value) {
405382
throw new UnsupportedOperationException();
406383
}
407-
408384
@Override
409385
public void bind(int index, Object value) {
410386
bindValues.put(index, value);
411387
}
412-
413388
@Override
414389
public void bindNull(String identifier, Class<?> type) {
415390
throw new UnsupportedOperationException();
416391
}
417-
418392
@Override
419393
public void bindNull(int index, Class<?> type) {
420394
throw new UnsupportedOperationException();
@@ -438,22 +412,18 @@ sql, factory, new MapBindParameterSource(
438412
"SELECT * FROM person where name = $0 or lastname = $0");
439413

440414
operation.bindTo(new BindTarget() {
441-
442415
@Override
443416
public void bind(String identifier, Object value) {
444417
throw new UnsupportedOperationException();
445418
}
446-
447419
@Override
448420
public void bind(int index, Object value) {
449421
throw new UnsupportedOperationException();
450422
}
451-
452423
@Override
453424
public void bindNull(String identifier, Class<?> type) {
454425
throw new UnsupportedOperationException();
455426
}
456-
457427
@Override
458428
public void bindNull(int index, Class<?> type) {
459429
assertThat(index).isEqualTo(0);
@@ -462,6 +432,7 @@ public void bindNull(int index, Class<?> type) {
462432
});
463433
}
464434

435+
465436
private String expand(ParsedSql sql) {
466437
return NamedParameterUtils.substituteNamedParameters(sql, BIND_MARKERS,
467438
new MapBindParameterSource()).toQuery();

0 commit comments

Comments
 (0)