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.
This commit is contained in:
committed by
Mark Paluch
parent
0ac0ee4b7d
commit
9c4273cf34
@@ -692,7 +692,7 @@ reservedWord
|
||||
| FOR
|
||||
| FORMAT
|
||||
| FROM
|
||||
// | FULL
|
||||
| FULL
|
||||
| FUNCTION
|
||||
| GROUP
|
||||
| GROUPS
|
||||
@@ -704,7 +704,7 @@ reservedWord
|
||||
| IN
|
||||
| INDEX
|
||||
| INDICES
|
||||
// | INNER
|
||||
| INNER
|
||||
| INSERT
|
||||
| INSTANT
|
||||
| INTERSECT
|
||||
@@ -714,7 +714,7 @@ reservedWord
|
||||
| KEY
|
||||
| LAST
|
||||
| LEADING
|
||||
// | LEFT
|
||||
| LEFT
|
||||
| LIKE
|
||||
| LIMIT
|
||||
| LIST
|
||||
@@ -752,7 +752,7 @@ reservedWord
|
||||
| OR
|
||||
| ORDER
|
||||
| OTHERS
|
||||
// | OUTER
|
||||
| OUTER
|
||||
| OVER
|
||||
| OVERFLOW
|
||||
| OVERLAY
|
||||
@@ -765,7 +765,7 @@ reservedWord
|
||||
| QUARTER
|
||||
| RANGE
|
||||
| RESPECT
|
||||
// | RIGHT
|
||||
| RIGHT
|
||||
| ROLLUP
|
||||
| ROW
|
||||
| ROWS
|
||||
|
||||
@@ -599,6 +599,9 @@ identification_variable
|
||||
| ORDER // Gap in the spec requires supporting 'Order' as an entity name
|
||||
| COUNT // Gap in the spec requires supporting 'count' as a possible name
|
||||
| KEY // Gap in the sepc requires supported 'key' as a possible name
|
||||
| LEFT
|
||||
| INNER
|
||||
| OUTER
|
||||
;
|
||||
|
||||
constructor_name
|
||||
|
||||
@@ -18,9 +18,13 @@ package org.springframework.data.jpa.repository.query;
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.assertj.core.api.SoftAssertions;
|
||||
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.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.jpa.domain.JpaSort;
|
||||
@@ -808,6 +812,30 @@ class HqlQueryTransformerTests {
|
||||
"select count(b) FROM BookError b WHERE portal = :portal");
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("queriesWithReservedWordsAsIdentifiers") // GH-2864
|
||||
void usingReservedWordAsRelationshipNameShouldWork(String relationshipName, String joinAlias) {
|
||||
|
||||
HqlQueryParser.parseQuery(String.format("""
|
||||
select u
|
||||
from UserAccountEntity u
|
||||
join fetch u.lossInspectorLimitConfiguration lil
|
||||
join fetch u.companyTeam ct
|
||||
where exists (
|
||||
select iu
|
||||
from UserAccountEntity iu
|
||||
join iu.roles u2r
|
||||
join u2r.role r
|
||||
join r.rights r2r
|
||||
join r2r.%s %s
|
||||
where
|
||||
%s.code = :rightCode
|
||||
and iu = u
|
||||
)
|
||||
and ct.id = :teamId
|
||||
""", relationshipName, joinAlias, joinAlias));
|
||||
}
|
||||
|
||||
@Test // GH-2508
|
||||
void detectAliasWithCastCorrectly() {
|
||||
|
||||
@@ -819,6 +847,16 @@ class HqlQueryTransformerTests {
|
||||
.isEqualTo("u");
|
||||
}
|
||||
|
||||
static Stream<Arguments> queriesWithReservedWordsAsIdentifiers() {
|
||||
|
||||
return Stream.of( //
|
||||
Arguments.of("right", "rt"), //
|
||||
Arguments.of("left", "lt"), //
|
||||
Arguments.of("outer", "ou"), //
|
||||
Arguments.of("full", "full"), //
|
||||
Arguments.of("inner", "inr"));
|
||||
}
|
||||
|
||||
private void assertCountQuery(String originalQuery, String countQuery) {
|
||||
assertThat(createCountQueryFor(originalQuery)).isEqualTo(countQuery);
|
||||
}
|
||||
|
||||
@@ -18,9 +18,13 @@ package org.springframework.data.jpa.repository.query;
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.assertj.core.api.SoftAssertions;
|
||||
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.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.jpa.domain.JpaSort;
|
||||
@@ -679,6 +683,40 @@ class JpqlQueryTransformerTests {
|
||||
assertThat(alias("select u from User as u left join u.roles as r")).isEqualTo("u");
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("queriesWithReservedWordsAsIdentifiers") // GH-2864
|
||||
void usingReservedWordAsRelationshipNameShouldWork(String relationshipName, String joinAlias) {
|
||||
|
||||
JpqlQueryParser.parseQuery(String.format("""
|
||||
select u
|
||||
from UserAccountEntity u
|
||||
join u.lossInspectorLimitConfiguration lil
|
||||
join u.companyTeam ct
|
||||
where exists (
|
||||
select iu
|
||||
from UserAccountEntity iu
|
||||
join iu.roles u2r
|
||||
join u2r.role r
|
||||
join r.rights r2r
|
||||
join r2r.inner inr
|
||||
where
|
||||
inr.code = :rightCode
|
||||
and iu = u
|
||||
)
|
||||
and ct.id = :teamId
|
||||
""", relationshipName, joinAlias, joinAlias));
|
||||
}
|
||||
|
||||
static Stream<Arguments> queriesWithReservedWordsAsIdentifiers() {
|
||||
|
||||
return Stream.of( //
|
||||
Arguments.of("right", "rt"), //
|
||||
Arguments.of("left", "lt"), //
|
||||
Arguments.of("outer", "ou"), //
|
||||
Arguments.of("full", "full"), //
|
||||
Arguments.of("inner", "inr"));
|
||||
}
|
||||
|
||||
private void assertCountQuery(String originalQuery, String countQuery) {
|
||||
assertThat(createCountQueryFor(originalQuery)).isEqualTo(countQuery);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user