Browse Source

Consistent support for square brackets around named parameter

See gh-27716
pull/27818/head
Juergen Hoeller 3 years ago
parent
commit
64b6beed5b
  1. 2
      spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/NamedParameterUtils.java
  2. 8
      spring-jdbc/src/test/java/org/springframework/jdbc/core/namedparam/NamedParameterUtilsTests.java
  3. 5
      spring-r2dbc/src/main/java/org/springframework/r2dbc/core/NamedParameterUtils.java
  4. 39
      spring-r2dbc/src/test/java/org/springframework/r2dbc/core/NamedParameterUtilsUnitTests.java

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

@ -55,7 +55,7 @@ public abstract class NamedParameterUtils { @@ -55,7 +55,7 @@ public abstract class NamedParameterUtils {
* Set of characters that qualify as parameter separators,
* indicating that a parameter name in an SQL String has ended.
*/
private static final String PARAMETER_SEPARATORS = "\"':&,;()|=+-*%/\\<>^";
private static final String PARAMETER_SEPARATORS = "\"':&,;()|=+-*%/\\<>^[]";
/**
* An index with separator flags per character code.

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

@ -319,4 +319,12 @@ public class NamedParameterUtilsTests { @@ -319,4 +319,12 @@ public class NamedParameterUtilsTests {
assertThat(psql2.getParameterNames().get(0)).isEqualTo("xxx");
}
@Test // gh-27716
public void parseSqlStatementWithSquareBracket() {
String sql = "SELECT ARRAY[:ext]";
ParsedSql psql = NamedParameterUtils.parseSqlStatement(sql);
assertThat(psql.getNamedParameterCount()).isEqualTo(1);
assertThat(psql.getParameterNames()).containsExactly("ext");
}
}

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

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2020 the original author or authors.
* Copyright 2002-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -37,8 +37,7 @@ import org.springframework.util.Assert; @@ -37,8 +37,7 @@ import org.springframework.util.Assert;
/**
* Helper methods for named parameter parsing.
*
* <p>Only intended for internal use within Spring's R2DBC
* framework.
* <p>Only intended for internal use within Spring's R2DBC framework.
*
* <p>References to the same parameter name are substituted with
* the same bind marker placeholder if a {@link BindMarkersFactory} uses

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

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2020 the original author or authors.
* Copyright 2002-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -44,6 +44,7 @@ public class NamedParameterUtilsUnitTests { @@ -44,6 +44,7 @@ public class NamedParameterUtilsUnitTests {
private final BindMarkersFactory BIND_MARKERS = BindMarkersFactory.indexed("$", 1);
@Test
public void shouldParseSql() {
String sql = "xxx :a yyyy :b :c :a zzzzz";
@ -146,7 +147,6 @@ public class NamedParameterUtilsUnitTests { @@ -146,7 +147,6 @@ public class NamedParameterUtilsUnitTests {
String sql = "select 'first name' from artists where info->'stat'->'albums' = ?? :album and '[\"1\",\"2\",\"3\"]'::jsonb ?? '4'";
ParsedSql parsedSql = NamedParameterUtils.parseSqlStatement(sql);
assertThat(parsedSql.getTotalParameterCount()).isEqualTo(1);
assertThat(expand(parsedSql)).isEqualTo(expectedSql);
}
@ -157,7 +157,6 @@ public class NamedParameterUtilsUnitTests { @@ -157,7 +157,6 @@ public class NamedParameterUtilsUnitTests {
String sql = "select '[\"3\", \"11\"]'::jsonb ?| '{1,3,11,12,17}'::text[]";
ParsedSql parsedSql = NamedParameterUtils.parseSqlStatement(sql);
assertThat(parsedSql.getTotalParameterCount()).isEqualTo(0);
assertThat(expand(parsedSql)).isEqualTo(expectedSql);
}
@ -178,7 +177,6 @@ public class NamedParameterUtilsUnitTests { @@ -178,7 +177,6 @@ public class NamedParameterUtilsUnitTests {
String sql = "select '0\\:0' as a, foo from bar where baz < DATE(:p1 23\\:59\\:59) and baz = :p2";
ParsedSql parsedSql = NamedParameterUtils.parseSqlStatement(sql);
assertThat(parsedSql.getParameterNames()).containsExactly("p1", "p2");
assertThat(expand(parsedSql)).isEqualTo(expectedSql);
}
@ -199,7 +197,6 @@ public class NamedParameterUtilsUnitTests { @@ -199,7 +197,6 @@ public class NamedParameterUtilsUnitTests {
String sql = "select foo from bar where baz = b:{}z";
ParsedSql parsedSql = NamedParameterUtils.parseSqlStatement(sql);
assertThat(parsedSql.getParameterNames()).isEmpty();
assertThat(expand(parsedSql)).isEqualTo(expectedSql);
@ -226,13 +223,11 @@ public class NamedParameterUtilsUnitTests { @@ -226,13 +223,11 @@ public class NamedParameterUtilsUnitTests {
String expectedSql = "xxx & yyyy";
ParsedSql parsedSql = NamedParameterUtils.parseSqlStatement(expectedSql);
assertThat(expand(parsedSql)).isEqualTo(expectedSql);
}
@Test
public void substituteNamedParametersWithLogicalAnd() {
String expectedSql = "xxx & yyyy";
assertThat(expand(expectedSql)).isEqualTo(expectedSql);
@ -250,7 +245,6 @@ public class NamedParameterUtilsUnitTests { @@ -250,7 +245,6 @@ public class NamedParameterUtilsUnitTests {
String sql = "SELECT ':foo'':doo', :xxx FROM DUAL";
ParsedSql psql = NamedParameterUtils.parseSqlStatement(sql);
assertThat(psql.getTotalParameterCount()).isEqualTo(1);
assertThat(psql.getParameterNames()).containsExactly("xxx");
}
@ -260,7 +254,6 @@ public class NamedParameterUtilsUnitTests { @@ -260,7 +254,6 @@ public class NamedParameterUtilsUnitTests {
String sql = "SELECT /*:doo*/':foo', :xxx FROM DUAL";
ParsedSql psql = NamedParameterUtils.parseSqlStatement(sql);
assertThat(psql.getTotalParameterCount()).isEqualTo(1);
assertThat(psql.getParameterNames()).containsExactly("xxx");
}
@ -270,30 +263,24 @@ public class NamedParameterUtilsUnitTests { @@ -270,30 +263,24 @@ public class NamedParameterUtilsUnitTests {
String sql2 = "SELECT ':foo'/*:doo*/, :xxx FROM DUAL";
ParsedSql psql2 = NamedParameterUtils.parseSqlStatement(sql2);
assertThat(psql2.getTotalParameterCount()).isEqualTo(1);
assertThat(psql2.getParameterNames()).containsExactly("xxx");
}
@Test public void parseSqlStatementWithSquareBracket() {
// given
@Test // gh-27716
public void parseSqlStatementWithSquareBracket() {
String sql = "SELECT ARRAY[:ext]";
// when
ParsedSql psql = NamedParameterUtils.parseSqlStatement(sql);
//then
assertThat(psql.getNamedParameterCount()).isEqualTo(1);
assertThat(psql.getParameterNames()).containsExactly("ext");
}
@Test
public void shouldAllowParsingMultipleUseOfParameter() {
String sql = "SELECT * FROM person where name = :id or lastname = :id";
ParsedSql parsed = NamedParameterUtils.parseSqlStatement(sql);
assertThat(parsed.getTotalParameterCount()).isEqualTo(2);
assertThat(parsed.getNamedParameterCount()).isEqualTo(1);
assertThat(parsed.getParameterNames()).containsExactly("id", "id");
@ -313,23 +300,19 @@ public class NamedParameterUtilsUnitTests { @@ -313,23 +300,19 @@ public class NamedParameterUtilsUnitTests {
"SELECT * FROM person where name = $0 or lastname = $0");
operation.bindTo(new BindTarget() {
@Override
public void bind(String identifier, Object value) {
throw new UnsupportedOperationException();
}
@Override
public void bind(int index, Object value) {
assertThat(index).isEqualTo(0);
assertThat(value).isEqualTo("foo");
}
@Override
public void bindNull(String identifier, Class<?> type) {
throw new UnsupportedOperationException();
}
@Override
public void bindNull(int index, Class<?> type) {
throw new UnsupportedOperationException();
@ -353,25 +336,20 @@ public class NamedParameterUtilsUnitTests { @@ -353,25 +336,20 @@ public class NamedParameterUtilsUnitTests {
"SELECT * FROM person where name IN ($0, $1, $2) or lastname IN ($0, $1, $2)");
operation.bindTo(new BindTarget() {
@Override
public void bind(String identifier, Object value) {
throw new UnsupportedOperationException();
}
@Override
public void bind(int index, Object value) {
assertThat(index).isIn(0, 1, 2);
assertThat(value).isIn("foo", "bar", "baz");
bindings.add(index, value);
}
@Override
public void bindNull(String identifier, Class<?> type) {
throw new UnsupportedOperationException();
}
@Override
public void bindNull(int index, Class<?> type) {
throw new UnsupportedOperationException();
@ -399,22 +377,18 @@ public class NamedParameterUtilsUnitTests { @@ -399,22 +377,18 @@ public class NamedParameterUtilsUnitTests {
Map<Integer, Object> bindValues = new LinkedHashMap<>();
operation.bindTo(new BindTarget() {
@Override
public void bind(String identifier, Object value) {
throw new UnsupportedOperationException();
}
@Override
public void bind(int index, Object value) {
bindValues.put(index, value);
}
@Override
public void bindNull(String identifier, Class<?> type) {
throw new UnsupportedOperationException();
}
@Override
public void bindNull(int index, Class<?> type) {
throw new UnsupportedOperationException();
@ -438,22 +412,18 @@ public class NamedParameterUtilsUnitTests { @@ -438,22 +412,18 @@ public class NamedParameterUtilsUnitTests {
"SELECT * FROM person where name = $0 or lastname = $0");
operation.bindTo(new BindTarget() {
@Override
public void bind(String identifier, Object value) {
throw new UnsupportedOperationException();
}
@Override
public void bind(int index, Object value) {
throw new UnsupportedOperationException();
}
@Override
public void bindNull(String identifier, Class<?> type) {
throw new UnsupportedOperationException();
}
@Override
public void bindNull(int index, Class<?> type) {
assertThat(index).isEqualTo(0);
@ -462,6 +432,7 @@ public class NamedParameterUtilsUnitTests { @@ -462,6 +432,7 @@ public class NamedParameterUtilsUnitTests {
});
}
private String expand(ParsedSql sql) {
return NamedParameterUtils.substituteNamedParameters(sql, BIND_MARKERS,
new MapBindParameterSource()).toQuery();

Loading…
Cancel
Save