Skip to content

Commit d6227e5

Browse files
christophstroblmp911de
authored andcommitted
Use exact matching for IN clause with ignore case.
Prior to this change the generated pattern would have matched more entries than it should have. The behavior is now aligned to its counterpart not using the IgnoreCase flag. Closes #4404 Original pull request: #4412
1 parent 7e6e029 commit d6227e5

File tree

4 files changed

+36
-3
lines changed

4 files changed

+36
-3
lines changed

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/MongoRegexCreator.java

+2
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,9 @@ public String toRegularExpression(@Nullable String source, @Nullable MatchMode m
107107
* @param source
108108
* @return
109109
* @since 2.2.14
110+
* @deprecated since 4.1.1
110111
*/
112+
@Deprecated(since = "4.1.1", forRemoval = true)
111113
public Object toCaseInsensitiveMatch(Object source) {
112114
return source instanceof String stringValue ? new BsonRegularExpression(Pattern.quote(stringValue), "i") : source;
113115
}

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryCreator.java

+14-2
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525

2626
import org.apache.commons.logging.Log;
2727
import org.apache.commons.logging.LogFactory;
28-
28+
import org.bson.BsonRegularExpression;
2929
import org.springframework.data.domain.Range;
3030
import org.springframework.data.domain.Range.Bound;
3131
import org.springframework.data.domain.Sort;
@@ -390,7 +390,18 @@ private java.util.List<?> nextAsList(Iterator<Object> iterator, Part part) {
390390

391391
Streamable<?> streamable = asStreamable(iterator.next());
392392
if (!isSimpleComparisionPossible(part)) {
393-
streamable = streamable.map(MongoRegexCreator.INSTANCE::toCaseInsensitiveMatch);
393+
394+
MatchMode matchMode = toMatchMode(part.getType());
395+
String regexOptions = toRegexOptions(part);
396+
397+
streamable = streamable.map(it -> {
398+
if (it instanceof String value) {
399+
400+
return new BsonRegularExpression(MongoRegexCreator.INSTANCE.toRegularExpression(value, matchMode),
401+
regexOptions);
402+
}
403+
return it;
404+
});
394405
}
395406

396407
return streamable.toList();
@@ -481,6 +492,7 @@ private static MatchMode toMatchMode(Type type) {
481492
return MatchMode.REGEX;
482493
case NEGATING_SIMPLE_PROPERTY:
483494
case SIMPLE_PROPERTY:
495+
case IN:
484496
return MatchMode.EXACT;
485497
default:
486498
return MatchMode.DEFAULT;

spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java

+8-1
Original file line numberDiff line numberDiff line change
@@ -1510,9 +1510,16 @@ void findByUnwrapped() {
15101510
assertThat(result.get(0).getId().equals(bart.getId()));
15111511
}
15121512

1513-
@Test // GH-3395
1513+
@Test // GH-3395, GH-4404
15141514
void caseInSensitiveInClause() {
1515+
15151516
assertThat(repository.findByLastnameIgnoreCaseIn("bEAuFoRd", "maTTheWs")).hasSize(3);
1517+
1518+
repository.save(new Person("the-first", "The First"));
1519+
repository.save(new Person("the-first-one", "The First One"));
1520+
repository.save(new Person("the-second", "The Second"));
1521+
1522+
assertThat(repository.findByLastnameIgnoreCaseIn("tHE fIRsT")).hasSize(1);
15161523
}
15171524

15181525
@Test // GH-3395

spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoQueryCreatorUnitTests.java

+12
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import java.util.List;
2626
import java.util.regex.Pattern;
2727

28+
import org.bson.BsonRegularExpression;
2829
import org.bson.Document;
2930
import org.bson.types.ObjectId;
3031
import org.junit.jupiter.api.BeforeEach;
@@ -273,6 +274,17 @@ void createsQueryWithFindByIgnoreCaseCorrectly() {
273274
assertThat(query).isEqualTo(query(where("firstName").regex("^dave$", "i")));
274275
}
275276

277+
@Test // GH-4404
278+
void createsQueryWithFindByInClauseHavingIgnoreCaseCorrectly() {
279+
280+
PartTree tree = new PartTree("findAllByFirstNameInIgnoreCase", Person.class);
281+
MongoQueryCreator creator = new MongoQueryCreator(tree, getAccessor(converter, List.of("da've", "carter")), context);
282+
283+
Query query = creator.createQuery();
284+
assertThat(query).isEqualTo(query(where("firstName")
285+
.in(List.of(new BsonRegularExpression("^\\Qda've\\E$", "i"), new BsonRegularExpression("^carter$", "i")))));
286+
}
287+
276288
@Test // DATAMONGO-770
277289
void createsQueryWithFindByNotIgnoreCaseCorrectly() {
278290

0 commit comments

Comments
 (0)