Browse Source

Properly expand reused collection parameters in R2DBC NamedParameterUtils

Prior to this commit, NamedParameterUtils in spring-r2dbc did not
properly expand reused collection parameters. Specifically, values in a
supplied collection were only expanded in the resulting query once, for
the first occurrence of the named parameter.

To address that, this commit effectively reinstates the original logic
for ExpandedQuery from NamedParameterUtils in the Spring Data R2DBC
project.

94958f5eb6/spring-data-r2dbc/src/main/java/org/springframework/data/r2dbc/core/NamedParameterUtils.java (L486)

Closes gh-34768
pull/35405/head
Sam Brannen 7 months ago
parent
commit
dd6eede243
  1. 49
      spring-r2dbc/src/main/java/org/springframework/r2dbc/core/NamedParameterUtils.java
  2. 2
      spring-r2dbc/src/test/java/org/springframework/r2dbc/core/NamedParameterUtilsTests.java

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

@ -49,6 +49,7 @@ import org.springframework.util.Assert; @@ -49,6 +49,7 @@ import org.springframework.util.Assert;
* @author Juergen Hoeller
* @author Mark Paluch
* @author Anton Naydenov
* @author Sam Brannen
* @since 5.3
*/
abstract class NamedParameterUtils {
@ -545,41 +546,43 @@ abstract class NamedParameterUtils { @@ -545,41 +546,43 @@ abstract class NamedParameterUtils {
}
private void bindNull(BindTarget target, String identifier, Parameter parameter) {
List<BindMarker> bindMarkers = getBindMarkers(identifier);
List<List<BindMarker>> bindMarkers = getBindMarkers(identifier);
if (bindMarkers == null) {
target.bind(identifier, parameter);
return;
}
for (BindMarker bindMarker : bindMarkers) {
bindMarker.bind(target, parameter);
for (List<BindMarker> outer : bindMarkers) {
for (BindMarker bindMarker : outer) {
bindMarker.bind(target, parameter);
}
}
}
@SuppressWarnings({"rawtypes", "unchecked"})
private void bind(BindTarget target, String identifier, Parameter parameter) {
List<BindMarker> bindMarkers = getBindMarkers(identifier);
List<List<BindMarker>> bindMarkers = getBindMarkers(identifier);
if (bindMarkers == null) {
target.bind(identifier, parameter);
return;
}
if (parameter.getValue() instanceof Collection collection) {
Iterator<Object> iterator = collection.iterator();
Iterator<BindMarker> markers = bindMarkers.iterator();
while (iterator.hasNext()) {
Object valueToBind = iterator.next();
if (valueToBind instanceof Object[] objects) {
for (Object object : objects) {
bind(target, markers, object);
for (List<BindMarker> outer : bindMarkers) {
if (parameter.getValue() instanceof Collection<?> collection) {
Iterator<BindMarker> markers = outer.iterator();
for (Object valueToBind : collection) {
if (valueToBind instanceof Object[] objects) {
for (Object object : objects) {
bind(target, markers, object);
}
}
else {
bind(target, markers, valueToBind);
}
}
else {
bind(target, markers, valueToBind);
}
}
}
else {
for (BindMarker bindMarker : bindMarkers) {
bindMarker.bind(target, parameter);
else {
for (BindMarker bindMarker : outer) {
bindMarker.bind(target, parameter);
}
}
}
}
@ -592,14 +595,14 @@ abstract class NamedParameterUtils { @@ -592,14 +595,14 @@ abstract class NamedParameterUtils {
}
@Nullable
private List<BindMarker> getBindMarkers(String identifier) {
private List<List<BindMarker>> getBindMarkers(String identifier) {
List<NamedParameters.NamedParameter> parameters = this.parameters.getMarker(identifier);
if (parameters == null) {
return null;
}
List<BindMarker> markers = new ArrayList<>();
List<List<BindMarker>> markers = new ArrayList<>();
for (NamedParameters.NamedParameter parameter : parameters) {
markers.addAll(parameter.placeholders);
markers.add(new ArrayList<>(parameter.placeholders));
}
return markers;
}

2
spring-r2dbc/src/test/java/org/springframework/r2dbc/core/NamedParameterUtilsTests.java

@ -21,7 +21,6 @@ import java.util.List; @@ -21,7 +21,6 @@ import java.util.List;
import java.util.Map;
import io.r2dbc.spi.Parameters;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
@ -350,7 +349,6 @@ class NamedParameterUtilsTests { @@ -350,7 +349,6 @@ class NamedParameterUtilsTests {
}
@Test // gh-34768
@Disabled("Disabled until gh-34768 is addressed")
void multipleEqualCollectionParameterReferencesForAnonymousMarkersBindsValuesTwice() {
String sql = "SELECT * FROM fund_info WHERE fund_code IN (:fundCodes) OR fund_code IN (:fundCodes)";

Loading…
Cancel
Save