From fd13c12817de235c7a48e7ecd02597d41ba060de Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Mon, 10 Jun 2024 11:27:22 +0200 Subject: [PATCH] Fix conversion of regular expression in queries. This commit fixes an issue where patterns targeting id properties might have been falsely converted into the properties type, turning a Pattern into it's string representation. Closes #4674 Original pull request: #4718 --- .../mongodb/core/convert/QueryMapper.java | 27 +++++++++++++++++-- .../core/convert/QueryMapperUnitTests.java | 15 +++++++++++ 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java index 876c18eeb..4896a4548 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java @@ -788,6 +788,11 @@ public class QueryMapper { */ @Nullable public Object convertId(@Nullable Object id, Class targetType) { + + if (!SpecialTypeTreatment.INSTANCE.isConversionCandidate(id)) { + return id; + } + return converter.convertId(id, targetType); } @@ -849,8 +854,8 @@ public class QueryMapper { private Object applyFieldTargetTypeHintToValue(Field documentField, @Nullable Object value) { if (value == null || documentField.getProperty() == null || !documentField.getProperty().hasExplicitWriteTarget() - || value instanceof Document || value instanceof DBObject || value instanceof Pattern - || value instanceof BsonRegularExpression) { + || value instanceof Document || value instanceof DBObject + || !SpecialTypeTreatment.INSTANCE.isConversionCandidate(value)) { return value; } @@ -1569,4 +1574,22 @@ public class QueryMapper { public MongoConverter getConverter() { return converter; } + + /* + * Types that must not be converted + */ + enum SpecialTypeTreatment { + + INSTANCE; + + private final Set> types = Set.of(Pattern.class, BsonRegularExpression.class); + + boolean isConversionCandidate(@Nullable Object value) { + if (value == null) { + return false; + } + + return !types.contains(value.getClass()); + } + } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java index 018dff7c5..738fa6b43 100755 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java @@ -1026,6 +1026,21 @@ public class QueryMapperUnitTests { assertThat(document.get("text")).isInstanceOf(BsonRegularExpression.class); } + @Test // GH-4674 + void shouldRetainRegexPatternForIdProperty() { + + org.bson.Document javaRegex = mapper.getMappedObject(query(where("id").regex("^1234$")).getQueryObject(), + context.getPersistentEntity(WithStringId.class)); + + assertThat(javaRegex.get("_id")).isInstanceOf(Pattern.class); + + org.bson.Document bsonRegex = mapper.getMappedObject( + query(where("id").regex(new BsonRegularExpression("^1234$"))).getQueryObject(), + context.getPersistentEntity(WithStringId.class)); + + assertThat(bsonRegex.get("_id")).isInstanceOf(BsonRegularExpression.class); + } + @Test // DATAMONGO-2339 void findByIdUsesMappedIdFieldNameWithUnderscoreCorrectly() {