[#6485] Support parsing TRUNC() for date / timestamp
This commit is contained in:
parent
b68d48e9ee
commit
d26dceaa25
@ -547,8 +547,9 @@ term =
|
||||
| 'COALESCE' '(' fields ')'
|
||||
| 'CUME_DIST' ( '(' ')' over | '(' fields ')' withinGroup )
|
||||
| dateLiteral
|
||||
| 'DENSE_RANK' ( '(' ')' over | '(' fields ')' withinGroup )
|
||||
| 'DATE_TRUNC' '(' stringLiteral ',' field ')'
|
||||
| 'DAY' '(' field ')'
|
||||
| 'DENSE_RANK' ( '(' ')' over | '(' fields ')' withinGroup )
|
||||
| ( 'DEG' | 'DEGREE' ) '(' sum ')'
|
||||
| 'EXTRACT' '(' datePart 'FROM' field ')'
|
||||
| 'EXP' '(' sum ')'
|
||||
@ -640,6 +641,7 @@ term =
|
||||
| timestampLiteral
|
||||
| 'TRANSLATE' '(' field ',' field ',' field ')'
|
||||
| 'TRIM' '(' field ')'
|
||||
| 'TRUNC' '(' field ',' stringLiteral ')'
|
||||
| 'TRUNC' '(' sum ',' sum ')'
|
||||
| truthValue
|
||||
| ( 'UPPER' | 'UCASE' ) '(' field ')'
|
||||
|
||||
@ -201,6 +201,7 @@ import static org.jooq.impl.DSL.time;
|
||||
import static org.jooq.impl.DSL.timestamp;
|
||||
import static org.jooq.impl.DSL.translate;
|
||||
import static org.jooq.impl.DSL.trim;
|
||||
import static org.jooq.impl.DSL.trunc;
|
||||
import static org.jooq.impl.DSL.unique;
|
||||
import static org.jooq.impl.DSL.user;
|
||||
import static org.jooq.impl.DSL.values;
|
||||
@ -3621,6 +3622,8 @@ final class ParserImpl implements Parser {
|
||||
if (D.is(type))
|
||||
if ((field = parseFieldDateLiteralIf(ctx)) != null)
|
||||
return field;
|
||||
else if ((field = parseFieldDateTruncIf(ctx)) != null)
|
||||
return field;
|
||||
|
||||
if (N.is(type))
|
||||
if ((field = parseFieldDenseRankIf(ctx)) != null)
|
||||
@ -3859,9 +3862,7 @@ final class ParserImpl implements Parser {
|
||||
return field;
|
||||
|
||||
if (N.is(type))
|
||||
if ((field = parseFieldTruncIf(ctx)) != null)
|
||||
return field;
|
||||
else if (parseFunctionNameIf(ctx, "TANH"))
|
||||
if (parseFunctionNameIf(ctx, "TANH"))
|
||||
return tanh((Field) parseFieldSumParenthesised(ctx));
|
||||
else if (parseFunctionNameIf(ctx, "TAN"))
|
||||
return tan((Field) parseFieldSumParenthesised(ctx));
|
||||
@ -3872,6 +3873,10 @@ final class ParserImpl implements Parser {
|
||||
else if ((field = parseFieldTimeLiteralIf(ctx)) != null)
|
||||
return field;
|
||||
|
||||
if (N.is(type) || D.is(type))
|
||||
if ((field = parseFieldTruncIf(ctx)) != null)
|
||||
return field;
|
||||
|
||||
break;
|
||||
|
||||
case 'u':
|
||||
@ -4087,11 +4092,37 @@ final class ParserImpl implements Parser {
|
||||
private static final Field<?> parseFieldTruncIf(ParserContext ctx) {
|
||||
if (parseFunctionNameIf(ctx, "TRUNC")) {
|
||||
parse(ctx, '(');
|
||||
Field<?> arg1 = toField(ctx, parseSum(ctx, N));
|
||||
Field<?> arg1 = parseField(ctx);
|
||||
parse(ctx, ',');
|
||||
Field<?> arg2 = toField(ctx, parseSum(ctx, N));
|
||||
parse(ctx, ')');
|
||||
return DSL.trunc((Field) arg1, (Field) arg2);
|
||||
|
||||
String part;
|
||||
if ((part = parseStringLiteralIf(ctx)) != null) {
|
||||
part = part.toUpperCase();
|
||||
|
||||
DatePart p;
|
||||
if ("YY".equals(part) || "YYYY".equals(part) || "YEAR".equals(part))
|
||||
p = DatePart.YEAR;
|
||||
else if ("MM".equals(part) || "MONTH".equals(part))
|
||||
p = DatePart.MONTH;
|
||||
else if ("DD".equals(part))
|
||||
p = DatePart.DAY;
|
||||
else if ("HH".equals(part))
|
||||
p = DatePart.HOUR;
|
||||
else if ("MI".equals(part))
|
||||
p = DatePart.MINUTE;
|
||||
else if ("SS".equals(part))
|
||||
p = DatePart.SECOND;
|
||||
else
|
||||
throw ctx.unexpectedToken();
|
||||
|
||||
parse(ctx, ')');
|
||||
return DSL.trunc((Field) arg1, p);
|
||||
}
|
||||
else {
|
||||
Field<?> arg2 = toField(ctx, parseSum(ctx, N));
|
||||
parse(ctx, ')');
|
||||
return DSL.trunc((Field) arg1, (Field) arg2);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
@ -4287,6 +4318,21 @@ final class ParserImpl implements Parser {
|
||||
return null;
|
||||
}
|
||||
|
||||
private static final Field<?> parseFieldDateTruncIf(ParserContext ctx) {
|
||||
if (parseFunctionNameIf(ctx, "DATE_TRUNC")) {
|
||||
parse(ctx, '(');
|
||||
DatePart part = DatePart.valueOf(parseStringLiteral(ctx).toUpperCase());
|
||||
parse(ctx, ',');
|
||||
Field<?> field = parseField(ctx, D);
|
||||
parse(ctx, ')');
|
||||
|
||||
return trunc(field, part);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private static final Date parseDateLiteral(ParserContext ctx) {
|
||||
try {
|
||||
return Date.valueOf(parseStringLiteral(ctx));
|
||||
@ -6095,14 +6141,25 @@ final class ParserImpl implements Parser {
|
||||
}
|
||||
|
||||
private static final String parseStringLiteral(ParserContext ctx) {
|
||||
String result = parseStringLiteralIf(ctx);
|
||||
|
||||
if (result == null)
|
||||
throw ctx.unexpectedToken();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static final String parseStringLiteralIf(ParserContext ctx) {
|
||||
parseWhitespaceIf(ctx);
|
||||
|
||||
if (parseIf(ctx, 'q') || parseIf(ctx, 'Q'))
|
||||
if (parseIf(ctx, 'q', '\'') || parseIf(ctx, 'Q', '\''))
|
||||
return parseOracleQuotedStringLiteral(ctx);
|
||||
else if (parseIf(ctx, 'e') || parseIf(ctx, 'E'))
|
||||
else if (parseIf(ctx, 'e', '\'') || parseIf(ctx, 'E', '\''))
|
||||
return parseUnquotedStringLiteral(ctx, true);
|
||||
else
|
||||
else if (peek(ctx, '\''))
|
||||
return parseUnquotedStringLiteral(ctx, false);
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
private static final byte[] parseBinaryLiteralIf(ParserContext ctx) {
|
||||
@ -6661,19 +6718,31 @@ final class ParserImpl implements Parser {
|
||||
}
|
||||
|
||||
private static final boolean parseIf(ParserContext ctx, String string) {
|
||||
parseWhitespaceIf(ctx);
|
||||
int length = string.length();
|
||||
boolean result = peek(ctx, string);
|
||||
|
||||
if (ctx.sql.length < ctx.position + length)
|
||||
if (result)
|
||||
ctx.position = ctx.position + string.length();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static final boolean parseIf(ParserContext ctx, String string, String peek) {
|
||||
parseWhitespaceIf(ctx);
|
||||
int l1 = string.length();
|
||||
int l2 = peek.length();
|
||||
|
||||
if (ctx.sql.length < ctx.position + l1 + l2)
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < length; i++) {
|
||||
char c = string.charAt(i);
|
||||
if (ctx.sql[ctx.position + i] != c)
|
||||
for (int i = 0; i < l1; i++)
|
||||
if (ctx.sql[ctx.position + i] != string.charAt(i))
|
||||
return false;
|
||||
}
|
||||
|
||||
ctx.position = ctx.position + length;
|
||||
for (int i = l1; i < l2; i++)
|
||||
if (ctx.sql[ctx.position + i] != peek.charAt(i))
|
||||
return false;
|
||||
|
||||
ctx.position = ctx.position + l1;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -6683,11 +6752,23 @@ final class ParserImpl implements Parser {
|
||||
}
|
||||
|
||||
private static final boolean parseIf(ParserContext ctx, char c) {
|
||||
boolean result = peek(ctx, c);
|
||||
|
||||
if (result)
|
||||
ctx.position = ctx.position + 1;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static final boolean parseIf(ParserContext ctx, char c, char peek) {
|
||||
parseWhitespaceIf(ctx);
|
||||
|
||||
if (ctx.character() != c)
|
||||
return false;
|
||||
|
||||
if (ctx.character(ctx.position + 1) != peek)
|
||||
return false;
|
||||
|
||||
ctx.position = ctx.position + 1;
|
||||
return true;
|
||||
}
|
||||
@ -6738,6 +6819,29 @@ final class ParserImpl implements Parser {
|
||||
return null;
|
||||
}
|
||||
|
||||
private static final boolean peek(ParserContext ctx, char c) {
|
||||
parseWhitespaceIf(ctx);
|
||||
|
||||
if (ctx.character() != c)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static final boolean peek(ParserContext ctx, String string) {
|
||||
parseWhitespaceIf(ctx);
|
||||
int length = string.length();
|
||||
|
||||
if (ctx.sql.length < ctx.position + length)
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < length; i++)
|
||||
if (ctx.sql[ctx.position + i] != string.charAt(i))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static final boolean peekKeyword(ParserContext ctx, String... keywords) {
|
||||
for (String keyword : keywords)
|
||||
if (peekKeyword(ctx, keyword))
|
||||
|
||||
Loading…
Reference in New Issue
Block a user