Skip to content

Commit 00ee738

Browse files
committed
Register individual bindings for IN bindings if parameter is already bound differently.
We now register a new parameter binding if the named/positional parameter is already bound in an incompatible style. Closes #3126
1 parent 508667f commit 00ee738

File tree

2 files changed

+39
-19
lines changed

2 files changed

+39
-19
lines changed

spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/StringQuery.java

+9-17
Original file line numberDiff line numberDiff line change
@@ -288,36 +288,28 @@ private String parseParameterBindingsOfQueryIntoBindingsAndReturnCleanedQuery(St
288288
: ParameterOrigin.ofExpression(expression);
289289

290290
BindingIdentifier targetBinding = queryParameter;
291+
Function<BindingIdentifier, ParameterBinding> bindingFactory;
291292
switch (ParameterBindingType.of(typeSource)) {
292293

293294
case LIKE:
294295

295296
Type likeType = LikeParameterBinding.getLikeTypeFrom(matcher.group(2));
296-
297-
if (origin.isExpression()) {
298-
parameterBindings.register(new LikeParameterBinding(queryParameter, origin, likeType));
299-
} else {
300-
targetBinding = parameterBindings.register(queryParameter, origin,
301-
(identifier) -> new LikeParameterBinding(identifier, origin, likeType));
302-
}
303-
297+
bindingFactory = (identifier) -> new LikeParameterBinding(identifier, origin, likeType);
304298
break;
305299

306300
case IN:
307-
308-
parameterBindings.register(new InParameterBinding(queryParameter, origin));
309-
301+
bindingFactory = (identifier) -> new InParameterBinding(identifier, origin);
310302
break;
311303

312304
case AS_IS: // fall-through we don't need a special parameter queryParameter for the given parameter.
313305
default:
306+
bindingFactory = (identifier) -> new ParameterBinding(identifier, origin);
307+
}
314308

315-
if (origin.isExpression()) {
316-
parameterBindings.register(new ParameterBinding(queryParameter, origin));
317-
} else {
318-
targetBinding = parameterBindings.register(queryParameter, origin,
319-
(identifier) -> new ParameterBinding(identifier, origin));
320-
}
309+
if (origin.isExpression()) {
310+
parameterBindings.register(bindingFactory.apply(queryParameter));
311+
} else {
312+
targetBinding = parameterBindings.register(queryParameter, origin, bindingFactory);
321313
}
322314

323315
replacement = targetBinding.hasName() ? ":" + targetBinding.getName()

spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/StringQueryUnitTests.java

+30-2
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,6 @@ void detectsNamedInParameterBindings() {
243243
assertThat(bindings).hasSize(1);
244244

245245
assertNamedBinding(InParameterBinding.class, "ids", bindings.get(0));
246-
247246
}
248247

249248
@Test // DATAJPA-461
@@ -276,7 +275,37 @@ void detectsPositionalInParameterBindings() {
276275
assertThat(bindings).hasSize(1);
277276

278277
assertPositionalBinding(InParameterBinding.class, 1, bindings.get(0));
278+
}
279+
280+
@Test // GH-3126
281+
void allowsReuseOfParameterWithInAndRegularBinding() {
282+
283+
StringQuery query = new StringQuery(
284+
"select u from User u where COALESCE(?1) is null OR u.id in ?1 OR COALESCE(?1) is null OR u.id in ?1", true);
285+
286+
assertThat(query.hasParameterBindings()).isTrue();
287+
assertThat(query.getQueryString()).isEqualTo(
288+
"select u from User u where COALESCE(?1) is null OR u.id in ?2 OR COALESCE(?1) is null OR u.id in ?2");
289+
290+
List<ParameterBinding> bindings = query.getParameterBindings();
291+
assertThat(bindings).hasSize(2);
279292

293+
assertPositionalBinding(ParameterBinding.class, 1, bindings.get(0));
294+
assertPositionalBinding(InParameterBinding.class, 2, bindings.get(1));
295+
296+
query = new StringQuery(
297+
"select u from User u where COALESCE(:foo) is null OR u.id in :foo OR COALESCE(:foo) is null OR u.id in :foo",
298+
true);
299+
300+
assertThat(query.hasParameterBindings()).isTrue();
301+
assertThat(query.getQueryString()).isEqualTo(
302+
"select u from User u where COALESCE(:foo) is null OR u.id in :foo_1 OR COALESCE(:foo) is null OR u.id in :foo_1");
303+
304+
bindings = query.getParameterBindings();
305+
assertThat(bindings).hasSize(2);
306+
307+
assertNamedBinding(ParameterBinding.class, "foo", bindings.get(0));
308+
assertNamedBinding(InParameterBinding.class, "foo_1", bindings.get(1));
280309
}
281310

282311
@Test // DATAJPA-461
@@ -349,7 +378,6 @@ void detectsInBindingWithSpecialFrenchCharactersInParentheses() {
349378

350379
assertThat(bindings).hasSize(1);
351380
assertNamedBinding(InParameterBinding.class, "abonnés", bindings.get(0));
352-
353381
}
354382

355383
@Test // DATAJPA-545

0 commit comments

Comments
 (0)