diff --git a/spring-r2dbc/src/main/java/org/springframework/r2dbc/core/NamedParameterUtils.java b/spring-r2dbc/src/main/java/org/springframework/r2dbc/core/NamedParameterUtils.java index 680213cb0909..f7138a3b7631 100644 --- a/spring-r2dbc/src/main/java/org/springframework/r2dbc/core/NamedParameterUtils.java +++ b/spring-r2dbc/src/main/java/org/springframework/r2dbc/core/NamedParameterUtils.java @@ -526,17 +526,19 @@ public void bind(BindTarget target, String identifier, Parameter parameter) { return; } if (parameter.getValue() instanceof Collection collection) { - Iterator iterator = collection.iterator(); Iterator markers = bindMarkers.iterator(); - while (iterator.hasNext()) { - Object valueToBind = iterator.next(); - if (valueToBind instanceof Object[] objects) { - for (Object object : objects) { - bind(target, markers, object); + while(markers.hasNext()){ + Iterator iterator = collection.iterator(); + while (iterator.hasNext()) { + Object valueToBind = iterator.next(); + if (valueToBind instanceof Object[] objects) { + for (Object object : objects) { + bind(target, markers, object); + } + } + else { + bind(target, markers, valueToBind); } - } - else { - bind(target, markers, valueToBind); } } } diff --git a/spring-r2dbc/src/test/java/org/springframework/r2dbc/core/NamedParameterUtilsTests.java b/spring-r2dbc/src/test/java/org/springframework/r2dbc/core/NamedParameterUtilsTests.java index 413c218909e1..d00bddf97ea2 100644 --- a/spring-r2dbc/src/test/java/org/springframework/r2dbc/core/NamedParameterUtilsTests.java +++ b/spring-r2dbc/src/test/java/org/springframework/r2dbc/core/NamedParameterUtilsTests.java @@ -16,6 +16,7 @@ package org.springframework.r2dbc.core; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -497,6 +498,66 @@ public void bindNull(int index, Class type) { .containsEntry(0, Parameters.in(String.class)); } + @Test + void multipleInParameterReferencesBindsMultiple(){ + List userIds = List.of("user1", "user2", "user3"); + String sql = """ + SELECT * FROM PERSON + WHERE name IN (:ids) + GROUP BY address + + UNION + + SELECT * FROM PERSON + WHERE name NOT IN (:ids) + """; + + BindMarkersFactory factory = BindMarkersFactory.anonymous("?"); + + PreparedOperation operation = NamedParameterUtils.substituteNamedParameters( + sql, factory, new MapBindParameterSource( + Collections.singletonMap("ids", Parameters.in(userIds)))); + + assertThat(operation.toQuery()).isEqualTo( + """ + SELECT * FROM PERSON + WHERE name IN (?, ?, ?) + GROUP BY address + + UNION + + SELECT * FROM PERSON + WHERE name NOT IN (?, ?, ?) + """); + final String[] expectedValues = {"user1", "user2", "user3", "user1", "user2", "user3"}; + final int[] bindingCount = {0}; + final boolean[] isBinding = new boolean[6]; + final String[] bindingValue = new String[6]; + operation.bindTo(new BindTarget() { + + @Override + public void bind(String identifier, Object value) { + throw new UnsupportedOperationException(); + } + @Override + public void bind(int index, Object value) { + bindingCount[0]++; + isBinding[index] = true; + bindingValue[index] = (String) value; + } + @Override + public void bindNull(String identifier, Class type) { + throw new UnsupportedOperationException(); + } + @Override + public void bindNull(int index, Class type) { + throw new UnsupportedOperationException(); + } + }); + assertThat(bindingCount[0]).isEqualTo(6); + assertThat(isBinding).containsExactly(true, true, true, true, true, true); + assertThat(bindingValue).containsExactly(expectedValues); + } private static String expand(ParsedSql sql) { return NamedParameterUtils.substituteNamedParameters(sql, INDEXED_MARKERS,