This is an automated email from the ASF dual-hosted git repository.
morrysnow pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/master by this push:
new 469b6b8466 [enhancement](Nereids) datetime v2 type precision derive
(#17079)
469b6b8466 is described below
commit 469b6b846682105f6cc8b5510e2896fbf5e6b232
Author: morrySnow <[email protected]>
AuthorDate: Sun Feb 26 22:33:55 2023 +0800
[enhancement](Nereids) datetime v2 type precision derive (#17079)
---
.../trees/expressions/TimestampArithmetic.java | 26 +--
.../expressions/functions/ComputeSignature.java | 18 +-
.../trees/expressions/literal/DateLiteral.java | 56 ++++--
.../trees/expressions/literal/DateTimeLiteral.java | 200 ++++++++++++++++-----
.../expressions/literal/DateTimeV2Literal.java | 59 +++---
.../trees/expressions/literal/DateV2Literal.java | 15 +-
.../apache/doris/nereids/types/DateTimeV2Type.java | 1 +
.../org/apache/doris/nereids/util/DateUtils.java | 86 +++++----
.../doris/nereids/util/TypeCoercionUtils.java | 12 +-
.../expression/rewrite/ExpressionRewriteTest.java | 4 +-
.../test_timestamp_arithmetic.out | 4 +
.../test_timestamp_arithmetic.groovy | 32 ++++
12 files changed, 371 insertions(+), 142 deletions(-)
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/TimestampArithmetic.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/TimestampArithmetic.java
index b0c0a19b8f..1da77201c9 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/TimestampArithmetic.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/TimestampArithmetic.java
@@ -25,12 +25,11 @@ import
org.apache.doris.nereids.trees.expressions.shape.BinaryExpression;
import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor;
import org.apache.doris.nereids.types.DataType;
import org.apache.doris.nereids.types.DateTimeType;
+import org.apache.doris.nereids.types.DateTimeV2Type;
import org.apache.doris.nereids.types.DateType;
-import org.apache.doris.nereids.types.IntegerType;
-import org.apache.doris.nereids.types.coercion.AbstractDataType;
+import org.apache.doris.nereids.types.DateV2Type;
import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableList;
import java.util.List;
import java.util.Objects;
@@ -44,15 +43,6 @@ import java.util.Objects;
*/
public class TimestampArithmetic extends Expression implements
BinaryExpression, PropagateNullable {
- //the size and order of EXPECTED_INPUT_TYPES must follow the function
signature parameters
- //For example: days_sub('2000-01-01', interval 5 days),
- // '2000-01-01'->DateTimeType.INSTANCE
- // 5 -> IntegerType
- private static final List<AbstractDataType> EXPECTED_INPUT_TYPES =
ImmutableList.of(
- DateTimeType.INSTANCE,
- IntegerType.INSTANCE
- );
-
private final String funcName;
private final boolean intervalFirst;
private final Operator op;
@@ -98,7 +88,17 @@ public class TimestampArithmetic extends Expression
implements BinaryExpression,
if (intervalFirst) {
dateChildIndex = 1;
}
- if (child(dateChildIndex).getDataType() instanceof DateTimeType ||
timeUnit.isDateTimeUnit()) {
+ DataType childType = child(dateChildIndex).getDataType();
+ if (childType instanceof DateTimeV2Type) {
+ return childType;
+ }
+ if (childType instanceof DateV2Type) {
+ if (timeUnit.isDateTimeUnit()) {
+ return DateTimeV2Type.SYSTEM_DEFAULT;
+ }
+ return DateV2Type.INSTANCE;
+ }
+ if (childType instanceof DateTimeType || timeUnit.isDateTimeUnit()) {
return DateTimeType.INSTANCE;
} else {
return DateType.INSTANCE;
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/ComputeSignature.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/ComputeSignature.java
index 93d6d74928..5ed35349d1 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/ComputeSignature.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/ComputeSignature.java
@@ -19,9 +19,11 @@ package org.apache.doris.nereids.trees.expressions.functions;
import org.apache.doris.catalog.FunctionSignature;
import org.apache.doris.nereids.annotation.Developing;
+import org.apache.doris.nereids.trees.expressions.Expression;
import
org.apache.doris.nereids.trees.expressions.functions.ComputeSignatureHelper.ComputeSignatureChain;
import
org.apache.doris.nereids.trees.expressions.typecoercion.ImplicitCastInputTypes;
import org.apache.doris.nereids.types.DataType;
+import org.apache.doris.nereids.types.DateTimeV2Type;
import org.apache.doris.nereids.types.coercion.AbstractDataType;
import com.google.common.collect.ImmutableList;
@@ -88,7 +90,21 @@ public interface ComputeSignature extends FunctionTrait,
ImplicitCastInputTypes
*/
@Override
default DataType getDataType() {
- return (DataType) getSignature().returnType;
+ DataType returnType = (DataType) getSignature().returnType;
+
+ // datetime v2 type precision derive
+ if (returnType instanceof DateTimeV2Type) {
+ for (Expression argument : getArguments()) {
+ if (argument.getDataType() instanceof DateTimeV2Type) {
+ DateTimeV2Type argType = (DateTimeV2Type)
argument.getDataType();
+ if (((DateTimeV2Type) returnType).getScale() <
argType.getScale()) {
+ returnType = argType;
+ }
+ }
+ }
+ }
+
+ return returnType;
}
@Override
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateLiteral.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateLiteral.java
index e7ff6d9327..a56ce591d3 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateLiteral.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateLiteral.java
@@ -28,8 +28,12 @@ import org.apache.doris.nereids.util.DateUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
-import org.joda.time.LocalDateTime;
-import org.joda.time.format.DateTimeFormatter;
+
+import java.time.LocalDateTime;
+import java.time.Year;
+import java.time.format.DateTimeFormatter;
+import java.time.temporal.ChronoField;
+import java.time.temporal.TemporalAccessor;
/**
* Date literal in Nereids.
@@ -41,6 +45,10 @@ public class DateLiteral extends Literal {
protected static DateTimeFormatter DATEKEY_FORMATTER = null;
private static final Logger LOG = LogManager.getLogger(DateLiteral.class);
+
+ private static final DateLiteral MIN_DATE = new DateLiteral(0000, 1, 1);
+ private static final DateLiteral MAX_DATE = new DateLiteral(9999, 12, 31);
+ private static final int[] DAYS_IN_MONTH = new int[] {0, 31, 28, 31, 30,
31, 30, 31, 31, 30, 31, 30, 31};
private static final int DATEKEY_LENGTH = 8;
protected long year;
@@ -100,20 +108,38 @@ public class DateLiteral extends Literal {
protected void init(String s) throws AnalysisException {
try {
- LocalDateTime dateTime;
+ TemporalAccessor dateTime;
if (s.split("-")[0].length() == 2) {
- dateTime = DATE_FORMATTER_TWO_DIGIT.parseLocalDateTime(s);
+ dateTime = DATE_FORMATTER_TWO_DIGIT.parse(s);
} else if (s.length() == DATEKEY_LENGTH && !s.contains("-")) {
- dateTime = DATEKEY_FORMATTER.parseLocalDateTime(s);
+ dateTime = DATEKEY_FORMATTER.parse(s);
} else {
- dateTime = DATE_FORMATTER.parseLocalDateTime(s);
+ dateTime = DATE_FORMATTER.parse(s);
}
- year = dateTime.getYear();
- month = dateTime.getMonthOfYear();
- day = dateTime.getDayOfMonth();
+ year = DateUtils.getOrDefault(dateTime, ChronoField.YEAR);
+ month = DateUtils.getOrDefault(dateTime,
ChronoField.MONTH_OF_YEAR);
+ day = DateUtils.getOrDefault(dateTime, ChronoField.DAY_OF_MONTH);
} catch (Exception ex) {
throw new AnalysisException("date literal [" + s + "] is invalid");
}
+
+ if (checkRange() || checkDate()) {
+ throw new AnalysisException("date literal [" + s + "] is out of
range");
+ }
+ }
+
+ protected boolean checkRange() {
+ return year > MAX_DATE.getYear() || month > MAX_DATE.getMonth() || day
> MAX_DATE.getDay();
+ }
+
+ protected boolean checkDate() {
+ if (month != 0 && day > DAYS_IN_MONTH[((int) month)]) {
+ if (month == 2 && day == 29 && Year.isLeap(year)) {
+ return false;
+ }
+ return true;
+ }
+ return false;
}
@Override
@@ -159,18 +185,18 @@ public class DateLiteral extends Literal {
}
public DateLiteral plusDays(int days) {
- LocalDateTime dateTime = LocalDateTime.parse(getStringValue(),
DATE_FORMATTER).plusDays(days);
- return new DateLiteral(dateTime.getYear(), dateTime.getMonthOfYear(),
dateTime.getDayOfMonth());
+ LocalDateTime dateTime = DateUtils.getTime(DATE_FORMATTER,
getStringValue()).plusDays(days);
+ return new DateLiteral(dateTime.getYear(), dateTime.getMonthValue(),
dateTime.getDayOfMonth());
}
public DateLiteral plusMonths(int months) {
- LocalDateTime dateTime = LocalDateTime.parse(getStringValue(),
DATE_FORMATTER).plusMonths(months);
- return new DateLiteral(dateTime.getYear(), dateTime.getMonthOfYear(),
dateTime.getDayOfMonth());
+ LocalDateTime dateTime = DateUtils.getTime(DATE_FORMATTER,
getStringValue()).plusMonths(months);
+ return new DateLiteral(dateTime.getYear(), dateTime.getMonthValue(),
dateTime.getDayOfMonth());
}
public DateLiteral plusYears(int years) {
- LocalDateTime dateTime = LocalDateTime.parse(getStringValue(),
DATE_FORMATTER).plusYears(years);
- return new DateLiteral(dateTime.getYear(), dateTime.getMonthOfYear(),
dateTime.getDayOfMonth());
+ LocalDateTime dateTime = DateUtils.getTime(DATE_FORMATTER,
getStringValue()).plusYears(years);
+ return new DateLiteral(dateTime.getYear(), dateTime.getMonthValue(),
dateTime.getDayOfMonth());
}
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateTimeLiteral.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateTimeLiteral.java
index a2211d5c8f..a0a9abbd81 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateTimeLiteral.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateTimeLiteral.java
@@ -25,11 +25,19 @@ import org.apache.doris.nereids.types.DateTimeType;
import org.apache.doris.nereids.types.coercion.DateLikeType;
import org.apache.doris.nereids.util.DateUtils;
+import com.google.common.collect.Lists;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
-import org.joda.time.LocalDateTime;
-import org.joda.time.format.DateTimeFormatter;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeFormatterBuilder;
+import java.time.format.DateTimeParseException;
+import java.time.format.ResolverStyle;
+import java.time.temporal.ChronoField;
+import java.time.temporal.TemporalAccessor;
+import java.util.Collections;
+import java.util.List;
import java.util.Objects;
/**
@@ -37,20 +45,24 @@ import java.util.Objects;
*/
public class DateTimeLiteral extends DateLiteral {
- protected static final int DATETIME_TO_MINUTE_STRING_LENGTH = 16;
- protected static final int DATETIME_TO_HOUR_STRING_LENGTH = 13;
- protected static final int DATETIME_DEFAULT_STRING_LENGTH = 10;
- protected static DateTimeFormatter DATE_TIME_DEFAULT_FORMATTER = null;
protected static DateTimeFormatter DATE_TIME_FORMATTER = null;
protected static DateTimeFormatter DATE_TIME_FORMATTER_TO_HOUR = null;
protected static DateTimeFormatter DATE_TIME_FORMATTER_TO_MINUTE = null;
protected static DateTimeFormatter DATE_TIME_FORMATTER_TWO_DIGIT = null;
+ protected static DateTimeFormatter DATETIMEKEY_FORMATTER = null;
+ protected static DateTimeFormatter DATE_TIME_FORMATTER_TO_MICRO_SECOND =
null;
+ protected static List<DateTimeFormatter> formatterList = null;
+
+ private static final DateTimeLiteral MIN_DATETIME = new
DateTimeLiteral(0000, 1, 1, 0, 0, 0);
+ private static final DateTimeLiteral MAX_DATETIME = new
DateTimeLiteral(9999, 12, 31, 23, 59, 59);
+ private static final int MAX_MICROSECOND = 999999;
private static final Logger LOG =
LogManager.getLogger(DateTimeLiteral.class);
protected long hour;
protected long minute;
protected long second;
+ protected long microSecond;
static {
try {
@@ -58,7 +70,24 @@ public class DateTimeLiteral extends DateLiteral {
DATE_TIME_FORMATTER_TO_HOUR = DateUtils.formatBuilder("%Y-%m-%d
%H").toFormatter();
DATE_TIME_FORMATTER_TO_MINUTE = DateUtils.formatBuilder("%Y-%m-%d
%H:%i").toFormatter();
DATE_TIME_FORMATTER_TWO_DIGIT = DateUtils.formatBuilder("%y-%m-%d
%H:%i:%s").toFormatter();
- DATE_TIME_DEFAULT_FORMATTER =
DateUtils.formatBuilder("%Y-%m-%d").toFormatter();
+
+ DATETIMEKEY_FORMATTER =
DateUtils.formatBuilder("%Y%m%d%H%i%s").toFormatter();
+
+ DATE_TIME_FORMATTER_TO_MICRO_SECOND = new
DateTimeFormatterBuilder()
+ .appendPattern("uuuu-MM-dd HH:mm:ss")
+ .appendFraction(ChronoField.MICRO_OF_SECOND, 0, 6, true)
+ .toFormatter();
+
+ formatterList = Lists.newArrayList(
+
DateUtils.formatBuilder("%Y%m%d").appendLiteral('T').appendPattern("HHmmss")
+ .appendFraction(ChronoField.MICRO_OF_SECOND, 0, 6,
true).toFormatter(),
+
DateUtils.formatBuilder("%Y%m%d").appendLiteral('T').appendPattern("HHmmss")
+ .appendFraction(ChronoField.MICRO_OF_SECOND, 0, 6,
false).toFormatter(),
+ DateUtils.formatBuilder("%Y%m%d%H%i%s")
+ .appendFraction(ChronoField.MICRO_OF_SECOND, 0, 6,
true).toFormatter(),
+ DateUtils.formatBuilder("%Y%m%d%H%i%s")
+ .appendFraction(ChronoField.MICRO_OF_SECOND, 0, 6,
false).toFormatter(),
+ DATETIMEKEY_FORMATTER, DATEKEY_FORMATTER);
} catch (AnalysisException e) {
LOG.error("invalid date format", e);
System.exit(-1);
@@ -86,10 +115,19 @@ public class DateTimeLiteral extends DateLiteral {
*/
public DateTimeLiteral(DateLikeType dataType, long year, long month, long
day,
long hour, long minute, long second) {
+ this(dataType, year, month, day, hour, minute, second, 0L);
+ }
+
+ /**
+ * C'tor data time literal.
+ */
+ public DateTimeLiteral(DateLikeType dataType, long year, long month, long
day,
+ long hour, long minute, long second, long microSecond) {
super(dataType);
this.hour = hour;
this.minute = minute;
this.second = second;
+ this.microSecond = microSecond;
this.year = year;
this.month = month;
this.day = day;
@@ -98,29 +136,105 @@ public class DateTimeLiteral extends DateLiteral {
@Override
protected void init(String s) throws AnalysisException {
try {
- LocalDateTime dateTime;
- if (s.split("-")[0].length() == 2) {
- dateTime = DATE_TIME_FORMATTER_TWO_DIGIT.parseLocalDateTime(s);
+ TemporalAccessor dateTime = null;
+ if (!s.contains("-")) {
+ // handle format like 20210106, but should not handle 2021-1-6
+ boolean parsed = false;
+ for (DateTimeFormatter formatter : formatterList) {
+ try {
+ dateTime = formatter.parse(s);
+ parsed = true;
+ break;
+ } catch (DateTimeParseException ex) {
+ // ignore
+ }
+ }
+ if (!parsed) {
+ throw new AnalysisException("datetime literal [" + s + "]
is invalid");
+ }
} else {
- if (s.length() == DATETIME_TO_MINUTE_STRING_LENGTH) {
- dateTime =
DATE_TIME_FORMATTER_TO_MINUTE.parseLocalDateTime(s);
- } else if (s.length() == DATETIME_TO_HOUR_STRING_LENGTH) {
- dateTime =
DATE_TIME_FORMATTER_TO_HOUR.parseLocalDateTime(s);
- } else if (s.length() == DATETIME_DEFAULT_STRING_LENGTH) {
- dateTime =
DATE_TIME_DEFAULT_FORMATTER.parseLocalDateTime(s);
- } else {
- dateTime = DATE_TIME_FORMATTER.parseLocalDateTime(s);
+ String[] datePart = s.contains(" ") ? s.split("
")[0].split("-") : s.split("-");
+ DateTimeFormatterBuilder builder = new
DateTimeFormatterBuilder();
+ if (datePart.length != 3) {
+ throw new AnalysisException("datetime literal [" + s + "]
is invalid");
+ }
+ for (int i = 0; i < datePart.length; i++) {
+ switch (i) {
+ case 0:
+ if (datePart[i].length() == 2) {
+ // If year is represented by two digits,
number bigger than 70 will be prefixed
+ // with 19 otherwise 20. e.g. 69 -> 2069, 70
-> 1970.
+ builder.appendValueReduced(ChronoField.YEAR,
2, 2, 1970);
+ } else {
+ builder.appendPattern(String.join("",
Collections.nCopies(datePart[i].length(), "u")));
+ }
+ break;
+ case 1:
+ builder.appendPattern(String.join("",
Collections.nCopies(datePart[i].length(), "M")));
+ break;
+ case 2:
+ builder.appendPattern(String.join("",
Collections.nCopies(datePart[i].length(), "d")));
+ break;
+ default:
+ throw new AnalysisException("two many parts in
date format " + s);
+ }
+ if (i < datePart.length - 1) {
+ builder.appendLiteral("-");
+ }
+ }
+ if (s.contains(" ")) {
+ builder.appendLiteral(" ");
}
+ String[] timePart = s.contains(" ") ? s.split("
")[1].split(":") : new String[]{};
+ for (int i = 0; i < timePart.length; i++) {
+ switch (i) {
+ case 0:
+ builder.appendPattern(String.join("",
Collections.nCopies(timePart[i].length(), "H")));
+ break;
+ case 1:
+ builder.appendPattern(String.join("",
Collections.nCopies(timePart[i].length(), "m")));
+ break;
+ case 2:
+ builder.appendPattern(String.join("",
Collections.nCopies(timePart[i].contains(".")
+ ? timePart[i].split("\\.")[0].length() :
timePart[i].length(), "s")));
+ if (timePart[i].contains(".")) {
+
builder.appendFraction(ChronoField.MICRO_OF_SECOND, 0, 6, true);
+ }
+ break;
+ default:
+ throw new AnalysisException("too many parts in
time format " + s);
+ }
+ if (i < timePart.length - 1) {
+ builder.appendLiteral(":");
+ }
+ }
+ // The default resolver style is 'SMART', which parses
"2022-06-31" as "2022-06-30"
+ // and does not throw an exception. 'STRICT' is used here.
+ DateTimeFormatter formatter =
builder.toFormatter().withResolverStyle(ResolverStyle.STRICT);
+ dateTime = formatter.parse(s);
}
- year = dateTime.getYear();
- month = dateTime.getMonthOfYear();
- day = dateTime.getDayOfMonth();
- hour = dateTime.getHourOfDay();
- minute = dateTime.getMinuteOfHour();
- second = dateTime.getSecondOfMinute();
+
+ year = DateUtils.getOrDefault(dateTime, ChronoField.YEAR);
+ month = DateUtils.getOrDefault(dateTime,
ChronoField.MONTH_OF_YEAR);
+ day = DateUtils.getOrDefault(dateTime, ChronoField.DAY_OF_MONTH);
+ hour = DateUtils.getOrDefault(dateTime, ChronoField.HOUR_OF_DAY);
+ minute = DateUtils.getOrDefault(dateTime,
ChronoField.MINUTE_OF_HOUR);
+ second = DateUtils.getOrDefault(dateTime,
ChronoField.SECOND_OF_MINUTE);
+ microSecond = DateUtils.getOrDefault(dateTime,
ChronoField.MICRO_OF_SECOND);
+
} catch (Exception ex) {
- throw new AnalysisException("date time literal [" + s + "] is
invalid");
+ throw new AnalysisException("datetime literal [" + s + "] is
invalid");
}
+
+ if (checkRange() || checkDate()) {
+ throw new AnalysisException("datetime literal [" + s + "] is out
of range");
+ }
+ }
+
+ @Override
+ protected boolean checkRange() {
+ return super.checkRange() || hour > MAX_DATETIME.getHour() || minute >
MAX_DATETIME.getMinute()
+ || second > MAX_DATETIME.getSecond() || microSecond >
MAX_MICROSECOND;
}
@Override
@@ -154,39 +268,39 @@ public class DateTimeLiteral extends DateLiteral {
}
public DateTimeLiteral plusDays(int days) {
- LocalDateTime d = LocalDateTime.parse(getStringValue(),
DATE_TIME_FORMATTER).plusDays(days);
- return new DateTimeLiteral(d.getYear(), d.getMonthOfYear(),
d.getDayOfMonth(),
- d.getHourOfDay(), d.getMinuteOfHour(), d.getSecondOfMinute());
+ LocalDateTime d = DateUtils.getTime(DATE_TIME_FORMATTER,
getStringValue()).plusDays(days);
+ return new DateTimeLiteral(d.getYear(), d.getMonthValue(),
d.getDayOfMonth(),
+ d.getHour(), d.getMinute(), d.getSecond());
}
public DateTimeLiteral plusYears(int years) {
- LocalDateTime d = LocalDateTime.parse(getStringValue(),
DATE_TIME_FORMATTER).plusYears(years);
- return new DateTimeLiteral(d.getYear(), d.getMonthOfYear(),
d.getDayOfMonth(),
- d.getHourOfDay(), d.getMinuteOfHour(), d.getSecondOfMinute());
+ LocalDateTime d = DateUtils.getTime(DATE_TIME_FORMATTER,
getStringValue()).plusYears(years);
+ return new DateTimeLiteral(d.getYear(), d.getMonthValue(),
d.getDayOfMonth(),
+ d.getHour(), d.getMinute(), d.getSecond());
}
public DateTimeLiteral plusMonths(int months) {
- LocalDateTime d = LocalDateTime.parse(getStringValue(),
DATE_TIME_FORMATTER).plusMonths(months);
- return new DateTimeLiteral(d.getYear(), d.getMonthOfYear(),
d.getDayOfMonth(),
- d.getHourOfDay(), d.getMinuteOfHour(), d.getSecondOfMinute());
+ LocalDateTime d = DateUtils.getTime(DATE_TIME_FORMATTER,
getStringValue()).plusMonths(months);
+ return new DateTimeLiteral(d.getYear(), d.getMonthValue(),
d.getDayOfMonth(),
+ d.getHour(), d.getMinute(), d.getSecond());
}
public DateTimeLiteral plusHours(int hours) {
- LocalDateTime d = LocalDateTime.parse(getStringValue(),
DATE_TIME_FORMATTER).plusHours(hours);
- return new DateTimeLiteral(d.getYear(), d.getMonthOfYear(),
d.getDayOfMonth(),
- d.getHourOfDay(), d.getMinuteOfHour(), d.getSecondOfMinute());
+ LocalDateTime d = DateUtils.getTime(DATE_TIME_FORMATTER,
getStringValue()).plusHours(hours);
+ return new DateTimeLiteral(d.getYear(), d.getMonthValue(),
d.getDayOfMonth(),
+ d.getHour(), d.getMinute(), d.getSecond());
}
public DateTimeLiteral plusMinutes(int minutes) {
- LocalDateTime d = LocalDateTime.parse(getStringValue(),
DATE_TIME_FORMATTER).plusMinutes(minutes);
- return new DateTimeLiteral(d.getYear(), d.getMonthOfYear(),
d.getDayOfMonth(),
- d.getHourOfDay(), d.getMinuteOfHour(), d.getSecondOfMinute());
+ LocalDateTime d = DateUtils.getTime(DATE_TIME_FORMATTER,
getStringValue()).plusMinutes(minutes);
+ return new DateTimeLiteral(d.getYear(), d.getMonthValue(),
d.getDayOfMonth(),
+ d.getHour(), d.getMinute(), d.getSecond());
}
public DateTimeLiteral plusSeconds(int seconds) {
- LocalDateTime d = LocalDateTime.parse(getStringValue(),
DATE_TIME_FORMATTER).plusSeconds(seconds);
- return new DateTimeLiteral(d.getYear(), d.getMonthOfYear(),
d.getDayOfMonth(),
- d.getHourOfDay(), d.getMinuteOfHour(), d.getSecondOfMinute());
+ LocalDateTime d = DateUtils.getTime(DATE_TIME_FORMATTER,
getStringValue()).plusSeconds(seconds);
+ return new DateTimeLiteral(d.getYear(), d.getMonthValue(),
d.getDayOfMonth(),
+ d.getHour(), d.getMinute(), d.getSecond());
}
public long getHour() {
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateTimeV2Literal.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateTimeV2Literal.java
index b611016c93..1ddfef835e 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateTimeV2Literal.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateTimeV2Literal.java
@@ -19,8 +19,9 @@ package org.apache.doris.nereids.trees.expressions.literal;
import org.apache.doris.nereids.exceptions.UnboundException;
import org.apache.doris.nereids.types.DateTimeV2Type;
+import org.apache.doris.nereids.util.DateUtils;
-import org.joda.time.LocalDateTime;
+import java.time.LocalDateTime;
/**
* date time v2 literal for nereids
@@ -28,16 +29,16 @@ import org.joda.time.LocalDateTime;
public class DateTimeV2Literal extends DateTimeLiteral {
public DateTimeV2Literal(String s) {
- super(DateTimeV2Type.SYSTEM_DEFAULT, s);
+ super(DateTimeV2Type.MAX, s);
}
- public DateTimeV2Literal(long year, long month, long day, long hour, long
minute, long second) {
- super(DateTimeV2Type.SYSTEM_DEFAULT, year, month, day, hour, minute,
second);
+ public DateTimeV2Literal(long year, long month, long day, long hour, long
minute, long second, long microSecond) {
+ super(DateTimeV2Type.SYSTEM_DEFAULT, year, month, day, hour, minute,
second, microSecond);
}
public DateTimeV2Literal(DateTimeV2Type dataType,
- long year, long month, long day, long hour, long minute, long
second) {
- super(dataType, year, month, day, hour, minute, second);
+ long year, long month, long day, long hour, long minute, long
second, long microSecond) {
+ super(dataType, year, month, day, hour, minute, second, microSecond);
}
@Override
@@ -45,45 +46,55 @@ public class DateTimeV2Literal extends DateTimeLiteral {
return (DateTimeV2Type) super.getDataType();
}
+ @Override
+ public String toString() {
+ return String.format("%04d-%02d-%02d %02d:%02d:%02d.%06d", year,
month, day, hour, minute, second, microSecond);
+ }
+
+ @Override
+ public String getStringValue() {
+ return String.format("%04d-%02d-%02d %02d:%02d:%02d.%06d", year,
month, day, hour, minute, second, microSecond);
+ }
+
@Override
public DateTimeV2Literal plusYears(int years) {
- LocalDateTime d = LocalDateTime.parse(getStringValue(),
DATE_TIME_FORMATTER).plusYears(years);
- return new DateTimeV2Literal(this.getDataType(), d.getYear(),
d.getMonthOfYear(), d.getDayOfMonth(),
- d.getHourOfDay(), d.getMinuteOfHour(), d.getSecondOfMinute());
+ LocalDateTime d =
DateUtils.getTime(DATE_TIME_FORMATTER_TO_MICRO_SECOND,
getStringValue()).plusYears(years);
+ return new DateTimeV2Literal(this.getDataType(), d.getYear(),
d.getMonthValue(), d.getDayOfMonth(),
+ d.getHour(), d.getMinute(), d.getSecond(), d.getNano() /
1000L);
}
@Override
public DateTimeV2Literal plusMonths(int months) {
- LocalDateTime d = LocalDateTime.parse(getStringValue(),
DATE_TIME_FORMATTER).plusMonths(months);
- return new DateTimeV2Literal(this.getDataType(), d.getYear(),
d.getMonthOfYear(), d.getDayOfMonth(),
- d.getHourOfDay(), d.getMinuteOfHour(), d.getSecondOfMinute());
+ LocalDateTime d =
DateUtils.getTime(DATE_TIME_FORMATTER_TO_MICRO_SECOND,
getStringValue()).plusMonths(months);
+ return new DateTimeV2Literal(this.getDataType(), d.getYear(),
d.getMonthValue(), d.getDayOfMonth(),
+ d.getHour(), d.getMinute(), d.getSecond(), d.getNano() /
1000L);
}
@Override
public DateTimeV2Literal plusDays(int days) {
- LocalDateTime d = LocalDateTime.parse(getStringValue(),
DATE_TIME_FORMATTER).plusDays(days);
- return new DateTimeV2Literal(this.getDataType(), d.getYear(),
d.getMonthOfYear(), d.getDayOfMonth(),
- d.getHourOfDay(), d.getMinuteOfHour(), d.getSecondOfMinute());
+ LocalDateTime d =
DateUtils.getTime(DATE_TIME_FORMATTER_TO_MICRO_SECOND,
getStringValue()).plusDays(days);
+ return new DateTimeV2Literal(this.getDataType(), d.getYear(),
d.getMonthValue(), d.getDayOfMonth(),
+ d.getHour(), d.getMinute(), d.getSecond(), d.getNano() /
1000L);
}
@Override
public DateTimeV2Literal plusHours(int hours) {
- LocalDateTime d = LocalDateTime.parse(getStringValue(),
DATE_TIME_FORMATTER).plusHours(hours);
- return new DateTimeV2Literal(this.getDataType(), d.getYear(),
d.getMonthOfYear(), d.getDayOfMonth(),
- d.getHourOfDay(), d.getMinuteOfHour(), d.getSecondOfMinute());
+ LocalDateTime d =
DateUtils.getTime(DATE_TIME_FORMATTER_TO_MICRO_SECOND,
getStringValue()).plusHours(hours);
+ return new DateTimeV2Literal(this.getDataType(), d.getYear(),
d.getMonthValue(), d.getDayOfMonth(),
+ d.getHour(), d.getMinute(), d.getSecond(), d.getNano() /
1000L);
}
@Override
public DateTimeV2Literal plusMinutes(int minutes) {
- LocalDateTime d = LocalDateTime.parse(getStringValue(),
DATE_TIME_FORMATTER).plusMinutes(minutes);
- return new DateTimeV2Literal(this.getDataType(), d.getYear(),
d.getMonthOfYear(), d.getDayOfMonth(),
- d.getHourOfDay(), d.getMinuteOfHour(), d.getSecondOfMinute());
+ LocalDateTime d =
DateUtils.getTime(DATE_TIME_FORMATTER_TO_MICRO_SECOND,
getStringValue()).plusMinutes(minutes);
+ return new DateTimeV2Literal(this.getDataType(), d.getYear(),
d.getMonthValue(), d.getDayOfMonth(),
+ d.getHour(), d.getMinute(), d.getSecond(), d.getNano() /
1000L);
}
@Override
public DateTimeV2Literal plusSeconds(int seconds) {
- LocalDateTime d = LocalDateTime.parse(getStringValue(),
DATE_TIME_FORMATTER).plusSeconds(seconds);
- return new DateTimeV2Literal(this.getDataType(), d.getYear(),
d.getMonthOfYear(), d.getDayOfMonth(),
- d.getHourOfDay(), d.getMinuteOfHour(), d.getSecondOfMinute());
+ LocalDateTime d =
DateUtils.getTime(DATE_TIME_FORMATTER_TO_MICRO_SECOND,
getStringValue()).plusSeconds(seconds);
+ return new DateTimeV2Literal(this.getDataType(), d.getYear(),
d.getMonthValue(), d.getDayOfMonth(),
+ d.getHour(), d.getMinute(), d.getSecond(), d.getNano() /
1000L);
}
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateV2Literal.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateV2Literal.java
index d40af8031e..f70454a942 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateV2Literal.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateV2Literal.java
@@ -21,8 +21,9 @@ import org.apache.doris.analysis.LiteralExpr;
import org.apache.doris.catalog.Type;
import org.apache.doris.nereids.exceptions.AnalysisException;
import org.apache.doris.nereids.types.DateV2Type;
+import org.apache.doris.nereids.util.DateUtils;
-import org.joda.time.LocalDateTime;
+import java.time.LocalDateTime;
/**
* date v2 literal for nereids
@@ -43,17 +44,17 @@ public class DateV2Literal extends DateLiteral {
}
public DateV2Literal plusDays(int days) {
- LocalDateTime dateTime = LocalDateTime.parse(getStringValue(),
DATE_FORMATTER).plusDays(days);
- return new DateV2Literal(dateTime.getYear(),
dateTime.getMonthOfYear(), dateTime.getDayOfMonth());
+ LocalDateTime dateTime = DateUtils.getTime(DATE_FORMATTER,
getStringValue()).plusDays(days);
+ return new DateV2Literal(dateTime.getYear(), dateTime.getMonthValue(),
dateTime.getDayOfMonth());
}
public DateV2Literal plusMonths(int months) {
- LocalDateTime dateTime = LocalDateTime.parse(getStringValue(),
DATE_FORMATTER).plusMonths(months);
- return new DateV2Literal(dateTime.getYear(),
dateTime.getMonthOfYear(), dateTime.getDayOfMonth());
+ LocalDateTime dateTime = DateUtils.getTime(DATE_FORMATTER,
getStringValue()).plusMonths(months);
+ return new DateV2Literal(dateTime.getYear(), dateTime.getMonthValue(),
dateTime.getDayOfMonth());
}
public DateV2Literal plusYears(int years) {
- LocalDateTime dateTime = LocalDateTime.parse(getStringValue(),
DATE_FORMATTER).plusYears(years);
- return new DateV2Literal(dateTime.getYear(),
dateTime.getMonthOfYear(), dateTime.getDayOfMonth());
+ LocalDateTime dateTime = DateUtils.getTime(DATE_FORMATTER,
getStringValue()).plusYears(years);
+ return new DateV2Literal(dateTime.getYear(), dateTime.getMonthValue(),
dateTime.getDayOfMonth());
}
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DateTimeV2Type.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DateTimeV2Type.java
index 51c604e2e8..b046df7c9f 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DateTimeV2Type.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DateTimeV2Type.java
@@ -33,6 +33,7 @@ import java.util.Objects;
public class DateTimeV2Type extends DateLikeType {
public static final int MAX_SCALE = 6;
public static final DateTimeV2Type SYSTEM_DEFAULT = new DateTimeV2Type(0);
+ public static final DateTimeV2Type MAX = new DateTimeV2Type(MAX_SCALE);
private static final int WIDTH = 8;
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/util/DateUtils.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/util/DateUtils.java
index 6228fe8ef8..06da317dee 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/util/DateUtils.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/util/DateUtils.java
@@ -19,7 +19,12 @@ package org.apache.doris.nereids.util;
import org.apache.doris.nereids.exceptions.AnalysisException;
-import org.joda.time.format.DateTimeFormatterBuilder;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeFormatterBuilder;
+import java.time.format.TextStyle;
+import java.time.temporal.ChronoField;
+import java.time.temporal.TemporalAccessor;
/**
* date util tools.
@@ -37,84 +42,75 @@ public class DateUtils {
if (escaped) {
switch (character) {
case 'a': // %a Abbreviated weekday name (Sun..Sat)
- builder.appendDayOfWeekShortText();
+ builder.appendText(ChronoField.DAY_OF_WEEK,
TextStyle.SHORT);
break;
case 'b': // %b Abbreviated month name (Jan..Dec)
- builder.appendMonthOfYearShortText();
+ builder.appendText(ChronoField.MONTH_OF_YEAR,
TextStyle.SHORT);
break;
case 'c': // %c Month, numeric (0..12)
- builder.appendMonthOfYear(1);
+ builder.appendValue(ChronoField.MONTH_OF_YEAR);
break;
case 'd': // %d Day of the month, numeric (00..31)
- builder.appendDayOfMonth(2);
+ builder.appendValue(ChronoField.DAY_OF_MONTH, 2);
break;
case 'e': // %e Day of the month, numeric (0..31)
- builder.appendDayOfMonth(1);
+ builder.appendValue(ChronoField.DAY_OF_MONTH);
break;
case 'H': // %H Hour (00..23)
- builder.appendHourOfDay(2);
+ builder.appendValue(ChronoField.HOUR_OF_DAY, 2);
break;
case 'h': // %h Hour (01..12)
case 'I': // %I Hour (01..12)
- builder.appendClockhourOfHalfday(2);
+ builder.appendValue(ChronoField.HOUR_OF_AMPM, 2);
break;
case 'i': // %i Minutes, numeric (00..59)
- builder.appendMinuteOfHour(2);
+ builder.appendValue(ChronoField.MINUTE_OF_HOUR, 2);
break;
case 'j': // %j Day of year (001..366)
- builder.appendDayOfYear(3);
+ builder.appendValue(ChronoField.DAY_OF_YEAR, 3);
break;
case 'k': // %k Hour (0..23)
- builder.appendHourOfDay(1);
+ builder.appendValue(ChronoField.HOUR_OF_DAY);
break;
case 'l': // %l Hour (1..12)
- builder.appendClockhourOfHalfday(1);
+ builder.appendValue(ChronoField.HOUR_OF_AMPM);
break;
case 'M': // %M Month name (January..December)
- builder.appendMonthOfYearText();
+ builder.appendText(ChronoField.MONTH_OF_YEAR,
TextStyle.FULL);
break;
case 'm': // %m Month, numeric (00..12)
- builder.appendMonthOfYear(2);
+ builder.appendValue(ChronoField.MONTH_OF_YEAR, 2);
break;
case 'p': // %p AM or PM
- builder.appendHalfdayOfDayText();
+ builder.appendText(ChronoField.AMPM_OF_DAY);
break;
case 'r': // %r Time, 12-hour (hh:mm:ss followed by AM or
PM)
- builder.appendClockhourOfHalfday(2)
- .appendLiteral(':')
- .appendMinuteOfHour(2)
- .appendLiteral(':')
- .appendSecondOfMinute(2)
- .appendLiteral(' ')
- .appendHalfdayOfDayText();
+ builder.appendValue(ChronoField.HOUR_OF_AMPM, 2)
+ .appendPattern(":mm:ss ")
+ .appendText(ChronoField.AMPM_OF_DAY,
TextStyle.FULL)
+ .toFormatter();
break;
case 'S': // %S Seconds (00..59)
case 's': // %s Seconds (00..59)
- builder.appendSecondOfMinute(2);
+ builder.appendValue(ChronoField.SECOND_OF_MINUTE, 2);
break;
case 'T': // %T Time, 24-hour (hh:mm:ss)
- builder.appendHourOfDay(2)
- .appendLiteral(':')
- .appendMinuteOfHour(2)
- .appendLiteral(':')
- .appendSecondOfMinute(2);
+ builder.appendPattern("HH:mm:ss");
break;
case 'v': // %v Week (01..53), where Monday is the first
day of the week; used with %x
- builder.appendWeekOfWeekyear(2);
+ builder.appendValue(ChronoField.ALIGNED_WEEK_OF_YEAR,
2);
break;
case 'x':
+ case 'Y': // %Y Year, numeric, four digits
// %x Year for the week, where Monday is the first day
of the week,
// numeric, four digits; used with %v
- builder.appendWeekyear(4, 4);
+ builder.appendValue(ChronoField.YEAR, 4);
break;
case 'W': // %W Weekday name (Sunday..Saturday)
- builder.appendDayOfWeekText();
- break;
- case 'Y': // %Y Year, numeric, four digits
- builder.appendYear(4, 4);
+ builder.appendText(ChronoField.DAY_OF_WEEK,
TextStyle.FULL);
break;
case 'y': // %y Year, numeric (two digits)
- builder.appendTwoDigitYear(2020);
+ builder.appendValueReduced(ChronoField.YEAR, 2, 2,
1970);
break;
// TODO(Gabriel): support microseconds in date literal
case 'f': // %f Microseconds (000000..999999)
@@ -143,4 +139,24 @@ public class DateUtils {
}
return builder;
}
+
+ /**
+ * construct local date time from string
+ */
+ public static LocalDateTime getTime(DateTimeFormatter formatter, String
value) {
+ TemporalAccessor accessor = formatter.parse(value);
+ return LocalDateTime.of(
+ getOrDefault(accessor, ChronoField.YEAR),
+ getOrDefault(accessor, ChronoField.MONTH_OF_YEAR),
+ getOrDefault(accessor, ChronoField.DAY_OF_MONTH),
+ getOrDefault(accessor, ChronoField.HOUR_OF_DAY),
+ getOrDefault(accessor, ChronoField.MINUTE_OF_HOUR),
+ getOrDefault(accessor, ChronoField.SECOND_OF_MINUTE),
+ getOrDefault(accessor, ChronoField.MICRO_OF_SECOND)
+ );
+ }
+
+ public static int getOrDefault(final TemporalAccessor accessor, final
ChronoField field) {
+ return accessor.isSupported(field) ? accessor.get(field) : /*default
value*/ 0;
+ }
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/util/TypeCoercionUtils.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/util/TypeCoercionUtils.java
index c29a88aa38..0f75e5537e 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/util/TypeCoercionUtils.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/util/TypeCoercionUtils.java
@@ -612,9 +612,17 @@ public class TypeCoercionUtils {
if (leftType.isDateTimeV2Type() && rightType.isDateTimeV2Type()) {
return DateTimeV2Type.getWiderDatetimeV2Type((DateTimeV2Type)
leftType, (DateTimeV2Type) rightType);
} else if (leftType.isDateTimeV2Type()) {
- return leftType;
+ if (rightType.isIntegerLikeType()) {
+ return leftType;
+ } else {
+ return DateTimeV2Type.MAX;
+ }
} else if (rightType.isDateTimeV2Type()) {
- return rightType;
+ if (rightType.isIntegerLikeType()) {
+ return rightType;
+ } else {
+ return DateTimeV2Type.MAX;
+ }
} else if (leftType.isDateV2Type() && (rightType.isDateType() ||
rightType.isDateV2Type())) {
return leftType;
} else if (rightType.isDateV2Type() && (leftType.isDateType() ||
leftType.isDateV2Type())) {
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/rewrite/ExpressionRewriteTest.java
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/rewrite/ExpressionRewriteTest.java
index 32e7e0b394..a55659dbaa 100644
---
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/rewrite/ExpressionRewriteTest.java
+++
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/rewrite/ExpressionRewriteTest.java
@@ -228,7 +228,7 @@ public class ExpressionRewriteTest extends
ExpressionRewriteTestHelper {
public void testSimplifyComparisonPredicateRule() {
executor = new
ExpressionRuleExecutor(ImmutableList.of(SimplifyComparisonPredicate.INSTANCE));
- Expression dtv2 = new DateTimeV2Literal(1, 1, 1, 1, 1, 1);
+ Expression dtv2 = new DateTimeV2Literal(1, 1, 1, 1, 1, 1, 0);
Expression dt = new DateTimeLiteral(1, 1, 1, 1, 1, 1);
Expression dtNoTime = new DateTimeLiteral(1, 1, 1, 0, 0, 0);
Expression dv2 = new DateV2Literal(1, 1, 1);
@@ -291,7 +291,7 @@ public class ExpressionRewriteTest extends
ExpressionRewriteTestHelper {
new GreaterThan(new Cast(d, DateTimeType.INSTANCE), dtNoTime));
// test hour, minute and second all zero
- Expression dtv2AtZeroClock = new DateTimeV2Literal(1, 1, 1, 0, 0, 0);
+ Expression dtv2AtZeroClock = new DateTimeV2Literal(1, 1, 1, 0, 0, 0,
0);
assertRewrite(
new GreaterThan(new Cast(dv2, DateTimeV2Type.SYSTEM_DEFAULT),
dtv2AtZeroClock),
new GreaterThan(dv2, dv2));
diff --git
a/regression-test/data/nereids_syntax_p0/test_timestamp_arithmetic.out
b/regression-test/data/nereids_syntax_p0/test_timestamp_arithmetic.out
new file mode 100644
index 0000000000..521083445d
--- /dev/null
+++ b/regression-test/data/nereids_syntax_p0/test_timestamp_arithmetic.out
@@ -0,0 +1,4 @@
+-- This file is automatically generated. You should know what you did if you
want to edit this
+-- !test_add --
+0001-01-02 0001-01-01T00:00:01 0001-01-02T00:01:01
0001-01-02T00:01:01.001 0001-01-02T00:01:01.003050
+
diff --git
a/regression-test/suites/nereids_syntax_p0/test_timestamp_arithmetic.groovy
b/regression-test/suites/nereids_syntax_p0/test_timestamp_arithmetic.groovy
index a3e1c04511..46bb27fe42 100644
--- a/regression-test/suites/nereids_syntax_p0/test_timestamp_arithmetic.groovy
+++ b/regression-test/suites/nereids_syntax_p0/test_timestamp_arithmetic.groovy
@@ -29,4 +29,36 @@ suite("nereids_timestamp_arithmetic") {
sql = "select date '20200808' + interval array() day;"
exception = "the second argument must be a scalar type. but it is
array()"
}
+
+ sql """
+ DROP TABLE IF EXISTS nereids_test_ta;
+ """
+ sql """
+ CREATE TABLE `nereids_test_ta` (
+ `c1` int(11) NULL,
+ `c2` date NULL,
+ `c3` datev2 NULL,
+ `c4` datetime NULL,
+ `c5` datetimev2(3) NULL,
+ `c6` datetimev2(5) NULL
+ ) ENGINE=OLAP
+ DUPLICATE KEY(`c1`, `c2`, `c3`)
+ COMMENT 'OLAP'
+ DISTRIBUTED BY HASH(`c1`) BUCKETS 10
+ PROPERTIES (
+ "replication_allocation" = "tag.location.default: 1",
+ "in_memory" = "false",
+ "storage_format" = "V2",
+ "light_schema_change" = "true",
+ "disable_auto_compaction" = "false"
+ );
+ """
+
+ sql """
+ INSERT INTO nereids_test_ta VALUES (1, '0001-01-01', '0001-01-01',
'0001-01-01 00:01:01', '0001-01-01: 00:01:01.001', '0001-01-01 00:01:01.00305');
+ """
+
+ qt_test_add """
+ SELECT c2 + INTERVAL 1 DAY, c3 + INTERVAL 1 SECOND, c4 + INTERVAL 1
DAY, c5 + INTERVAL 1 DAY, c6 + INTERVAL 1 DAY FROM nereids_test_ta
+ """
}
\ No newline at end of file
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]