@@ -314,8 +314,10 @@ literal
|
||||
| NULL
|
||||
| booleanLiteral
|
||||
| numericLiteral
|
||||
| dateTimeLiteral
|
||||
| binaryLiteral
|
||||
| temporalLiteral
|
||||
| arrayLiteral
|
||||
| generalizedLiteral
|
||||
;
|
||||
|
||||
// https://docs.jboss.org/hibernate/orm/6.1/userguide/html_single/Hibernate_User_Guide.html#hql-boolean-literals
|
||||
@@ -326,30 +328,157 @@ booleanLiteral
|
||||
|
||||
// https://docs.jboss.org/hibernate/orm/6.1/userguide/html_single/Hibernate_User_Guide.html#hql-numeric-literals
|
||||
numericLiteral
|
||||
: INTEGER_LITERAL
|
||||
| LONG_LITERAL
|
||||
| BIG_INTEGER_LITERAL
|
||||
| FLOAT_LITERAL
|
||||
| DOUBLE_LITERAL
|
||||
| BIG_DECIMAL_LITERAL
|
||||
| HEX_LITERAL
|
||||
;
|
||||
: INTEGER_LITERAL
|
||||
| LONG_LITERAL
|
||||
| BIG_INTEGER_LITERAL
|
||||
| FLOAT_LITERAL
|
||||
| DOUBLE_LITERAL
|
||||
| BIG_DECIMAL_LITERAL
|
||||
| HEX_LITERAL
|
||||
;
|
||||
|
||||
// https://docs.jboss.org/hibernate/orm/6.1/userguide/html_single/Hibernate_User_Guide.html#hql-datetime-literals
|
||||
/**
|
||||
* A literal datetime, in braces, or with the 'datetime' keyword
|
||||
*/
|
||||
dateTimeLiteral
|
||||
: LOCAL_DATE
|
||||
| LOCAL_TIME
|
||||
| LOCAL_DATETIME
|
||||
| CURRENT_DATE
|
||||
| CURRENT_TIME
|
||||
| CURRENT_TIMESTAMP
|
||||
| OFFSET_DATETIME
|
||||
| (LOCAL | CURRENT) DATE
|
||||
| (LOCAL | CURRENT) TIME
|
||||
| (LOCAL | CURRENT | OFFSET) DATETIME
|
||||
| INSTANT
|
||||
: localDateTimeLiteral
|
||||
| zonedDateTimeLiteral
|
||||
| offsetDateTimeLiteral
|
||||
;
|
||||
|
||||
localDateTimeLiteral
|
||||
: '(' localDateTime ')'
|
||||
| LOCAL? DATETIME localDateTime
|
||||
;
|
||||
|
||||
zonedDateTimeLiteral
|
||||
: '(' zonedDateTime ')'
|
||||
| ZONED? DATETIME zonedDateTime
|
||||
;
|
||||
|
||||
offsetDateTimeLiteral
|
||||
: '(' offsetDateTime ')'
|
||||
| OFFSET? DATETIME offsetDateTimeWithMinutes
|
||||
;
|
||||
/**
|
||||
* A literal date, in braces, or with the 'date' keyword
|
||||
*/
|
||||
dateLiteral
|
||||
: '(' date ')'
|
||||
| LOCAL? DATE date
|
||||
;
|
||||
|
||||
/**
|
||||
* A literal time, in braces, or with the 'time' keyword
|
||||
*/
|
||||
timeLiteral
|
||||
: '(' time ')'
|
||||
| LOCAL? TIME time
|
||||
;
|
||||
|
||||
/**
|
||||
* A literal datetime
|
||||
*/
|
||||
dateTime
|
||||
: localDateTime
|
||||
| zonedDateTime
|
||||
| offsetDateTime
|
||||
;
|
||||
|
||||
localDateTime
|
||||
: date time
|
||||
;
|
||||
|
||||
zonedDateTime
|
||||
: date time zoneId
|
||||
;
|
||||
|
||||
offsetDateTime
|
||||
: date time offset
|
||||
;
|
||||
|
||||
offsetDateTimeWithMinutes
|
||||
: date time offsetWithMinutes
|
||||
;
|
||||
|
||||
/**
|
||||
* A JDBC-style timestamp escape, as required by JPQL
|
||||
*/
|
||||
jdbcTimestampLiteral
|
||||
: TIMESTAMP_ESCAPE_START (dateTime | genericTemporalLiteralText) '}'
|
||||
;
|
||||
|
||||
/**
|
||||
* A JDBC-style date escape, as required by JPQL
|
||||
*/
|
||||
jdbcDateLiteral
|
||||
: DATE_ESCAPE_START (date | genericTemporalLiteralText) '}'
|
||||
;
|
||||
|
||||
/**
|
||||
* A JDBC-style time escape, as required by JPQL
|
||||
*/
|
||||
jdbcTimeLiteral
|
||||
: TIME_ESCAPE_START (time | genericTemporalLiteralText) '}'
|
||||
;
|
||||
|
||||
genericTemporalLiteralText
|
||||
: STRING_LITERAL
|
||||
;
|
||||
|
||||
/**
|
||||
* A generic format for specifying literal values of arbitary types
|
||||
*/
|
||||
arrayLiteral
|
||||
: '[' (expression (',' expression)*)? ']'
|
||||
;
|
||||
|
||||
/**
|
||||
* A generic format for specifying literal values of arbitary types
|
||||
*/
|
||||
generalizedLiteral
|
||||
: '(' generalizedLiteralType ':' generalizedLiteralText ')'
|
||||
;
|
||||
|
||||
generalizedLiteralType : STRING_LITERAL;
|
||||
generalizedLiteralText : STRING_LITERAL;
|
||||
|
||||
/**
|
||||
* A literal date
|
||||
*/
|
||||
date
|
||||
: year '-' month '-' day
|
||||
;
|
||||
|
||||
/**
|
||||
* A literal time
|
||||
*/
|
||||
time
|
||||
: hour ':' minute (':' second)?
|
||||
;
|
||||
|
||||
/**
|
||||
* A literal offset
|
||||
*/
|
||||
offset
|
||||
: (PLUS | MINUS) hour (':' minute)?
|
||||
;
|
||||
|
||||
offsetWithMinutes
|
||||
: (PLUS | MINUS) hour ':' minute
|
||||
;
|
||||
|
||||
year: INTEGER_LITERAL;
|
||||
month: INTEGER_LITERAL;
|
||||
day: INTEGER_LITERAL;
|
||||
hour: INTEGER_LITERAL;
|
||||
minute: INTEGER_LITERAL;
|
||||
second: INTEGER_LITERAL | DOUBLE_LITERAL;
|
||||
zoneId
|
||||
: IDENTIFIER ('/' IDENTIFIER)?
|
||||
| STRING_LITERAL;
|
||||
|
||||
/**
|
||||
* A field that may be extracted from a date, time, or datetime
|
||||
*/
|
||||
@@ -402,8 +531,17 @@ binaryLiteral
|
||||
| '{' HEX_LITERAL (',' HEX_LITERAL)* '}'
|
||||
;
|
||||
|
||||
// https://docs.jboss.org/hibernate/orm/6.1/userguide/html_single/Hibernate_User_Guide.html#hql-enum-literals
|
||||
// TBD
|
||||
/**
|
||||
* A literal date, time, or datetime, in HQL syntax, or as a JDBC-style "escape" syntax
|
||||
*/
|
||||
temporalLiteral
|
||||
: dateTimeLiteral
|
||||
| dateLiteral
|
||||
| timeLiteral
|
||||
| jdbcTimestampLiteral
|
||||
| jdbcDateLiteral
|
||||
| jdbcTimeLiteral
|
||||
;
|
||||
|
||||
// https://docs.jboss.org/hibernate/orm/6.1/userguide/html_single/Hibernate_User_Guide.html#hql-java-constants
|
||||
// TBD
|
||||
@@ -1685,6 +1823,16 @@ BINARY_LITERAL : [xX] '\'' HEX_DIGIT+ '\''
|
||||
| [xX] '"' HEX_DIGIT+ '"'
|
||||
;
|
||||
|
||||
// ESCAPE start tokens
|
||||
TIMESTAMP_ESCAPE_START : '{ts';
|
||||
DATE_ESCAPE_START : '{d';
|
||||
TIME_ESCAPE_START : '{t';
|
||||
|
||||
PLUS : '+';
|
||||
MINUS : '-';
|
||||
|
||||
|
||||
|
||||
fragment
|
||||
LETTER : [a-zA-Z\u0080-\ufffe_$];
|
||||
|
||||
|
||||
@@ -1038,8 +1038,12 @@ class HqlQueryRenderer extends HqlBaseVisitor<QueryTokenStream> {
|
||||
return QueryRendererBuilder.from(QueryTokens.expression(ctx.STRING_LITERAL()));
|
||||
} else if (ctx.numericLiteral() != null) {
|
||||
return visit(ctx.numericLiteral());
|
||||
} else if (ctx.dateTimeLiteral() != null) {
|
||||
return visit(ctx.dateTimeLiteral());
|
||||
} else if (ctx.temporalLiteral() != null) {
|
||||
return visit(ctx.temporalLiteral());
|
||||
} else if (ctx.arrayLiteral() != null) {
|
||||
return visit(ctx.arrayLiteral());
|
||||
} else if (ctx.generalizedLiteral() != null) {
|
||||
return visit(ctx.generalizedLiteral());
|
||||
} else if (ctx.binaryLiteral() != null) {
|
||||
return visit(ctx.binaryLiteral());
|
||||
} else {
|
||||
@@ -1084,48 +1088,365 @@ class HqlQueryRenderer extends HqlBaseVisitor<QueryTokenStream> {
|
||||
@Override
|
||||
public QueryTokenStream visitDateTimeLiteral(HqlParser.DateTimeLiteralContext ctx) {
|
||||
|
||||
if (ctx.localDateTimeLiteral() != null) {
|
||||
return visit(ctx.localDateTimeLiteral());
|
||||
}
|
||||
|
||||
if (ctx.offsetDateTimeLiteral() != null) {
|
||||
return visit(ctx.offsetDateTimeLiteral());
|
||||
}
|
||||
|
||||
if (ctx.zonedDateTimeLiteral() != null) {
|
||||
return visit(ctx.zonedDateTimeLiteral());
|
||||
}
|
||||
|
||||
return QueryTokenStream.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryTokenStream visitLocalDateTimeLiteral(HqlParser.LocalDateTimeLiteralContext ctx) {
|
||||
|
||||
QueryRendererBuilder builder = QueryRenderer.builder();
|
||||
|
||||
if (ctx.LOCAL_DATE() != null) {
|
||||
builder.append(QueryTokens.expression(ctx.LOCAL_DATE()));
|
||||
} else if (ctx.LOCAL_TIME() != null) {
|
||||
builder.append(QueryTokens.expression(ctx.LOCAL_TIME()));
|
||||
} else if (ctx.LOCAL_DATETIME() != null) {
|
||||
builder.append(QueryTokens.expression(ctx.LOCAL_DATETIME()));
|
||||
} else if (ctx.CURRENT_DATE() != null) {
|
||||
builder.append(QueryTokens.expression(ctx.CURRENT_DATE()));
|
||||
} else if (ctx.CURRENT_TIME() != null) {
|
||||
builder.append(QueryTokens.expression(ctx.CURRENT_TIME()));
|
||||
} else if (ctx.CURRENT_TIMESTAMP() != null) {
|
||||
builder.append(QueryTokens.expression(ctx.CURRENT_TIMESTAMP()));
|
||||
} else if (ctx.OFFSET_DATETIME() != null) {
|
||||
builder.append(QueryTokens.expression(ctx.OFFSET_DATETIME()));
|
||||
} else {
|
||||
|
||||
if (ctx.DATETIME() != null) {
|
||||
if (ctx.LOCAL() != null) {
|
||||
builder.append(QueryTokens.expression(ctx.LOCAL()));
|
||||
} else if (ctx.CURRENT() != null) {
|
||||
builder.append(QueryTokens.expression(ctx.CURRENT()));
|
||||
} else if (ctx.OFFSET() != null) {
|
||||
builder.append(QueryTokens.expression(ctx.OFFSET()));
|
||||
}
|
||||
|
||||
if (ctx.DATE() != null) {
|
||||
builder.append(QueryTokens.expression(ctx.DATE()));
|
||||
} else if (ctx.TIME() != null) {
|
||||
builder.append(QueryTokens.expression(ctx.TIME()));
|
||||
} else if (ctx.DATETIME() != null) {
|
||||
builder.append(QueryTokens.expression(ctx.DATETIME()));
|
||||
}
|
||||
|
||||
if (ctx.INSTANT() != null) {
|
||||
builder.append(QueryTokens.expression(ctx.INSTANT()));
|
||||
}
|
||||
builder.append(QueryTokens.expression(ctx.DATETIME()));
|
||||
builder.append(visit(ctx.localDateTime()));
|
||||
} else {
|
||||
builder.append(TOKEN_OPEN_PAREN);
|
||||
builder.append(visit(ctx.localDateTime()));
|
||||
builder.append(TOKEN_CLOSE_PAREN);
|
||||
}
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryTokenStream visitZonedDateTimeLiteral(HqlParser.ZonedDateTimeLiteralContext ctx) {
|
||||
|
||||
QueryRendererBuilder builder = QueryRenderer.builder();
|
||||
|
||||
if (ctx.DATETIME() != null) {
|
||||
if (ctx.ZONED() != null) {
|
||||
builder.append(QueryTokens.expression(ctx.ZONED()));
|
||||
}
|
||||
builder.append(QueryTokens.expression(ctx.DATETIME()));
|
||||
builder.append(visit(ctx.zonedDateTime()));
|
||||
} else {
|
||||
builder.append(TOKEN_OPEN_PAREN);
|
||||
builder.append(visit(ctx.zonedDateTime()));
|
||||
builder.append(TOKEN_CLOSE_PAREN);
|
||||
}
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryTokenStream visitOffsetDateTimeLiteral(HqlParser.OffsetDateTimeLiteralContext ctx) {
|
||||
|
||||
QueryRendererBuilder builder = QueryRenderer.builder();
|
||||
|
||||
if (ctx.DATETIME() != null) {
|
||||
if (ctx.OFFSET() != null) {
|
||||
builder.append(QueryTokens.expression(ctx.OFFSET()));
|
||||
}
|
||||
builder.append(QueryTokens.expression(ctx.DATETIME()));
|
||||
builder.append(visit(ctx.offsetDateTimeWithMinutes()));
|
||||
} else {
|
||||
builder.append(TOKEN_OPEN_PAREN);
|
||||
builder.append(visit(ctx.offsetDateTime()));
|
||||
builder.append(TOKEN_CLOSE_PAREN);
|
||||
}
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryTokenStream visitDateLiteral(HqlParser.DateLiteralContext ctx) {
|
||||
|
||||
QueryRendererBuilder builder = QueryRenderer.builder();
|
||||
|
||||
if (ctx.DATE() != null) {
|
||||
if (ctx.LOCAL() != null) {
|
||||
builder.append(QueryTokens.expression(ctx.LOCAL()));
|
||||
}
|
||||
builder.append(QueryTokens.expression(ctx.DATE()));
|
||||
builder.append(visit(ctx.date()));
|
||||
} else {
|
||||
builder.append(TOKEN_OPEN_PAREN);
|
||||
builder.append(visit(ctx.date()));
|
||||
builder.append(TOKEN_CLOSE_PAREN);
|
||||
}
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryTokenStream visitTimeLiteral(HqlParser.TimeLiteralContext ctx) {
|
||||
|
||||
QueryRendererBuilder builder = QueryRenderer.builder();
|
||||
|
||||
if (ctx.TIME() != null) {
|
||||
if (ctx.LOCAL() != null) {
|
||||
builder.append(QueryTokens.expression(ctx.LOCAL()));
|
||||
}
|
||||
builder.append(QueryTokens.expression(ctx.TIME()));
|
||||
builder.append(visit(ctx.time()));
|
||||
} else {
|
||||
builder.append(TOKEN_OPEN_PAREN);
|
||||
builder.append(visit(ctx.time()));
|
||||
builder.append(TOKEN_CLOSE_PAREN);
|
||||
}
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryTokenStream visitDateTime(HqlParser.DateTimeContext ctx) {
|
||||
|
||||
if (ctx.localDateTime() != null) {
|
||||
return visit(ctx.localDateTime());
|
||||
}
|
||||
|
||||
if (ctx.offsetDateTime() != null) {
|
||||
return visit(ctx.offsetDateTime());
|
||||
}
|
||||
|
||||
if (ctx.zonedDateTime() != null) {
|
||||
return visit(ctx.zonedDateTime());
|
||||
}
|
||||
|
||||
return QueryTokenStream.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryTokenStream visitLocalDateTime(HqlParser.LocalDateTimeContext ctx) {
|
||||
|
||||
QueryRendererBuilder builder = QueryRenderer.builder();
|
||||
|
||||
builder.appendExpression(visit(ctx.date()));
|
||||
builder.appendExpression(visit(ctx.time()));
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryTokenStream visitZonedDateTime(HqlParser.ZonedDateTimeContext ctx) {
|
||||
|
||||
QueryRendererBuilder builder = QueryRenderer.builder();
|
||||
|
||||
builder.appendExpression(visit(ctx.date()));
|
||||
builder.appendExpression(visit(ctx.time()));
|
||||
builder.appendExpression(visit(ctx.zoneId()));
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryTokenStream visitOffsetDateTime(HqlParser.OffsetDateTimeContext ctx) {
|
||||
|
||||
QueryRendererBuilder builder = QueryRenderer.builder();
|
||||
|
||||
builder.appendExpression(visit(ctx.date()));
|
||||
builder.appendInline(visit(ctx.time()));
|
||||
builder.appendInline(visit(ctx.offset()));
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryTokenStream visitOffsetDateTimeWithMinutes(HqlParser.OffsetDateTimeWithMinutesContext ctx) {
|
||||
|
||||
QueryRendererBuilder builder = QueryRenderer.builder();
|
||||
|
||||
builder.appendExpression(visit(ctx.date()));
|
||||
builder.appendInline(visit(ctx.time()));
|
||||
builder.appendInline(visit(ctx.offsetWithMinutes()));
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryTokenStream visitJdbcTimestampLiteral(HqlParser.JdbcTimestampLiteralContext ctx) {
|
||||
|
||||
QueryRendererBuilder builder = QueryRenderer.builder();
|
||||
|
||||
builder.append(TOKEN_OPEN_BRACE);
|
||||
builder.append(QueryTokens.token("ts"));
|
||||
builder.append(visit(ctx.dateTime() != null ? ctx.dateTime() : ctx.genericTemporalLiteralText()));
|
||||
builder.append(QueryTokens.TOKEN_CLOSE_BRACE);
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryTokenStream visitJdbcDateLiteral(HqlParser.JdbcDateLiteralContext ctx) {
|
||||
|
||||
QueryRendererBuilder builder = QueryRenderer.builder();
|
||||
|
||||
builder.append(TOKEN_OPEN_BRACE);
|
||||
builder.append(QueryTokens.token("d"));
|
||||
builder.append(visit(ctx.date() != null ? ctx.date() : ctx.genericTemporalLiteralText()));
|
||||
builder.append(QueryTokens.TOKEN_CLOSE_BRACE);
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryTokenStream visitJdbcTimeLiteral(HqlParser.JdbcTimeLiteralContext ctx) {
|
||||
|
||||
QueryRendererBuilder builder = QueryRenderer.builder();
|
||||
|
||||
builder.append(TOKEN_OPEN_BRACE);
|
||||
builder.append(QueryTokens.token("t"));
|
||||
builder.append(visit(ctx.time() != null ? ctx.time() : ctx.genericTemporalLiteralText()));
|
||||
builder.append(QueryTokens.TOKEN_CLOSE_BRACE);
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryTokenStream visitGenericTemporalLiteralText(HqlParser.GenericTemporalLiteralTextContext ctx) {
|
||||
return QueryRendererBuilder.from(QueryTokens.token(ctx.STRING_LITERAL()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryTokenStream visitArrayLiteral(HqlParser.ArrayLiteralContext ctx) {
|
||||
|
||||
QueryRendererBuilder builder = QueryRenderer.builder();
|
||||
builder.append(TOKEN_OPEN_SQUARE_BRACKET);
|
||||
builder.append(QueryTokenStream.concat(ctx.expression(), this::visit, TOKEN_COMMA));
|
||||
builder.append(TOKEN_CLOSE_SQUARE_BRACKET);
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryTokenStream visitGeneralizedLiteral(HqlParser.GeneralizedLiteralContext ctx) {
|
||||
|
||||
QueryRendererBuilder builder = QueryRenderer.builder();
|
||||
builder.append(TOKEN_OPEN_PAREN);
|
||||
builder.append(visit(ctx.generalizedLiteralType()));
|
||||
builder.append(TOKEN_COLON);
|
||||
builder.append(visit(ctx.generalizedLiteralText()));
|
||||
builder.append(TOKEN_CLOSE_PAREN);
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryTokenStream visitGeneralizedLiteralType(HqlParser.GeneralizedLiteralTypeContext ctx) {
|
||||
return QueryRendererBuilder.from(QueryTokens.token(ctx.STRING_LITERAL()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryTokenStream visitGeneralizedLiteralText(HqlParser.GeneralizedLiteralTextContext ctx) {
|
||||
return QueryRendererBuilder.from(QueryTokens.token(ctx.STRING_LITERAL()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryTokenStream visitDate(HqlParser.DateContext ctx) {
|
||||
|
||||
QueryRendererBuilder builder = QueryRenderer.builder();
|
||||
builder.append(visit(ctx.year()));
|
||||
builder.append(TOKEN_DASH);
|
||||
builder.append(visit(ctx.month()));
|
||||
builder.append(TOKEN_DASH);
|
||||
builder.append(visit(ctx.day()));
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryTokenStream visitTime(HqlParser.TimeContext ctx) {
|
||||
|
||||
QueryRendererBuilder builder = QueryRenderer.builder();
|
||||
builder.append(visit(ctx.hour()));
|
||||
builder.append(TOKEN_COLON);
|
||||
builder.append(visit(ctx.minute()));
|
||||
|
||||
if (ctx.second() != null) {
|
||||
builder.append(TOKEN_COLON);
|
||||
builder.append(visit(ctx.second()));
|
||||
}
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryTokenStream visitOffset(HqlParser.OffsetContext ctx) {
|
||||
|
||||
QueryRendererBuilder builder = QueryRenderer.builder();
|
||||
if (ctx.MINUS() != null) {
|
||||
builder.append(QueryTokens.token(ctx.MINUS()));
|
||||
} else if (ctx.PLUS() != null) {
|
||||
builder.append(QueryTokens.token(ctx.PLUS()));
|
||||
}
|
||||
builder.append(visit(ctx.hour()));
|
||||
|
||||
if (ctx.minute() != null) {
|
||||
builder.append(TOKEN_COLON);
|
||||
builder.append(visit(ctx.minute()));
|
||||
}
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryTokenStream visitOffsetWithMinutes(HqlParser.OffsetWithMinutesContext ctx) {
|
||||
|
||||
QueryRendererBuilder builder = QueryRenderer.builder();
|
||||
|
||||
if (ctx.MINUS() != null) {
|
||||
builder.append(QueryTokens.token(ctx.MINUS()));
|
||||
} else if (ctx.PLUS() != null) {
|
||||
builder.append(QueryTokens.token(ctx.PLUS()));
|
||||
}
|
||||
|
||||
builder.append(visit(ctx.hour()));
|
||||
builder.append(TOKEN_COLON);
|
||||
builder.append(visit(ctx.minute()));
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryTokenStream visitYear(HqlParser.YearContext ctx) {
|
||||
return QueryRendererBuilder.from(QueryTokens.token(ctx.INTEGER_LITERAL()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryTokenStream visitMonth(HqlParser.MonthContext ctx) {
|
||||
return QueryRendererBuilder.from(QueryTokens.token(ctx.INTEGER_LITERAL()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryTokenStream visitDay(HqlParser.DayContext ctx) {
|
||||
return QueryRendererBuilder.from(QueryTokens.token(ctx.INTEGER_LITERAL()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryTokenStream visitHour(HqlParser.HourContext ctx) {
|
||||
return QueryRendererBuilder.from(QueryTokens.token(ctx.INTEGER_LITERAL()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryTokenStream visitMinute(HqlParser.MinuteContext ctx) {
|
||||
return QueryRendererBuilder.from(QueryTokens.token(ctx.INTEGER_LITERAL()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryTokenStream visitSecond(HqlParser.SecondContext ctx) {
|
||||
return QueryRendererBuilder.from(QueryTokens.token(ctx.INTEGER_LITERAL()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryTokenStream visitZoneId(HqlParser.ZoneIdContext ctx) {
|
||||
return QueryRendererBuilder.from(QueryTokens.token(ctx.STRING_LITERAL()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryTokenStream visitDatetimeField(HqlParser.DatetimeFieldContext ctx) {
|
||||
|
||||
@@ -1250,6 +1571,36 @@ class HqlQueryRenderer extends HqlBaseVisitor<QueryTokenStream> {
|
||||
return builder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryTokenStream visitTemporalLiteral(HqlParser.TemporalLiteralContext ctx) {
|
||||
|
||||
if (ctx.dateTimeLiteral() != null) {
|
||||
return visit(ctx.dateTimeLiteral());
|
||||
}
|
||||
|
||||
if (ctx.dateLiteral() != null) {
|
||||
return visit(ctx.dateLiteral());
|
||||
}
|
||||
|
||||
if (ctx.timeLiteral() != null) {
|
||||
return visit(ctx.timeLiteral());
|
||||
}
|
||||
|
||||
if (ctx.jdbcTimestampLiteral() != null) {
|
||||
return visit(ctx.jdbcTimestampLiteral());
|
||||
}
|
||||
|
||||
if (ctx.jdbcDateLiteral() != null) {
|
||||
return visit(ctx.jdbcDateLiteral());
|
||||
}
|
||||
|
||||
if (ctx.jdbcTimeLiteral() != null) {
|
||||
return visit(ctx.jdbcTimeLiteral());
|
||||
}
|
||||
|
||||
return QueryTokenStream.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryTokenStream visitPlainPrimaryExpression(HqlParser.PlainPrimaryExpressionContext ctx) {
|
||||
return visit(ctx.primaryExpression());
|
||||
|
||||
@@ -47,6 +47,7 @@ class QueryTokens {
|
||||
static final QueryToken TOKEN_OPEN_SQUARE_BRACKET = token("[");
|
||||
static final QueryToken TOKEN_CLOSE_SQUARE_BRACKET = token("]");
|
||||
static final QueryToken TOKEN_COLON = token(":");
|
||||
static final QueryToken TOKEN_DASH = token("-");
|
||||
static final QueryToken TOKEN_QUESTION_MARK = token("?");
|
||||
static final QueryToken TOKEN_OPEN_BRACE = token("{");
|
||||
static final QueryToken TOKEN_CLOSE_BRACE = token("}");
|
||||
|
||||
@@ -1749,6 +1749,36 @@ class HqlQueryRendererTests {
|
||||
assertQuery("SELECT ce.id as id, cd.startDate + 5 %s AS summedDate FROM CalendarEvent ce".formatted(dtField));
|
||||
}
|
||||
|
||||
@Test // GH-3739
|
||||
void dateTimeLiterals() {
|
||||
|
||||
assertQuery("SELECT e FROM Employee e WHERE e.startDate = {d'2012-01-03'}");
|
||||
assertQuery("SELECT e FROM Employee e WHERE e.startTime = {t'09:00:00'}");
|
||||
assertQuery("SELECT e FROM Employee e WHERE e.version = {ts'2012-01-03 09:00:00'}");
|
||||
assertQuery("SELECT e FROM Employee e WHERE e.version = {ts'something weird'}");
|
||||
assertQuery("SELECT e FROM Employee e WHERE e.version = {ts2012-01-03 09:00:00+1}");
|
||||
assertQuery("SELECT e FROM Employee e WHERE e.version = {ts2012-01-03 09:00:00-1}");
|
||||
assertQuery("SELECT e FROM Employee e WHERE e.version = {ts2012-01-03 09:00:00+1:00}");
|
||||
assertQuery("SELECT e FROM Employee e WHERE e.version = {ts2012-01-03 09:00:00-1:00}");
|
||||
|
||||
assertQuery("SELECT e FROM Employee e WHERE e.version = OFFSET DATETIME 2012-01-03 09:00:00+1:01");
|
||||
assertQuery("SELECT e FROM Employee e WHERE e.version = OFFSET DATETIME 2012-01-03 09:00:00-1:01");
|
||||
}
|
||||
|
||||
@Test
|
||||
void literals() {
|
||||
|
||||
assertQuery("SELECT e FROM Employee e WHERE e.name = 'Bob'");
|
||||
assertQuery("SELECT e FROM Employee e WHERE e.names = [e.firstName, e.lastName]");
|
||||
assertQuery("SELECT e FROM Employee e WHERE e.id = 1234");
|
||||
assertQuery("SELECT e FROM Employee e WHERE e.id = 1234L");
|
||||
assertQuery("SELECT s FROM Stat s WHERE s.ratio > 3.14F");
|
||||
assertQuery("SELECT s FROM Stat s WHERE s.ratio > 3.14e32D");
|
||||
assertQuery("SELECT e FROM Employee e WHERE e.active = TRUE");
|
||||
assertQuery("SELECT e FROM Employee e WHERE e.gender = org.acme.Gender.MALE");
|
||||
assertQuery("UPDATE Employee e SET e.manager = NULL WHERE e.manager = :manager");
|
||||
}
|
||||
|
||||
@ParameterizedTest // GH-3711
|
||||
@ValueSource(strings = { "1", "1_000", "1L", "1_000L", "1bi", "1.1f", "2.2d", "2.2bd" })
|
||||
void numberLiteralsShouldWork(String literal) {
|
||||
|
||||
Reference in New Issue
Block a user