Fix EQL and JPQL LIKE with ESCAPE clause parsing.

Closes #3873
This commit is contained in:
Mark Paluch
2025-05-12 09:54:51 +02:00
parent 0d5fd5a0ba
commit 8e95f2e5be
7 changed files with 44 additions and 5 deletions

View File

@@ -677,7 +677,8 @@ entity_type_literal
escape_character
: CHARACTER
| character_valued_input_parameter //
| string_literal
| character_valued_input_parameter
;
numeric_literal

View File

@@ -653,7 +653,8 @@ entity_type_literal
escape_character
: CHARACTER
| character_valued_input_parameter //
| string_literal
| character_valued_input_parameter
;
numeric_literal
@@ -949,7 +950,7 @@ NOT_EQUAL : '<>' | '!=' ;
CHARACTER : '\'' (~ ('\'' | '\\')) '\'' ;
IDENTIFICATION_VARIABLE : ('a' .. 'z' | 'A' .. 'Z' | '\u0080' .. '\ufffe' | '$' | '_') ('a' .. 'z' | 'A' .. 'Z' | '\u0080' .. '\ufffe' | '0' .. '9' | '$' | '_')* ;
STRINGLITERAL : '\'' (~ ('\'' | '\\'))* '\'' ;
STRINGLITERAL : '\'' (~ ('\'' | '\\')|'\\')* '\'' ;
JAVASTRINGLITERAL : '"' ( ('\\' [btnfr"']) | ~('"'))* '"';
FLOATLITERAL : ('0' .. '9')* '.' ('0' .. '9')+ (E ('0' .. '9')+)* (F|D)?;
INTLITERAL : ('0' .. '9')+ ;

View File

@@ -2418,7 +2418,16 @@ class EqlQueryRenderer extends EqlBaseVisitor<List<JpaQueryParsingToken>> {
@Override
public List<JpaQueryParsingToken> visitEscape_character(EqlParser.Escape_characterContext ctx) {
return List.of(new JpaQueryParsingToken(ctx.CHARACTER()));
if (ctx.CHARACTER() != null) {
return List.of(new JpaQueryParsingToken(ctx.CHARACTER()));
} else if (ctx.character_valued_input_parameter() != null) {
return visit(ctx.character_valued_input_parameter());
} else if (ctx.string_literal() != null) {
return visit(ctx.string_literal());
}
return List.of();
}
@Override

View File

@@ -2225,7 +2225,16 @@ class JpqlQueryRenderer extends JpqlBaseVisitor<List<JpaQueryParsingToken>> {
@Override
public List<JpaQueryParsingToken> visitEscape_character(JpqlParser.Escape_characterContext ctx) {
return List.of(new JpaQueryParsingToken(ctx.CHARACTER()));
if (ctx.CHARACTER() != null) {
return List.of(new JpaQueryParsingToken(ctx.CHARACTER()));
} else if (ctx.character_valued_input_parameter() != null) {
return visit(ctx.character_valued_input_parameter());
} else if (ctx.string_literal() != null) {
return visit(ctx.string_literal());
}
return List.of();
}
@Override

View File

@@ -1038,6 +1038,14 @@ class EqlQueryRendererTests {
assertQuery(query);
}
@Test // GH-3873
void escapeClauseShouldWork() {
assertQuery("select t.name from SomeDbo t where t.name LIKE :name escape '\\\\'");
assertQuery("SELECT e FROM SampleEntity e WHERE LOWER(e.label) LIKE LOWER(?1) ESCAPE '\\\\'");
assertQuery("SELECT e FROM SampleEntity e WHERE LOWER(e.label) LIKE LOWER(?1) ESCAPE ?1");
assertQuery("SELECT e FROM SampleEntity e WHERE LOWER(e.label) LIKE LOWER(?1) ESCAPE :param");
}
@ParameterizedTest // GH-3451
@MethodSource("reservedWords")
void entityNameWithPackageContainingReservedWord(String reservedWord) {

View File

@@ -1569,6 +1569,9 @@ class HqlQueryRendererTests {
@Test // GH-3040
void escapeClauseShouldWork() {
assertQuery("select t.name from SomeDbo t where t.name LIKE :name escape '\\\\'");
assertQuery("SELECT e FROM SampleEntity e WHERE LOWER(e.label) LIKE LOWER(?1) ESCAPE '\\\\'");
assertQuery("SELECT e FROM SampleEntity e WHERE LOWER(e.label) LIKE LOWER(?1) ESCAPE ?1");
assertQuery("SELECT e FROM SampleEntity e WHERE LOWER(e.label) LIKE LOWER(?1) ESCAPE :param");
}
@Test // GH-3062, GH-3056

View File

@@ -1046,6 +1046,14 @@ class JpqlQueryRendererTests {
assertQuery(query);
}
@Test // GH-3873
void escapeClauseShouldWork() {
assertQuery("select t.name from SomeDbo t where t.name LIKE :name escape '\\\\'");
assertQuery("SELECT e FROM SampleEntity e WHERE LOWER(e.label) LIKE LOWER(?1) ESCAPE '\\\\'");
assertQuery("SELECT e FROM SampleEntity e WHERE LOWER(e.label) LIKE LOWER(?1) ESCAPE ?1");
assertQuery("SELECT e FROM SampleEntity e WHERE LOWER(e.label) LIKE LOWER(?1) ESCAPE :param");
}
@ParameterizedTest // GH-3451
@MethodSource("reservedWords")
void entityNameWithPackageContainingReservedWord(String reservedWord) {