From 2185f22ef0a45388e138ee0baca6c30db8ccf722 Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Thu, 13 Jun 2019 15:26:34 +0200 Subject: [PATCH] [jOOQ/jOOQ#8789] Add support for parsing MySQL numeric interval literals --- .../main/java/org/jooq/impl/ParserImpl.java | 120 +++++++++++++++++- 1 file changed, 118 insertions(+), 2 deletions(-) diff --git a/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java b/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java index 5f26350944..36c242c849 100644 --- a/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java @@ -6369,8 +6369,43 @@ final class ParserImpl implements Parser { return inline(parseIntervalLiteral(ctx)); } else { - ctx.position(position); - return field(parseIdentifier(ctx)); + Long interval = parseUnsignedIntegerIf(ctx); + + if (interval != null) { + DatePart part = parseIntervalDatePart(ctx); + long l = interval; + int i = (int) l; + + switch (part) { + case YEAR: + return inline(new YearToMonth(i)); + case QUARTER: + return inline(new YearToMonth(0, 3 * i)); + case MONTH: + return inline(new YearToMonth(0, i)); + case WEEK: + return inline(new DayToSecond(7 * i)); + case DAY: + return inline(new DayToSecond(i)); + case HOUR: + return inline(new DayToSecond(0, i)); + case MINUTE: + return inline(new DayToSecond(0, 0, i)); + case SECOND: + return inline(new DayToSecond(0, 0, 0, i)); + case MILLISECOND: + return inline(new DayToSecond(0, 0, 0, (int) (l / 1000), (int) (l % 1000 * 1000000))); + case MICROSECOND: + return inline(new DayToSecond(0, 0, 0, (int) (l / 1000000), (int) (l % 1000000 * 1000))); + case NANOSECOND: + return inline(new DayToSecond(0, 0, 0, (int) (l / 1000000000), (int) (l % 1000000000))); + } + } + + else { + ctx.position(position); + return field(parseIdentifier(ctx)); + } } } @@ -6781,6 +6816,87 @@ final class ParserImpl implements Parser { throw ctx.expected("DatePart"); } + private static final DatePart parseIntervalDatePart(ParserContext ctx) { + char character = ctx.character(); + + switch (character) { + case 'd': + case 'D': + if (parseKeywordIf(ctx, "DAY") || + parseKeywordIf(ctx, "DAYS")) + return DatePart.DAY; + + break; + + case 'h': + case 'H': + if (parseKeywordIf(ctx, "HOUR") || + parseKeywordIf(ctx, "HOURS")) + return DatePart.HOUR; + + break; + + case 'm': + case 'M': + if (parseKeywordIf(ctx, "MINUTE") || + parseKeywordIf(ctx, "MINUTES")) + return DatePart.MINUTE; + else if (parseKeywordIf(ctx, "MICROSECOND") || + parseKeywordIf(ctx, "MICROSECONDS")) + return DatePart.MICROSECOND; + else if (parseKeywordIf(ctx, "MILLISECOND") || + parseKeywordIf(ctx, "MILLISECONDS")) + return DatePart.MILLISECOND; + else if (parseKeywordIf(ctx, "MONTH") || + parseKeywordIf(ctx, "MONTHS")) + return DatePart.MONTH; + + break; + + case 'n': + case 'N': + if (parseKeywordIf(ctx, "NANOSECOND") || + parseKeywordIf(ctx, "NANOSECONDS")) + return DatePart.NANOSECOND; + + break; + + case 'q': + case 'Q': + if (parseKeywordIf(ctx, "QUARTER") || + parseKeywordIf(ctx, "QUARTERS")) + return DatePart.QUARTER; + + break; + + case 's': + case 'S': + if (parseKeywordIf(ctx, "SECOND") || + parseKeywordIf(ctx, "SECONDS")) + return DatePart.SECOND; + + break; + + case 'w': + case 'W': + if (parseKeywordIf(ctx, "WEEK") || + parseKeywordIf(ctx, "WEEKS")) + return DatePart.WEEK; + + break; + + case 'y': + case 'Y': + if (parseKeywordIf(ctx, "YEAR") || + parseKeywordIf(ctx, "YEARS")) + return DatePart.YEAR; + + break; + } + + throw ctx.expected("Interval DatePart"); + } + private static final Field parseFieldAsciiIf(ParserContext ctx) { if (parseFunctionNameIf(ctx, "ASCII")) { parse(ctx, '(');