Properly handle CAST functions on HQL.

See #3024
This commit is contained in:
Greg L. Turnquist
2023-06-14 11:58:33 -05:00
parent 3132f4945b
commit 0d03612633
3 changed files with 49 additions and 4 deletions

View File

@@ -492,9 +492,18 @@ frameEnd
// https://docs.jboss.org/hibernate/orm/6.1/userguide/html_single/Hibernate_User_Guide.html#hql-functions
castFunction
: CAST '(' expression AS identifier ')'
: CAST '(' expression AS castTarget ')'
;
castTarget
: castTargetType ('(' INTEGER_LITERAL (',' INTEGER_LITERAL)? ')')?
;
castTargetType
returns [String fullTargetName]
: (i=identifier { $fullTargetName = _localctx.i.getText(); }) ('.' c=identifier { $fullTargetName += ("." + _localctx.c.getText() ); })*
;
extractFunction
: EXTRACT '(' expression FROM expression ')'
| dateTimeFunction '(' expression ')'

View File

@@ -106,7 +106,7 @@ class HqlQueryRenderer extends HqlBaseVisitor<List<JpaQueryParsingToken>> {
if (ctx.MATERIALIZED() != null) {
tokens.add(TOKEN_MATERIALIZED);
}
tokens.add(TOKEN_OPEN_PAREN);
tokens.addAll(visit(ctx.queryExpression()));
tokens.add(TOKEN_CLOSE_PAREN);
@@ -1790,16 +1790,47 @@ class HqlQueryRenderer extends HqlBaseVisitor<List<JpaQueryParsingToken>> {
List<JpaQueryParsingToken> tokens = new ArrayList<>();
tokens.add(new JpaQueryParsingToken(ctx.CAST()));
tokens.add(new JpaQueryParsingToken(ctx.CAST(), false));
tokens.add(TOKEN_OPEN_PAREN);
tokens.addAll(visit(ctx.expression()));
tokens.add(new JpaQueryParsingToken(ctx.AS()));
tokens.addAll(visit(ctx.identifier()));
tokens.addAll(visit(ctx.castTarget()));
NOSPACE(tokens);
tokens.add(TOKEN_CLOSE_PAREN);
return tokens;
}
@Override
public List<JpaQueryParsingToken> visitCastTarget(HqlParser.CastTargetContext ctx) {
List<JpaQueryParsingToken> tokens = new ArrayList<>();
tokens.addAll(visit(ctx.castTargetType()));
if (ctx.INTEGER_LITERAL() != null && !ctx.INTEGER_LITERAL().isEmpty()) {
tokens.add(TOKEN_OPEN_PAREN);
ctx.INTEGER_LITERAL().forEach(terminalNode -> {
tokens.add(new JpaQueryParsingToken(terminalNode));
tokens.add(TOKEN_COMMA);
});
CLIP(tokens);
NOSPACE(tokens);
tokens.add(TOKEN_CLOSE_PAREN);
}
return tokens;
}
@Override
public List<JpaQueryParsingToken> visitCastTargetType(HqlParser.CastTargetTypeContext ctx) {
return List.of(new JpaQueryParsingToken(ctx.fullTargetName));
}
@Override
public List<JpaQueryParsingToken> visitExtractFunction(HqlParser.ExtractFunctionContext ctx) {

View File

@@ -1521,4 +1521,9 @@ class HqlQueryRendererTests {
void queryWithSignShouldWork() {
assertQuery("select t.sign from TestEntity t");
}
@Test // GH-3024
void castFunctionWithFqdnShouldWork() {
assertQuery("SELECT o FROM Order o WHERE CAST(:userId AS java.util.UUID) IS NULL OR o.user.id = :userId");
}
}