From e101ce44404486b8ca67f3723a2fd998bb0913d0 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 ++++ .../repository/query/JpqlQueryRenderer.java | 19 +++++++++++++++++-- .../query/EqlQueryRendererTests.java | 9 +++++++++ .../query/HqlQueryRendererTests.java | 9 +++++++++ .../query/JpqlQueryRendererTests.java | 9 +++++++++ 5 files changed, 48 insertions(+), 2 deletions(-) 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 a7f319b79..c9e392a97 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 @@ -681,18 +681,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 3320c390d..fceaae797 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 @@ -2164,7 +2164,7 @@ class JpqlQueryRenderer extends JpqlBaseVisitor> { tokens.add(new JpaQueryParsingToken(ctx.INTLITERAL())); } else if (ctx.FLOATLITERAL() != null) { tokens.add(new JpaQueryParsingToken(ctx.FLOATLITERAL())); - } else if(ctx.LONGLITERAL() != null) { + } else if (ctx.LONGLITERAL() != null) { tokens.add(new JpaQueryParsingToken(ctx.LONGLITERAL())); } else if (ctx.boolean_literal() != null) { tokens.addAll(visit(ctx.boolean_literal())); @@ -2226,7 +2226,7 @@ class JpqlQueryRenderer extends JpqlBaseVisitor> { return List.of(new JpaQueryParsingToken(ctx.INTLITERAL())); } else if (ctx.FLOATLITERAL() != null) { return List.of(new JpaQueryParsingToken(ctx.FLOATLITERAL())); - } else if(ctx.LONGLITERAL() != null) { + } else if (ctx.LONGLITERAL() != null) { return List.of(new JpaQueryParsingToken(ctx.LONGLITERAL())); } else { return List.of(); @@ -2275,21 +2275,36 @@ class JpqlQueryRenderer extends JpqlBaseVisitor> { @Override public List 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 List 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 List visitState_field(JpqlParser.State_fieldContext ctx) { + + if (ctx.reserved_word() != null) { + return visit(ctx.reserved_word()); + } return visit(ctx.identification_variable()); } @Override public List 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 4267925d5..d0e6f125d 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 @@ -1031,4 +1031,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 72ce32c5b..5b97963f6 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 @@ -1674,4 +1674,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 18a46691e..5241bc280 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 @@ -1033,4 +1033,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"); + } + }