From 101259839d8bc329a4ed1ae94f44bac1e9753cff Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 9 Apr 2025 15:30:19 +0200 Subject: [PATCH] Accept functions and paths with reserved words (string expressions) in EQL IN expressions. Closes #3834 --- .../org/springframework/data/jpa/repository/query/Eql.g4 | 2 +- .../org/springframework/data/jpa/repository/query/Jpql.g4 | 2 +- .../data/jpa/repository/query/EqlQueryRenderer.java | 4 ++-- .../data/jpa/repository/query/JpqlQueryRenderer.java | 4 ++-- .../data/jpa/repository/query/EqlQueryRendererTests.java | 5 ++++- .../data/jpa/repository/query/JpqlQueryRendererTests.java | 3 ++- 6 files changed, 12 insertions(+), 8 deletions(-) diff --git a/spring-data-jpa/src/main/antlr4/org/springframework/data/jpa/repository/query/Eql.g4 b/spring-data-jpa/src/main/antlr4/org/springframework/data/jpa/repository/query/Eql.g4 index 4dc5817c1..45be6c6ff 100644 --- a/spring-data-jpa/src/main/antlr4/org/springframework/data/jpa/repository/query/Eql.g4 +++ b/spring-data-jpa/src/main/antlr4/org/springframework/data/jpa/repository/query/Eql.g4 @@ -349,7 +349,7 @@ between_expression ; in_expression - : (state_valued_path_expression | type_discriminator) (NOT)? IN (('(' in_item (',' in_item)* ')') | ( '(' subquery ')') | collection_valued_input_parameter) + : (string_expression | type_discriminator) (NOT)? IN (('(' in_item (',' in_item)* ')') | ( '(' subquery ')') | collection_valued_input_parameter) ; in_item diff --git a/spring-data-jpa/src/main/antlr4/org/springframework/data/jpa/repository/query/Jpql.g4 b/spring-data-jpa/src/main/antlr4/org/springframework/data/jpa/repository/query/Jpql.g4 index 8ba5bf48f..3b82b67da 100644 --- a/spring-data-jpa/src/main/antlr4/org/springframework/data/jpa/repository/query/Jpql.g4 +++ b/spring-data-jpa/src/main/antlr4/org/springframework/data/jpa/repository/query/Jpql.g4 @@ -337,7 +337,7 @@ between_expression ; in_expression - : (state_valued_path_expression | type_discriminator) (NOT)? IN (('(' in_item (',' in_item)* ')') | ( '(' subquery ')') | collection_valued_input_parameter) + : (string_expression | type_discriminator) (NOT)? IN (('(' in_item (',' in_item)* ')') | ( '(' subquery ')') | collection_valued_input_parameter) ; in_item diff --git a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/EqlQueryRenderer.java b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/EqlQueryRenderer.java index e8e8d051a..eb18221ac 100644 --- a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/EqlQueryRenderer.java +++ b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/EqlQueryRenderer.java @@ -1155,8 +1155,8 @@ class EqlQueryRenderer extends EqlBaseVisitor { QueryRendererBuilder builder = QueryRenderer.builder(); - if (ctx.state_valued_path_expression() != null) { - builder.append(visit(ctx.state_valued_path_expression())); + if (ctx.string_expression() != null) { + builder.append(visit(ctx.string_expression())); } if (ctx.type_discriminator() != null) { builder.append(visit(ctx.type_discriminator())); diff --git a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/JpqlQueryRenderer.java b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/JpqlQueryRenderer.java index 8334d67ce..c624f2642 100644 --- a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/JpqlQueryRenderer.java +++ b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/JpqlQueryRenderer.java @@ -1078,8 +1078,8 @@ class JpqlQueryRenderer extends JpqlBaseVisitor { QueryRendererBuilder builder = QueryRenderer.builder(); - if (ctx.state_valued_path_expression() != null) { - builder.appendExpression(visit(ctx.state_valued_path_expression())); + if (ctx.string_expression() != null) { + builder.appendExpression(visit(ctx.string_expression())); } if (ctx.type_discriminator() != null) { builder.appendExpression(visit(ctx.type_discriminator())); diff --git a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/EqlQueryRendererTests.java b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/EqlQueryRendererTests.java index 695e47819..6c036c3e7 100644 --- a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/EqlQueryRendererTests.java +++ b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/EqlQueryRendererTests.java @@ -36,6 +36,7 @@ import org.springframework.data.jpa.repository.query.QueryRenderer.TokenRenderer * * @author Greg Turnquist * @author Christoph Strobl + * @author Mark Paluch */ class EqlQueryRendererTests { @@ -1041,12 +1042,14 @@ class EqlQueryRendererTests { assertQuery("select te from TestEntity te where te.lateral = :lateral"); } - @Test + @Test // GH-3834 void reservedWordsShouldWork() { assertQuery("select ie from ItemExample ie left join ie.object io where io.externalId = :externalId"); assertQuery("select ie.object from ItemExample ie left join ie.object io where io.externalId = :externalId"); assertQuery("select ie from ItemExample ie left join ie.object io where io.object = :externalId"); assertQuery("select ie from ItemExample ie where ie.status = com.app.domain.object.Status.UP"); + assertQuery("select f from FooEntity f where upper(f.name) IN :names"); + assertQuery("select f from FooEntity f where f.size IN :sizes"); } } diff --git a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/JpqlQueryRendererTests.java b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/JpqlQueryRendererTests.java index 036666da7..8613362c4 100644 --- a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/JpqlQueryRendererTests.java +++ b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/JpqlQueryRendererTests.java @@ -36,6 +36,7 @@ import org.springframework.data.jpa.repository.query.QueryRenderer.TokenRenderer * * @author Greg Turnquist * @author Christoph Strobl + * @author Mark Paluch * @since 3.1 */ class JpqlQueryRendererTests { @@ -1027,7 +1028,7 @@ class JpqlQueryRendererTests { assertQuery(source); } - @Test + @Test // GH-3834 void reservedWordsShouldWork() { assertQuery("select ie from ItemExample ie left join ie.object io where io.externalId = :externalId");