diff --git a/pom.xml b/pom.xml index 10c1adf1bf..00d4916b2e 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.data spring-data-mongodb-parent - 3.2.0-SNAPSHOT + 3.2.0-GH-3395-SNAPSHOT pom Spring Data MongoDB diff --git a/spring-data-mongodb-benchmarks/pom.xml b/spring-data-mongodb-benchmarks/pom.xml index f0fbb601c8..bea13f6b0a 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 - 3.2.0-SNAPSHOT + 3.2.0-GH-3395-SNAPSHOT ../pom.xml diff --git a/spring-data-mongodb-distribution/pom.xml b/spring-data-mongodb-distribution/pom.xml index 1a17321782..e38a2a1df4 100644 --- a/spring-data-mongodb-distribution/pom.xml +++ b/spring-data-mongodb-distribution/pom.xml @@ -14,7 +14,7 @@ org.springframework.data spring-data-mongodb-parent - 3.2.0-SNAPSHOT + 3.2.0-GH-3395-SNAPSHOT ../pom.xml diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml index 0248517caf..c146f65cf5 100644 --- a/spring-data-mongodb/pom.xml +++ b/spring-data-mongodb/pom.xml @@ -11,7 +11,7 @@ org.springframework.data spring-data-mongodb-parent - 3.2.0-SNAPSHOT + 3.2.0-GH-3395-SNAPSHOT ../pom.xml 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 5913bcb28b..a0dad3aeb4 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 @@ -17,6 +17,7 @@ import java.util.regex.Pattern; +import org.bson.BsonRegularExpression; import org.springframework.lang.Nullable; /** @@ -102,6 +103,10 @@ public String toRegularExpression(@Nullable String source, @Nullable MatchMode m } } + public Object toCaseInsensitiveMatch(Object source) { + return source instanceof String ? new BsonRegularExpression(Pattern.quote((String)source), "i") : source; + } + private String prepareAndEscapeStringBeforeApplyingLikeRegex(String source, MatchMode matcherType) { if (MatchMode.REGEX == matcherType) { 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 24e5033a67..ab8744792f 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,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import org.springframework.data.domain.Range; import org.springframework.data.domain.Range.Bound; import org.springframework.data.domain.Sort; @@ -51,8 +50,10 @@ import org.springframework.data.repository.query.parser.Part.IgnoreCaseType; 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.util.Assert; import org.springframework.util.ClassUtils; +import org.springframework.util.ObjectUtils; /** * Custom query creator to create Mongo criterias. @@ -196,9 +197,9 @@ private Criteria from(Part part, MongoPersistentProperty property, Criteria crit case IS_NULL: return criteria.is(null); case NOT_IN: - return criteria.nin(nextAsArray(parameters)); + return criteria.nin(nextAsList(parameters, part)); case IN: - return criteria.in(nextAsArray(parameters)); + return criteria.in(nextAsList(parameters, part)); case LIKE: case STARTING_WITH: case ENDING_WITH: @@ -337,7 +338,7 @@ private Criteria createContainingCriteria(Part part, MongoPersistentProperty pro Iterator parameters) { if (property.isCollectionLike()) { - return criteria.in(nextAsArray(parameters)); + return criteria.in(nextAsList(parameters, part)); } return addAppropriateLikeRegexTo(criteria, part, parameters.next()); @@ -400,17 +401,24 @@ private T nextAs(Iterator iterator, Class type) { String.format("Expected parameter type of %s but got %s!", type, parameter.getClass())); } - private Object[] nextAsArray(Iterator iterator) { + private java.util.List nextAsList(Iterator iterator, Part part) { + + Streamable streamable = asStreamable(iterator.next()); + if(!isSimpleComparisionPossible(part)) { + streamable = streamable.map(MongoRegexCreator.INSTANCE::toCaseInsensitiveMatch); + } + + return streamable.toList(); + } - Object next = iterator.next(); + private Streamable asStreamable(Object value) { - if (next instanceof Collection) { - return ((Collection) next).toArray(); - } else if (next != null && next.getClass().isArray()) { - return (Object[]) next; + if (value instanceof Collection) { + return Streamable.of((Collection) value); + } else if (ObjectUtils.isArray(value)) { + return Streamable.of((Object[]) value); } - - return new Object[] { next }; + return Streamable.of(value); } private String toLikeRegex(String source, Part part) { 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 7055a73e25..841d4706a7 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 @@ -1363,4 +1363,19 @@ void spelExpressionArgumentsGetReevaluatedOnEveryInvocation() { assertThat(repository.findWithSpelByFirstnameForSpELExpressionWithParameterIndexOnly("Dave")).containsExactly(dave); assertThat(repository.findWithSpelByFirstnameForSpELExpressionWithParameterIndexOnly("Carter")).containsExactly(carter); } + + @Test // GH-3395 + void caseInSensitiveInClause() { + assertThat(repository.findByLastnameIgnoreCaseIn("bEAuFoRd", "maTTheWs")).hasSize(3); + } + + @Test // GH-3395 + void caseInSensitiveInClauseQuotesExpressions() { + assertThat(repository.findByLastnameIgnoreCaseIn(".*")).isEmpty(); + } + + @Test // GH-3395 + void caseSensitiveInClauseIgnoresExpressions() { + assertThat(repository.findByFirstnameIn(".*")).isEmpty(); + } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepository.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepository.java index 1d340bd196..e58d258f41 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepository.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepository.java @@ -125,6 +125,8 @@ public interface PersonRepository extends MongoRepository, Query @Query("{ 'lastname' : { '$regex' : '?0', '$options' : 'i'}}") Page findByLastnameLikeWithPageable(String lastname, Pageable pageable); + List findByLastnameIgnoreCaseIn(String... lastname); + /** * Returns all {@link Person}s with a firstname contained in the given varargs. *