diff --git a/pom.xml b/pom.xml
index 17776328bc..304d3ef310 100755
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
org.springframework.data
spring-data-jpa-parent
- 3.3.0-SNAPSHOT
+ 3.3.x-3451-SNAPSHOT
pom
Spring Data JPA Parent
diff --git a/spring-data-envers/pom.xml b/spring-data-envers/pom.xml
index 470678d048..d33f60279a 100755
--- a/spring-data-envers/pom.xml
+++ b/spring-data-envers/pom.xml
@@ -5,12 +5,12 @@
org.springframework.data
spring-data-envers
- 3.3.0-SNAPSHOT
+ 3.3.x-3451-SNAPSHOT
org.springframework.data
spring-data-jpa-parent
- 3.3.0-SNAPSHOT
+ 3.3.x-3451-SNAPSHOT
../pom.xml
diff --git a/spring-data-jpa-distribution/pom.xml b/spring-data-jpa-distribution/pom.xml
index 6bd074181c..f3c95c2f7b 100644
--- a/spring-data-jpa-distribution/pom.xml
+++ b/spring-data-jpa-distribution/pom.xml
@@ -14,7 +14,7 @@
org.springframework.data
spring-data-jpa-parent
- 3.3.0-SNAPSHOT
+ 3.3.x-3451-SNAPSHOT
../pom.xml
diff --git a/spring-data-jpa/pom.xml b/spring-data-jpa/pom.xml
index 67ad4cabb2..cb787d9275 100644
--- a/spring-data-jpa/pom.xml
+++ b/spring-data-jpa/pom.xml
@@ -6,7 +6,7 @@
org.springframework.data
spring-data-jpa
- 3.3.0-SNAPSHOT
+ 3.3.x-3451-SNAPSHOT
Spring Data JPA
Spring Data module for JPA repositories.
@@ -15,7 +15,7 @@
org.springframework.data
spring-data-jpa-parent
- 3.3.0-SNAPSHOT
+ 3.3.x-3451-SNAPSHOT
../pom.xml
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 46748477a0..3ed025efb5 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
@@ -638,7 +638,7 @@ identification_variable
;
constructor_name
- : state_field_path_expression
+ : entity_name
;
literal
@@ -720,7 +720,7 @@ collection_value_field
;
entity_name
- : identification_variable ('.' identification_variable)* // Hibernate sometimes expands the entity name to FQDN when using named queries
+ : reserved_word ('.' reserved_word)* // Hibernate sometimes expands the entity name to FQDN when using named queries
;
result_variable
@@ -748,6 +748,90 @@ character_valued_input_parameter
| input_parameter
;
+reserved_word
+ : IDENTIFICATION_VARIABLE
+ | f=(ABS
+ |ALL
+ |AND
+ |ANY
+ |AS
+ |ASC
+ |AVG
+ |BETWEEN
+ |BOTH
+ |BY
+ |CASE
+ |CEILING
+ |COALESCE
+ |CONCAT
+ |COUNT
+ |CURRENT_DATE
+ |CURRENT_TIME
+ |CURRENT_TIMESTAMP
+ |DATE
+ |DATETIME
+ |DELETE
+ |DESC
+ |DISTINCT
+ |END
+ |ELSE
+ |EMPTY
+ |ENTRY
+ |ESCAPE
+ |EXISTS
+ |EXP
+ |EXTRACT
+ |FALSE
+ |FETCH
+ |FLOOR
+ |FUNCTION
+ |IN
+ |INDEX
+ |INNER
+ |IS
+ |KEY
+ |LEFT
+ |LENGTH
+ |LIKE
+ |LN
+ |LOCAL
+ |LOCATE
+ |LOWER
+ |MAX
+ |MEMBER
+ |MIN
+ |MOD
+ |NEW
+ |NOT
+ |NULL
+ |NULLIF
+ |OBJECT
+ |OF
+ |ON
+ |OR
+ |ORDER
+ |OUTER
+ |POWER
+ |ROUND
+ |SELECT
+ |SET
+ |SIGN
+ |SIZE
+ |SOME
+ |SQRT
+ |SUBSTRING
+ |SUM
+ |THEN
+ |TIME
+ |TRAILING
+ |TREAT
+ |TRIM
+ |TRUE
+ |TYPE
+ |UPDATE
+ |UPPER
+ |VALUE)
+ ;
/*
Lexer rules
*/
diff --git a/spring-data-jpa/src/main/antlr4/org/springframework/data/jpa/repository/query/Hql.g4 b/spring-data-jpa/src/main/antlr4/org/springframework/data/jpa/repository/query/Hql.g4
index 6d6f7567d6..7984d4881b 100644
--- a/spring-data-jpa/src/main/antlr4/org/springframework/data/jpa/repository/query/Hql.g4
+++ b/spring-data-jpa/src/main/antlr4/org/springframework/data/jpa/repository/query/Hql.g4
@@ -737,6 +737,7 @@ reservedWord
| EXCEPT
| EXCLUDE
| EXISTS
+ | EXP
| EXTRACT
| FETCH
| FILTER
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 b80e499ffa..a7f319b793 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
@@ -616,7 +616,7 @@ identification_variable
;
constructor_name
- : state_field_path_expression
+ : entity_name
;
literal
@@ -696,7 +696,7 @@ collection_value_field
;
entity_name
- : identification_variable ('.' identification_variable)* // Hibernate sometimes expands the entity name to FQDN when using named queries
+ : reserved_word ('.' reserved_word)* // Hibernate sometimes expands the entity name to FQDN when using named queries
;
result_variable
@@ -724,6 +724,90 @@ character_valued_input_parameter
| input_parameter
;
+reserved_word
+ : IDENTIFICATION_VARIABLE
+ | f=(ABS
+ |ALL
+ |AND
+ |ANY
+ |AS
+ |ASC
+ |AVG
+ |BETWEEN
+ |BOTH
+ |BY
+ |CASE
+ |CEILING
+ |COALESCE
+ |CONCAT
+ |COUNT
+ |CURRENT_DATE
+ |CURRENT_TIME
+ |CURRENT_TIMESTAMP
+ |DATE
+ |DATETIME
+ |DELETE
+ |DESC
+ |DISTINCT
+ |END
+ |ELSE
+ |EMPTY
+ |ENTRY
+ |ESCAPE
+ |EXISTS
+ |EXP
+ |EXTRACT
+ |FALSE
+ |FETCH
+ |FLOOR
+ |FUNCTION
+ |IN
+ |INDEX
+ |INNER
+ |IS
+ |KEY
+ |LEFT
+ |LENGTH
+ |LIKE
+ |LN
+ |LOCAL
+ |LOCATE
+ |LOWER
+ |MAX
+ |MEMBER
+ |MIN
+ |MOD
+ |NEW
+ |NOT
+ |NULL
+ |NULLIF
+ |OBJECT
+ |OF
+ |ON
+ |OR
+ |ORDER
+ |OUTER
+ |POWER
+ |ROUND
+ |SELECT
+ |SET
+ |SIGN
+ |SIZE
+ |SOME
+ |SQRT
+ |SUBSTRING
+ |SUM
+ |THEN
+ |TIME
+ |TRAILING
+ |TREAT
+ |TRIM
+ |TRUE
+ |TYPE
+ |UPDATE
+ |UPPER
+ |VALUE)
+ ;
/*
Lexer rules
*/
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 22a10faee4..f3ecafe01e 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
@@ -2331,7 +2331,7 @@ public List visitConstructor_name(EqlParser.Constructor_na
List tokens = new ArrayList<>();
- tokens.addAll(visit(ctx.state_field_path_expression()));
+ tokens.addAll(visit(ctx.entity_name()));
NOSPACE(tokens);
return tokens;
@@ -2492,8 +2492,8 @@ public List visitEntity_name(EqlParser.Entity_nameContext
List tokens = new ArrayList<>();
- ctx.identification_variable().forEach(identificationVariableContext -> {
- tokens.addAll(visit(identificationVariableContext));
+ ctx.reserved_word().forEach(identificationVariableContext -> {
+ tokens.addAll(visitReserved_word(identificationVariableContext));
NOSPACE(tokens);
tokens.add(TOKEN_DOT);
});
@@ -2543,4 +2543,15 @@ public List visitCharacter_valued_input_parameter(
return List.of();
}
}
+
+ @Override
+ public List visitReserved_word(EqlParser.Reserved_wordContext ctx) {
+ if (ctx.IDENTIFICATION_VARIABLE() != null) {
+ return List.of(new JpaQueryParsingToken(ctx.IDENTIFICATION_VARIABLE()));
+ } else if (ctx.f != null) {
+ return List.of(new JpaQueryParsingToken(ctx.f));
+ } else {
+ return List.of();
+ }
+ }
}
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 1061e102c4..492215e48f 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
@@ -20,6 +20,8 @@
import java.util.ArrayList;
import java.util.List;
+import org.springframework.data.jpa.repository.query.JpqlParser.Reserved_wordContext;
+
/**
* An ANTLR {@link org.antlr.v4.runtime.tree.ParseTreeVisitor} that renders a JPQL query without making any changes.
*
@@ -2143,7 +2145,7 @@ public List visitConstructor_name(JpqlParser.Constructor_n
List tokens = new ArrayList<>();
- tokens.addAll(visit(ctx.state_field_path_expression()));
+ tokens.addAll(visit(ctx.entity_name()));
NOSPACE(tokens);
return tokens;
@@ -2296,8 +2298,8 @@ public List visitEntity_name(JpqlParser.Entity_nameContext
List tokens = new ArrayList<>();
- ctx.identification_variable().forEach(identificationVariableContext -> {
- tokens.addAll(visit(identificationVariableContext));
+ ctx.reserved_word().forEach(ctx2 -> {
+ tokens.addAll(visitReserved_word(ctx2));
NOSPACE(tokens);
tokens.add(TOKEN_DOT);
});
@@ -2347,4 +2349,15 @@ public List visitCharacter_valued_input_parameter(
return List.of();
}
}
+
+ @Override
+ public List visitReserved_word(Reserved_wordContext ctx) {
+ if (ctx.IDENTIFICATION_VARIABLE() != null) {
+ return List.of(new JpaQueryParsingToken(ctx.IDENTIFICATION_VARIABLE()));
+ } else if (ctx.f != null) {
+ return List.of(new JpaQueryParsingToken(ctx.f));
+ } else {
+ return List.of();
+ }
+ }
}
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 9fd8a3a79b..ec11428a80 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
@@ -18,11 +18,15 @@
import static org.assertj.core.api.Assertions.*;
import static org.springframework.data.jpa.repository.query.JpaQueryParsingToken.*;
+import java.util.stream.Stream;
+
import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonTokenStream;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
import org.junit.jupiter.params.provider.ValueSource;
/**
@@ -53,6 +57,10 @@ private static String parseWithoutChanges(String query) {
return render(new EqlQueryRenderer().visit(parsedQuery));
}
+ static Stream reservedWords() {
+ return Stream.of("abs", "exp", "any", "case", "else", "index", "time").map(Arguments::of);
+ }
+
private void assertQuery(String query) {
String slimmedDownQuery = reduceWhitespace(query);
@@ -995,25 +1003,25 @@ void powerShouldBeLegalInAQuery() {
}
@ParameterizedTest // GH-3342
- @ValueSource(strings = {
- "select 1 from User u",
- "select -1 from User u",
- "select +1 from User u",
- "select +1*-100 from User u",
- "select count(u)*-0.7f from User u",
+ @ValueSource(strings = { "select 1 from User u", "select -1 from User u", "select +1 from User u",
+ "select +1*-100 from User u", "select count(u)*-0.7f from User u",
"select count(oi) + (-100) as perc from StockOrderItem oi",
- "select p from Payment p where length(p.cardNumber) between +16 and -20"
- })
+ "select p from Payment p where length(p.cardNumber) between +16 and -20" })
void signedLiteralShouldWork(String query) {
assertQuery(query);
}
@ParameterizedTest // GH-3342
- @ValueSource(strings = {
- "select -count(u) from User u",
- "select +1*(-count(u)) from User u"
- })
+ @ValueSource(strings = { "select -count(u) from User u", "select +1*(-count(u)) from User u" })
void signedExpressionsShouldWork(String query) {
assertQuery(query);
}
+
+ @ParameterizedTest // GH-3451
+ @MethodSource("reservedWords")
+ void entityNameWithPackageContainingReservedWord(String reservedWord) {
+
+ String source = "select new com.company.%s.thing.stuff.ClassName(e.id) from Experience e".formatted(reservedWord);
+ assertQuery(source);
+ }
}
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 c879c26d82..6f617314ba 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
@@ -18,11 +18,15 @@
import static org.assertj.core.api.Assertions.*;
import static org.springframework.data.jpa.repository.query.JpaQueryParsingToken.*;
+import java.util.stream.Stream;
+
import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonTokenStream;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
import org.junit.jupiter.params.provider.ValueSource;
/**
@@ -55,6 +59,10 @@ private static String parseWithoutChanges(String query) {
return render(new HqlQueryRenderer().visit(parsedQuery));
}
+ static Stream reservedWords() {
+ return Stream.of("abs", "exp", "any", "case", "else", "index", "time").map(Arguments::of);
+ }
+
private void assertQuery(String query) {
String slimmedDownQuery = reduceWhitespace(query);
@@ -1638,25 +1646,25 @@ group by extract(epoch from departureTime)
}
@ParameterizedTest // GH-3342
- @ValueSource(strings = {
- "select 1 from User",
- "select -1 from User",
- "select +1 from User",
- "select +1*-100 from User",
- "select count(u)*-0.7f from User u",
- "select count(oi) + (-100) as perc from StockOrderItem oi",
- "select p from Payment p where length(p.cardNumber) between +16 and -20"
- })
+ @ValueSource(
+ strings = { "select 1 from User", "select -1 from User", "select +1 from User", "select +1*-100 from User",
+ "select count(u)*-0.7f from User u", "select count(oi) + (-100) as perc from StockOrderItem oi",
+ "select p from Payment p where length(p.cardNumber) between +16 and -20" })
void signedLiteralShouldWork(String query) {
assertQuery(query);
}
@ParameterizedTest // GH-3342
- @ValueSource(strings = {
- "select -count(u) from User u",
- "select +1*(-count(u)) from User u"
- })
+ @ValueSource(strings = { "select -count(u) from User u", "select +1*(-count(u)) from User u" })
void signedExpressionsShouldWork(String query) {
assertQuery(query);
}
+
+ @ParameterizedTest // GH-3451
+ @MethodSource("reservedWords")
+ void entityNameWithPackageContainingReservedWord(String reservedWord) {
+
+ String source = "select new com.company.%s.thing.stuff.ClassName(e.id) from Experience e".formatted(reservedWord);
+ assertQuery(source);
+ }
}
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 b8e2a55830..71836ed390 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
@@ -18,11 +18,15 @@
import static org.assertj.core.api.Assertions.*;
import static org.springframework.data.jpa.repository.query.JpaQueryParsingToken.*;
+import java.util.stream.Stream;
+
import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonTokenStream;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
import org.junit.jupiter.params.provider.ValueSource;
/**
@@ -54,6 +58,10 @@ private static String parseWithoutChanges(String query) {
return render(new JpqlQueryRenderer().visit(parsedQuery));
}
+ static Stream reservedWords() {
+ return Stream.of("abs", "exp", "any", "case", "else", "index", "time").map(Arguments::of);
+ }
+
private void assertQuery(String query) {
String slimmedDownQuery = reduceWhitespace(query);
@@ -996,25 +1004,26 @@ void powerShouldBeLegalInAQuery() {
}
@ParameterizedTest // GH-3342
- @ValueSource(strings = {
- "select 1 as value from User u",
- "select -1 as value from User u",
- "select +1 as value from User u",
- "select +1*-100 as value from User u",
- "select count(u)*-0.7f as value from User u",
- "select count(oi) + (-100) as perc from StockOrderItem oi",
- "select p from Payment p where length(p.cardNumber) between +16 and -20"
- })
+ @ValueSource(strings = { "select 1 as value from User u", "select -1 as value from User u",
+ "select +1 as value from User u", "select +1*-100 as value from User u",
+ "select count(u)*-0.7f as value from User u", "select count(oi) + (-100) as perc from StockOrderItem oi",
+ "select p from Payment p where length(p.cardNumber) between +16 and -20" })
void signedLiteralShouldWork(String query) {
assertQuery(query);
}
@ParameterizedTest // GH-3342
- @ValueSource(strings = {
- "select -count(u) from User u",
- "select +1*(-count(u)) from User u"
- })
+ @ValueSource(strings = { "select -count(u) from User u", "select +1*(-count(u)) from User u" })
void signedExpressionsShouldWork(String query) {
assertQuery(query);
}
+
+ @ParameterizedTest // GH-3451
+ @MethodSource("reservedWords")
+ void entityNameWithPackageContainingReservedWord(String reservedWord) {
+
+ String source = "select new com.company.%s.thing.stuff.ClassName(e.id) from Experience e".formatted(reservedWord);
+ assertQuery(source);
+ }
+
}