fix an ambiguity in the grammar of datetime literals
this was my very stupid mistake
This commit is contained in:
parent
43cce5fe5e
commit
ae978b3d10
|
@ -304,6 +304,7 @@ WITH : [wW] [iI] [tT] [hH];
|
|||
WITHIN : [wW] [iI] [tT] [hH] [iI] [nN];
|
||||
WITHOUT : [wW] [iI] [tT] [hH] [oO] [uU] [tT];
|
||||
YEAR : [yY] [eE] [aA] [rR];
|
||||
ZONED : [zZ] [oO] [nN] [eE] [dD];
|
||||
|
||||
// case-insensitive true, false and null recognition (split vote :)
|
||||
TRUE : [tT] [rR] [uU] [eE];
|
||||
|
|
|
@ -877,8 +877,24 @@ temporalLiteral
|
|||
* A literal datetime, in braces, or with the 'datetime' keyword
|
||||
*/
|
||||
dateTimeLiteral
|
||||
: LEFT_BRACE dateTime RIGHT_BRACE
|
||||
| DATETIME dateTime
|
||||
: localDateTimeLiteral
|
||||
| zonedDateTimeLiteral
|
||||
| offsetDateTimeLiteral
|
||||
;
|
||||
|
||||
localDateTimeLiteral
|
||||
: LEFT_BRACE localDateTime RIGHT_BRACE
|
||||
| LOCAL? DATETIME localDateTime
|
||||
;
|
||||
|
||||
zonedDateTimeLiteral
|
||||
: LEFT_BRACE zonedDateTime RIGHT_BRACE
|
||||
| ZONED? DATETIME zonedDateTime
|
||||
;
|
||||
|
||||
offsetDateTimeLiteral
|
||||
: LEFT_BRACE offsetDateTime RIGHT_BRACE
|
||||
| OFFSET? DATETIME offsetDateTimeWithMinutes
|
||||
;
|
||||
|
||||
/**
|
||||
|
@ -900,8 +916,26 @@ timeLiteral
|
|||
/**
|
||||
* A literal datetime
|
||||
*/
|
||||
dateTime
|
||||
: date time (zoneId | offset)?
|
||||
dateTime
|
||||
: localDateTime
|
||||
| zonedDateTime
|
||||
| offsetDateTime
|
||||
;
|
||||
|
||||
localDateTime
|
||||
: date time
|
||||
;
|
||||
|
||||
zonedDateTime
|
||||
: date time zoneId
|
||||
;
|
||||
|
||||
offsetDateTime
|
||||
: date time offset
|
||||
;
|
||||
|
||||
offsetDateTimeWithMinutes
|
||||
: date time offsetWithMinutes
|
||||
;
|
||||
|
||||
/**
|
||||
|
@ -925,6 +959,10 @@ offset
|
|||
: (PLUS | MINUS) hour (COLON minute)?
|
||||
;
|
||||
|
||||
offsetWithMinutes
|
||||
: (PLUS | MINUS) hour COLON minute
|
||||
;
|
||||
|
||||
year: INTEGER_LITERAL;
|
||||
month: INTEGER_LITERAL;
|
||||
day: INTEGER_LITERAL;
|
||||
|
@ -1174,19 +1212,19 @@ frameClause
|
|||
*/
|
||||
frameStart
|
||||
: UNBOUNDED PRECEDING
|
||||
| expression PRECEDING
|
||||
| CURRENT ROW
|
||||
| expression FOLLOWING
|
||||
| expression PRECEDING
|
||||
| CURRENT ROW
|
||||
| expression FOLLOWING
|
||||
;
|
||||
|
||||
/**
|
||||
* The end of the window content
|
||||
*/
|
||||
frameEnd
|
||||
: expression PRECEDING
|
||||
| CURRENT ROW
|
||||
| expression FOLLOWING
|
||||
| UNBOUNDED FOLLOWING
|
||||
: expression PRECEDING
|
||||
| CURRENT ROW
|
||||
| expression FOLLOWING
|
||||
| UNBOUNDED FOLLOWING
|
||||
;
|
||||
|
||||
/**
|
||||
|
@ -1194,9 +1232,9 @@ frameEnd
|
|||
*/
|
||||
frameExclusion
|
||||
: EXCLUDE CURRENT ROW
|
||||
| EXCLUDE GROUP
|
||||
| EXCLUDE TIES
|
||||
| EXCLUDE NO OTHERS
|
||||
| EXCLUDE GROUP
|
||||
| EXCLUDE TIES
|
||||
| EXCLUDE NO OTHERS
|
||||
;
|
||||
|
||||
/**
|
||||
|
|
|
@ -3288,7 +3288,30 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
|
||||
@Override
|
||||
public Object visitDateTimeLiteral(HqlParser.DateTimeLiteralContext ctx) {
|
||||
return ctx.getChild( 1 ).accept( this );
|
||||
return ctx.getChild( 0 ).accept( this );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitLocalDateTimeLiteral(HqlParser.LocalDateTimeLiteralContext ctx) {
|
||||
return ctx.localDateTime().accept( this );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitZonedDateTimeLiteral(HqlParser.ZonedDateTimeLiteralContext ctx) {
|
||||
return ctx.zonedDateTime().accept( this );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitOffsetDateTimeLiteral(HqlParser.OffsetDateTimeLiteralContext ctx) {
|
||||
if ( ctx.offsetDateTime() != null ) {
|
||||
return ctx.offsetDateTime().accept(this);
|
||||
}
|
||||
else if ( ctx.offsetDateTimeWithMinutes() != null ) {
|
||||
return ctx.offsetDateTimeWithMinutes().accept(this);
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -3336,42 +3359,48 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
|
||||
@Override
|
||||
public Object visitDateTime(HqlParser.DateTimeContext ctx) {
|
||||
final ParseTree parseTree = ctx.getChild( 2 );
|
||||
if ( parseTree instanceof HqlParser.ZoneIdContext || parseTree == null ) {
|
||||
return dateTimeLiteralFrom(
|
||||
(HqlParser.DateContext) ctx.getChild( 0 ),
|
||||
(HqlParser.TimeContext) ctx.getChild( 1 ),
|
||||
(HqlParser.ZoneIdContext) parseTree
|
||||
);
|
||||
}
|
||||
else {
|
||||
return offsetDatetimeLiteralFrom(
|
||||
(HqlParser.DateContext) ctx.getChild( 0 ),
|
||||
(HqlParser.TimeContext) ctx.getChild( 1 ),
|
||||
(HqlParser.OffsetContext) parseTree
|
||||
);
|
||||
}
|
||||
return ctx.getChild( 0 ).accept( this );
|
||||
}
|
||||
|
||||
private SqmLiteral<?> dateTimeLiteralFrom(
|
||||
@Override
|
||||
public Object visitLocalDateTime(HqlParser.LocalDateTimeContext ctx) {
|
||||
return localDateTimeLiteralFrom( ctx.date(), ctx.time() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitOffsetDateTime(HqlParser.OffsetDateTimeContext ctx) {
|
||||
return offsetDatetimeLiteralFrom( ctx.date(), ctx.time(), ctx.offset() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitOffsetDateTimeWithMinutes(HqlParser.OffsetDateTimeWithMinutesContext ctx) {
|
||||
return offsetDatetimeLiteralFrom( ctx.date(), ctx.time(), ctx.offsetWithMinutes() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitZonedDateTime(HqlParser.ZonedDateTimeContext ctx) {
|
||||
return zonedDateTimeLiteralFrom( ctx.date(), ctx.time(), ctx.zoneId() );
|
||||
}
|
||||
|
||||
private SqmLiteral<?> localDateTimeLiteralFrom(
|
||||
HqlParser.DateContext date,
|
||||
HqlParser.TimeContext time) {
|
||||
return new SqmLiteral<>(
|
||||
LocalDateTime.of( localDate( date ), localTime( time ) ),
|
||||
resolveExpressibleTypeBasic( LocalDateTime.class ),
|
||||
creationContext.getNodeBuilder()
|
||||
);
|
||||
}
|
||||
|
||||
private SqmLiteral<?> zonedDateTimeLiteralFrom(
|
||||
HqlParser.DateContext date,
|
||||
HqlParser.TimeContext time,
|
||||
HqlParser.ZoneIdContext timezone) {
|
||||
if ( timezone == null ) {
|
||||
return new SqmLiteral<>(
|
||||
LocalDateTime.of( localDate( date ), localTime( time ) ),
|
||||
resolveExpressibleTypeBasic( LocalDateTime.class ),
|
||||
creationContext.getNodeBuilder()
|
||||
);
|
||||
}
|
||||
else {
|
||||
final ZoneId zoneId = visitZoneId( timezone );
|
||||
return new SqmLiteral<>(
|
||||
ZonedDateTime.of( localDate( date ), localTime( time ), zoneId ),
|
||||
resolveExpressibleTypeBasic( ZonedDateTime.class ),
|
||||
creationContext.getNodeBuilder()
|
||||
);
|
||||
}
|
||||
return new SqmLiteral<>(
|
||||
ZonedDateTime.of( localDate( date ), localTime( time ), visitZoneId( timezone ) ),
|
||||
resolveExpressibleTypeBasic( ZonedDateTime.class ),
|
||||
creationContext.getNodeBuilder()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -3404,6 +3433,17 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
);
|
||||
}
|
||||
|
||||
private SqmLiteral<?> offsetDatetimeLiteralFrom(
|
||||
HqlParser.DateContext date,
|
||||
HqlParser.TimeContext time,
|
||||
HqlParser.OffsetWithMinutesContext offset) {
|
||||
return new SqmLiteral<>(
|
||||
OffsetDateTime.of( localDate( date ), localTime( time ), zoneOffset( offset ) ),
|
||||
resolveExpressibleTypeBasic( OffsetDateTime.class ),
|
||||
creationContext.getNodeBuilder()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitDate(HqlParser.DateContext ctx) {
|
||||
return new SqmLiteral<>(
|
||||
|
@ -3423,10 +3463,10 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
}
|
||||
|
||||
private static LocalTime localTime(HqlParser.TimeContext ctx) {
|
||||
final int hour = Integer.parseInt( ctx.getChild( 0 ).getText() );
|
||||
final int minute = Integer.parseInt( ctx.getChild( 2 ).getText() );
|
||||
if ( ctx.getChildCount() == 5 ) {
|
||||
final String secondText = ctx.getChild( 4 ).getText();
|
||||
final int hour = Integer.parseInt( ctx.hour().getText() );
|
||||
final int minute = Integer.parseInt( ctx.minute().getText() );
|
||||
if ( ctx.second() != null ) {
|
||||
final String secondText = ctx.second().getText();
|
||||
final int index = secondText.indexOf( '.');
|
||||
if ( index < 0 ) {
|
||||
return LocalTime.of(
|
||||
|
@ -3451,67 +3491,35 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
|
||||
private static LocalDate localDate(HqlParser.DateContext ctx) {
|
||||
return LocalDate.of(
|
||||
Integer.parseInt( ctx.getChild( 0 ).getText() ),
|
||||
Integer.parseInt( ctx.getChild( 2 ).getText() ),
|
||||
Integer.parseInt( ctx.getChild( 4 ).getText() )
|
||||
Integer.parseInt( ctx.year().getText() ),
|
||||
Integer.parseInt( ctx.month().getText() ),
|
||||
Integer.parseInt( ctx.day().getText() )
|
||||
);
|
||||
}
|
||||
|
||||
private static ZoneOffset zoneOffset(HqlParser.OffsetContext offset) {
|
||||
final int factor = ( (TerminalNode) offset.getChild( 0 ) ).getSymbol().getType() == PLUS ? 1 : -1;
|
||||
final int hour = factor * Integer.parseInt( offset.getChild( 1 ).getText() );
|
||||
final int hour = factor * Integer.parseInt( offset.hour().getText() );
|
||||
if ( offset.getChildCount() == 2 ) {
|
||||
return ZoneOffset.ofHours( hour );
|
||||
}
|
||||
return ZoneOffset.ofHoursMinutes(
|
||||
hour,
|
||||
factor * Integer.parseInt( offset.getChild( 3 ).getText() )
|
||||
factor * Integer.parseInt( offset.minute().getText() )
|
||||
);
|
||||
}
|
||||
|
||||
// private SqmLiteral<OffsetDateTime> offsetDatetimeLiteralFrom(String literalText) {
|
||||
// TemporalAccessor parsed = OFFSET_DATE_TIME.parse( literalText );
|
||||
// return new SqmLiteral<>(
|
||||
// OffsetDateTime.from( parsed ),
|
||||
// resolveExpressibleTypeBasic( OffsetDateTime.class ),
|
||||
// creationContext.getNodeBuilder()
|
||||
// );
|
||||
// }
|
||||
//
|
||||
// private SqmLiteral<?> dateTimeLiteralFrom(String literalText) {
|
||||
// //TO DO: return an OffsetDateTime when appropriate?
|
||||
// TemporalAccessor parsed = DATE_TIME.parse( literalText );
|
||||
// try {
|
||||
// return new SqmLiteral<>(
|
||||
// ZonedDateTime.from( parsed ),
|
||||
// resolveExpressibleTypeBasic( ZonedDateTime.class ),
|
||||
// creationContext.getNodeBuilder()
|
||||
// );
|
||||
// }
|
||||
// catch (DateTimeException dte) {
|
||||
// return new SqmLiteral<>(
|
||||
// LocalDateTime.from( parsed ),
|
||||
// resolveExpressibleTypeBasic( LocalDateTime.class ),
|
||||
// creationContext.getNodeBuilder()
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private SqmLiteral<LocalDate> localDateLiteralFrom(String literalText) {
|
||||
// return new SqmLiteral<>(
|
||||
// LocalDate.from( ISO_LOCAL_DATE.parse( literalText ) ),
|
||||
// resolveExpressibleTypeBasic( LocalDate.class ),
|
||||
// creationContext.getNodeBuilder()
|
||||
// );
|
||||
// }
|
||||
//
|
||||
// private SqmLiteral<LocalTime> localTimeLiteralFrom(String literalText) {
|
||||
// return new SqmLiteral<>(
|
||||
// LocalTime.from( ISO_LOCAL_TIME.parse( literalText ) ),
|
||||
// resolveExpressibleTypeBasic( LocalTime.class ),
|
||||
// creationContext.getNodeBuilder()
|
||||
// );
|
||||
// }
|
||||
private static ZoneOffset zoneOffset(HqlParser.OffsetWithMinutesContext offset) {
|
||||
final int factor = ( (TerminalNode) offset.getChild( 0 ) ).getSymbol().getType() == PLUS ? 1 : -1;
|
||||
final int hour = factor * Integer.parseInt( offset.hour().getText() );
|
||||
if ( offset.getChildCount() == 2 ) {
|
||||
return ZoneOffset.ofHours( hour );
|
||||
}
|
||||
return ZoneOffset.ofHoursMinutes(
|
||||
hour,
|
||||
factor * Integer.parseInt( offset.minute().getText() )
|
||||
);
|
||||
}
|
||||
|
||||
private SqmLiteral<?> sqlTimestampLiteralFrom(String literalText) {
|
||||
final TemporalAccessor parsed = DATE_TIME.parse( literalText.subSequence( 1, literalText.length() - 1 ) );
|
||||
|
|
Loading…
Reference in New Issue