11/*
2- * Copyright 2002-2024 the original author or authors.
2+ * Copyright 2002-2025 the original author or authors.
33 *
44 * Licensed under the Apache License, Version 2.0 (the "License");
55 * you may not use this file except in compliance with the License.
1616
1717package org .springframework .r2dbc .core ;
1818
19- import java .util .Arrays ;
20- import java .util .Collections ;
2119import java .util .HashMap ;
22- import java .util .LinkedHashMap ;
20+ import java .util .List ;
2321import java .util .Map ;
2422
2523import io .r2dbc .spi .Parameters ;
4240 * @author Mark Paluch
4341 * @author Jens Schauder
4442 * @author Anton Naydenov
43+ * @author Sam Brannen
4544 */
4645class NamedParameterUtilsTests {
4746
48- private final BindMarkersFactory BIND_MARKERS = BindMarkersFactory .indexed ("$" , 1 );
47+ private static final BindMarkersFactory INDEXED_MARKERS = BindMarkersFactory .indexed ("$" , 1 );
48+
49+ private static final BindMarkersFactory ANONYMOUS_MARKERS = BindMarkersFactory .anonymous ("?" );
4950
5051
5152 @ Test
@@ -73,7 +74,7 @@ void substituteNamedParameters() {
7374 namedParams .addValue ("a" , "a" ).addValue ("b" , "b" ).addValue ("c" , "c" );
7475
7576 PreparedOperation <?> operation = NamedParameterUtils .substituteNamedParameters (
76- "xxx :a :b :c" , BIND_MARKERS , namedParams );
77+ "xxx :a :b :c" , INDEXED_MARKERS , namedParams );
7778
7879 assertThat (operation .toQuery ()).isEqualTo ("xxx $1 $2 $3" );
7980
@@ -87,11 +88,11 @@ void substituteNamedParameters() {
8788 void substituteObjectArray () {
8889 MapBindParameterSource namedParams = new MapBindParameterSource (new HashMap <>());
8990 namedParams .addValue ("a" ,
90- Arrays . asList (new Object [] {"Walter" , "Heisenberg" },
91- new Object [] {"Walt Jr." , "Flynn" }));
91+ List . of (new Object [] {"Walter" , "Heisenberg" },
92+ new Object [] {"Walt Jr." , "Flynn" }));
9293
9394 PreparedOperation <?> operation = NamedParameterUtils .substituteNamedParameters (
94- "xxx :a" , BIND_MARKERS , namedParams );
95+ "xxx :a" , INDEXED_MARKERS , namedParams );
9596
9697 assertThat (operation .toQuery ()).isEqualTo ("xxx ($1, $2), ($3, $4)" );
9798 }
@@ -100,13 +101,13 @@ void substituteObjectArray() {
100101 void shouldBindObjectArray () {
101102 MapBindParameterSource namedParams = new MapBindParameterSource (new HashMap <>());
102103 namedParams .addValue ("a" ,
103- Arrays . asList (new Object [] {"Walter" , "Heisenberg" },
104- new Object [] {"Walt Jr." , "Flynn" }));
104+ List . of (new Object [] {"Walter" , "Heisenberg" },
105+ new Object [] {"Walt Jr." , "Flynn" }));
105106
106107 BindTarget bindTarget = mock ();
107108
108109 PreparedOperation <?> operation = NamedParameterUtils .substituteNamedParameters (
109- "xxx :a" , BIND_MARKERS , namedParams );
110+ "xxx :a" , INDEXED_MARKERS , namedParams );
110111 operation .bindTo (bindTarget );
111112
112113 verify (bindTarget ).bind (0 , "Walter" );
@@ -141,7 +142,7 @@ void parseSqlStatementWithPostgresCasting() {
141142
142143 ParsedSql parsedSql = NamedParameterUtils .parseSqlStatement (sql );
143144 PreparedOperation <?> operation = NamedParameterUtils .substituteNamedParameters (
144- parsedSql , BIND_MARKERS , new MapBindParameterSource ());
145+ parsedSql , INDEXED_MARKERS , new MapBindParameterSource ());
145146
146147 assertThat (operation .toQuery ()).isEqualTo (expectedSql );
147148 }
@@ -312,14 +313,13 @@ void shouldAllowParsingMultipleUseOfParameter() {
312313 void multipleEqualParameterReferencesBindsValueOnce () {
313314 String sql = "SELECT * FROM person where name = :id or lastname = :id" ;
314315
315- BindMarkersFactory factory = BindMarkersFactory .indexed ("$" , 0 );
316+ MapBindParameterSource source = new MapBindParameterSource (Map .of ("id" , Parameters .in ("foo" )));
317+ PreparedOperation <String > operation = NamedParameterUtils .substituteNamedParameters (sql , INDEXED_MARKERS , source );
316318
317- PreparedOperation <String > operation = NamedParameterUtils .substituteNamedParameters (
318- sql , factory , new MapBindParameterSource (
319- Collections .singletonMap ("id" , Parameters .in ("foo" ))));
319+ assertThat (operation .toQuery ())
320+ .isEqualTo ("SELECT * FROM person where name = $1 or lastname = $1" );
320321
321- assertThat (operation .toQuery ()).isEqualTo (
322- "SELECT * FROM person where name = $0 or lastname = $0" );
322+ Map <Integer , Object > bindings = new HashMap <>();
323323
324324 operation .bindTo (new BindTarget () {
325325 @ Override
@@ -328,8 +328,7 @@ public void bind(String identifier, Object value) {
328328 }
329329 @ Override
330330 public void bind (int index , Object value ) {
331- assertThat (index ).isEqualTo (0 );
332- assertThat (value ).isEqualTo (Parameters .in ("foo" ));
331+ bindings .put (index , value );
333332 }
334333 @ Override
335334 public void bindNull (String identifier , Class <?> type ) {
@@ -340,22 +339,24 @@ public void bindNull(int index, Class<?> type) {
340339 throw new UnsupportedOperationException ();
341340 }
342341 });
342+
343+ assertThat (bindings )
344+ .hasSize (1 )
345+ .containsEntry (0 , Parameters .in ("foo" ));
343346 }
344347
345348 @ Test
346- void multipleEqualCollectionParameterReferencesBindsValueOnce () {
349+ void multipleEqualCollectionParameterReferencesForIndexedMarkersBindsValueOnce () {
347350 String sql = "SELECT * FROM person where name IN (:ids) or lastname IN (:ids)" ;
348351
349- BindMarkersFactory factory = BindMarkersFactory . indexed ( "$" , 0 );
350-
351- MultiValueMap < Integer , Object > bindings = new LinkedMultiValueMap <>( );
352+ MapBindParameterSource source = new MapBindParameterSource ( Map . of ( "ids" ,
353+ Parameters . in ( List . of ( "foo" , "bar" , "baz" ))));
354+ PreparedOperation < String > operation = NamedParameterUtils . substituteNamedParameters ( sql , INDEXED_MARKERS , source );
352355
353- PreparedOperation <String > operation = NamedParameterUtils .substituteNamedParameters (
354- sql , factory , new MapBindParameterSource (Collections .singletonMap ("ids" ,
355- Parameters .in (Arrays .asList ("foo" , "bar" , "baz" )))));
356+ assertThat (operation .toQuery ())
357+ .isEqualTo ("SELECT * FROM person where name IN ($1, $2, $3) or lastname IN ($1, $2, $3)" );
356358
357- assertThat (operation .toQuery ()).isEqualTo (
358- "SELECT * FROM person where name IN ($0, $1, $2) or lastname IN ($0, $1, $2)" );
359+ MultiValueMap <Integer , Object > bindings = new LinkedMultiValueMap <>();
359360
360361 operation .bindTo (new BindTarget () {
361362 @ Override
@@ -364,8 +365,6 @@ public void bind(String identifier, Object value) {
364365 }
365366 @ Override
366367 public void bind (int index , Object value ) {
367- assertThat (index ).isIn (0 , 1 , 2 );
368- assertThat (value ).isIn ("foo" , "bar" , "baz" );
369368 bindings .add (index , value );
370369 }
371370 @ Override
@@ -378,25 +377,24 @@ public void bindNull(int index, Class<?> type) {
378377 }
379378 });
380379
381- assertThat (bindings ).containsEntry (0 , Collections .singletonList ("foo" )) //
382- .containsEntry (1 , Collections .singletonList ("bar" )) //
383- .containsEntry (2 , Collections .singletonList ("baz" ));
380+ assertThat (bindings )
381+ .hasSize (3 )
382+ .containsEntry (0 , List .of ("foo" ))
383+ .containsEntry (1 , List .of ("bar" ))
384+ .containsEntry (2 , List .of ("baz" ));
384385 }
385386
386387 @ Test
387- void multipleEqualParameterReferencesForAnonymousMarkersBindsValueMultipleTimes () {
388+ void multipleEqualParameterReferencesForAnonymousMarkersBindsValueTwice () {
388389 String sql = "SELECT * FROM person where name = :id or lastname = :id" ;
389390
390- BindMarkersFactory factory = BindMarkersFactory .anonymous ("?" );
391-
392- PreparedOperation <String > operation = NamedParameterUtils .substituteNamedParameters (
393- sql , factory , new MapBindParameterSource (
394- Collections .singletonMap ("id" , Parameters .in ("foo" ))));
391+ MapBindParameterSource source = new MapBindParameterSource (Map .of ("id" , Parameters .in ("foo" )));
392+ PreparedOperation <String > operation = NamedParameterUtils .substituteNamedParameters (sql , ANONYMOUS_MARKERS , source );
395393
396- assertThat (operation .toQuery ()). isEqualTo (
397- "SELECT * FROM person where name = ? or lastname = ?" );
394+ assertThat (operation .toQuery ())
395+ . isEqualTo ( "SELECT * FROM person where name = ? or lastname = ?" );
398396
399- Map <Integer , Object > bindValues = new LinkedHashMap <>();
397+ Map <Integer , Object > bindings = new HashMap <>();
400398
401399 operation .bindTo (new BindTarget () {
402400 @ Override
@@ -405,7 +403,7 @@ public void bind(String identifier, Object value) {
405403 }
406404 @ Override
407405 public void bind (int index , Object value ) {
408- bindValues .put (index , value );
406+ bindings .put (index , value );
409407 }
410408 @ Override
411409 public void bindNull (String identifier , Class <?> type ) {
@@ -417,21 +415,23 @@ public void bindNull(int index, Class<?> type) {
417415 }
418416 });
419417
420- assertThat (bindValues ).hasSize (2 ).containsEntry (0 , Parameters .in ("foo" )).containsEntry (1 , Parameters .in ("foo" ));
418+ assertThat (bindings )
419+ .hasSize (2 )
420+ .containsEntry (0 , Parameters .in ("foo" ))
421+ .containsEntry (1 , Parameters .in ("foo" ));
421422 }
422423
423424 @ Test
424425 void multipleEqualParameterReferencesBindsNullOnce () {
425426 String sql = "SELECT * FROM person where name = :id or lastname = :id" ;
426427
427- BindMarkersFactory factory = BindMarkersFactory .indexed ("$" , 0 );
428+ MapBindParameterSource source = new MapBindParameterSource (Map .of ("id" , Parameters .in (String .class )));
429+ PreparedOperation <String > operation = NamedParameterUtils .substituteNamedParameters (sql , INDEXED_MARKERS , source );
428430
429- PreparedOperation <String > operation = NamedParameterUtils .substituteNamedParameters (
430- sql , factory , new MapBindParameterSource (
431- Collections .singletonMap ("id" , Parameters .in (String .class ))));
431+ assertThat (operation .toQuery ())
432+ .isEqualTo ("SELECT * FROM person where name = $1 or lastname = $1" );
432433
433- assertThat (operation .toQuery ()).isEqualTo (
434- "SELECT * FROM person where name = $0 or lastname = $0" );
434+ Map <Integer , Object > bindings = new HashMap <>();
435435
436436 operation .bindTo (new BindTarget () {
437437 @ Override
@@ -440,8 +440,7 @@ public void bind(String identifier, Object value) {
440440 }
441441 @ Override
442442 public void bind (int index , Object value ) {
443- assertThat (index ).isEqualTo (0 );
444- assertThat (value ).isEqualTo (Parameters .in (String .class ));
443+ bindings .put (index , value );
445444 }
446445 @ Override
447446 public void bindNull (String identifier , Class <?> type ) {
@@ -452,16 +451,20 @@ public void bindNull(int index, Class<?> type) {
452451 throw new UnsupportedOperationException ();
453452 }
454453 });
454+
455+ assertThat (bindings )
456+ .hasSize (1 )
457+ .containsEntry (0 , Parameters .in (String .class ));
455458 }
456459
457460
458- private String expand (ParsedSql sql ) {
459- return NamedParameterUtils .substituteNamedParameters (sql , BIND_MARKERS ,
461+ private static String expand (ParsedSql sql ) {
462+ return NamedParameterUtils .substituteNamedParameters (sql , INDEXED_MARKERS ,
460463 new MapBindParameterSource ()).toQuery ();
461464 }
462465
463- private String expand (String sql ) {
464- return NamedParameterUtils .substituteNamedParameters (sql , BIND_MARKERS ,
466+ private static String expand (String sql ) {
467+ return NamedParameterUtils .substituteNamedParameters (sql , INDEXED_MARKERS ,
465468 new MapBindParameterSource ()).toQuery ();
466469 }
467470
0 commit comments