diff --git a/src/main/java/org/springframework/data/repository/query/SpelQueryContext.java b/src/main/java/org/springframework/data/repository/query/SpelQueryContext.java index 8767f2bc1..d3f39f63b 100644 --- a/src/main/java/org/springframework/data/repository/query/SpelQueryContext.java +++ b/src/main/java/org/springframework/data/repository/query/SpelQueryContext.java @@ -41,6 +41,7 @@ import org.springframework.util.Assert; * * @author Jens Schauder * @author Gerrit Meier + * @author Mark Paluch * @since 2.1 */ @RequiredArgsConstructor(staticName = "of") @@ -145,7 +146,7 @@ public class SpelQueryContext { /** * Parses a query string, identifies the contained SpEL expressions, replaces them with bind parameters and offers a - * {@link Map} from those bind parameters to the spel expression. + * {@link Map} from those bind parameters to the SpEL expression. *

* The parser detects quoted parts of the query string and does not detect SpEL expressions inside such quoted parts * of the query. @@ -208,7 +209,9 @@ public class SpelQueryContext { this.expressions = Collections.unmodifiableMap(expressions); this.query = resultQuery.toString(); - this.quotations = quotedAreas; + + // recreate quotation map based on rewritten query. + this.quotations = new QuotationMap(this.query); } /** @@ -220,6 +223,12 @@ public class SpelQueryContext { return query; } + /** + * Return whether the {@link #getQueryString() query} at {@code index} is quoted. + * + * @param index + * @return {@literal true} if quoted; {@literal false} otherwise. + */ public boolean isQuoted(int index) { return quotations.isQuoted(index); } diff --git a/src/test/java/org/springframework/data/repository/query/SpelQueryContextUnitTests.java b/src/test/java/org/springframework/data/repository/query/SpelQueryContextUnitTests.java index d5dae44d6..927ebf89a 100644 --- a/src/test/java/org/springframework/data/repository/query/SpelQueryContextUnitTests.java +++ b/src/test/java/org/springframework/data/repository/query/SpelQueryContextUnitTests.java @@ -23,14 +23,15 @@ import org.junit.Test; /** * Unit tests for {@link SpelQueryContext}. - * + * * @author Oliver Gierke * @author Jens Schauder + * @author Mark Paluch */ public class SpelQueryContextUnitTests { static final QueryMethodEvaluationContextProvider EVALUATION_CONTEXT_PROVIDER = QueryMethodEvaluationContextProvider.DEFAULT; - static final BiFunction PARAMETER_NAME_SOURCE = (index, spel) -> "EPP" + index; + static final BiFunction PARAMETER_NAME_SOURCE = (index, spel) -> "__$synthetic$__" + index; static final BiFunction REPLACEMENT_SOURCE = (prefix, name) -> prefix + name; @Test // DATACMNS-1258 @@ -63,4 +64,18 @@ public class SpelQueryContextUnitTests { assertThat(context.withEvaluationContextProvider(EVALUATION_CONTEXT_PROVIDER)).isNotNull(); } + + @Test // DATACMNS-1683 + public void reportsQuotationCorrectly() { + + SpelQueryContext context = SpelQueryContext.of(PARAMETER_NAME_SOURCE, REPLACEMENT_SOURCE); + + SpelQueryContext.SpelExtractor extractor = context.parse( + "select n from NetworkServer n where (LOWER(n.name) LIKE LOWER(NULLIF(text(concat('%',:#{#networkRequest.name},'%')), '')) OR :#{#networkRequest.name} IS NULL )"); + + assertThat(extractor.getQueryString()).isEqualTo( + "select n from NetworkServer n where (LOWER(n.name) LIKE LOWER(NULLIF(text(concat('%',:__$synthetic$__0,'%')), '')) OR :__$synthetic$__1 IS NULL )"); + assertThat(extractor.isQuoted(extractor.getQueryString().indexOf(":__$synthetic$__0"))).isFalse(); + assertThat(extractor.isQuoted(extractor.getQueryString().indexOf(":__$synthetic$__1"))).isFalse(); + } }