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
This commit is contained in:
Mark Paluch
2023-08-25 09:16:06 +02:00
parent 508667f43e
commit 00ee738231
2 changed files with 39 additions and 19 deletions

View File

@@ -288,36 +288,28 @@ class StringQuery implements DeclaredQuery {
: ParameterOrigin.ofExpression(expression);
BindingIdentifier targetBinding = queryParameter;
Function<BindingIdentifier, ParameterBinding> bindingFactory;
switch (ParameterBindingType.of(typeSource)) {
case LIKE:
Type likeType = LikeParameterBinding.getLikeTypeFrom(matcher.group(2));
if (origin.isExpression()) {
parameterBindings.register(new LikeParameterBinding(queryParameter, origin, likeType));
} else {
targetBinding = parameterBindings.register(queryParameter, origin,
(identifier) -> new LikeParameterBinding(identifier, origin, likeType));
}
bindingFactory = (identifier) -> new LikeParameterBinding(identifier, origin, likeType);
break;
case IN:
parameterBindings.register(new InParameterBinding(queryParameter, origin));
bindingFactory = (identifier) -> new InParameterBinding(identifier, origin);
break;
case AS_IS: // fall-through we don't need a special parameter queryParameter for the given parameter.
default:
bindingFactory = (identifier) -> new ParameterBinding(identifier, origin);
}
if (origin.isExpression()) {
parameterBindings.register(new ParameterBinding(queryParameter, origin));
} else {
targetBinding = parameterBindings.register(queryParameter, origin,
(identifier) -> new ParameterBinding(identifier, origin));
}
if (origin.isExpression()) {
parameterBindings.register(bindingFactory.apply(queryParameter));
} else {
targetBinding = parameterBindings.register(queryParameter, origin, bindingFactory);
}
replacement = targetBinding.hasName() ? ":" + targetBinding.getName()

View File

@@ -243,7 +243,6 @@ class StringQueryUnitTests {
assertThat(bindings).hasSize(1);
assertNamedBinding(InParameterBinding.class, "ids", bindings.get(0));
}
@Test // DATAJPA-461
@@ -276,7 +275,37 @@ class StringQueryUnitTests {
assertThat(bindings).hasSize(1);
assertPositionalBinding(InParameterBinding.class, 1, bindings.get(0));
}
@Test // GH-3126
void allowsReuseOfParameterWithInAndRegularBinding() {
StringQuery query = new StringQuery(
"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);
assertThat(query.hasParameterBindings()).isTrue();
assertThat(query.getQueryString()).isEqualTo(
"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");
List<ParameterBinding> bindings = query.getParameterBindings();
assertThat(bindings).hasSize(2);
assertPositionalBinding(ParameterBinding.class, 1, bindings.get(0));
assertPositionalBinding(InParameterBinding.class, 2, bindings.get(1));
query = new StringQuery(
"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",
true);
assertThat(query.hasParameterBindings()).isTrue();
assertThat(query.getQueryString()).isEqualTo(
"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");
bindings = query.getParameterBindings();
assertThat(bindings).hasSize(2);
assertNamedBinding(ParameterBinding.class, "foo", bindings.get(0));
assertNamedBinding(InParameterBinding.class, "foo_1", bindings.get(1));
}
@Test // DATAJPA-461
@@ -349,7 +378,6 @@ class StringQueryUnitTests {
assertThat(bindings).hasSize(1);
assertNamedBinding(InParameterBinding.class, "abonnés", bindings.get(0));
}
@Test // DATAJPA-545