Skip to content

Commit

Permalink
Fix parsing entity names in JPQL query with package names that contai…
Browse files Browse the repository at this point in the history
…n reserved words.

Resolves: #3451
Original pull request: #3457
  • Loading branch information
mp911de committed Apr 30, 2024
1 parent 6a2510d commit 8c1174f
Show file tree
Hide file tree
Showing 5 changed files with 134 additions and 48 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -638,7 +638,7 @@ identification_variable
;

constructor_name
: state_field_path_expression
: entity_name
;

literal
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2331,7 +2331,7 @@ public List<JpaQueryParsingToken> visitConstructor_name(EqlParser.Constructor_na

List<JpaQueryParsingToken> tokens = new ArrayList<>();

tokens.addAll(visit(ctx.state_field_path_expression()));
tokens.addAll(visit(ctx.entity_name()));
NOSPACE(tokens);

return tokens;
Expand Down Expand Up @@ -2492,8 +2492,8 @@ public List<JpaQueryParsingToken> visitEntity_name(EqlParser.Entity_nameContext

List<JpaQueryParsingToken> 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);
});
Expand Down Expand Up @@ -2543,4 +2543,15 @@ public List<JpaQueryParsingToken> visitCharacter_valued_input_parameter(
return List.of();
}
}

@Override
public List<JpaQueryParsingToken> 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();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;

/**
Expand Down Expand Up @@ -53,6 +57,10 @@ private static String parseWithoutChanges(String query) {
return render(new EqlQueryRenderer().visit(parsedQuery));
}

static Stream<Arguments> reservedWords() {
return Stream.of("abs", "exp", "any", "case", "else", "index", "time").map(Arguments::of);
}

private void assertQuery(String query) {

String slimmedDownQuery = reduceWhitespace(query);
Expand Down Expand Up @@ -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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ private static String parseWithoutChanges(String query) {
return render(new HqlQueryRenderer().visit(parsedQuery));
}

public static Stream<Arguments> reservedWords() {
static Stream<Arguments> reservedWords() {
return Stream.of("abs", "exp", "any", "case", "else", "index", "time").map(Arguments::of);
}

Expand Down Expand Up @@ -1646,30 +1646,22 @@ 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"})
@MethodSource("reservedWords")
void entityNameWithPackageContainingReservedWord(String reservedWord) {

String source = "select new com.company.%s.thing.stuff.ClassName(e.id) from Experience e".formatted(reservedWord);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ private static String parseWithoutChanges(String query) {
return render(new JpqlQueryRenderer().visit(parsedQuery));
}

public static Stream<Arguments> reservedWords() {
static Stream<Arguments> reservedWords() {
return Stream.of("abs", "exp", "any", "case", "else", "index", "time").map(Arguments::of);
}

Expand Down Expand Up @@ -1004,35 +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"})
@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);
}


}

0 comments on commit 8c1174f

Please sign in to comment.