@@ -78,7 +78,7 @@ class StringQuery implements DeclaredQuery {
78
78
79
79
Metadata queryMeta = new Metadata ();
80
80
this .query = ParameterBindingParser .INSTANCE .parseParameterBindingsOfQueryIntoBindingsAndReturnCleanedQuery (query ,
81
- this .bindings , queryMeta );
81
+ this .bindings , queryMeta , isNative );
82
82
83
83
this .usesJdbcStyleParameters = queryMeta .usesJdbcStyleParameters ;
84
84
@@ -212,7 +212,7 @@ enum ParameterBindingParser {
212
212
* the cleaned up query.
213
213
*/
214
214
private String parseParameterBindingsOfQueryIntoBindingsAndReturnCleanedQuery (String query ,
215
- List <ParameterBinding > bindings , Metadata queryMeta ) {
215
+ List <ParameterBinding > bindings , Metadata queryMeta , boolean isNative ) {
216
216
217
217
int greatestParameterIndex = tryFindGreatestParameterIndexIn (query );
218
218
boolean parametersShouldBeAccessedByIndex = greatestParameterIndex != -1 ;
@@ -299,7 +299,7 @@ private String parseParameterBindingsOfQueryIntoBindingsAndReturnCleanedQuery(St
299
299
}
300
300
301
301
if (replacement != null ) {
302
- resultingQuery = replaceFirst (resultingQuery , matcher .group (2 ), replacement );
302
+ resultingQuery = replaceFirst (resultingQuery , matcher .group (2 ), replacement , isNative );
303
303
}
304
304
305
305
}
@@ -327,14 +327,14 @@ private static SpelExtractor createSpelExtractor(String queryWithSpel, boolean p
327
327
return SpelQueryContext .of (indexToParameterName , parameterNameToReplacement ).parse (queryWithSpel );
328
328
}
329
329
330
- private static String replaceFirst (String text , String substring , String replacement ) {
330
+ private static String replaceFirst (String text , String substring , String replacement , boolean isNative ) {
331
331
332
332
int index = text .indexOf (substring );
333
333
if (index < 0 ) {
334
334
return text ;
335
335
}
336
336
337
- return text .substring (0 , index ) + potentiallyWrapWithWildcards (replacement , substring )
337
+ return text .substring (0 , index ) + potentiallyWrapWithWildcards (replacement , substring , isNative )
338
338
+ text .substring (index + substring .length ());
339
339
}
340
340
@@ -348,7 +348,7 @@ private static String replaceFirst(String text, String substring, String replace
348
348
* @return the replacement string properly wrapped in a {@literal CONCAT} function with wildcards applied.
349
349
* @since 3.1
350
350
*/
351
- private static String potentiallyWrapWithWildcards (String replacement , String substring ) {
351
+ private static String potentiallyWrapWithWildcards (String replacement , String substring , boolean isNative ) {
352
352
353
353
boolean wildcards = substring .startsWith ("%" ) || substring .endsWith ("%" );
354
354
@@ -362,7 +362,11 @@ private static String potentiallyWrapWithWildcards(String replacement, String su
362
362
concatWrapper .append ("'%'," );
363
363
}
364
364
365
- concatWrapper .append (replacement );
365
+ if (isNative ) {
366
+ concatWrapper .append (coalesce (replacement , "''" ));
367
+ } else {
368
+ concatWrapper .append (coalesce (castAsText (replacement ), "''" ));
369
+ }
366
370
367
371
if (substring .endsWith ("%" )) {
368
372
concatWrapper .append (",'%'" );
@@ -373,6 +377,27 @@ private static String potentiallyWrapWithWildcards(String replacement, String su
373
377
return concatWrapper .toString ();
374
378
}
375
379
380
+ /**
381
+ * Apply the {@literal COALESCE} function with a default value.
382
+ *
383
+ * @param expression
384
+ * @param defaultValue
385
+ * @return
386
+ */
387
+ private static String coalesce (String expression , String defaultValue ) {
388
+ return "COALESCE(" + expression + "," + defaultValue + ")" ;
389
+ }
390
+
391
+ /**
392
+ * {@literal CAST} the expression into a {@literal text}.
393
+ *
394
+ * @param expression
395
+ * @return
396
+ */
397
+ private static String castAsText (String expression ) {
398
+ return "CAST(" + expression + " as text)" ;
399
+ }
400
+
376
401
@ Nullable
377
402
private static Integer getParameterIndex (@ Nullable String parameterIndexString ) {
378
403
0 commit comments