[Enhancement](planner)support fold constant for date_trunc() (#22122)

This commit is contained in:
mch_ucchi
2023-08-04 13:32:48 +08:00
committed by GitHub
parent 3d0d5bfd6d
commit d5a21de796
2 changed files with 80 additions and 0 deletions

View File

@ -350,6 +350,83 @@ public class FEFunctions {
return null;
}
@FEFunction(name = "date_trunc", argTypes = {"DATETIME", "VARCHAR"}, returnType = "DATETIME")
public static DateLiteral dateTrunc(LiteralExpr date, LiteralExpr truncate) {
if (date.getType().isDateLike()) {
DateLiteral dateLiteral = ((DateLiteral) date);
LocalDateTime localDate = dateTruncHelper(LocalDateTime.of(
(int) dateLiteral.getYear(), (int) dateLiteral.getMonth(), (int) dateLiteral.getDay(),
(int) dateLiteral.getHour(), (int) dateLiteral.getMinute(), (int) dateLiteral.getSecond()),
truncate.getStringValue());
return new DateLiteral(localDate.getYear(), localDate.getMonthValue(), localDate.getDayOfMonth(),
localDate.getHour(), localDate.getMinute(), localDate.getSecond(), date.getType());
}
return null;
}
@FEFunction(name = "date_trunc", argTypes = {"DATETIMEV2", "VARCHAR"}, returnType = "DATETIMEV2")
public static DateLiteral dateTruncV2(LiteralExpr date, LiteralExpr truncate) {
if (date.getType().isDateLike()) {
DateLiteral dateLiteral = ((DateLiteral) date);
LocalDateTime localDate = dateTruncHelper(LocalDateTime.of(
(int) dateLiteral.getYear(), (int) dateLiteral.getMonth(), (int) dateLiteral.getDay(),
(int) dateLiteral.getHour(), (int) dateLiteral.getMinute(), (int) dateLiteral.getSecond()),
truncate.getStringValue());
return new DateLiteral(localDate.getYear(), localDate.getMonthValue(), localDate.getDayOfMonth(),
localDate.getHour(), localDate.getMinute(), localDate.getSecond(), date.getType());
}
return null;
}
private static LocalDateTime dateTruncHelper(LocalDateTime dateTime, String trunc) {
int year = dateTime.getYear();
int month = dateTime.getMonthValue();
int day = dateTime.getDayOfMonth();
int hour = dateTime.getHour();
int minute = dateTime.getMinute();
int second = dateTime.getSecond();
switch (trunc.toLowerCase()) {
case "year":
month = 0;
case "quarter": // CHECKSTYLE IGNORE THIS LINE
month = ((month - 1) / 3) * 3 + 1;
case "month": // CHECKSTYLE IGNORE THIS LINE
day = 1;
break;
case "week":
LocalDateTime firstDayOfWeek = firstDayOfWeek(dateTime);
year = firstDayOfWeek.getYear();
month = firstDayOfWeek.getMonthValue();
day = firstDayOfWeek.getDayOfMonth();
default: // CHECKSTYLE IGNORE THIS LINE
break;
}
switch (trunc.toLowerCase()) {
case "year":
case "quarter":
case "month":
case "week":
case "day": // CHECKSTYLE IGNORE THIS LINE
hour = 0;
case "hour": // CHECKSTYLE IGNORE THIS LINE
minute = 0;
case "minute": // CHECKSTYLE IGNORE THIS LINE
second = 0;
default: // CHECKSTYLE IGNORE THIS LINE
}
return LocalDateTime.of(year, month, day, hour, minute, second);
}
private static int distanceToFirstDayOfWeek(LocalDateTime dateTime) {
return dateTime.getDayOfWeek().getValue() - 1;
}
private static LocalDateTime firstDayOfWeek(LocalDateTime dateTime) {
return dateTime.plusDays(-distanceToFirstDayOfWeek(dateTime));
}
private static LocalDateTime toMonday(LocalDateTime dateTime) {
LocalDateTime specialUpperBound = LocalDateTime.of(1970, 1, 4, 0, 0, 0);
LocalDateTime specialLowerBound = LocalDateTime.of(1970, 1, 1, 0, 0, 0);