@@ -160,6 +160,66 @@ void rewritesNamedLikeToUniqueParametersIfNecessary() {
160160 assertThat (((MethodInvocationArgument ) parameterBinding .getOrigin ()).identifier ().getName ()).isEqualTo ("firstname" );
161161 }
162162
163+ @ Test // GH-3784
164+ void rewritesNamedLikeToUniqueParametersRetainingCountQuery () {
165+
166+ DeclaredQuery query = new StringQuery (
167+ "select u from User u where u.firstname like %:firstname or u.firstname like :firstname% or u.firstname = :firstname" ,
168+ false ).deriveCountQuery (null );
169+
170+ assertThat (query .getQueryString ()) //
171+ .isEqualTo (
172+ "select count(u) from User u where u.firstname like :firstname or u.firstname like :firstname_1 or u.firstname = :firstname_2" );
173+
174+ List <ParameterBinding > bindings = query .getParameterBindings ();
175+ assertThat (bindings ).hasSize (3 );
176+
177+ LikeParameterBinding binding = (LikeParameterBinding ) bindings .get (0 );
178+ assertThat (binding ).isNotNull ();
179+ assertThat (binding .getOrigin ()).isEqualTo (ParameterOrigin .ofParameter ("firstname" ));
180+ assertThat (binding .getName ()).isEqualTo ("firstname" );
181+ assertThat (binding .getType ()).isEqualTo (Type .ENDING_WITH );
182+
183+ binding = (LikeParameterBinding ) bindings .get (1 );
184+ assertThat (binding ).isNotNull ();
185+ assertThat (binding .getOrigin ()).isEqualTo (ParameterOrigin .ofParameter ("firstname" ));
186+ assertThat (binding .getName ()).isEqualTo ("firstname_1" );
187+ assertThat (binding .getType ()).isEqualTo (Type .STARTING_WITH );
188+
189+ ParameterBinding parameterBinding = bindings .get (2 );
190+ assertThat (parameterBinding ).isNotNull ();
191+ assertThat (parameterBinding .getOrigin ()).isEqualTo (ParameterOrigin .ofParameter ("firstname" ));
192+ assertThat (parameterBinding .getName ()).isEqualTo ("firstname_2" );
193+ assertThat (((MethodInvocationArgument ) parameterBinding .getOrigin ()).identifier ().getName ()).isEqualTo ("firstname" );
194+ }
195+
196+ @ Test // GH-3784
197+ void rewritesExpressionsLikeToUniqueParametersRetainingCountQuery () {
198+
199+ DeclaredQuery query = new StringQuery (
200+ "select u from User u where u.firstname like %:#{firstname} or u.firstname like :#{firstname}%" , false )
201+ .deriveCountQuery (null );
202+
203+ assertThat (query .getQueryString ()) //
204+ .isEqualTo (
205+ "select count(u) from User u where u.firstname like :__$synthetic$__1 or u.firstname like :__$synthetic$__2" );
206+
207+ List <ParameterBinding > bindings = query .getParameterBindings ();
208+ assertThat (bindings ).hasSize (2 );
209+
210+ LikeParameterBinding binding = (LikeParameterBinding ) bindings .get (0 );
211+ assertThat (binding ).isNotNull ();
212+ assertThat (binding .getOrigin ()).isEqualTo (ParameterOrigin .ofExpression ("firstname" ));
213+ assertThat (binding .getName ()).isEqualTo ("__$synthetic$__1" );
214+ assertThat (binding .getType ()).isEqualTo (Type .ENDING_WITH );
215+
216+ binding = (LikeParameterBinding ) bindings .get (1 );
217+ assertThat (binding ).isNotNull ();
218+ assertThat (binding .getOrigin ()).isEqualTo (ParameterOrigin .ofExpression ("firstname" ));
219+ assertThat (binding .getName ()).isEqualTo ("__$synthetic$__2" );
220+ assertThat (binding .getType ()).isEqualTo (Type .STARTING_WITH );
221+ }
222+
163223 @ Test // GH-3041
164224 void rewritesPositionalLikeToUniqueParametersIfNecessary () {
165225
@@ -263,6 +323,48 @@ void detectsMultipleNamedInParameterBindings() {
263323 assertNamedBinding (ParameterBinding .class , "bar" , bindings .get (2 ));
264324 }
265325
326+ @ Test // GH-3784
327+ void deriveCountQueryWithNamedInRetainsOrigin () {
328+
329+ String queryString = "select u from User u where (:logins) IS NULL OR LOWER(u.login) IN (:logins)" ;
330+ DeclaredQuery query = new StringQuery (queryString , false ).deriveCountQuery (null );
331+
332+ assertThat (query .getQueryString ())
333+ .isEqualTo ("select count(u) from User u where (:logins) IS NULL OR LOWER(u.login) IN (:logins_1)" );
334+
335+ List <ParameterBinding > bindings = query .getParameterBindings ();
336+ assertThat (bindings ).hasSize (2 );
337+
338+ assertNamedBinding (ParameterBinding .class , "logins" , bindings .get (0 ));
339+ assertThat ((MethodInvocationArgument ) bindings .get (0 ).getOrigin ()).extracting (MethodInvocationArgument ::identifier )
340+ .extracting (BindingIdentifier ::getName ).isEqualTo ("logins" );
341+
342+ assertNamedBinding (InParameterBinding .class , "logins_1" , bindings .get (1 ));
343+ assertThat ((MethodInvocationArgument ) bindings .get (1 ).getOrigin ()).extracting (MethodInvocationArgument ::identifier )
344+ .extracting (BindingIdentifier ::getName ).isEqualTo ("logins" );
345+ }
346+
347+ @ Test // GH-3784
348+ void deriveCountQueryWithPositionalInRetainsOrigin () {
349+
350+ String queryString = "select u from User u where (?1) IS NULL OR LOWER(u.login) IN (?1)" ;
351+ DeclaredQuery query = new StringQuery (queryString , false ).deriveCountQuery (null );
352+
353+ assertThat (query .getQueryString ())
354+ .isEqualTo ("select count(u) from User u where (?1) IS NULL OR LOWER(u.login) IN (?2)" );
355+
356+ List <ParameterBinding > bindings = query .getParameterBindings ();
357+ assertThat (bindings ).hasSize (2 );
358+
359+ assertPositionalBinding (ParameterBinding .class , 1 , bindings .get (0 ));
360+ assertThat ((MethodInvocationArgument ) bindings .get (0 ).getOrigin ()).extracting (MethodInvocationArgument ::identifier )
361+ .extracting (BindingIdentifier ::getPosition ).isEqualTo (1 );
362+
363+ assertPositionalBinding (InParameterBinding .class , 2 , bindings .get (1 ));
364+ assertThat ((MethodInvocationArgument ) bindings .get (1 ).getOrigin ()).extracting (MethodInvocationArgument ::identifier )
365+ .extracting (BindingIdentifier ::getPosition ).isEqualTo (1 );
366+ }
367+
266368 @ Test // DATAJPA-461
267369 void detectsPositionalInParameterBindings () {
268370
0 commit comments