From 13f9395d0518ecf601d164515b15d04f4e172583 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 9 Apr 2025 09:03:06 +0200 Subject: [PATCH] Extend reserved word usage also to JPQL parser. Closes #3832 --- .../data/jpa/repository/query/Jpql.g4 | 4 ++++ .../jpa/repository/query/JpqlQueryRenderer.java | 15 +++++++++++++++ .../repository/query/EqlQueryRendererTests.java | 9 +++++++++ .../repository/query/HqlQueryRendererTests.java | 9 +++++++++ .../repository/query/JpqlQueryRendererTests.java | 9 +++++++++ 5 files changed, 46 insertions(+) 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 9ddbcadb4..8ba5bf48f 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 @@ -685,18 +685,22 @@ subtype collection_valued_field : identification_variable + | reserved_word ; single_valued_object_field : identification_variable + | reserved_word ; state_field : identification_variable + | reserved_word ; collection_value_field : identification_variable + | reserved_word ; entity_name 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 105ef169b..8334d67ce 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 @@ -2108,21 +2108,36 @@ class JpqlQueryRenderer extends JpqlBaseVisitor { @Override public QueryTokenStream visitCollection_valued_field(JpqlParser.Collection_valued_fieldContext ctx) { + if (ctx.reserved_word() != null) { + return visit(ctx.reserved_word()); + } return visit(ctx.identification_variable()); } @Override public QueryTokenStream visitSingle_valued_object_field(JpqlParser.Single_valued_object_fieldContext ctx) { + + if (ctx.reserved_word() != null) { + return visit(ctx.reserved_word()); + } return visit(ctx.identification_variable()); } @Override public QueryTokenStream visitState_field(JpqlParser.State_fieldContext ctx) { + + if (ctx.reserved_word() != null) { + return visit(ctx.reserved_word()); + } return visit(ctx.identification_variable()); } @Override public QueryTokenStream visitCollection_value_field(JpqlParser.Collection_value_fieldContext ctx) { + + if (ctx.reserved_word() != null) { + return visit(ctx.reserved_word()); + } return visit(ctx.identification_variable()); } 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 70ecb1fe5..695e47819 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 @@ -1040,4 +1040,13 @@ class EqlQueryRendererTests { assertQuery("select e from Employee e where e.lateral = :_lateral"); assertQuery("select te from TestEntity te where te.lateral = :lateral"); } + + @Test + 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"); + } } diff --git a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/HqlQueryRendererTests.java b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/HqlQueryRendererTests.java index 922c20bc2..cdb81af4d 100644 --- a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/HqlQueryRendererTests.java +++ b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/HqlQueryRendererTests.java @@ -1923,4 +1923,13 @@ class HqlQueryRendererTests { String source = "select new com.company.%s.thing.stuff.ClassName(e.id) from Experience e".formatted(reservedWord); assertQuery(source); } + + @Test + 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"); + } } 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 1047d4cc1..036666da7 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 @@ -1027,4 +1027,13 @@ class JpqlQueryRendererTests { assertQuery(source); } + @Test + 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"); + } + }