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
This commit is contained in:
Sam Brannen
2025-05-09 14:27:19 +02:00
parent de97e35189
commit dd6eede243
2 changed files with 26 additions and 25 deletions

View File

@@ -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 {
}
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 {
}
@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;
}

View File

@@ -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 {
}
@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)";