From caf3841a8b2233627b03ffbee49dc2b687565aff Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Tue, 13 Jun 2023 07:54:34 +0200 Subject: [PATCH 1/3] Prepare issue branch. --- pom.xml | 2 +- spring-data-mongodb-benchmarks/pom.xml | 2 +- spring-data-mongodb-distribution/pom.xml | 2 +- spring-data-mongodb/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 5225d1e3df..22c2443721 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.data spring-data-mongodb-parent - 4.2.0-SNAPSHOT + 4.2.x-4404-SNAPSHOT pom Spring Data MongoDB diff --git a/spring-data-mongodb-benchmarks/pom.xml b/spring-data-mongodb-benchmarks/pom.xml index 2de4b6b635..eb3999a450 100644 --- a/spring-data-mongodb-benchmarks/pom.xml +++ b/spring-data-mongodb-benchmarks/pom.xml @@ -7,7 +7,7 @@ org.springframework.data spring-data-mongodb-parent - 4.2.0-SNAPSHOT + 4.2.x-4404-SNAPSHOT ../pom.xml diff --git a/spring-data-mongodb-distribution/pom.xml b/spring-data-mongodb-distribution/pom.xml index 060a6d0dd9..2a65586b54 100644 --- a/spring-data-mongodb-distribution/pom.xml +++ b/spring-data-mongodb-distribution/pom.xml @@ -15,7 +15,7 @@ org.springframework.data spring-data-mongodb-parent - 4.2.0-SNAPSHOT + 4.2.x-4404-SNAPSHOT ../pom.xml diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml index 921254ca44..d6897ee994 100644 --- a/spring-data-mongodb/pom.xml +++ b/spring-data-mongodb/pom.xml @@ -13,7 +13,7 @@ org.springframework.data spring-data-mongodb-parent - 4.2.0-SNAPSHOT + 4.2.x-4404-SNAPSHOT ../pom.xml From 54d7e122c8cb9aa1584b71e653e6e2a4be02e4b9 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Tue, 13 Jun 2023 08:26:43 +0200 Subject: [PATCH 2/3] 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. --- .../mongodb/core/query/MongoRegexCreator.java | 2 ++ .../repository/query/MongoQueryCreator.java | 16 ++++++++++++++-- ...AbstractPersonRepositoryIntegrationTests.java | 9 ++++++++- .../query/MongoQueryCreatorUnitTests.java | 12 ++++++++++++ 4 files changed, 36 insertions(+), 3 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/MongoRegexCreator.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/MongoRegexCreator.java index 23511d760a..b052207255 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/MongoRegexCreator.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/MongoRegexCreator.java @@ -107,7 +107,9 @@ public String toRegularExpression(@Nullable String source, @Nullable MatchMode m * @param source * @return * @since 2.2.14 + * @deprecated since 4.2 */ + @Deprecated(since = "4.2", forRemoval = true) public Object toCaseInsensitiveMatch(Object source) { return source instanceof String stringValue ? new BsonRegularExpression(Pattern.quote(stringValue), "i") : source; } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryCreator.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryCreator.java index f9cc596e68..b4f903b229 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryCreator.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryCreator.java @@ -25,7 +25,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; - +import org.bson.BsonRegularExpression; import org.springframework.data.domain.Range; import org.springframework.data.domain.Range.Bound; import org.springframework.data.domain.Sort; @@ -390,7 +390,18 @@ private java.util.List nextAsList(Iterator iterator, Part part) { Streamable streamable = asStreamable(iterator.next()); if (!isSimpleComparisionPossible(part)) { - streamable = streamable.map(MongoRegexCreator.INSTANCE::toCaseInsensitiveMatch); + + MatchMode matchMode = toMatchMode(part.getType()); + String regexOptions = toRegexOptions(part); + + streamable = streamable.map(it -> { + if (it instanceof String value) { + + return new BsonRegularExpression(MongoRegexCreator.INSTANCE.toRegularExpression(value, matchMode), + regexOptions); + } + return it; + }); } return streamable.toList(); @@ -481,6 +492,7 @@ private static MatchMode toMatchMode(Type type) { return MatchMode.REGEX; case NEGATING_SIMPLE_PROPERTY: case SIMPLE_PROPERTY: + case IN: return MatchMode.EXACT; default: return MatchMode.DEFAULT; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java index 646a268e0e..ac278c8bae 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java @@ -1510,9 +1510,16 @@ void findByUnwrapped() { assertThat(result.get(0).getId().equals(bart.getId())); } - @Test // GH-3395 + @Test // GH-3395, GH-4404 void caseInSensitiveInClause() { + assertThat(repository.findByLastnameIgnoreCaseIn("bEAuFoRd", "maTTheWs")).hasSize(3); + + repository.save(new Person("the-first", "The First")); + repository.save(new Person("the-first-one", "The First One")); + repository.save(new Person("the-second", "The Second")); + + assertThat(repository.findByLastnameIgnoreCaseIn("tHE fIRsT")).hasSize(1); } @Test // GH-3395 diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoQueryCreatorUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoQueryCreatorUnitTests.java index f81ff21fe5..158f69db73 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoQueryCreatorUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoQueryCreatorUnitTests.java @@ -25,6 +25,7 @@ import java.util.List; import java.util.regex.Pattern; +import org.bson.BsonRegularExpression; import org.bson.Document; import org.bson.types.ObjectId; import org.junit.jupiter.api.BeforeEach; @@ -273,6 +274,17 @@ void createsQueryWithFindByIgnoreCaseCorrectly() { assertThat(query).isEqualTo(query(where("firstName").regex("^dave$", "i"))); } + @Test // GH-4404 + void createsQueryWithFindByInClauseHavingIgnoreCaseCorrectly() { + + PartTree tree = new PartTree("findAllByFirstNameInIgnoreCase", Person.class); + MongoQueryCreator creator = new MongoQueryCreator(tree, getAccessor(converter, List.of("da've", "carter")), context); + + Query query = creator.createQuery(); + assertThat(query).isEqualTo(query(where("firstName") + .in(List.of(new BsonRegularExpression("^\\Qda've\\E$", "i"), new BsonRegularExpression("^carter$", "i"))))); + } + @Test // DATAMONGO-770 void createsQueryWithFindByNotIgnoreCaseCorrectly() { From 7977a257e572cae847c036281af78b430804e973 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Tue, 13 Jun 2023 09:39:55 +0200 Subject: [PATCH 3/3] Polishing. Mark method potentially returning null as such and remove unused imports. --- .../data/mongodb/repository/query/MongoQueryCreator.java | 2 ++ .../mongodb/repository/query/MongoQueryCreatorUnitTests.java | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryCreator.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryCreator.java index b4f903b229..1784700b5f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryCreator.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryCreator.java @@ -52,6 +52,7 @@ import org.springframework.data.repository.query.parser.Part.Type; import org.springframework.data.repository.query.parser.PartTree; import org.springframework.data.util.Streamable; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; import org.springframework.util.ObjectUtils; @@ -352,6 +353,7 @@ private Criteria addAppropriateLikeRegexTo(Criteria criteria, Part part, Object * @param part * @return the regex options or {@literal null}. */ + @Nullable private String toRegexOptions(Part part) { String regexOptions = null; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoQueryCreatorUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoQueryCreatorUnitTests.java index 158f69db73..e24cfc7a8d 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoQueryCreatorUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoQueryCreatorUnitTests.java @@ -15,7 +15,6 @@ */ package org.springframework.data.mongodb.repository.query; -import static org.mockito.Mockito.*; import static org.springframework.data.mongodb.core.query.Criteria.*; import static org.springframework.data.mongodb.core.query.Query.*; import static org.springframework.data.mongodb.repository.query.StubParameterAccessor.*;