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

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

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

Loading…
Cancel
Save