Skip to content

Commit 2a3be81

Browse files
committedMar 15, 2025
Improve Case Insensitive Conditions
Make the case-insensitive conditions work as expected. With a map operation, the values will now be upper-cased if possible.
1 parent ea3b0a8 commit 2a3be81

9 files changed

+35
-117
lines changed
 

‎src/main/java/org/mybatis/dynamic/sql/util/StringUtilities.java

+8-4
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@
1515
*/
1616
package org.mybatis.dynamic.sql.util;
1717

18-
import java.util.function.Function;
19-
2018
import org.jspecify.annotations.Nullable;
2119

2220
public interface StringUtilities {
@@ -62,7 +60,13 @@ static String formatConstantForSQL(String in) {
6260
return "'" + escaped + "'"; //$NON-NLS-1$ //$NON-NLS-2$
6361
}
6462

65-
static Function<String, String> mapToUpperCase(Function<String, String> f) {
66-
return f.andThen(String::toUpperCase);
63+
static <T> T upperCaseIfPossible(T value) {
64+
if (value instanceof String) {
65+
@SuppressWarnings("unchecked")
66+
T t = (T) safelyUpperCase((String) value);
67+
return t;
68+
}
69+
70+
return value;
6771
}
6872
}

‎src/main/java/org/mybatis/dynamic/sql/where/condition/IsInCaseInsensitive.java

+3-16
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import java.util.Collections;
2121
import java.util.function.Function;
2222
import java.util.function.Predicate;
23+
import java.util.stream.Collectors;
2324

2425
import org.mybatis.dynamic.sql.AbstractListValueCondition;
2526
import org.mybatis.dynamic.sql.render.RenderingContext;
@@ -38,7 +39,7 @@ public static <T> IsInCaseInsensitive<T> empty() {
3839
}
3940

4041
protected IsInCaseInsensitive(Collection<T> values) {
41-
super(values);
42+
super(values.stream().map(StringUtilities::upperCaseIfPossible).collect(Collectors.toList()));
4243
}
4344

4445
@Override
@@ -57,19 +58,6 @@ public IsInCaseInsensitive<T> filter(Predicate<? super T> predicate) {
5758
return filterSupport(predicate, IsInCaseInsensitive::new, this, IsInCaseInsensitive::empty);
5859
}
5960

60-
/**
61-
* If renderable, apply the mapping to the value and return a new condition with the new value. Else return a
62-
* condition that will not render (this).
63-
*
64-
* <p>This function DOES NOT automatically transform values to uppercase, so it potentially creates a
65-
* case-sensitive query. For String conditions you can use {@link StringUtilities#mapToUpperCase(Function)}
66-
* to add an uppercase transform after your mapping function.
67-
*
68-
* @param mapper a mapping function to apply to the value, if renderable
69-
* @param <R> type of the new condition
70-
* @return a new condition with the result of applying the mapper to the value of this condition,
71-
* if renderable, otherwise a condition that will not render.
72-
*/
7361
@Override
7462
public <R> IsInCaseInsensitive<R> map(Function<? super T, ? extends R> mapper) {
7563
return mapSupport(mapper, IsInCaseInsensitive::new, IsInCaseInsensitive::empty);
@@ -80,7 +68,6 @@ public static IsInCaseInsensitive<String> of(String... values) {
8068
}
8169

8270
public static IsInCaseInsensitive<String> of(Collection<String> values) {
83-
// Keep the null safe upper case utility for backwards compatibility in case someone passes in a null
84-
return new IsInCaseInsensitive<>(values.stream().map(StringUtilities::safelyUpperCase).toList());
71+
return new IsInCaseInsensitive<>(values);
8572
}
8673
}

‎src/main/java/org/mybatis/dynamic/sql/where/condition/IsInCaseInsensitiveWhenPresent.java

+2-16
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ public static <T> IsInCaseInsensitiveWhenPresent<T> empty() {
3939
}
4040

4141
protected IsInCaseInsensitiveWhenPresent(Collection<T> values) {
42-
super(values);
42+
super(values.stream().filter(Objects::nonNull).map(StringUtilities::upperCaseIfPossible).toList());
4343
}
4444

4545
@Override
@@ -53,19 +53,6 @@ public IsInCaseInsensitiveWhenPresent<T> filter(Predicate<? super T> predicate)
5353
IsInCaseInsensitiveWhenPresent::empty);
5454
}
5555

56-
/**
57-
* If renderable, apply the mapping to the value and return a new condition with the new value. Else return a
58-
* condition that will not render (this).
59-
*
60-
* <p>This function DOES NOT automatically transform values to uppercase, so it potentially creates a
61-
* case-sensitive query. For String conditions you can use {@link StringUtilities#mapToUpperCase(Function)}
62-
* to add an uppercase transform after your mapping function.
63-
*
64-
* @param mapper a mapping function to apply to the value, if renderable
65-
* @param <R> type of the new condition
66-
* @return a new condition with the result of applying the mapper to the value of this condition,
67-
* if renderable, otherwise a condition that will not render.
68-
*/
6956
@Override
7057
public <R> IsInCaseInsensitiveWhenPresent<R> map(Function<? super T, ? extends R> mapper) {
7158
return mapSupport(mapper, IsInCaseInsensitiveWhenPresent::new, IsInCaseInsensitiveWhenPresent::empty);
@@ -76,7 +63,6 @@ public static IsInCaseInsensitiveWhenPresent<String> of(@Nullable String... valu
7663
}
7764

7865
public static IsInCaseInsensitiveWhenPresent<String> of(Collection<@Nullable String> values) {
79-
return new IsInCaseInsensitiveWhenPresent<>(
80-
values.stream().filter(Objects::nonNull).map(String::toUpperCase).toList());
66+
return new IsInCaseInsensitiveWhenPresent<>(values);
8167
}
8268
}

‎src/main/java/org/mybatis/dynamic/sql/where/condition/IsLikeCaseInsensitive.java

+2-16
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public static <T> IsLikeCaseInsensitive<T> empty() {
4444
}
4545

4646
protected IsLikeCaseInsensitive(T value) {
47-
super(value);
47+
super(StringUtilities.upperCaseIfPossible(value));
4848
}
4949

5050
@Override
@@ -57,26 +57,12 @@ public IsLikeCaseInsensitive<T> filter(Predicate<? super T> predicate) {
5757
return filterSupport(predicate, IsLikeCaseInsensitive::empty, this);
5858
}
5959

60-
/**
61-
* If renderable, apply the mapping to the value and return a new condition with the new value. Else return a
62-
* condition that will not render (this).
63-
*
64-
* <p>This function DOES NOT automatically transform values to uppercase, so it potentially creates a
65-
* case-sensitive query. For String conditions you can use {@link StringUtilities#mapToUpperCase(Function)}
66-
* to add an uppercase transform after your mapping function.
67-
*
68-
* @param mapper a mapping function to apply to the value, if renderable
69-
* @param <R> type of the new condition
70-
* @return a new condition with the result of applying the mapper to the value of this condition,
71-
* if renderable, otherwise a condition that will not render.
72-
*/
7360
@Override
7461
public <R> IsLikeCaseInsensitive<R> map(Function<? super T, ? extends R> mapper) {
7562
return mapSupport(mapper, IsLikeCaseInsensitive::new, IsLikeCaseInsensitive::empty);
7663
}
7764

7865
public static IsLikeCaseInsensitive<String> of(String value) {
79-
// Keep the null safe upper case utility for backwards compatibility in case someone passes in a null
80-
return new IsLikeCaseInsensitive<>(StringUtilities.safelyUpperCase(value));
66+
return new IsLikeCaseInsensitive<>(value);
8167
}
8268
}

‎src/main/java/org/mybatis/dynamic/sql/where/condition/IsNotInCaseInsensitive.java

+2-16
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public static <T> IsNotInCaseInsensitive<T> empty() {
3838
}
3939

4040
protected IsNotInCaseInsensitive(Collection<T> values) {
41-
super(values);
41+
super(values.stream().map(StringUtilities::upperCaseIfPossible).toList());
4242
}
4343

4444
@Override
@@ -57,19 +57,6 @@ public IsNotInCaseInsensitive<T> filter(Predicate<? super T> predicate) {
5757
return filterSupport(predicate, IsNotInCaseInsensitive::new, this, IsNotInCaseInsensitive::empty);
5858
}
5959

60-
/**
61-
* If renderable, apply the mapping to the value and return a new condition with the new value. Else return a
62-
* condition that will not render (this).
63-
*
64-
* <p>This function DOES NOT automatically transform values to uppercase, so it potentially creates a
65-
* case-sensitive query. For String conditions you can use {@link StringUtilities#mapToUpperCase(Function)}
66-
* to add an uppercase transform after your mapping function.
67-
*
68-
* @param mapper a mapping function to apply to the value, if renderable
69-
* @param <R> type of the new condition
70-
* @return a new condition with the result of applying the mapper to the value of this condition,
71-
* if renderable, otherwise a condition that will not render.
72-
*/
7360
@Override
7461
public <R> IsNotInCaseInsensitive<R> map(Function<? super T, ? extends R> mapper) {
7562
return mapSupport(mapper, IsNotInCaseInsensitive::new, IsNotInCaseInsensitive::empty);
@@ -80,7 +67,6 @@ public static IsNotInCaseInsensitive<String> of(String... values) {
8067
}
8168

8269
public static IsNotInCaseInsensitive<String> of(Collection<String> values) {
83-
// Keep the null safe upper case utility for backwards compatibility in case someone passes in a null
84-
return new IsNotInCaseInsensitive<>(values.stream().map(StringUtilities::safelyUpperCase).toList());
70+
return new IsNotInCaseInsensitive<>(values);
8571
}
8672
}

‎src/main/java/org/mybatis/dynamic/sql/where/condition/IsNotInCaseInsensitiveWhenPresent.java

+2-16
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ public static <T> IsNotInCaseInsensitiveWhenPresent<T> empty() {
3939
}
4040

4141
protected IsNotInCaseInsensitiveWhenPresent(Collection<T> values) {
42-
super(values);
42+
super(values.stream().filter(Objects::nonNull).map(StringUtilities::upperCaseIfPossible).toList());
4343
}
4444

4545
@Override
@@ -53,19 +53,6 @@ public IsNotInCaseInsensitiveWhenPresent<T> filter(Predicate<? super T> predicat
5353
this, IsNotInCaseInsensitiveWhenPresent::empty);
5454
}
5555

56-
/**
57-
* If renderable, apply the mapping to the value and return a new condition with the new value. Else return a
58-
* condition that will not render (this).
59-
*
60-
* <p>This function DOES NOT automatically transform values to uppercase, so it potentially creates a
61-
* case-sensitive query. For String conditions you can use {@link StringUtilities#mapToUpperCase(Function)}
62-
* to add an uppercase transform after your mapping function.
63-
*
64-
* @param mapper a mapping function to apply to the value, if renderable
65-
* @param <R> type of the new condition
66-
* @return a new condition with the result of applying the mapper to the value of this condition,
67-
* if renderable, otherwise a condition that will not render.
68-
*/
6956
@Override
7057
public <R> IsNotInCaseInsensitiveWhenPresent<R> map(Function<? super T, ? extends R> mapper) {
7158
return mapSupport(mapper, IsNotInCaseInsensitiveWhenPresent::new, IsNotInCaseInsensitiveWhenPresent::empty);
@@ -76,7 +63,6 @@ public static IsNotInCaseInsensitiveWhenPresent<String> of(@Nullable String... v
7663
}
7764

7865
public static IsNotInCaseInsensitiveWhenPresent<String> of(Collection<@Nullable String> values) {
79-
return new IsNotInCaseInsensitiveWhenPresent<>(
80-
values.stream().filter(Objects::nonNull).map(String::toUpperCase).toList());
66+
return new IsNotInCaseInsensitiveWhenPresent<>(values);
8167
}
8268
}

‎src/main/java/org/mybatis/dynamic/sql/where/condition/IsNotLikeCaseInsensitive.java

+2-16
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public static <T> IsNotLikeCaseInsensitive<T> empty() {
4444
}
4545

4646
protected IsNotLikeCaseInsensitive(T value) {
47-
super(value);
47+
super(StringUtilities.upperCaseIfPossible(value));
4848
}
4949

5050
@Override
@@ -57,26 +57,12 @@ public IsNotLikeCaseInsensitive<T> filter(Predicate<? super T> predicate) {
5757
return filterSupport(predicate, IsNotLikeCaseInsensitive::empty, this);
5858
}
5959

60-
/**
61-
* If renderable, apply the mapping to the value and return a new condition with the new value. Else return a
62-
* condition that will not render (this).
63-
*
64-
* <p>This function DOES NOT automatically transform values to uppercase, so it potentially creates a
65-
* case-sensitive query. For String conditions you can use {@link StringUtilities#mapToUpperCase(Function)}
66-
* to add an uppercase transform after your mapping function.
67-
*
68-
* @param mapper a mapping function to apply to the value, if renderable
69-
* @param <R> type of the new condition
70-
* @return a new condition with the result of applying the mapper to the value of this condition,
71-
* if renderable, otherwise a condition that will not render.
72-
*/
7360
@Override
7461
public <R> IsNotLikeCaseInsensitive<R> map(Function<? super T, ? extends R> mapper) {
7562
return mapSupport(mapper, IsNotLikeCaseInsensitive::new, IsNotLikeCaseInsensitive::empty);
7663
}
7764

7865
public static IsNotLikeCaseInsensitive<String> of(String value) {
79-
// Keep the null safe upper case utility for backwards compatibility in case someone passes in a null
80-
return new IsNotLikeCaseInsensitive<>(StringUtilities.safelyUpperCase(value));
66+
return new IsNotLikeCaseInsensitive<>(value);
8167
}
8268
}

‎src/test/java/org/mybatis/dynamic/sql/util/StringUtilitiesTest.java

+12
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,16 @@ void testNumeric() {
3838
String input = "USER%NAME%3";
3939
assertThat(StringUtilities.toCamelCase(input)).isEqualTo("userName3");
4040
}
41+
42+
@Test
43+
void testUpperCaseInteger() {
44+
Integer i = StringUtilities.upperCaseIfPossible(3);
45+
assertThat(i).isEqualTo(3);
46+
}
47+
48+
@Test
49+
void testUpperCaseString() {
50+
String i = StringUtilities.upperCaseIfPossible("fred");
51+
assertThat(i).isEqualTo("FRED");
52+
}
4153
}

‎src/test/java/org/mybatis/dynamic/sql/where/condition/FilterAndMapTest.java

+2-17
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424

2525
import org.junit.jupiter.api.Test;
2626
import org.mybatis.dynamic.sql.SqlBuilder;
27-
import org.mybatis.dynamic.sql.util.StringUtilities;
2827

2928
class FilterAndMapTest {
3029
@Test
@@ -543,31 +542,17 @@ void testMappingAnEmptyListCondition() {
543542
assertThat(filtered).isSameAs(mapped);
544543
}
545544

546-
@Test
547-
void testIsInCaseInsensitiveWhenPresentMap() {
548-
var cond = SqlBuilder.isInCaseInsensitiveWhenPresent("Fred", "Wilma");
549-
var mapped = cond.map(s -> s + " Flintstone");
550-
assertThat(mapped.values().toList()).containsExactly("FRED Flintstone", "WILMA Flintstone");
551-
}
552-
553545
@Test
554546
void testIsInCaseInsensitiveWhenPresentMapCaseInsensitive() {
555547
var cond = SqlBuilder.isInCaseInsensitiveWhenPresent("Fred", "Wilma");
556-
var mapped = cond.map(StringUtilities.mapToUpperCase(s -> s + " Flintstone"));
557-
assertThat(mapped.values().toList()).containsExactly("FRED FLINTSTONE", "WILMA FLINTSTONE");
558-
}
559-
560-
@Test
561-
void testIsNotInCaseInsensitiveWhenPresentMap() {
562-
var cond = SqlBuilder.isNotInCaseInsensitiveWhenPresent("Fred", "Wilma");
563548
var mapped = cond.map(s -> s + " Flintstone");
564-
assertThat(mapped.values().toList()).containsExactly("FRED Flintstone", "WILMA Flintstone");
549+
assertThat(mapped.values().toList()).containsExactly("FRED FLINTSTONE", "WILMA FLINTSTONE");
565550
}
566551

567552
@Test
568553
void testIsNotInCaseInsensitiveWhenPresentMapCaseInsensitive() {
569554
var cond = SqlBuilder.isNotInCaseInsensitiveWhenPresent("Fred", "Wilma");
570-
var mapped = cond.map(StringUtilities.mapToUpperCase(s -> s + " Flintstone"));
555+
var mapped = cond.map(s -> s + " Flintstone");
571556
assertThat(mapped.values().toList()).containsExactly("FRED FLINTSTONE", "WILMA FLINTSTONE");
572557
}
573558
}

0 commit comments

Comments
 (0)
Failed to load comments.