Skip to content

Commit 9c4273c

Browse files
gregturnmp911de
authored andcommitted
Recognize RIGHT, LEFT, OUTER, INNER and FULL as JPQL/HQL reserved words.
RIGHT, LEFT, OUTER, INNER, and FULL are HQL tokens. This means they also need to be recognized as potential reserved words and thus possibly identifiers. This can show up if someone, for example, uses "right" as the name of a relationship in a JPA entity. Resolves #2864. Original pull request: #2874.
1 parent 0ac0ee4 commit 9c4273c

File tree

4 files changed

+84
-5
lines changed

4 files changed

+84
-5
lines changed

spring-data-jpa/src/main/antlr4/org/springframework/data/jpa/repository/query/Hql.g4

+5-5
Original file line numberDiff line numberDiff line change
@@ -692,7 +692,7 @@ reservedWord
692692
| FOR
693693
| FORMAT
694694
| FROM
695-
// | FULL
695+
| FULL
696696
| FUNCTION
697697
| GROUP
698698
| GROUPS
@@ -704,7 +704,7 @@ reservedWord
704704
| IN
705705
| INDEX
706706
| INDICES
707-
// | INNER
707+
| INNER
708708
| INSERT
709709
| INSTANT
710710
| INTERSECT
@@ -714,7 +714,7 @@ reservedWord
714714
| KEY
715715
| LAST
716716
| LEADING
717-
// | LEFT
717+
| LEFT
718718
| LIKE
719719
| LIMIT
720720
| LIST
@@ -752,7 +752,7 @@ reservedWord
752752
| OR
753753
| ORDER
754754
| OTHERS
755-
// | OUTER
755+
| OUTER
756756
| OVER
757757
| OVERFLOW
758758
| OVERLAY
@@ -765,7 +765,7 @@ reservedWord
765765
| QUARTER
766766
| RANGE
767767
| RESPECT
768-
// | RIGHT
768+
| RIGHT
769769
| ROLLUP
770770
| ROW
771771
| ROWS

spring-data-jpa/src/main/antlr4/org/springframework/data/jpa/repository/query/Jpql.g4

+3
Original file line numberDiff line numberDiff line change
@@ -599,6 +599,9 @@ identification_variable
599599
| ORDER // Gap in the spec requires supporting 'Order' as an entity name
600600
| COUNT // Gap in the spec requires supporting 'count' as a possible name
601601
| KEY // Gap in the sepc requires supported 'key' as a possible name
602+
| LEFT
603+
| INNER
604+
| OUTER
602605
;
603606

604607
constructor_name

spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/HqlQueryTransformerTests.java

+38
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,13 @@
1818
import static org.assertj.core.api.Assertions.*;
1919

2020
import java.util.regex.Pattern;
21+
import java.util.stream.Stream;
2122

2223
import org.assertj.core.api.SoftAssertions;
2324
import org.junit.jupiter.api.Test;
25+
import org.junit.jupiter.params.ParameterizedTest;
26+
import org.junit.jupiter.params.provider.Arguments;
27+
import org.junit.jupiter.params.provider.MethodSource;
2428
import org.springframework.dao.InvalidDataAccessApiUsageException;
2529
import org.springframework.data.domain.Sort;
2630
import org.springframework.data.jpa.domain.JpaSort;
@@ -808,6 +812,30 @@ void countQueryShouldWorkEvenWithoutExplicitAlias() {
808812
"select count(b) FROM BookError b WHERE portal = :portal");
809813
}
810814

815+
@ParameterizedTest
816+
@MethodSource("queriesWithReservedWordsAsIdentifiers") // GH-2864
817+
void usingReservedWordAsRelationshipNameShouldWork(String relationshipName, String joinAlias) {
818+
819+
HqlQueryParser.parseQuery(String.format("""
820+
select u
821+
from UserAccountEntity u
822+
join fetch u.lossInspectorLimitConfiguration lil
823+
join fetch u.companyTeam ct
824+
where exists (
825+
select iu
826+
from UserAccountEntity iu
827+
join iu.roles u2r
828+
join u2r.role r
829+
join r.rights r2r
830+
join r2r.%s %s
831+
where
832+
%s.code = :rightCode
833+
and iu = u
834+
)
835+
and ct.id = :teamId
836+
""", relationshipName, joinAlias, joinAlias));
837+
}
838+
811839
@Test // GH-2508
812840
void detectAliasWithCastCorrectly() {
813841

@@ -819,6 +847,16 @@ void detectAliasWithCastCorrectly() {
819847
.isEqualTo("u");
820848
}
821849

850+
static Stream<Arguments> queriesWithReservedWordsAsIdentifiers() {
851+
852+
return Stream.of( //
853+
Arguments.of("right", "rt"), //
854+
Arguments.of("left", "lt"), //
855+
Arguments.of("outer", "ou"), //
856+
Arguments.of("full", "full"), //
857+
Arguments.of("inner", "inr"));
858+
}
859+
822860
private void assertCountQuery(String originalQuery, String countQuery) {
823861
assertThat(createCountQueryFor(originalQuery)).isEqualTo(countQuery);
824862
}

spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/JpqlQueryTransformerTests.java

+38
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,13 @@
1818
import static org.assertj.core.api.Assertions.*;
1919

2020
import java.util.regex.Pattern;
21+
import java.util.stream.Stream;
2122

2223
import org.assertj.core.api.SoftAssertions;
2324
import org.junit.jupiter.api.Test;
25+
import org.junit.jupiter.params.ParameterizedTest;
26+
import org.junit.jupiter.params.provider.Arguments;
27+
import org.junit.jupiter.params.provider.MethodSource;
2428
import org.springframework.dao.InvalidDataAccessApiUsageException;
2529
import org.springframework.data.domain.Sort;
2630
import org.springframework.data.jpa.domain.JpaSort;
@@ -679,6 +683,40 @@ void queryParserPicksCorrectAliasAmidstMultipleAlises() {
679683
assertThat(alias("select u from User as u left join u.roles as r")).isEqualTo("u");
680684
}
681685

686+
@ParameterizedTest
687+
@MethodSource("queriesWithReservedWordsAsIdentifiers") // GH-2864
688+
void usingReservedWordAsRelationshipNameShouldWork(String relationshipName, String joinAlias) {
689+
690+
JpqlQueryParser.parseQuery(String.format("""
691+
select u
692+
from UserAccountEntity u
693+
join u.lossInspectorLimitConfiguration lil
694+
join u.companyTeam ct
695+
where exists (
696+
select iu
697+
from UserAccountEntity iu
698+
join iu.roles u2r
699+
join u2r.role r
700+
join r.rights r2r
701+
join r2r.inner inr
702+
where
703+
inr.code = :rightCode
704+
and iu = u
705+
)
706+
and ct.id = :teamId
707+
""", relationshipName, joinAlias, joinAlias));
708+
}
709+
710+
static Stream<Arguments> queriesWithReservedWordsAsIdentifiers() {
711+
712+
return Stream.of( //
713+
Arguments.of("right", "rt"), //
714+
Arguments.of("left", "lt"), //
715+
Arguments.of("outer", "ou"), //
716+
Arguments.of("full", "full"), //
717+
Arguments.of("inner", "inr"));
718+
}
719+
682720
private void assertCountQuery(String originalQuery, String countQuery) {
683721
assertThat(createCountQueryFor(originalQuery)).isEqualTo(countQuery);
684722
}

0 commit comments

Comments
 (0)