diff --git a/fe/fe-core/src/main/cup/sql_parser.cup b/fe/fe-core/src/main/cup/sql_parser.cup index 53ccf909becad2..58289ea2fd5747 100644 --- a/fe/fe-core/src/main/cup/sql_parser.cup +++ b/fe/fe-core/src/main/cup/sql_parser.cup @@ -4599,11 +4599,15 @@ type ::= | KW_DOUBLE {: RESULT = Type.DOUBLE; :} | KW_DATE - {: RESULT = Type.DATE; :} + {: RESULT = ScalarType.createDateType(); :} + | KW_DATETIME LPAREN INTEGER_LITERAL:precision RPAREN + {: RESULT = ScalarType.createDatetimeV2Type(precision.intValue()); :} | KW_DATETIME - {: RESULT = Type.DATETIME; :} + {: RESULT = ScalarType.createDatetimeType(); :} + | KW_TIME LPAREN INTEGER_LITERAL:precision RPAREN + {: RESULT = ScalarType.createTimeV2Type(precision.intValue()); :} | KW_TIME - {: RESULT = Type.TIME; :} + {: RESULT = ScalarType.createTimeType(); :} | KW_BITMAP {: RESULT = Type.BITMAP; :} | KW_QUANTILE_STATE diff --git a/fe/fe-core/src/main/java/org/apache/doris/alter/Alter.java b/fe/fe-core/src/main/java/org/apache/doris/alter/Alter.java index d64440713acd1a..4545b55cd03b08 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/alter/Alter.java +++ b/fe/fe-core/src/main/java/org/apache/doris/alter/Alter.java @@ -55,6 +55,7 @@ import org.apache.doris.catalog.Type; import org.apache.doris.catalog.View; import org.apache.doris.common.AnalysisException; +import org.apache.doris.common.Config; import org.apache.doris.common.DdlException; import org.apache.doris.common.MetaNotFoundException; import org.apache.doris.common.UserException; @@ -677,12 +678,18 @@ public void modifyPartitionsProperty(Database db, // 4.2 combine the old properties with new ones Map newProperties = new HashMap<>(); newProperties.put(PropertyAnalyzer.PROPERTIES_STORAGE_MEDIUM, dataProperty.getStorageMedium().name()); + Type datetimeType; + if (Config.use_date_v2_by_default) { + datetimeType = Type.DATETIMEV2; + } else { + datetimeType = Type.DATETIME; + } DateLiteral dateLiteral = new DateLiteral(dataProperty.getCooldownTimeMs(), - TimeUtils.getTimeZone(), Type.DATETIME); + TimeUtils.getTimeZone(), datetimeType); newProperties.put(PropertyAnalyzer.PROPERTIES_STORAGE_COOLDOWN_TIME, dateLiteral.getStringValue()); newProperties.put(PropertyAnalyzer.PROPERTIES_REMOTE_STORAGE_RESOURCE, dataProperty.getRemoteStorageResourceName()); DateLiteral dateLiteral1 = new DateLiteral(dataProperty.getRemoteCooldownTimeMs(), - TimeUtils.getTimeZone(), Type.DATETIME); + TimeUtils.getTimeZone(), datetimeType); newProperties.put(PropertyAnalyzer.PROPERTIES_REMOTE_STORAGE_COOLDOWN_TIME, dateLiteral1.getStringValue()); newProperties.putAll(properties); // 4.3 analyze new properties diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/CastExpr.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/CastExpr.java index 10cd2d065c5a50..9511ae6bc90ccf 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/CastExpr.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/CastExpr.java @@ -138,8 +138,7 @@ public TypeDef getTargetTypeDef() { private static boolean disableRegisterCastingFunction(Type fromType, Type toType) { // Disable casting from boolean to decimal or datetime or date - if (fromType.isBoolean() - && (toType.equals(Type.DECIMALV2) || toType.equals(Type.DATETIME) || toType.equals(Type.DATE))) { + if (fromType.isBoolean() && (toType.equals(Type.DECIMALV2) || toType.isDateType())) { return true; } @@ -165,7 +164,9 @@ public static void initBuiltins(FunctionSet functionSet) { beClass = "TimeOperators"; } String typeName = Function.getUdfTypeName(toType.getPrimitiveType()); - if (toType.getPrimitiveType() == PrimitiveType.DATE) { + // only refactor date/datetime for vectorized engine. + if (toType.getPrimitiveType() == PrimitiveType.DATE + || toType.getPrimitiveType() == PrimitiveType.DATEV2) { typeName = "date_val"; } String beSymbol = "doris::" + beClass + "::cast_to_" diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/ColumnDef.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/ColumnDef.java index d3831f2de639f7..71903c07afde72 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/ColumnDef.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/ColumnDef.java @@ -316,7 +316,9 @@ public static void validateDefaultValue(Type type, String defaultValue) throws A break; case DATE: case DATETIME: - new DateLiteral(defaultValue, type); + case DATEV2: + case DATETIMEV2: + new DateLiteral(defaultValue, DateLiteral.getDefaultDateType(type)); break; case CHAR: case VARCHAR: @@ -327,11 +329,8 @@ public static void validateDefaultValue(Type type, String defaultValue) throws A } break; case BITMAP: - break; case ARRAY: - break; case MAP: - break; case STRUCT: break; case BOOLEAN: diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/CreateFunctionStmt.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/CreateFunctionStmt.java index 89f5603fd78831..ff3aaff823997a 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/CreateFunctionStmt.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/CreateFunctionStmt.java @@ -467,10 +467,13 @@ private Types.PGenericType convertToPParameterType(Type arg) throws AnalysisExce typeBuilder.setId(Types.PGenericType.TypeId.BITMAP); break; case DATE: + case DATEV2: typeBuilder.setId(Types.PGenericType.TypeId.DATE); break; case DATETIME: + case DATETIMEV2: case TIME: + case TIMEV2: typeBuilder.setId(Types.PGenericType.TypeId.DATETIME); break; case DECIMALV2: diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/DataDescription.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/DataDescription.java index 34a2c23dcd195c..f52fd851abd038 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/DataDescription.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/DataDescription.java @@ -378,7 +378,7 @@ private static void validateHllHash(List args, Map colum } private static void validateNowFunction(Column mappingColumn) throws AnalysisException { - if (!mappingColumn.getOriginType().equals(Type.DATE) && !mappingColumn.getOriginType().equals(Type.DATETIME)) { + if (!mappingColumn.getOriginType().isDateType()) { throw new AnalysisException("Now() function is only support for DATE/DATETIME column"); } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/DateLiteral.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/DateLiteral.java index a59952f55edd38..2eb854415b6f56 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/DateLiteral.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/DateLiteral.java @@ -21,8 +21,10 @@ package org.apache.doris.analysis; import org.apache.doris.catalog.PrimitiveType; +import org.apache.doris.catalog.ScalarType; import org.apache.doris.catalog.Type; import org.apache.doris.common.AnalysisException; +import org.apache.doris.common.Config; import org.apache.doris.common.InvalidFormatException; import org.apache.doris.thrift.TDateLiteral; import org.apache.doris.thrift.TExprNode; @@ -55,8 +57,6 @@ public class DateLiteral extends LiteralExpr { private static final DateLiteral MAX_DATE = new DateLiteral(9999, 12, 31); private static final DateLiteral MIN_DATETIME = new DateLiteral(0000, 1, 1, 0, 0, 0); private static final DateLiteral MAX_DATETIME = new DateLiteral(9999, 12, 31, 23, 59, 59); - public static final DateLiteral UNIX_EPOCH_TIME = new DateLiteral(1970, 01, 01, 00, 00, 00); - private static final int DATEKEY_LENGTH = 8; private static final int MAX_MICROSECOND = 999999; private static final int DATETIME_TO_MINUTE_STRING_LENGTH = 16; @@ -151,7 +151,10 @@ public class DateLiteral extends LiteralExpr { //Date Literal persist type in meta private enum DateLiteralType { DATETIME(0), - DATE(1); + DATE(1), + + DATETIMEV2(2), + DATEV2(3); private final int value; private DateLiteralType(int value) { @@ -192,7 +195,7 @@ public DateLiteral(String s, Type type) throws AnalysisException { analysisDone(); } - public DateLiteral(long unixTimestamp, TimeZone timeZone, Type type) { + public DateLiteral(long unixTimestamp, TimeZone timeZone, Type type) throws AnalysisException { DateTime dt = new DateTime(unixTimestamp, DateTimeZone.forTimeZone(timeZone)); year = dt.getYear(); month = dt.getMonthOfYear(); @@ -205,8 +208,17 @@ public DateLiteral(long unixTimestamp, TimeZone timeZone, Type type) { minute = 0; second = 0; this.type = Type.DATE; - } else { + } else if (type.equals(Type.DATETIME)) { this.type = Type.DATETIME; + } else if (type.equals(Type.DATEV2)) { + hour = 0; + minute = 0; + second = 0; + this.type = Type.DATEV2; + } else if (type.equals(Type.DATETIMEV2)) { + this.type = Type.DATETIMEV2; + } else { + throw new AnalysisException("Error date literal type : " + type); } } @@ -217,7 +229,23 @@ public DateLiteral(long year, long month, long day) { this.year = year; this.month = month; this.day = day; - this.type = Type.DATE; + try { + this.type = DateLiteral.getDefaultDateType(Type.DATE); + } catch (AnalysisException e) { + this.type = Type.DATE; + } + } + + public DateLiteral(long year, long month, long day, Type type) { + this.hour = hour; + this.minute = minute; + this.second = second; + this.year = year; + this.month = month; + this.day = day; + Preconditions.checkArgument(type.getPrimitiveType().equals(Type.DATE.getPrimitiveType()) + || type.getPrimitiveType().equals(Type.DATEV2.getPrimitiveType())); + this.type = type; } public DateLiteral(long year, long month, long day, long hour, long minute, long second) { @@ -227,7 +255,34 @@ public DateLiteral(long year, long month, long day, long hour, long minute, long this.year = year; this.month = month; this.day = day; - this.type = Type.DATETIME; + try { + this.type = DateLiteral.getDefaultDateType(Type.DATETIME); + } catch (AnalysisException e) { + this.type = Type.DATETIME; + } + } + + public DateLiteral(long year, long month, long day, long hour, long minute, long second, long microsecond) { + this.hour = hour; + this.minute = minute; + this.second = second; + this.year = year; + this.month = month; + this.day = day; + this.microsecond = microsecond; + this.type = Type.DATETIMEV2; + } + + public DateLiteral(long year, long month, long day, long hour, long minute, long second, Type type) { + this.hour = hour; + this.minute = minute; + this.second = second; + this.year = year; + this.month = month; + this.day = day; + Preconditions.checkArgument(type.getPrimitiveType().equals(Type.DATETIME.getPrimitiveType()) + || type.getPrimitiveType().equals(Type.DATETIMEV2.getPrimitiveType())); + this.type = type; } public DateLiteral(LocalDateTime dateTime, Type type) { @@ -260,7 +315,7 @@ private void init(String s, Type type) throws AnalysisException { try { Preconditions.checkArgument(type.isDateType()); LocalDateTime dateTime; - if (type.equals(Type.DATE)) { + if (type.equals(Type.DATE) || type.equals(Type.DATEV2)) { if (s.split("-")[0].length() == 2) { dateTime = DATE_FORMATTER_TWO_DIGIT.parseLocalDateTime(s); } else if (s.length() == DATEKEY_LENGTH && !s.contains("-")) { @@ -316,8 +371,10 @@ public Expr clone() { public boolean isMinValue() { switch (type.getPrimitiveType()) { case DATE: + case DATEV2: return this.getStringValue().compareTo(MIN_DATE.getStringValue()) == 0; case DATETIME: + case DATETIMEV2: return this.getStringValue().compareTo(MIN_DATETIME.getStringValue()) == 0; default: return false; @@ -330,6 +387,11 @@ public Object getRealValue() { return year * 16 * 32L + month * 32 + day; } else if (type.equals(Type.DATETIME)) { return (year * 10000 + month * 100 + day) * 1000000L + hour * 10000 + minute * 100 + second; + } else if (type.equals(Type.DATEV2)) { + return (year << 16) | (month << 8) | day; + } else if (type.equals(Type.DATETIMEV2)) { + return (year << 50) | (month << 46) | (day << 41) | (hour << 36) + | (minute << 30) | (second << 24) | microsecond; } else { Preconditions.checkState(false, "invalid date type: " + type); return -1L; @@ -339,6 +401,8 @@ public Object getRealValue() { // Date column and Datetime column's hash value is not same. @Override public ByteBuffer getHashValue(PrimitiveType type) { + // This hash value should be computed using new String since precision is introduced to datetime. + // But it is hard to keep compatibility. So I don't change this function here. String value = convertToString(type); ByteBuffer buffer; try { @@ -369,12 +433,25 @@ public String toSqlImpl() { @Override public String getStringValue() { - return convertToString(type.getPrimitiveType()); + if (type.isDate() || type.isDateV2()) { + return String.format("%04d-%02d-%02d", year, month, day); + } else if (type.isDatetimeV2()) { + String s = String.format("%04d-%02d-%02d %02d:%02d:%02d", year, month, day, hour, minute, second); + if (((ScalarType) type).decimalScale() == 0) { + return s; + } + return s + "." + microsecond / (10L * (6 - ((ScalarType) type).decimalScale())); + } else { + return String.format("%04d-%02d-%02d %02d:%02d:%02d", year, month, day, hour, minute, second); + } } private String convertToString(PrimitiveType type) { - if (type == PrimitiveType.DATE) { + if (type == PrimitiveType.DATE || type == PrimitiveType.DATEV2) { return String.format("%04d-%02d-%02d", year, month, day); + } else if (type == PrimitiveType.DATETIMEV2) { + return String.format("%04d-%02d-%02d %02d:%02d:%02d.%06d", + year, month, day, hour, minute, second, microsecond); } else { return String.format("%04d-%02d-%02d %02d:%02d:%02d", year, month, day, hour, minute, second); } @@ -402,10 +479,13 @@ protected Expr uncheckedCastTo(Type targetType) throws AnalysisException { if (type.equals(targetType)) { return this; } - if (targetType.equals(Type.DATE)) { + if (targetType.equals(Type.DATE) || targetType.equals(Type.DATEV2)) { return new DateLiteral(this.year, this.month, this.day); } else if (targetType.equals(Type.DATETIME)) { return new DateLiteral(this.year, this.month, this.day, this.hour, this.minute, this.second); + } else if (targetType.isDatetimeV2()) { + return new DateLiteral(this.year, this.month, this.day, this.hour, this.minute, this.microsecond, + targetType); } else { throw new AnalysisException("Error date literal type : " + type); } @@ -419,7 +499,11 @@ protected Expr uncheckedCastTo(Type targetType) throws AnalysisException { } public void castToDate() { - this.type = Type.DATE; + if (Config.use_date_v2_by_default) { + this.type = Type.DATEV2; + } else { + this.type = Type.DATE; + } hour = 0; minute = 0; second = 0; @@ -432,31 +516,43 @@ private long makePackedDatetime() { return packedDatetime; } + private long makePackedDatetimeV2() { + return (year << 50) | (month << 46) | (day << 41) | (hour << 36) + | (minute << 30) | (second << 24) | microsecond; + } + @Override public void write(DataOutput out) throws IOException { super.write(out); //set flag bit in meta, 0 is DATETIME and 1 is DATE if (this.type.equals(Type.DATETIME)) { out.writeShort(DateLiteralType.DATETIME.value()); + out.writeLong(makePackedDatetime()); } else if (this.type.equals(Type.DATE)) { out.writeShort(DateLiteralType.DATE.value()); + out.writeLong(makePackedDatetime()); + } else if (this.type.equals(Type.DATETIMEV2)) { + out.writeShort(DateLiteralType.DATETIMEV2.value()); + out.writeLong(makePackedDatetimeV2()); + } else if (this.type.equals(Type.DATEV2)) { + out.writeShort(DateLiteralType.DATEV2.value()); + out.writeLong(makePackedDatetimeV2()); } else { throw new IOException("Error date literal type : " + type); } - out.writeLong(makePackedDatetime()); } private void fromPackedDatetime(long packedTime) { microsecond = (packedTime % (1L << 24)); long ymdhms = (packedTime >> 24); long ymd = ymdhms >> 17; - long hms = ymdhms % (1 << 17); - day = ymd % (1 << 5); long ym = ymd >> 5; month = ym % 13; year = ym / 13; year %= 10000; + + long hms = ymdhms % (1 << 17); second = hms % (1 << 6); minute = (hms >> 6) % (1 << 6); hour = (hms >> 12); @@ -465,6 +561,24 @@ private void fromPackedDatetime(long packedTime) { this.type = Type.DATETIME; } + private void fromPackedDatetimeV2(long packedTime) { + microsecond = (packedTime % (1L << 24)); + long ymdhms = (packedTime >> 24); + long ymd = ymdhms >> 17; + day = ymd % (1 << 5); + long ym = ymd >> 5; + month = ym % (1 << 4); + year = ym >> 4; + + long hms = ymdhms % (1 << 17); + second = hms % (1 << 6); + minute = (hms >> 6) % (1 << 6); + hour = (hms >> 12); + // set default date literal type to DATETIME + // date literal read from meta will set type by flag bit; + this.type = Type.DATETIMEV2; + } + public void readFields(DataInput in) throws IOException { super.readFields(in); short dateLiteralType = in.readShort(); @@ -473,6 +587,12 @@ public void readFields(DataInput in) throws IOException { this.type = Type.DATETIME; } else if (dateLiteralType == DateLiteralType.DATE.value()) { this.type = Type.DATE; + } else if (dateLiteralType == DateLiteralType.DATETIMEV2.value()) { + fromPackedDatetime(in.readLong()); + this.type = Type.DATETIMEV2; + } else if (dateLiteralType == DateLiteralType.DATEV2.value()) { + fromPackedDatetime(in.readLong()); + this.type = Type.DATEV2; } else { throw new IOException("Error date literal type : " + type); } @@ -597,7 +717,9 @@ private static DateTimeFormatterBuilder formatBuilder(String pattern) throws Ana case 'v': // %v Week (01..53), where Monday is the first day of the week; used with %x builder.appendWeekOfWeekyear(2); break; - case 'x': // %x Year for the week, where Monday is the first day of the week, numeric, four digits; used with %v + case 'x': + // %x Year for the week, where Monday is the first day of the week, + // numeric, four digits; used with %v builder.appendWeekyear(4, 4); break; case 'W': // %W Weekday name (Sunday..Saturday) @@ -609,14 +731,17 @@ private static DateTimeFormatterBuilder formatBuilder(String pattern) throws Ana case 'y': // %y Year, numeric (two digits) builder.appendTwoDigitYear(2020); break; + // TODO(Gabriel): support microseconds in date literal case 'f': // %f Microseconds (000000..999999) case 'w': // %w Day of the week (0=Sunday..6=Saturday) case 'U': // %U Week (00..53), where Sunday is the first day of the week case 'u': // %u Week (00..53), where Monday is the first day of the week case 'V': // %V Week (01..53), where Sunday is the first day of the week; used with %X - case 'X': // %X Year for the week where Sunday is the first day of the week, numeric, four digits; used with %V + case 'X': // %X Year for the week where Sunday is the first day of the week, + // numeric, four digits; used with %V case 'D': // %D Day of the month with English suffix (0th, 1st, 2nd, 3rd, …) - throw new AnalysisException(String.format("%%%s not supported in date format string", character)); + throw new AnalysisException(String.format("%%%s not supported in date format string", + character)); case '%': // %% A literal "%" character builder.appendLiteral('%'); break; @@ -635,9 +760,9 @@ private static DateTimeFormatterBuilder formatBuilder(String pattern) throws Ana } public LocalDateTime getTimeFormatter() throws AnalysisException { - if (type.equals(Type.DATE)) { + if (type.equals(Type.DATE) || type.equals(Type.DATEV2)) { return DATE_FORMATTER.parseLocalDateTime(getStringValue()); - } else if (type.equals(Type.DATETIME)) { + } else if (type.equals(Type.DATETIME) || type.equals(Type.DATETIMEV2)) { return DATE_TIME_FORMATTER.parseLocalDateTime(getStringValue()); } else { throw new AnalysisException("Not support date literal type"); @@ -700,7 +825,6 @@ public long getSecond() { private long second; private long microsecond; - @Override public int hashCode() { return 31 * super.hashCode() + Objects.hashCode(unixTimestamp(TimeZone.getDefault())); @@ -957,7 +1081,8 @@ public int fromDateFormatStr(String format, String value, boolean hasSubVal) thr } } else if (format.charAt(fp) != ' ') { if (format.charAt(fp) != value.charAt(vp)) { - throw new InvalidFormatException("Invalid char: " + value.charAt(vp) + ", expected: " + format.charAt(fp)); + throw new InvalidFormatException("Invalid char: " + value.charAt(vp) + ", expected: " + + format.charAt(fp)); } fp++; vp++; @@ -1034,6 +1159,8 @@ public int fromDateFormatStr(String format, String value, boolean hasSubVal) thr } // Compute timestamp type + // TODO(Gabriel): we still use old version datetime/date and change this to new version when + // we think it's stable enough if (datePartUsed) { if (timePartUsed) { this.type = Type.DATETIME; @@ -1048,11 +1175,37 @@ public int fromDateFormatStr(String format, String value, boolean hasSubVal) thr return 0; } + public int fromDateFormatStr(String format, String value, boolean hasSubVal, Type type) + throws InvalidFormatException { + switch (type.getPrimitiveType()) { + case DATETIME: + case DATE: + return fromDateFormatStr(format, value, hasSubVal); + default: + int val = fromDateFormatStr(format, value, hasSubVal); + convertTypeToV2(); + return val; + } + } + + private void convertTypeToV2() { + switch (type.getPrimitiveType()) { + case DATETIME: + this.type = Type.DATETIMEV2; + break; + case DATE: + this.type = Type.DATEV2; + break; + default: + } + } + private boolean checkRange() { return year > MAX_DATETIME.year || month > MAX_DATETIME.month || day > MAX_DATETIME.day || hour > MAX_DATETIME.hour || minute > MAX_DATETIME.minute || second > MAX_DATETIME.second || microsecond > MAX_MICROSECOND; } + private boolean checkDate() { if (month != 0 && day > DAYS_IN_MONTH[((int) month)]) { if (month == 2 && day == 29 && Year.isLeap(year)) { @@ -1195,7 +1348,8 @@ public void fromDateStr(String dateStr) throws AnalysisException { int start = pre; int tempVal = 0; boolean scanToDelim = (!isIntervalFormat) && (fieldIdx != 6); - while (pre < dateStr.length() && Character.isDigit(dateStr.charAt(pre)) && (scanToDelim || fieldLen-- != 0)) { + while (pre < dateStr.length() && Character.isDigit(dateStr.charAt(pre)) + && (scanToDelim || fieldLen-- != 0)) { tempVal = tempVal * 10 + (dateStr.charAt(pre++) - '0'); } dateVal[fieldIdx] = tempVal; @@ -1276,4 +1430,38 @@ public void fromDateStr(String dateStr) throws AnalysisException { throw new AnalysisException("Datetime value is out of range: " + dateStr); } } + + public void fromDateStr(String dateStr, Type type) throws AnalysisException { + switch (type.getPrimitiveType()) { + case DATETIME: + case DATE: + fromDateStr(dateStr); + break; + default: + fromDateStr(dateStr); + convertTypeToV2(); + } + } + + public static Type getDefaultDateType(Type type) throws AnalysisException { + switch (type.getPrimitiveType()) { + case DATE: + if (Config.use_date_v2_by_default) { + return Type.DATEV2; + } else { + return Type.DATE; + } + case DATETIME: + if (Config.use_date_v2_by_default) { + return Type.DATETIMEV2; + } else { + return Type.DATETIME; + } + case DATEV2: + case DATETIMEV2: + return type; + default: + throw new AnalysisException("Invalid date type: " + type); + } + } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/FloatLiteral.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/FloatLiteral.java index ea1322835d4fea..8920898d151c48 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/FloatLiteral.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/FloatLiteral.java @@ -20,6 +20,7 @@ import org.apache.doris.catalog.PrimitiveType; import org.apache.doris.catalog.Type; import org.apache.doris.common.AnalysisException; +import org.apache.doris.common.Config; import org.apache.doris.common.NotImplementedException; import org.apache.doris.thrift.TExprNode; import org.apache.doris.thrift.TExprNodeType; @@ -129,12 +130,27 @@ public String toSqlImpl() { public String getStringValue() { // TODO: Here is weird use float to represent TIME type // rethink whether it is reasonable to use this way - if (type.equals(Type.TIME)) { + if (type.equals(Type.TIME) || type.equals(Type.TIMEV2)) { return timeStrFromFloat(value); } return Double.toString(value); } + public static Type getDefaultTimeType(Type type) throws AnalysisException { + switch (type.getPrimitiveType()) { + case TIME: + if (Config.use_date_v2_by_default) { + return Type.TIMEV2; + } else { + return Type.TIME; + } + case TIMEV2: + return type; + default: + throw new AnalysisException("Invalid time type: " + type); + } + } + @Override public long getLongValue() { return (long) value; diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/FunctionCallExpr.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/FunctionCallExpr.java index 3c2451630b04a5..2ef0599c296f06 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/FunctionCallExpr.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/FunctionCallExpr.java @@ -1013,12 +1013,12 @@ public void analyzeImpl(Analyzer analyzer) throws AnalysisException { Expr child1Result = getChild(1).getResultValue(); if (child1Result instanceof StringLiteral) { if (DateLiteral.hasTimePart(((StringLiteral) child1Result).getStringValue())) { - this.type = Type.DATETIME; + this.type = DateLiteral.getDefaultDateType(Type.DATETIME); } else { - this.type = Type.DATE; + this.type = DateLiteral.getDefaultDateType(Type.DATE); } } else { - this.type = Type.DATETIME; + this.type = DateLiteral.getDefaultDateType(Type.DATETIME); } } else { this.type = fn.getReturnType(); diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/LiteralExpr.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/LiteralExpr.java index 375fe8d27c1ac4..df96968ca56779 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/LiteralExpr.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/LiteralExpr.java @@ -79,6 +79,8 @@ public static LiteralExpr create(String value, Type type) throws AnalysisExcepti break; case DATE: case DATETIME: + case DATEV2: + case DATETIMEV2: literalExpr = new DateLiteral(value, type); break; default: @@ -139,6 +141,8 @@ public static LiteralExpr createInfinity(Type type, boolean isMax) throws Analys return LargeIntLiteral.createMinValue(); case DATE: case DATETIME: + case DATEV2: + case DATETIMEV2: return DateLiteral.createMinValue(type); default: throw new AnalysisException("Invalid data type for creating infinity: " + type); diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/ShowAlterStmt.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/ShowAlterStmt.java index 8bfc5ed59d14d1..a089751610865e 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/ShowAlterStmt.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/ShowAlterStmt.java @@ -119,7 +119,8 @@ private void getPredicateValue(Expr subExpr) throws AnalysisException { throw new AnalysisException("Where clause : CreateTime/FinishTime =|>=|<=|>|<|!= " + "\"2019-12-02|2019-12-02 14:54:00\""); } - subExpr.setChild(1, ((StringLiteral) subExpr.getChild(1)).castTo(Type.DATETIME)); + subExpr.setChild(1, (subExpr.getChild(1)).castTo( + DateLiteral.getDefaultDateType(Type.DATETIME))); } else { throw new AnalysisException("The columns of TableName/CreateTime/FinishTime/State are supported."); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/StringLiteral.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/StringLiteral.java index 16eaddf45534a8..5f2c663bae51ff 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/StringLiteral.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/StringLiteral.java @@ -175,11 +175,11 @@ public String getRealValue() { public LiteralExpr convertToDate(Type targetType) throws AnalysisException { LiteralExpr newLiteral = null; try { - newLiteral = new DateLiteral(value, targetType); + newLiteral = new DateLiteral(value, DateLiteral.getDefaultDateType(targetType)); } catch (AnalysisException e) { if (targetType.isScalarType(PrimitiveType.DATETIME)) { - newLiteral = new DateLiteral(value, Type.DATE); - newLiteral.setType(Type.DATETIME); + newLiteral = new DateLiteral(value, DateLiteral.getDefaultDateType(Type.DATE)); + newLiteral.setType(DateLiteral.getDefaultDateType(Type.DATETIME)); } else { throw e; } diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/TypeDef.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/TypeDef.java index 9f82878d764218..7d0f6fd74a66dd 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/TypeDef.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/TypeDef.java @@ -30,8 +30,6 @@ import org.apache.doris.common.AnalysisException; import org.apache.doris.common.Config; -import com.google.common.base.Preconditions; - import java.util.ArrayList; /** @@ -53,6 +51,14 @@ public static TypeDef createDecimal(int precision, int scale) { return new TypeDef(ScalarType.createDecimalV2Type(precision, scale)); } + public static TypeDef createDatetimeV2(int scale) { + return new TypeDef(ScalarType.createDatetimeV2Type(scale)); + } + + public static TypeDef createTimeV2(int scale) { + return new TypeDef(ScalarType.createTimeV2Type(scale)); + } + public static TypeDef createVarchar(int len) { return new TypeDef(ScalarType.createVarchar(len)); } @@ -69,9 +75,9 @@ public void analyze(Analyzer analyzer) throws AnalysisException { // Check the max nesting depth before calling the recursive analyze() to avoid // a stack overflow. if (parsedType.exceedsMaxNestingDepth()) { - throw new AnalysisException( - String.format("Type exceeds the maximum nesting depth of %s:\n%s", Type.MAX_NESTING_DEPTH, - parsedType.toSql())); + throw new AnalysisException(String.format( + "Type exceeds the maximum nesting depth of %s:\n%s", + Type.MAX_NESTING_DEPTH, parsedType.toSql())); } analyze(parsedType); isAnalyzed = true; @@ -115,6 +121,10 @@ private void analyzeNestedType(ScalarType type) throws AnalysisException { if (type.isNull()) { throw new AnalysisException("Unsupported data type: " + type.toSql()); } + if (!type.getPrimitiveType().isIntegerType() + && !type.getPrimitiveType().isCharFamily()) { + throw new AnalysisException("Array column just support INT/VARCHAR sub-type"); + } if (type.getPrimitiveType().isStringType() && !type.isAssignedStrLenInColDefinition()) { type.setLength(1); @@ -133,11 +143,9 @@ private void analyzeScalarType(ScalarType scalarType) if (type == PrimitiveType.VARCHAR) { name = "VARCHAR"; maxLen = ScalarType.MAX_VARCHAR_LENGTH; - } else if (type == PrimitiveType.CHAR) { + } else { name = "CHAR"; maxLen = ScalarType.MAX_CHAR_LENGTH; - } else { - Preconditions.checkState(false); return; } int len = scalarType.getLength(); @@ -172,10 +180,25 @@ private void analyzeScalarType(ScalarType scalarType) } break; } + case TIMEV2: + case DATETIMEV2: { + int precision = scalarType.decimalPrecision(); + int scale = scalarType.decimalScale(); + // precision: [1, 27] + if (precision != ScalarType.DATETIME_PRECISION) { + throw new AnalysisException("Precision of Datetime/Time must be " + ScalarType.DATETIME_PRECISION + + "." + " Precision was set to: " + precision + "."); + } + // scale: [0, 9] + if (scale < 0 || scale > 6) { + throw new AnalysisException("Scale of Datetime/Time must between 0 and 6." + + " Scale was set to: " + scale + "."); + } + break; + } case INVALID_TYPE: throw new AnalysisException("Invalid type."); - default: - break; + default: break; } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/Column.java b/fe/fe-core/src/main/java/org/apache/doris/catalog/Column.java index 81eb14af0bec6f..cda29d7c7dcd15 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/catalog/Column.java +++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/Column.java @@ -445,14 +445,6 @@ public void checkSchemaChangeAllowed(Column other) throws DdlException { || other.getDataType() == PrimitiveType.STRING)) { return; } - - if (this.getPrecision() != other.getPrecision()) { - throw new DdlException("Cannot change precision"); - } - - if (this.getScale() != other.getScale()) { - throw new DdlException("Cannot change scale"); - } } public boolean nameEquals(String otherColName, boolean ignorePrefix) { diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/ColumnType.java b/fe/fe-core/src/main/java/org/apache/doris/catalog/ColumnType.java index 41575518b4c7d8..77c2eebf52d3f5 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/catalog/ColumnType.java +++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/ColumnType.java @@ -111,8 +111,21 @@ public abstract class ColumnType { schemaChangeMatrix[PrimitiveType.DECIMALV2.ordinal()][PrimitiveType.STRING.ordinal()] = true; schemaChangeMatrix[PrimitiveType.DATETIME.ordinal()][PrimitiveType.DATE.ordinal()] = true; - schemaChangeMatrix[PrimitiveType.DATE.ordinal()][PrimitiveType.DATETIME.ordinal()] = true; + schemaChangeMatrix[PrimitiveType.DATETIME.ordinal()][PrimitiveType.DATEV2.ordinal()] = true; + schemaChangeMatrix[PrimitiveType.DATE.ordinal()][PrimitiveType.DATETIMEV2.ordinal()] = true; + schemaChangeMatrix[PrimitiveType.DATETIME.ordinal()][PrimitiveType.DATETIMEV2.ordinal()] = true; + schemaChangeMatrix[PrimitiveType.DATE.ordinal()][PrimitiveType.DATEV2.ordinal()] = true; + + schemaChangeMatrix[PrimitiveType.DATETIMEV2.ordinal()][PrimitiveType.DATE.ordinal()] = true; + schemaChangeMatrix[PrimitiveType.DATEV2.ordinal()][PrimitiveType.DATETIME.ordinal()] = true; + schemaChangeMatrix[PrimitiveType.DATETIMEV2.ordinal()][PrimitiveType.DATEV2.ordinal()] = true; + schemaChangeMatrix[PrimitiveType.DATEV2.ordinal()][PrimitiveType.DATETIMEV2.ordinal()] = true; + schemaChangeMatrix[PrimitiveType.DATETIMEV2.ordinal()][PrimitiveType.DATETIME.ordinal()] = true; + schemaChangeMatrix[PrimitiveType.DATEV2.ordinal()][PrimitiveType.DATE.ordinal()] = true; + + // we should support schema change between different precision + schemaChangeMatrix[PrimitiveType.DATETIMEV2.ordinal()][PrimitiveType.DATETIMEV2.ordinal()] = true; } static boolean isSchemaChangeAllowed(Type lhs, Type rhs) { diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/Function.java b/fe/fe-core/src/main/java/org/apache/doris/catalog/Function.java index 7e609c5070dc95..943a3364079af9 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/catalog/Function.java +++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/Function.java @@ -495,6 +495,7 @@ public static String getUdfTypeName(PrimitiveType t) { return "float_val"; case DOUBLE: case TIME: + case TIMEV2: return "double_val"; case VARCHAR: case CHAR: @@ -505,6 +506,8 @@ public static String getUdfTypeName(PrimitiveType t) { return "string_val"; case DATE: case DATETIME: + case DATEV2: + case DATETIMEV2: return "datetime_val"; case DECIMALV2: return "decimalv2_val"; @@ -534,6 +537,7 @@ public static String getUdfType(PrimitiveType t) { return "FloatVal"; case DOUBLE: case TIME: + case TIMEV2: return "DoubleVal"; case VARCHAR: case CHAR: @@ -544,6 +548,8 @@ public static String getUdfType(PrimitiveType t) { return "StringVal"; case DATE: case DATETIME: + case DATEV2: + case DATETIMEV2: return "DateTimeVal"; case DECIMALV2: return "DecimalV2Val"; diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/PartitionKey.java b/fe/fe-core/src/main/java/org/apache/doris/catalog/PartitionKey.java index 3b4436562684b6..d8bcb961e290e2 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/catalog/PartitionKey.java +++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/PartitionKey.java @@ -310,6 +310,8 @@ public void readFields(DataInput in) throws IOException { break; case DATE: case DATETIME: + case DATEV2: + case DATETIMEV2: literal = DateLiteral.read(in); break; case CHAR: diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/PrimitiveType.java b/fe/fe-core/src/main/java/org/apache/doris/catalog/PrimitiveType.java index d88369b77e4a98..fd3273f082f0dd 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/catalog/PrimitiveType.java +++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/PrimitiveType.java @@ -54,6 +54,9 @@ public enum PrimitiveType { HLL("HLL", 16, TPrimitiveType.HLL), BITMAP("BITMAP", 16, TPrimitiveType.OBJECT), QUANTILE_STATE("QUANTILE_STATE", 16, TPrimitiveType.QUANTILE_STATE), + DATEV2("DATEV2", 4, TPrimitiveType.DATEV2), + DATETIMEV2("DATETIMEV2", 8, TPrimitiveType.DATETIMEV2), + TIMEV2("TIMEV2", 8, TPrimitiveType.TIMEV2), ARRAY("ARRAY", 24, TPrimitiveType.ARRAY), MAP("MAP", 24, TPrimitiveType.MAP), @@ -84,12 +87,15 @@ public enum PrimitiveType { builder.put(NULL_TYPE, DOUBLE); builder.put(NULL_TYPE, DATE); builder.put(NULL_TYPE, DATETIME); + builder.put(NULL_TYPE, DATEV2); + builder.put(NULL_TYPE, DATETIMEV2); builder.put(NULL_TYPE, DECIMALV2); builder.put(NULL_TYPE, CHAR); builder.put(NULL_TYPE, VARCHAR); builder.put(NULL_TYPE, STRING); builder.put(NULL_TYPE, BITMAP); //TODO(weixiang):why null type can cast to bitmap? builder.put(NULL_TYPE, TIME); + builder.put(NULL_TYPE, TIMEV2); // Boolean builder.put(BOOLEAN, BOOLEAN); builder.put(BOOLEAN, TINYINT); @@ -101,6 +107,8 @@ public enum PrimitiveType { builder.put(BOOLEAN, DOUBLE); builder.put(BOOLEAN, DATE); builder.put(BOOLEAN, DATETIME); + builder.put(BOOLEAN, DATEV2); + builder.put(BOOLEAN, DATETIMEV2); builder.put(BOOLEAN, DECIMALV2); builder.put(BOOLEAN, VARCHAR); builder.put(BOOLEAN, STRING); @@ -115,6 +123,8 @@ public enum PrimitiveType { builder.put(TINYINT, DOUBLE); builder.put(TINYINT, DATE); builder.put(TINYINT, DATETIME); + builder.put(TINYINT, DATEV2); + builder.put(TINYINT, DATETIMEV2); builder.put(TINYINT, DECIMALV2); builder.put(TINYINT, VARCHAR); builder.put(TINYINT, STRING); @@ -129,6 +139,8 @@ public enum PrimitiveType { builder.put(SMALLINT, DOUBLE); builder.put(SMALLINT, DATE); builder.put(SMALLINT, DATETIME); + builder.put(SMALLINT, DATEV2); + builder.put(SMALLINT, DATETIMEV2); builder.put(SMALLINT, DECIMALV2); builder.put(SMALLINT, VARCHAR); builder.put(SMALLINT, STRING); @@ -143,6 +155,8 @@ public enum PrimitiveType { builder.put(INT, DOUBLE); builder.put(INT, DATE); builder.put(INT, DATETIME); + builder.put(INT, DATEV2); + builder.put(INT, DATETIMEV2); builder.put(INT, DECIMALV2); builder.put(INT, VARCHAR); builder.put(INT, STRING); @@ -157,6 +171,8 @@ public enum PrimitiveType { builder.put(BIGINT, DOUBLE); builder.put(BIGINT, DATE); builder.put(BIGINT, DATETIME); + builder.put(BIGINT, DATEV2); + builder.put(BIGINT, DATETIMEV2); builder.put(BIGINT, DECIMALV2); builder.put(BIGINT, VARCHAR); builder.put(BIGINT, STRING); @@ -171,6 +187,8 @@ public enum PrimitiveType { builder.put(LARGEINT, DOUBLE); builder.put(LARGEINT, DATE); builder.put(LARGEINT, DATETIME); + builder.put(LARGEINT, DATEV2); + builder.put(LARGEINT, DATETIMEV2); builder.put(LARGEINT, DECIMALV2); builder.put(LARGEINT, VARCHAR); builder.put(LARGEINT, STRING); @@ -185,6 +203,8 @@ public enum PrimitiveType { builder.put(FLOAT, DOUBLE); builder.put(FLOAT, DATE); builder.put(FLOAT, DATETIME); + builder.put(FLOAT, DATEV2); + builder.put(FLOAT, DATETIMEV2); builder.put(FLOAT, DECIMALV2); builder.put(FLOAT, VARCHAR); builder.put(FLOAT, STRING); @@ -199,6 +219,8 @@ public enum PrimitiveType { builder.put(DOUBLE, DOUBLE); builder.put(DOUBLE, DATE); builder.put(DOUBLE, DATETIME); + builder.put(DOUBLE, DATEV2); + builder.put(DOUBLE, DATETIMEV2); builder.put(DOUBLE, DECIMALV2); builder.put(DOUBLE, VARCHAR); builder.put(DOUBLE, STRING); @@ -213,6 +235,8 @@ public enum PrimitiveType { builder.put(DATE, DOUBLE); builder.put(DATE, DATE); builder.put(DATE, DATETIME); + builder.put(DATE, DATEV2); + builder.put(DATE, DATETIMEV2); builder.put(DATE, DECIMALV2); builder.put(DATE, VARCHAR); builder.put(DATE, STRING); @@ -227,9 +251,43 @@ public enum PrimitiveType { builder.put(DATETIME, DOUBLE); builder.put(DATETIME, DATE); builder.put(DATETIME, DATETIME); + builder.put(DATETIME, DATEV2); + builder.put(DATETIME, DATETIMEV2); builder.put(DATETIME, DECIMALV2); builder.put(DATETIME, VARCHAR); builder.put(DATETIME, STRING); + // DateV2 + builder.put(DATEV2, BOOLEAN); + builder.put(DATEV2, TINYINT); + builder.put(DATEV2, SMALLINT); + builder.put(DATEV2, INT); + builder.put(DATEV2, BIGINT); + builder.put(DATEV2, LARGEINT); + builder.put(DATEV2, FLOAT); + builder.put(DATEV2, DOUBLE); + builder.put(DATEV2, DATE); + builder.put(DATEV2, DATETIME); + builder.put(DATEV2, DATEV2); + builder.put(DATEV2, DATETIMEV2); + builder.put(DATEV2, DECIMALV2); + builder.put(DATEV2, VARCHAR); + builder.put(DATEV2, STRING); + // DatetimeV2 + builder.put(DATETIMEV2, BOOLEAN); + builder.put(DATETIMEV2, TINYINT); + builder.put(DATETIMEV2, SMALLINT); + builder.put(DATETIMEV2, INT); + builder.put(DATETIMEV2, BIGINT); + builder.put(DATETIMEV2, LARGEINT); + builder.put(DATETIMEV2, FLOAT); + builder.put(DATETIMEV2, DOUBLE); + builder.put(DATETIMEV2, DATE); + builder.put(DATETIMEV2, DATETIME); + builder.put(DATETIMEV2, DATEV2); + builder.put(DATETIMEV2, DATETIMEV2); + builder.put(DATETIMEV2, DECIMALV2); + builder.put(DATETIMEV2, VARCHAR); + builder.put(DATETIMEV2, STRING); // Char builder.put(CHAR, BOOLEAN); builder.put(CHAR, TINYINT); @@ -242,6 +300,8 @@ public enum PrimitiveType { builder.put(CHAR, DOUBLE); builder.put(CHAR, DATE); builder.put(CHAR, DATETIME); + builder.put(CHAR, DATEV2); + builder.put(CHAR, DATETIMEV2); builder.put(CHAR, DECIMALV2); builder.put(CHAR, VARCHAR); builder.put(CHAR, STRING); @@ -256,6 +316,8 @@ public enum PrimitiveType { builder.put(VARCHAR, DOUBLE); builder.put(VARCHAR, DATE); builder.put(VARCHAR, DATETIME); + builder.put(VARCHAR, DATEV2); + builder.put(VARCHAR, DATETIMEV2); builder.put(VARCHAR, DECIMALV2); builder.put(VARCHAR, VARCHAR); builder.put(VARCHAR, STRING); @@ -271,6 +333,8 @@ public enum PrimitiveType { builder.put(STRING, DOUBLE); builder.put(STRING, DATE); builder.put(STRING, DATETIME); + builder.put(STRING, DATEV2); + builder.put(STRING, DATETIMEV2); builder.put(STRING, DECIMALV2); builder.put(STRING, VARCHAR); builder.put(STRING, STRING); @@ -299,8 +363,14 @@ public enum PrimitiveType { //TIME builder.put(TIME, TIME); + builder.put(TIME, TIMEV2); builder.put(TIME, DOUBLE); + //TIMEV2 + builder.put(TIMEV2, TIME); + builder.put(TIMEV2, TIMEV2); + builder.put(TIMEV2, DOUBLE); + implicitCastMap = builder.build(); } @@ -343,6 +413,9 @@ public enum PrimitiveType { supportedTypes.add(DATE); supportedTypes.add(DATETIME); supportedTypes.add(TIME); + supportedTypes.add(DATEV2); + supportedTypes.add(DATETIMEV2); + supportedTypes.add(TIMEV2); supportedTypes.add(DECIMALV2); supportedTypes.add(BITMAP); supportedTypes.add(ARRAY); @@ -395,11 +468,14 @@ public static boolean isImplicitCast(PrimitiveType type, PrimitiveType target) { compatibilityMatrix[NULL_TYPE.ordinal()][DOUBLE.ordinal()] = DOUBLE; compatibilityMatrix[NULL_TYPE.ordinal()][DATE.ordinal()] = DATE; compatibilityMatrix[NULL_TYPE.ordinal()][DATETIME.ordinal()] = DATETIME; + compatibilityMatrix[NULL_TYPE.ordinal()][DATEV2.ordinal()] = DATEV2; + compatibilityMatrix[NULL_TYPE.ordinal()][DATETIMEV2.ordinal()] = DATETIMEV2; compatibilityMatrix[NULL_TYPE.ordinal()][CHAR.ordinal()] = CHAR; compatibilityMatrix[NULL_TYPE.ordinal()][VARCHAR.ordinal()] = VARCHAR; compatibilityMatrix[NULL_TYPE.ordinal()][STRING.ordinal()] = STRING; compatibilityMatrix[NULL_TYPE.ordinal()][DECIMALV2.ordinal()] = DECIMALV2; compatibilityMatrix[NULL_TYPE.ordinal()][TIME.ordinal()] = TIME; + compatibilityMatrix[NULL_TYPE.ordinal()][TIMEV2.ordinal()] = TIMEV2; compatibilityMatrix[NULL_TYPE.ordinal()][BITMAP.ordinal()] = BITMAP; //TODO(weixiang): bitmap can be null? compatibilityMatrix[NULL_TYPE.ordinal()][QUANTILE_STATE.ordinal()] = QUANTILE_STATE; //TODO(weixiang): QUANTILE_STATE can be null? @@ -413,11 +489,14 @@ public static boolean isImplicitCast(PrimitiveType type, PrimitiveType target) { compatibilityMatrix[BOOLEAN.ordinal()][DOUBLE.ordinal()] = DOUBLE; compatibilityMatrix[BOOLEAN.ordinal()][DATE.ordinal()] = INVALID_TYPE; compatibilityMatrix[BOOLEAN.ordinal()][DATETIME.ordinal()] = INVALID_TYPE; + compatibilityMatrix[BOOLEAN.ordinal()][DATEV2.ordinal()] = INVALID_TYPE; + compatibilityMatrix[BOOLEAN.ordinal()][DATETIMEV2.ordinal()] = INVALID_TYPE; compatibilityMatrix[BOOLEAN.ordinal()][CHAR.ordinal()] = INVALID_TYPE; compatibilityMatrix[BOOLEAN.ordinal()][VARCHAR.ordinal()] = INVALID_TYPE; compatibilityMatrix[BOOLEAN.ordinal()][STRING.ordinal()] = INVALID_TYPE; compatibilityMatrix[BOOLEAN.ordinal()][DECIMALV2.ordinal()] = DECIMALV2; compatibilityMatrix[BOOLEAN.ordinal()][TIME.ordinal()] = TIME; + compatibilityMatrix[BOOLEAN.ordinal()][TIMEV2.ordinal()] = TIMEV2; compatibilityMatrix[TINYINT.ordinal()][TINYINT.ordinal()] = TINYINT; compatibilityMatrix[TINYINT.ordinal()][SMALLINT.ordinal()] = SMALLINT; @@ -428,11 +507,14 @@ public static boolean isImplicitCast(PrimitiveType type, PrimitiveType target) { compatibilityMatrix[TINYINT.ordinal()][DOUBLE.ordinal()] = DOUBLE; compatibilityMatrix[TINYINT.ordinal()][DATE.ordinal()] = INVALID_TYPE; compatibilityMatrix[TINYINT.ordinal()][DATETIME.ordinal()] = INVALID_TYPE; + compatibilityMatrix[TINYINT.ordinal()][DATEV2.ordinal()] = INVALID_TYPE; + compatibilityMatrix[TINYINT.ordinal()][DATETIMEV2.ordinal()] = INVALID_TYPE; compatibilityMatrix[TINYINT.ordinal()][CHAR.ordinal()] = INVALID_TYPE; compatibilityMatrix[TINYINT.ordinal()][VARCHAR.ordinal()] = INVALID_TYPE; compatibilityMatrix[TINYINT.ordinal()][STRING.ordinal()] = INVALID_TYPE; compatibilityMatrix[TINYINT.ordinal()][DECIMALV2.ordinal()] = DECIMALV2; compatibilityMatrix[TINYINT.ordinal()][TIME.ordinal()] = TIME; + compatibilityMatrix[TINYINT.ordinal()][TIMEV2.ordinal()] = TIMEV2; compatibilityMatrix[SMALLINT.ordinal()][SMALLINT.ordinal()] = SMALLINT; compatibilityMatrix[SMALLINT.ordinal()][INT.ordinal()] = INT; @@ -442,11 +524,14 @@ public static boolean isImplicitCast(PrimitiveType type, PrimitiveType target) { compatibilityMatrix[SMALLINT.ordinal()][DOUBLE.ordinal()] = DOUBLE; compatibilityMatrix[SMALLINT.ordinal()][DATE.ordinal()] = INVALID_TYPE; compatibilityMatrix[SMALLINT.ordinal()][DATETIME.ordinal()] = INVALID_TYPE; + compatibilityMatrix[SMALLINT.ordinal()][DATEV2.ordinal()] = INVALID_TYPE; + compatibilityMatrix[SMALLINT.ordinal()][DATETIMEV2.ordinal()] = INVALID_TYPE; compatibilityMatrix[SMALLINT.ordinal()][CHAR.ordinal()] = INVALID_TYPE; compatibilityMatrix[SMALLINT.ordinal()][VARCHAR.ordinal()] = INVALID_TYPE; compatibilityMatrix[SMALLINT.ordinal()][STRING.ordinal()] = INVALID_TYPE; compatibilityMatrix[SMALLINT.ordinal()][DECIMALV2.ordinal()] = DECIMALV2; compatibilityMatrix[SMALLINT.ordinal()][TIME.ordinal()] = TIME; + compatibilityMatrix[SMALLINT.ordinal()][TIMEV2.ordinal()] = TIMEV2; compatibilityMatrix[INT.ordinal()][INT.ordinal()] = INT; compatibilityMatrix[INT.ordinal()][BIGINT.ordinal()] = BIGINT; @@ -455,11 +540,14 @@ public static boolean isImplicitCast(PrimitiveType type, PrimitiveType target) { compatibilityMatrix[INT.ordinal()][DOUBLE.ordinal()] = DOUBLE; compatibilityMatrix[INT.ordinal()][DATE.ordinal()] = INVALID_TYPE; compatibilityMatrix[INT.ordinal()][DATETIME.ordinal()] = INVALID_TYPE; + compatibilityMatrix[INT.ordinal()][DATEV2.ordinal()] = INVALID_TYPE; + compatibilityMatrix[INT.ordinal()][DATETIMEV2.ordinal()] = INVALID_TYPE; compatibilityMatrix[INT.ordinal()][CHAR.ordinal()] = INVALID_TYPE; compatibilityMatrix[INT.ordinal()][VARCHAR.ordinal()] = INVALID_TYPE; compatibilityMatrix[INT.ordinal()][STRING.ordinal()] = INVALID_TYPE; compatibilityMatrix[INT.ordinal()][DECIMALV2.ordinal()] = DECIMALV2; compatibilityMatrix[INT.ordinal()][TIME.ordinal()] = TIME; + compatibilityMatrix[INT.ordinal()][TIMEV2.ordinal()] = TIMEV2; compatibilityMatrix[BIGINT.ordinal()][BIGINT.ordinal()] = BIGINT; compatibilityMatrix[BIGINT.ordinal()][LARGEINT.ordinal()] = LARGEINT; @@ -467,81 +555,127 @@ public static boolean isImplicitCast(PrimitiveType type, PrimitiveType target) { compatibilityMatrix[BIGINT.ordinal()][DOUBLE.ordinal()] = DOUBLE; compatibilityMatrix[BIGINT.ordinal()][DATE.ordinal()] = INVALID_TYPE; compatibilityMatrix[BIGINT.ordinal()][DATETIME.ordinal()] = INVALID_TYPE; + compatibilityMatrix[BIGINT.ordinal()][DATEV2.ordinal()] = INVALID_TYPE; + compatibilityMatrix[BIGINT.ordinal()][DATETIMEV2.ordinal()] = INVALID_TYPE; compatibilityMatrix[BIGINT.ordinal()][CHAR.ordinal()] = INVALID_TYPE; compatibilityMatrix[BIGINT.ordinal()][VARCHAR.ordinal()] = INVALID_TYPE; compatibilityMatrix[BIGINT.ordinal()][STRING.ordinal()] = INVALID_TYPE; compatibilityMatrix[BIGINT.ordinal()][DECIMALV2.ordinal()] = DECIMALV2; compatibilityMatrix[BIGINT.ordinal()][TIME.ordinal()] = TIME; + compatibilityMatrix[BIGINT.ordinal()][TIMEV2.ordinal()] = TIMEV2; compatibilityMatrix[LARGEINT.ordinal()][LARGEINT.ordinal()] = LARGEINT; compatibilityMatrix[LARGEINT.ordinal()][FLOAT.ordinal()] = DOUBLE; compatibilityMatrix[LARGEINT.ordinal()][DOUBLE.ordinal()] = DOUBLE; compatibilityMatrix[LARGEINT.ordinal()][DATE.ordinal()] = INVALID_TYPE; compatibilityMatrix[LARGEINT.ordinal()][DATETIME.ordinal()] = INVALID_TYPE; + compatibilityMatrix[LARGEINT.ordinal()][DATEV2.ordinal()] = INVALID_TYPE; + compatibilityMatrix[LARGEINT.ordinal()][DATETIMEV2.ordinal()] = INVALID_TYPE; compatibilityMatrix[LARGEINT.ordinal()][CHAR.ordinal()] = INVALID_TYPE; compatibilityMatrix[LARGEINT.ordinal()][VARCHAR.ordinal()] = INVALID_TYPE; compatibilityMatrix[LARGEINT.ordinal()][STRING.ordinal()] = INVALID_TYPE; compatibilityMatrix[LARGEINT.ordinal()][DECIMALV2.ordinal()] = DECIMALV2; compatibilityMatrix[LARGEINT.ordinal()][TIME.ordinal()] = TIME; + compatibilityMatrix[LARGEINT.ordinal()][TIMEV2.ordinal()] = TIMEV2; compatibilityMatrix[FLOAT.ordinal()][FLOAT.ordinal()] = FLOAT; compatibilityMatrix[FLOAT.ordinal()][DOUBLE.ordinal()] = DOUBLE; compatibilityMatrix[FLOAT.ordinal()][DATE.ordinal()] = INVALID_TYPE; compatibilityMatrix[FLOAT.ordinal()][DATETIME.ordinal()] = INVALID_TYPE; + compatibilityMatrix[FLOAT.ordinal()][DATEV2.ordinal()] = INVALID_TYPE; + compatibilityMatrix[FLOAT.ordinal()][DATETIMEV2.ordinal()] = INVALID_TYPE; compatibilityMatrix[FLOAT.ordinal()][CHAR.ordinal()] = INVALID_TYPE; compatibilityMatrix[FLOAT.ordinal()][VARCHAR.ordinal()] = INVALID_TYPE; compatibilityMatrix[FLOAT.ordinal()][STRING.ordinal()] = INVALID_TYPE; compatibilityMatrix[FLOAT.ordinal()][DECIMALV2.ordinal()] = DECIMALV2; compatibilityMatrix[FLOAT.ordinal()][TIME.ordinal()] = TIME; + compatibilityMatrix[FLOAT.ordinal()][TIMEV2.ordinal()] = TIMEV2; compatibilityMatrix[DOUBLE.ordinal()][DOUBLE.ordinal()] = DOUBLE; compatibilityMatrix[DOUBLE.ordinal()][DATE.ordinal()] = INVALID_TYPE; compatibilityMatrix[DOUBLE.ordinal()][DATETIME.ordinal()] = INVALID_TYPE; + compatibilityMatrix[DOUBLE.ordinal()][DATEV2.ordinal()] = INVALID_TYPE; + compatibilityMatrix[DOUBLE.ordinal()][DATETIMEV2.ordinal()] = INVALID_TYPE; compatibilityMatrix[DOUBLE.ordinal()][CHAR.ordinal()] = INVALID_TYPE; compatibilityMatrix[DOUBLE.ordinal()][VARCHAR.ordinal()] = INVALID_TYPE; compatibilityMatrix[DOUBLE.ordinal()][STRING.ordinal()] = INVALID_TYPE; compatibilityMatrix[DOUBLE.ordinal()][DECIMALV2.ordinal()] = DECIMALV2; compatibilityMatrix[DOUBLE.ordinal()][TIME.ordinal()] = TIME; + compatibilityMatrix[DOUBLE.ordinal()][TIMEV2.ordinal()] = TIMEV2; compatibilityMatrix[DATE.ordinal()][DATE.ordinal()] = DATE; compatibilityMatrix[DATE.ordinal()][DATETIME.ordinal()] = DATETIME; + compatibilityMatrix[DATE.ordinal()][DATEV2.ordinal()] = DATEV2; + compatibilityMatrix[DATE.ordinal()][DATETIMEV2.ordinal()] = DATETIMEV2; compatibilityMatrix[DATE.ordinal()][CHAR.ordinal()] = INVALID_TYPE; compatibilityMatrix[DATE.ordinal()][VARCHAR.ordinal()] = INVALID_TYPE; compatibilityMatrix[DATE.ordinal()][STRING.ordinal()] = INVALID_TYPE; compatibilityMatrix[DATE.ordinal()][DECIMALV2.ordinal()] = INVALID_TYPE; compatibilityMatrix[DATE.ordinal()][TIME.ordinal()] = INVALID_TYPE; + compatibilityMatrix[DATE.ordinal()][TIMEV2.ordinal()] = INVALID_TYPE; + + compatibilityMatrix[DATEV2.ordinal()][DATE.ordinal()] = DATEV2; + compatibilityMatrix[DATEV2.ordinal()][DATETIME.ordinal()] = DATETIMEV2; + compatibilityMatrix[DATEV2.ordinal()][DATEV2.ordinal()] = DATEV2; + compatibilityMatrix[DATEV2.ordinal()][DATETIMEV2.ordinal()] = DATETIMEV2; + compatibilityMatrix[DATEV2.ordinal()][CHAR.ordinal()] = INVALID_TYPE; + compatibilityMatrix[DATEV2.ordinal()][VARCHAR.ordinal()] = INVALID_TYPE; + compatibilityMatrix[DATEV2.ordinal()][STRING.ordinal()] = INVALID_TYPE; + compatibilityMatrix[DATEV2.ordinal()][DECIMALV2.ordinal()] = INVALID_TYPE; + compatibilityMatrix[DATEV2.ordinal()][TIME.ordinal()] = INVALID_TYPE; + compatibilityMatrix[DATEV2.ordinal()][TIMEV2.ordinal()] = INVALID_TYPE; compatibilityMatrix[DATETIME.ordinal()][DATETIME.ordinal()] = DATETIME; + compatibilityMatrix[DATETIME.ordinal()][DATETIMEV2.ordinal()] = DATETIMEV2; compatibilityMatrix[DATETIME.ordinal()][CHAR.ordinal()] = INVALID_TYPE; compatibilityMatrix[DATETIME.ordinal()][VARCHAR.ordinal()] = INVALID_TYPE; compatibilityMatrix[DATETIME.ordinal()][STRING.ordinal()] = INVALID_TYPE; compatibilityMatrix[DATETIME.ordinal()][DECIMALV2.ordinal()] = INVALID_TYPE; compatibilityMatrix[DATETIME.ordinal()][TIME.ordinal()] = INVALID_TYPE; + compatibilityMatrix[DATETIME.ordinal()][TIMEV2.ordinal()] = INVALID_TYPE; + + compatibilityMatrix[DATETIMEV2.ordinal()][DATETIME.ordinal()] = DATETIMEV2; + compatibilityMatrix[DATETIMEV2.ordinal()][DATETIMEV2.ordinal()] = DATETIMEV2; + compatibilityMatrix[DATETIMEV2.ordinal()][CHAR.ordinal()] = INVALID_TYPE; + compatibilityMatrix[DATETIMEV2.ordinal()][VARCHAR.ordinal()] = INVALID_TYPE; + compatibilityMatrix[DATETIMEV2.ordinal()][STRING.ordinal()] = INVALID_TYPE; + compatibilityMatrix[DATETIMEV2.ordinal()][DECIMALV2.ordinal()] = INVALID_TYPE; + compatibilityMatrix[DATETIMEV2.ordinal()][TIME.ordinal()] = INVALID_TYPE; + compatibilityMatrix[DATETIMEV2.ordinal()][TIMEV2.ordinal()] = INVALID_TYPE; compatibilityMatrix[CHAR.ordinal()][CHAR.ordinal()] = CHAR; compatibilityMatrix[CHAR.ordinal()][VARCHAR.ordinal()] = VARCHAR; compatibilityMatrix[CHAR.ordinal()][STRING.ordinal()] = STRING; compatibilityMatrix[CHAR.ordinal()][DECIMALV2.ordinal()] = INVALID_TYPE; compatibilityMatrix[CHAR.ordinal()][TIME.ordinal()] = INVALID_TYPE; + compatibilityMatrix[CHAR.ordinal()][TIMEV2.ordinal()] = INVALID_TYPE; compatibilityMatrix[VARCHAR.ordinal()][VARCHAR.ordinal()] = VARCHAR; compatibilityMatrix[VARCHAR.ordinal()][STRING.ordinal()] = STRING; compatibilityMatrix[VARCHAR.ordinal()][DECIMALV2.ordinal()] = INVALID_TYPE; compatibilityMatrix[VARCHAR.ordinal()][TIME.ordinal()] = INVALID_TYPE; + compatibilityMatrix[VARCHAR.ordinal()][TIMEV2.ordinal()] = INVALID_TYPE; compatibilityMatrix[STRING.ordinal()][STRING.ordinal()] = STRING; compatibilityMatrix[STRING.ordinal()][DECIMALV2.ordinal()] = INVALID_TYPE; compatibilityMatrix[STRING.ordinal()][TIME.ordinal()] = INVALID_TYPE; + compatibilityMatrix[STRING.ordinal()][TIMEV2.ordinal()] = INVALID_TYPE; compatibilityMatrix[DECIMALV2.ordinal()][DECIMALV2.ordinal()] = DECIMALV2; compatibilityMatrix[DECIMALV2.ordinal()][TIME.ordinal()] = INVALID_TYPE; + compatibilityMatrix[DECIMALV2.ordinal()][TIMEV2.ordinal()] = INVALID_TYPE; compatibilityMatrix[HLL.ordinal()][HLL.ordinal()] = HLL; compatibilityMatrix[HLL.ordinal()][TIME.ordinal()] = INVALID_TYPE; + compatibilityMatrix[HLL.ordinal()][TIMEV2.ordinal()] = INVALID_TYPE; compatibilityMatrix[BITMAP.ordinal()][BITMAP.ordinal()] = BITMAP; compatibilityMatrix[TIME.ordinal()][TIME.ordinal()] = TIME; + compatibilityMatrix[TIME.ordinal()][TIMEV2.ordinal()] = TIMEV2; + + compatibilityMatrix[TIMEV2.ordinal()][TIME.ordinal()] = TIMEV2; + compatibilityMatrix[TIMEV2.ordinal()][TIMEV2.ordinal()] = TIMEV2; compatibilityMatrix[QUANTILE_STATE.ordinal()][QUANTILE_STATE.ordinal()] = QUANTILE_STATE; } @@ -601,12 +735,18 @@ public static PrimitiveType fromThrift(TPrimitiveType tPrimitiveType) { return DATE; case DATETIME: return DATETIME; + case DATEV2: + return DATEV2; + case DATETIMEV2: + return DATETIMEV2; case BINARY: return BINARY; case DECIMALV2: return DECIMALV2; case TIME: return TIME; + case TIMEV2: + return TIMEV2; case VARCHAR: return VARCHAR; case STRING: @@ -712,7 +852,11 @@ public boolean isNull() { } public boolean isDateType() { - return (this == DATE || this == DATETIME); + return (this == DATE || this == DATETIME || this == DATEV2 || this == DATETIMEV2); + } + + public boolean isDateV2Type() { + return (this == DATEV2 || this == DATETIMEV2); } public boolean isArrayType() { @@ -750,10 +894,13 @@ public MysqlColType toMysqlType() { case DOUBLE: return MysqlColType.MYSQL_TYPE_DOUBLE; case TIME: + case TIMEV2: return MysqlColType.MYSQL_TYPE_TIME; case DATE: + case DATEV2: return MysqlColType.MYSQL_TYPE_DATE; - case DATETIME: { + case DATETIME: + case DATETIMEV2: { if (isTimeType) { return MysqlColType.MYSQL_TYPE_TIME; } else { @@ -772,8 +919,10 @@ public MysqlColType toMysqlType() { public int getOlapColumnIndexSize() { switch (this) { case DATE: + case DATEV2: return DATE_INDEX_LEN; case DATETIME: + case DATETIMEV2: return DATETIME_INDEX_LEN; case VARCHAR: return VARCHAR_INDEX_LEN; diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/RangePartitionInfo.java b/fe/fe-core/src/main/java/org/apache/doris/catalog/RangePartitionInfo.java index 090c78c4e27b38..b26b61bfd150fd 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/catalog/RangePartitionInfo.java +++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/RangePartitionInfo.java @@ -79,11 +79,12 @@ public List> getPartitionItemEntryList(boolean is // create a new range and check it. private Range createAndCheckNewRange(PartitionKeyDesc partKeyDesc, boolean isTemp) throws AnalysisException, DdlException { - boolean isFixedPartitionKeyValueType = partKeyDesc.getPartitionType() == PartitionKeyDesc.PartitionKeyValueType.FIXED; + boolean isFixedPartitionKeyValueType = + partKeyDesc.getPartitionType() == PartitionKeyDesc.PartitionKeyValueType.FIXED; // generate partitionItemEntryList List> partitionItemEntryList = isFixedPartitionKeyValueType - ? getPartitionItemEntryList(isTemp, false) : getPartitionItemEntryList(isTemp, true); + ? getPartitionItemEntryList(isTemp, false) : getPartitionItemEntryList(isTemp, true); if (isFixedPartitionKeyValueType) { return createNewRangeForFixedPartitionValueType(partKeyDesc, partitionItemEntryList); @@ -138,8 +139,8 @@ private Range createNewRangeForFixedPartitionValueType(PartitionKe private Range createNewRangeForLessThanPartitionValueType(PartitionKey newRangeUpper, Range lastRange, Range currentRange) throws AnalysisException, DdlException { - PartitionKey lowKey = lastRange == null ? PartitionKey.createInfinityPartitionKey(partitionColumns, false) - : lastRange.upperEndpoint(); + PartitionKey lowKey = lastRange == null + ? PartitionKey.createInfinityPartitionKey(partitionColumns, false) : lastRange.upperEndpoint(); // check: [left, right), error if left equal right if (lowKey.compareTo(newRangeUpper) >= 0) { diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/ScalarFunction.java b/fe/fe-core/src/main/java/org/apache/doris/catalog/ScalarFunction.java index c87fd6548191b3..83e309db4f2e0e 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/catalog/ScalarFunction.java +++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/ScalarFunction.java @@ -152,6 +152,7 @@ public static ScalarFunction createBuiltinOperator( break; case DOUBLE: case TIME: + case TIMEV2: beFn += "_double_val"; break; case CHAR: @@ -164,6 +165,8 @@ public static ScalarFunction createBuiltinOperator( break; case DATE: case DATETIME: + case DATEV2: + case DATETIMEV2: beFn += "_datetime_val"; break; case DECIMALV2: @@ -226,6 +229,7 @@ public static ScalarFunction createVecBuiltinOperator( break; case DOUBLE: case TIME: + case TIMEV2: beFn.append("_double_val"); break; case CHAR: @@ -236,6 +240,8 @@ public static ScalarFunction createVecBuiltinOperator( break; case DATE: case DATETIME: + case DATEV2: + case DATETIMEV2: beFn.append("_datetime_val"); break; case DECIMALV2: diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/ScalarType.java b/fe/fe-core/src/main/java/org/apache/doris/catalog/ScalarType.java index bb9a7a952055cc..d4e40256c55d3f 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/catalog/ScalarType.java +++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/ScalarType.java @@ -17,6 +17,7 @@ package org.apache.doris.catalog; +import org.apache.doris.common.Config; import org.apache.doris.common.io.Text; import org.apache.doris.persist.gson.GsonUtils; import org.apache.doris.thrift.TColumnType; @@ -47,7 +48,8 @@ * indicating that any decimal type is a subtype of the decimal type. */ public class ScalarType extends Type { - private static final Logger LOG = LogManager.getLogger(ScalarType.class); + // We use a fixed-length decimal type to represent a date time. + public static final int DATETIME_PRECISION = 18; // SQL allows the engine to pick the default precision. We pick the largest // precision that is supported by the smallest decimal type in the BE (4 bytes). @@ -74,6 +76,7 @@ public class ScalarType extends Type { // Hive, mysql, sql server standard. public static final int MAX_PRECISION = 38; + private static final Logger LOG = LogManager.getLogger(ScalarType.class); @SerializedName(value = "type") private final PrimitiveType type; @@ -157,6 +160,12 @@ public static ScalarType createType(PrimitiveType type) { return DATE; case DATETIME: return DATETIME; + case DATEV2: + return DATEV2; + case DATETIMEV2: + return DEFAULT_DATETIMEV2; + case TIMEV2: + return TIMEV2; case TIME: return TIME; case DECIMALV2: @@ -209,6 +218,10 @@ public static ScalarType createType(String type) { return DATE; case "DATETIME": return DATETIME; + case "DATEV2": + return DATEV2; + case "DATETIMEV2": + return DATETIMEV2; case "TIME": return TIME; case "DECIMAL": @@ -279,6 +292,53 @@ public static ScalarType createDecimalV2TypeInternal(int precision, int scale) { return type; } + @SuppressWarnings("checkstyle:MissingJavadocMethod") + public static ScalarType createDatetimeV2Type(int scale) { + ScalarType type = new ScalarType(PrimitiveType.DATETIMEV2); + type.precision = DATETIME_PRECISION; + type.scale = scale; + return type; + } + + @SuppressWarnings("checkstyle:MissingJavadocMethod") + public static ScalarType createTimeV2Type(int scale) { + ScalarType type = new ScalarType(PrimitiveType.TIMEV2); + type.precision = DATETIME_PRECISION; + type.scale = scale; + return type; + } + + @SuppressWarnings("checkstyle:MissingJavadocMethod") + public static ScalarType createDatetimeType() { + if (!Config.use_date_v2_by_default) { + return new ScalarType(PrimitiveType.DATETIME); + } + ScalarType type = new ScalarType(PrimitiveType.DATETIMEV2); + type.precision = DATETIME_PRECISION; + type.scale = 0; + return type; + } + + @SuppressWarnings("checkstyle:MissingJavadocMethod") + public static ScalarType createDateType() { + if (Config.use_date_v2_by_default) { + return new ScalarType(PrimitiveType.DATEV2); + } else { + return new ScalarType(PrimitiveType.DATE); + } + } + + @SuppressWarnings("checkstyle:MissingJavadocMethod") + public static ScalarType createTimeType() { + if (!Config.use_date_v2_by_default) { + return new ScalarType(PrimitiveType.TIME); + } + ScalarType type = new ScalarType(PrimitiveType.TIMEV2); + type.precision = DATETIME_PRECISION; + type.scale = 0; + return type; + } + public static ScalarType createVarcharType(int len) { // length checked in analysis ScalarType type = new ScalarType(PrimitiveType.VARCHAR); @@ -329,6 +389,10 @@ public String toString() { return "DECIMAL(*,*)"; } return "DECIMAL(" + precision + "," + scale + ")"; + } else if (type == PrimitiveType.DATETIMEV2) { + return "Datetime(" + scale + ")"; + } else if (type == PrimitiveType.TIMEV2) { + return "Time(" + scale + ")"; } else if (type == PrimitiveType.VARCHAR) { if (isWildcardVarchar()) { return "VARCHAR(*)"; @@ -367,6 +431,12 @@ public String toSql(int depth) { stringBuilder.append("decimal").append("(`").append(precisionStr).append("`)"); } break; + case DATETIMEV2: + stringBuilder.append("datetime").append("(").append(scale).append(")"); + break; + case TIMEV2: + stringBuilder.append("time").append("(").append(scale).append(")"); + break; case BOOLEAN: return "boolean"; case TINYINT: @@ -383,6 +453,7 @@ public String toSql(int depth) { case DOUBLE: case DATE: case DATETIME: + case DATEV2: case HLL: case BITMAP: case QUANTILE_STATE: @@ -434,12 +505,14 @@ public void toThrift(TTypeDesc container) { } public int decimalPrecision() { - Preconditions.checkState(type == PrimitiveType.DECIMALV2); + Preconditions.checkState(type == PrimitiveType.DECIMALV2 || type == PrimitiveType.DATETIMEV2 + || type == PrimitiveType.TIMEV2); return precision; } public int decimalScale() { - Preconditions.checkState(type == PrimitiveType.DECIMALV2); + Preconditions.checkState(type == PrimitiveType.DECIMALV2 || type == PrimitiveType.DATETIMEV2 + || type == PrimitiveType.TIMEV2); return scale; } @@ -513,7 +586,8 @@ public boolean isFixedLengthType() { || type == PrimitiveType.BIGINT || type == PrimitiveType.FLOAT || type == PrimitiveType.DOUBLE || type == PrimitiveType.DATE || type == PrimitiveType.DATETIME || type == PrimitiveType.DECIMALV2 - || type == PrimitiveType.CHAR; + || type == PrimitiveType.CHAR || type == PrimitiveType.DATEV2 || type == PrimitiveType.DATETIMEV2 + || type == PrimitiveType.TIMEV2; } @Override @@ -583,6 +657,18 @@ public boolean equals(Object o) { return false; } ScalarType other = (ScalarType) o; + if ((this.isDate() && other.isDateV2()) || (this.isDateV2() && other.isDate())) { + return true; + } + if ((this.isDatetime() && other.isDatetimeV2()) || (this.isTime() && other.isTimeV2())) { + return other.decimalScale() == 0; + } + if ((this.isDatetimeV2() && other.isDatetime()) || (this.isTimeV2() && other.isTime())) { + return this.decimalScale() == 0; + } + if ((this.isDatetimeV2() && other.isDatetimeV2()) || (this.isTimeV2() && other.isTimeV2())) { + return this.decimalScale() == other.decimalScale(); + } if (type != other.type) { return false; } @@ -592,7 +678,7 @@ public boolean equals(Object o) { if (type == PrimitiveType.VARCHAR) { return len == other.len; } - if (type == PrimitiveType.DECIMALV2) { + if (type == PrimitiveType.DECIMALV2 || type == PrimitiveType.DATETIMEV2 || type == PrimitiveType.TIMEV2) { return precision == other.precision && scale == other.scale; } return true; @@ -610,6 +696,10 @@ public Type getMaxResolutionType() { return createDecimalV2TypeInternal(MAX_PRECISION, scale); } else if (isLargeIntType()) { return ScalarType.LARGEINT; + } else if (isDatetimeV2()) { + return createDatetimeV2Type(6); + } else if (isTimeV2()) { + return createTimeV2Type(6); } else { return ScalarType.INVALID; } @@ -621,6 +711,10 @@ public ScalarType getNextResolutionType() { return this; } else if (type == PrimitiveType.DECIMALV2) { return createDecimalV2TypeInternal(MAX_PRECISION, scale); + } else if (type == PrimitiveType.DATETIMEV2) { + return createDatetimeV2Type(6); + } else if (type == PrimitiveType.TIMEV2) { + return createTimeV2Type(6); } return createType(PrimitiveType.values()[type.ordinal() + 1]); } @@ -772,12 +866,16 @@ public int getStorageLayoutBytes() { case BIGINT: case TIME: case DATETIME: + // TODO(Gabriel): unify execution engine and storage engine + case TIMEV2: + case DATETIMEV2: return 8; case LARGEINT: case DECIMALV2: return 16; case DOUBLE: return 12; + case DATEV2: case DATE: return 3; case CHAR: @@ -803,7 +901,7 @@ public TColumnType toColumnTypeThrift() { if (type == PrimitiveType.CHAR || type == PrimitiveType.VARCHAR || type == PrimitiveType.HLL) { thrift.setLen(len); } - if (type == PrimitiveType.DECIMALV2) { + if (type == PrimitiveType.DECIMALV2 || type == PrimitiveType.DATETIMEV2 || type == PrimitiveType.TIMEV2) { thrift.setPrecision(precision); thrift.setScale(scale); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/Type.java b/fe/fe-core/src/main/java/org/apache/doris/catalog/Type.java index 0ffbcdd37a552e..079d8b3e5a2dda 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/catalog/Type.java +++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/Type.java @@ -17,8 +17,10 @@ package org.apache.doris.catalog; +import org.apache.doris.analysis.DateLiteral; import org.apache.doris.analysis.Expr; import org.apache.doris.analysis.StringLiteral; +import org.apache.doris.common.AnalysisException; import org.apache.doris.common.DdlException; import org.apache.doris.common.Pair; import org.apache.doris.thrift.TColumnType; @@ -44,8 +46,6 @@ * as abstract methods that subclasses must implement. */ public abstract class Type { - private static final Logger LOG = LogManager.getLogger(Type.class); - // Maximum nesting depth of a type. This limit was determined experimentally by // org.apache.doris.rewrite.FoldConstantsRule.apply generating and scanning // deeply nested Parquet and Avro files. In those experiments, we exceeded @@ -66,17 +66,21 @@ public abstract class Type { public static final ScalarType DOUBLE = new ScalarType(PrimitiveType.DOUBLE); public static final ScalarType DATE = new ScalarType(PrimitiveType.DATE); public static final ScalarType DATETIME = new ScalarType(PrimitiveType.DATETIME); + public static final ScalarType DATEV2 = new ScalarType(PrimitiveType.DATEV2); + public static final ScalarType TIMEV2 = new ScalarType(PrimitiveType.TIMEV2); public static final ScalarType TIME = new ScalarType(PrimitiveType.TIME); public static final ScalarType STRING = new ScalarType(PrimitiveType.STRING); - public static final ScalarType DEFAULT_DECIMALV2 = (ScalarType) - ScalarType.createDecimalV2Type(ScalarType.DEFAULT_PRECISION, - ScalarType.DEFAULT_SCALE); + public static final ScalarType DEFAULT_DECIMALV2 = + ScalarType.createDecimalV2Type(ScalarType.DEFAULT_PRECISION, ScalarType.DEFAULT_SCALE); + public static final ScalarType DEFAULT_DATETIMEV2 = ScalarType.createDatetimeV2Type(0); + public static final ScalarType DATETIMEV2 = DEFAULT_DATETIMEV2; + public static final ScalarType DEFAULT_TIMEV2 = ScalarType.createTimeV2Type(0); public static final ScalarType DECIMALV2 = DEFAULT_DECIMALV2; // (ScalarType) ScalarType.createDecimalTypeInternal(-1, -1); public static final ScalarType DEFAULT_VARCHAR = ScalarType.createVarcharType(-1); public static final ScalarType VARCHAR = ScalarType.createVarcharType(-1); public static final ScalarType HLL = ScalarType.createHllType(); - public static final ScalarType CHAR = (ScalarType) ScalarType.createCharType(-1); + public static final ScalarType CHAR = ScalarType.createCharType(-1); public static final ScalarType BITMAP = new ScalarType(PrimitiveType.BITMAP); public static final ScalarType QUANTILE_STATE = new ScalarType(PrimitiveType.QUANTILE_STATE); // Only used for alias function, to represent any type in function args @@ -85,9 +89,10 @@ public abstract class Type { public static final ArrayType ARRAY = ArrayType.create(); public static final StructType STRUCT = new StructType(); - private static ArrayList integerTypes; - private static ArrayList numericTypes; - private static ArrayList supportedTypes; + private static final Logger LOG = LogManager.getLogger(Type.class); + private static final ArrayList integerTypes; + private static final ArrayList numericTypes; + private static final ArrayList supportedTypes; static { integerTypes = Lists.newArrayList(); @@ -124,8 +129,11 @@ public abstract class Type { supportedTypes.add(CHAR); supportedTypes.add(DATE); supportedTypes.add(DATETIME); + supportedTypes.add(DATEV2); + supportedTypes.add(DATETIMEV2); supportedTypes.add(DECIMALV2); supportedTypes.add(TIME); + supportedTypes.add(TIMEV2); supportedTypes.add(STRING); } @@ -186,14 +194,20 @@ public boolean isDecimalV2() { return isScalarType(PrimitiveType.DECIMALV2); } + public boolean isDatetimeV2() { + return isScalarType(PrimitiveType.DATETIMEV2); + } + + public boolean isTimeV2() { + return isScalarType(PrimitiveType.TIMEV2); + } + public boolean isWildcardDecimal() { return false; } - public boolean isWildcardVarchar() { return false; } - public boolean isWildcardChar() { return false; } @@ -285,7 +299,8 @@ public boolean isNativeType() { } public boolean isDateType() { - return isScalarType(PrimitiveType.DATE) || isScalarType(PrimitiveType.DATETIME); + return isScalarType(PrimitiveType.DATE) || isScalarType(PrimitiveType.DATETIME) + || isScalarType(PrimitiveType.DATEV2) || isScalarType(PrimitiveType.DATETIMEV2); } public boolean isDatetime() { @@ -323,6 +338,10 @@ public boolean isStructType() { public boolean isDate() { return isScalarType(PrimitiveType.DATE); } + + public boolean isDateV2() { + return isScalarType(PrimitiveType.DATEV2); + } /** * Returns true if Impala supports this type in the metdata. It does not mean we * can manipulate data of this type. For tables that contain columns with these @@ -545,6 +564,12 @@ public static Type fromPrimitiveType(PrimitiveType type) { return Type.DATETIME; case TIME: return Type.TIME; + case DATEV2: + return Type.DATEV2; + case DATETIMEV2: + return Type.DATETIMEV2; + case TIMEV2: + return Type.TIMEV2; case DECIMALV2: return Type.DECIMALV2; case CHAR: @@ -614,6 +639,14 @@ protected static Pair fromThrift(TTypeDesc col, int nodeIdx) { && scalarType.isSetPrecision()); type = ScalarType.createDecimalV2Type(scalarType.getPrecision(), scalarType.getScale()); + } else if (scalarType.getType() == TPrimitiveType.DATETIMEV2) { + Preconditions.checkState(scalarType.isSetPrecision() + && scalarType.isSetScale()); + type = ScalarType.createDatetimeV2Type(scalarType.getScale()); + } else if (scalarType.getType() == TPrimitiveType.TIMEV2) { + Preconditions.checkState(scalarType.isSetPrecision() + && scalarType.isSetScale()); + type = ScalarType.createTimeV2Type(scalarType.getScale()); } else { type = ScalarType.createType( PrimitiveType.fromThrift(scalarType.getType())); @@ -753,6 +786,8 @@ public Integer getPrecision() { case DOUBLE: return 15; case DECIMALV2: + case DATETIMEV2: + case TIMEV2: return t.decimalPrecision(); default: return null; @@ -781,6 +816,8 @@ public Integer getDecimalDigits() { return 7; case DOUBLE: return 15; + case DATETIMEV2: + case TIMEV2: case DECIMALV2: return t.decimalScale(); default: @@ -865,6 +902,9 @@ public Integer getNumPrecRadix() { compatibilityMatrix[BOOLEAN.ordinal()][DOUBLE.ordinal()] = PrimitiveType.DOUBLE; compatibilityMatrix[BOOLEAN.ordinal()][DATE.ordinal()] = PrimitiveType.INVALID_TYPE; compatibilityMatrix[BOOLEAN.ordinal()][DATETIME.ordinal()] = PrimitiveType.INVALID_TYPE; + compatibilityMatrix[BOOLEAN.ordinal()][DATEV2.ordinal()] = PrimitiveType.INVALID_TYPE; + compatibilityMatrix[BOOLEAN.ordinal()][DATETIMEV2.ordinal()] = PrimitiveType.INVALID_TYPE; + compatibilityMatrix[BOOLEAN.ordinal()][TIMEV2.ordinal()] = PrimitiveType.DOUBLE; compatibilityMatrix[BOOLEAN.ordinal()][CHAR.ordinal()] = PrimitiveType.INVALID_TYPE; compatibilityMatrix[BOOLEAN.ordinal()][VARCHAR.ordinal()] = PrimitiveType.INVALID_TYPE; compatibilityMatrix[BOOLEAN.ordinal()][HLL.ordinal()] = PrimitiveType.INVALID_TYPE; @@ -884,6 +924,9 @@ public Integer getNumPrecRadix() { compatibilityMatrix[TINYINT.ordinal()][DOUBLE.ordinal()] = PrimitiveType.DOUBLE; compatibilityMatrix[TINYINT.ordinal()][DATE.ordinal()] = PrimitiveType.INVALID_TYPE; compatibilityMatrix[TINYINT.ordinal()][DATETIME.ordinal()] = PrimitiveType.INVALID_TYPE; + compatibilityMatrix[TINYINT.ordinal()][DATEV2.ordinal()] = PrimitiveType.INVALID_TYPE; + compatibilityMatrix[TINYINT.ordinal()][DATETIMEV2.ordinal()] = PrimitiveType.INVALID_TYPE; + compatibilityMatrix[TINYINT.ordinal()][TIMEV2.ordinal()] = PrimitiveType.DOUBLE; compatibilityMatrix[TINYINT.ordinal()][CHAR.ordinal()] = PrimitiveType.INVALID_TYPE; compatibilityMatrix[TINYINT.ordinal()][VARCHAR.ordinal()] = PrimitiveType.INVALID_TYPE; compatibilityMatrix[TINYINT.ordinal()][DECIMALV2.ordinal()] = PrimitiveType.INVALID_TYPE; @@ -902,6 +945,9 @@ public Integer getNumPrecRadix() { compatibilityMatrix[SMALLINT.ordinal()][DOUBLE.ordinal()] = PrimitiveType.DOUBLE; compatibilityMatrix[SMALLINT.ordinal()][DATE.ordinal()] = PrimitiveType.INVALID_TYPE; compatibilityMatrix[SMALLINT.ordinal()][DATETIME.ordinal()] = PrimitiveType.INVALID_TYPE; + compatibilityMatrix[SMALLINT.ordinal()][DATEV2.ordinal()] = PrimitiveType.INVALID_TYPE; + compatibilityMatrix[SMALLINT.ordinal()][DATETIMEV2.ordinal()] = PrimitiveType.INVALID_TYPE; + compatibilityMatrix[SMALLINT.ordinal()][TIMEV2.ordinal()] = PrimitiveType.DOUBLE; compatibilityMatrix[SMALLINT.ordinal()][CHAR.ordinal()] = PrimitiveType.INVALID_TYPE; compatibilityMatrix[SMALLINT.ordinal()][VARCHAR.ordinal()] = PrimitiveType.INVALID_TYPE; compatibilityMatrix[SMALLINT.ordinal()][DECIMALV2.ordinal()] = PrimitiveType.INVALID_TYPE; @@ -923,6 +969,9 @@ public Integer getNumPrecRadix() { compatibilityMatrix[INT.ordinal()][DOUBLE.ordinal()] = PrimitiveType.DOUBLE; compatibilityMatrix[INT.ordinal()][DATE.ordinal()] = PrimitiveType.INT; compatibilityMatrix[INT.ordinal()][DATETIME.ordinal()] = PrimitiveType.INVALID_TYPE; + compatibilityMatrix[INT.ordinal()][DATEV2.ordinal()] = PrimitiveType.INT; + compatibilityMatrix[INT.ordinal()][DATETIMEV2.ordinal()] = PrimitiveType.INVALID_TYPE; + compatibilityMatrix[INT.ordinal()][TIMEV2.ordinal()] = PrimitiveType.DOUBLE; compatibilityMatrix[INT.ordinal()][CHAR.ordinal()] = PrimitiveType.INVALID_TYPE; compatibilityMatrix[INT.ordinal()][VARCHAR.ordinal()] = PrimitiveType.INVALID_TYPE; compatibilityMatrix[INT.ordinal()][DECIMALV2.ordinal()] = PrimitiveType.INVALID_TYPE; @@ -946,6 +995,9 @@ public Integer getNumPrecRadix() { compatibilityMatrix[BIGINT.ordinal()][DOUBLE.ordinal()] = PrimitiveType.DOUBLE; compatibilityMatrix[BIGINT.ordinal()][DATE.ordinal()] = PrimitiveType.BIGINT; compatibilityMatrix[BIGINT.ordinal()][DATETIME.ordinal()] = PrimitiveType.BIGINT; + compatibilityMatrix[BIGINT.ordinal()][DATEV2.ordinal()] = PrimitiveType.BIGINT; + compatibilityMatrix[BIGINT.ordinal()][DATETIMEV2.ordinal()] = PrimitiveType.BIGINT; + compatibilityMatrix[BIGINT.ordinal()][TIMEV2.ordinal()] = PrimitiveType.DOUBLE; compatibilityMatrix[BIGINT.ordinal()][CHAR.ordinal()] = PrimitiveType.INVALID_TYPE; compatibilityMatrix[BIGINT.ordinal()][VARCHAR.ordinal()] = PrimitiveType.INVALID_TYPE; compatibilityMatrix[BIGINT.ordinal()][DECIMALV2.ordinal()] = PrimitiveType.INVALID_TYPE; @@ -960,6 +1012,9 @@ public Integer getNumPrecRadix() { compatibilityMatrix[LARGEINT.ordinal()][DOUBLE.ordinal()] = PrimitiveType.DOUBLE; compatibilityMatrix[LARGEINT.ordinal()][DATE.ordinal()] = PrimitiveType.LARGEINT; compatibilityMatrix[LARGEINT.ordinal()][DATETIME.ordinal()] = PrimitiveType.LARGEINT; + compatibilityMatrix[LARGEINT.ordinal()][DATEV2.ordinal()] = PrimitiveType.LARGEINT; + compatibilityMatrix[LARGEINT.ordinal()][DATETIMEV2.ordinal()] = PrimitiveType.LARGEINT; + compatibilityMatrix[LARGEINT.ordinal()][TIMEV2.ordinal()] = PrimitiveType.DOUBLE; compatibilityMatrix[LARGEINT.ordinal()][CHAR.ordinal()] = PrimitiveType.INVALID_TYPE; compatibilityMatrix[LARGEINT.ordinal()][VARCHAR.ordinal()] = PrimitiveType.INVALID_TYPE; compatibilityMatrix[LARGEINT.ordinal()][DECIMALV2.ordinal()] = PrimitiveType.DECIMALV2; @@ -973,6 +1028,9 @@ public Integer getNumPrecRadix() { compatibilityMatrix[FLOAT.ordinal()][DOUBLE.ordinal()] = PrimitiveType.DOUBLE; compatibilityMatrix[FLOAT.ordinal()][DATE.ordinal()] = PrimitiveType.INVALID_TYPE; compatibilityMatrix[FLOAT.ordinal()][DATETIME.ordinal()] = PrimitiveType.INVALID_TYPE; + compatibilityMatrix[FLOAT.ordinal()][DATEV2.ordinal()] = PrimitiveType.INVALID_TYPE; + compatibilityMatrix[FLOAT.ordinal()][DATETIMEV2.ordinal()] = PrimitiveType.INVALID_TYPE; + compatibilityMatrix[FLOAT.ordinal()][TIMEV2.ordinal()] = PrimitiveType.DOUBLE; compatibilityMatrix[FLOAT.ordinal()][CHAR.ordinal()] = PrimitiveType.INVALID_TYPE; compatibilityMatrix[FLOAT.ordinal()][VARCHAR.ordinal()] = PrimitiveType.INVALID_TYPE; compatibilityMatrix[FLOAT.ordinal()][DECIMALV2.ordinal()] = PrimitiveType.INVALID_TYPE; @@ -993,34 +1051,73 @@ public Integer getNumPrecRadix() { compatibilityMatrix[DOUBLE.ordinal()][BITMAP.ordinal()] = PrimitiveType.INVALID_TYPE; compatibilityMatrix[DOUBLE.ordinal()][STRING.ordinal()] = PrimitiveType.INVALID_TYPE; compatibilityMatrix[DOUBLE.ordinal()][QUANTILE_STATE.ordinal()] = PrimitiveType.INVALID_TYPE; + compatibilityMatrix[DOUBLE.ordinal()][DATEV2.ordinal()] = PrimitiveType.INVALID_TYPE; + compatibilityMatrix[DOUBLE.ordinal()][DATETIMEV2.ordinal()] = PrimitiveType.DOUBLE; + compatibilityMatrix[DOUBLE.ordinal()][TIMEV2.ordinal()] = PrimitiveType.DOUBLE; // DATE compatibilityMatrix[DATE.ordinal()][DATETIME.ordinal()] = PrimitiveType.DATETIME; + compatibilityMatrix[DATE.ordinal()][DATEV2.ordinal()] = PrimitiveType.DATEV2; + compatibilityMatrix[DATE.ordinal()][DATETIMEV2.ordinal()] = PrimitiveType.DATETIMEV2; compatibilityMatrix[DATE.ordinal()][CHAR.ordinal()] = PrimitiveType.INVALID_TYPE; compatibilityMatrix[DATE.ordinal()][VARCHAR.ordinal()] = PrimitiveType.INVALID_TYPE; compatibilityMatrix[DATE.ordinal()][DECIMALV2.ordinal()] = PrimitiveType.DECIMALV2; compatibilityMatrix[DATE.ordinal()][HLL.ordinal()] = PrimitiveType.INVALID_TYPE; compatibilityMatrix[DATE.ordinal()][TIME.ordinal()] = PrimitiveType.INVALID_TYPE; + compatibilityMatrix[DATE.ordinal()][TIMEV2.ordinal()] = PrimitiveType.INVALID_TYPE; compatibilityMatrix[DATE.ordinal()][BITMAP.ordinal()] = PrimitiveType.INVALID_TYPE; compatibilityMatrix[DATE.ordinal()][STRING.ordinal()] = PrimitiveType.INVALID_TYPE; compatibilityMatrix[DATE.ordinal()][QUANTILE_STATE.ordinal()] = PrimitiveType.INVALID_TYPE; + // DATEV2 + compatibilityMatrix[DATEV2.ordinal()][DATE.ordinal()] = PrimitiveType.DATEV2; + compatibilityMatrix[DATEV2.ordinal()][DATETIME.ordinal()] = PrimitiveType.DATETIMEV2; + compatibilityMatrix[DATEV2.ordinal()][DATETIMEV2.ordinal()] = PrimitiveType.DATETIMEV2; + compatibilityMatrix[DATEV2.ordinal()][CHAR.ordinal()] = PrimitiveType.INVALID_TYPE; + compatibilityMatrix[DATEV2.ordinal()][VARCHAR.ordinal()] = PrimitiveType.INVALID_TYPE; + compatibilityMatrix[DATEV2.ordinal()][DECIMALV2.ordinal()] = PrimitiveType.DECIMALV2; + compatibilityMatrix[DATEV2.ordinal()][HLL.ordinal()] = PrimitiveType.INVALID_TYPE; + compatibilityMatrix[DATEV2.ordinal()][TIME.ordinal()] = PrimitiveType.INVALID_TYPE; + compatibilityMatrix[DATEV2.ordinal()][TIMEV2.ordinal()] = PrimitiveType.INVALID_TYPE; + compatibilityMatrix[DATEV2.ordinal()][BITMAP.ordinal()] = PrimitiveType.INVALID_TYPE; + compatibilityMatrix[DATEV2.ordinal()][STRING.ordinal()] = PrimitiveType.INVALID_TYPE; + compatibilityMatrix[DATEV2.ordinal()][QUANTILE_STATE.ordinal()] = PrimitiveType.INVALID_TYPE; + // DATETIME compatibilityMatrix[DATETIME.ordinal()][CHAR.ordinal()] = PrimitiveType.INVALID_TYPE; + compatibilityMatrix[DATETIME.ordinal()][DATETIMEV2.ordinal()] = PrimitiveType.DATETIMEV2; + compatibilityMatrix[DATETIME.ordinal()][DATEV2.ordinal()] = PrimitiveType.DATETIMEV2; compatibilityMatrix[DATETIME.ordinal()][VARCHAR.ordinal()] = PrimitiveType.INVALID_TYPE; compatibilityMatrix[DATETIME.ordinal()][DECIMALV2.ordinal()] = PrimitiveType.DECIMALV2; compatibilityMatrix[DATETIME.ordinal()][HLL.ordinal()] = PrimitiveType.INVALID_TYPE; compatibilityMatrix[DATETIME.ordinal()][TIME.ordinal()] = PrimitiveType.INVALID_TYPE; + compatibilityMatrix[DATETIME.ordinal()][TIMEV2.ordinal()] = PrimitiveType.INVALID_TYPE; compatibilityMatrix[DATETIME.ordinal()][BITMAP.ordinal()] = PrimitiveType.INVALID_TYPE; compatibilityMatrix[DATETIME.ordinal()][STRING.ordinal()] = PrimitiveType.INVALID_TYPE; compatibilityMatrix[DATETIME.ordinal()][QUANTILE_STATE.ordinal()] = PrimitiveType.INVALID_TYPE; + // DATETIMEV2 + compatibilityMatrix[DATETIMEV2.ordinal()][CHAR.ordinal()] = PrimitiveType.INVALID_TYPE; + compatibilityMatrix[DATETIMEV2.ordinal()][DATETIME.ordinal()] = PrimitiveType.DATETIMEV2; + compatibilityMatrix[DATETIMEV2.ordinal()][DATEV2.ordinal()] = PrimitiveType.DATETIMEV2; + compatibilityMatrix[DATETIMEV2.ordinal()][VARCHAR.ordinal()] = PrimitiveType.INVALID_TYPE; + compatibilityMatrix[DATETIMEV2.ordinal()][DECIMALV2.ordinal()] = PrimitiveType.DECIMALV2; + compatibilityMatrix[DATETIMEV2.ordinal()][HLL.ordinal()] = PrimitiveType.INVALID_TYPE; + compatibilityMatrix[DATETIMEV2.ordinal()][TIME.ordinal()] = PrimitiveType.INVALID_TYPE; + compatibilityMatrix[DATETIMEV2.ordinal()][TIMEV2.ordinal()] = PrimitiveType.INVALID_TYPE; + compatibilityMatrix[DATETIMEV2.ordinal()][BITMAP.ordinal()] = PrimitiveType.INVALID_TYPE; + compatibilityMatrix[DATETIMEV2.ordinal()][STRING.ordinal()] = PrimitiveType.INVALID_TYPE; + compatibilityMatrix[DATETIMEV2.ordinal()][QUANTILE_STATE.ordinal()] = PrimitiveType.INVALID_TYPE; + // We can convert some but not all string values to timestamps. // CHAR compatibilityMatrix[CHAR.ordinal()][VARCHAR.ordinal()] = PrimitiveType.VARCHAR; + compatibilityMatrix[CHAR.ordinal()][DATEV2.ordinal()] = PrimitiveType.INVALID_TYPE; + compatibilityMatrix[CHAR.ordinal()][DATETIMEV2.ordinal()] = PrimitiveType.INVALID_TYPE; compatibilityMatrix[CHAR.ordinal()][DECIMALV2.ordinal()] = PrimitiveType.INVALID_TYPE; compatibilityMatrix[CHAR.ordinal()][HLL.ordinal()] = PrimitiveType.INVALID_TYPE; compatibilityMatrix[CHAR.ordinal()][TIME.ordinal()] = PrimitiveType.INVALID_TYPE; + compatibilityMatrix[CHAR.ordinal()][TIMEV2.ordinal()] = PrimitiveType.INVALID_TYPE; compatibilityMatrix[CHAR.ordinal()][BITMAP.ordinal()] = PrimitiveType.INVALID_TYPE; compatibilityMatrix[CHAR.ordinal()][STRING.ordinal()] = PrimitiveType.STRING; compatibilityMatrix[CHAR.ordinal()][QUANTILE_STATE.ordinal()] = PrimitiveType.INVALID_TYPE; @@ -1029,6 +1126,9 @@ public Integer getNumPrecRadix() { compatibilityMatrix[VARCHAR.ordinal()][DECIMALV2.ordinal()] = PrimitiveType.INVALID_TYPE; compatibilityMatrix[VARCHAR.ordinal()][HLL.ordinal()] = PrimitiveType.INVALID_TYPE; compatibilityMatrix[VARCHAR.ordinal()][TIME.ordinal()] = PrimitiveType.INVALID_TYPE; + compatibilityMatrix[VARCHAR.ordinal()][TIMEV2.ordinal()] = PrimitiveType.INVALID_TYPE; + compatibilityMatrix[VARCHAR.ordinal()][DATETIMEV2.ordinal()] = PrimitiveType.INVALID_TYPE; + compatibilityMatrix[VARCHAR.ordinal()][DATEV2.ordinal()] = PrimitiveType.INVALID_TYPE; compatibilityMatrix[VARCHAR.ordinal()][BITMAP.ordinal()] = PrimitiveType.INVALID_TYPE; compatibilityMatrix[VARCHAR.ordinal()][STRING.ordinal()] = PrimitiveType.STRING; compatibilityMatrix[VARCHAR.ordinal()][QUANTILE_STATE.ordinal()] = PrimitiveType.INVALID_TYPE; @@ -1036,6 +1136,9 @@ public Integer getNumPrecRadix() { //String compatibilityMatrix[STRING.ordinal()][HLL.ordinal()] = PrimitiveType.INVALID_TYPE; compatibilityMatrix[STRING.ordinal()][TIME.ordinal()] = PrimitiveType.INVALID_TYPE; + compatibilityMatrix[STRING.ordinal()][TIMEV2.ordinal()] = PrimitiveType.INVALID_TYPE; + compatibilityMatrix[STRING.ordinal()][DATEV2.ordinal()] = PrimitiveType.INVALID_TYPE; + compatibilityMatrix[STRING.ordinal()][DATETIMEV2.ordinal()] = PrimitiveType.INVALID_TYPE; compatibilityMatrix[STRING.ordinal()][BITMAP.ordinal()] = PrimitiveType.INVALID_TYPE; compatibilityMatrix[STRING.ordinal()][QUANTILE_STATE.ordinal()] = PrimitiveType.INVALID_TYPE; @@ -1043,6 +1146,9 @@ public Integer getNumPrecRadix() { // DECIMALV2 compatibilityMatrix[DECIMALV2.ordinal()][HLL.ordinal()] = PrimitiveType.INVALID_TYPE; compatibilityMatrix[DECIMALV2.ordinal()][TIME.ordinal()] = PrimitiveType.INVALID_TYPE; + compatibilityMatrix[DECIMALV2.ordinal()][TIMEV2.ordinal()] = PrimitiveType.INVALID_TYPE; + compatibilityMatrix[DECIMALV2.ordinal()][DATEV2.ordinal()] = PrimitiveType.DECIMALV2; + compatibilityMatrix[DECIMALV2.ordinal()][DATETIMEV2.ordinal()] = PrimitiveType.DECIMALV2; compatibilityMatrix[DECIMALV2.ordinal()][BITMAP.ordinal()] = PrimitiveType.INVALID_TYPE; compatibilityMatrix[DECIMALV2.ordinal()][STRING.ordinal()] = PrimitiveType.INVALID_TYPE; compatibilityMatrix[DECIMALV2.ordinal()][QUANTILE_STATE.ordinal()] = PrimitiveType.INVALID_TYPE; @@ -1050,6 +1156,9 @@ public Integer getNumPrecRadix() { // HLL compatibilityMatrix[HLL.ordinal()][TIME.ordinal()] = PrimitiveType.INVALID_TYPE; + compatibilityMatrix[HLL.ordinal()][TIMEV2.ordinal()] = PrimitiveType.INVALID_TYPE; + compatibilityMatrix[HLL.ordinal()][DATEV2.ordinal()] = PrimitiveType.INVALID_TYPE; + compatibilityMatrix[HLL.ordinal()][DATETIMEV2.ordinal()] = PrimitiveType.INVALID_TYPE; compatibilityMatrix[HLL.ordinal()][BITMAP.ordinal()] = PrimitiveType.INVALID_TYPE; compatibilityMatrix[HLL.ordinal()][STRING.ordinal()] = PrimitiveType.INVALID_TYPE; compatibilityMatrix[HLL.ordinal()][QUANTILE_STATE.ordinal()] = PrimitiveType.INVALID_TYPE; @@ -1057,15 +1166,23 @@ public Integer getNumPrecRadix() { // BITMAP compatibilityMatrix[BITMAP.ordinal()][TIME.ordinal()] = PrimitiveType.INVALID_TYPE; + compatibilityMatrix[BITMAP.ordinal()][TIMEV2.ordinal()] = PrimitiveType.INVALID_TYPE; compatibilityMatrix[BITMAP.ordinal()][STRING.ordinal()] = PrimitiveType.INVALID_TYPE; compatibilityMatrix[BITMAP.ordinal()][QUANTILE_STATE.ordinal()] = PrimitiveType.INVALID_TYPE; + compatibilityMatrix[BITMAP.ordinal()][DATEV2.ordinal()] = PrimitiveType.INVALID_TYPE; + compatibilityMatrix[BITMAP.ordinal()][DATETIMEV2.ordinal()] = PrimitiveType.INVALID_TYPE; //QUANTILE_STATE compatibilityMatrix[QUANTILE_STATE.ordinal()][STRING.ordinal()] = PrimitiveType.INVALID_TYPE; + compatibilityMatrix[QUANTILE_STATE.ordinal()][DATEV2.ordinal()] = PrimitiveType.INVALID_TYPE; + compatibilityMatrix[QUANTILE_STATE.ordinal()][DATETIMEV2.ordinal()] = PrimitiveType.INVALID_TYPE; // TIME why here not??? compatibilityMatrix[TIME.ordinal()][TIME.ordinal()] = PrimitiveType.INVALID_TYPE; + compatibilityMatrix[TIME.ordinal()][TIMEV2.ordinal()] = PrimitiveType.INVALID_TYPE; + compatibilityMatrix[TIMEV2.ordinal()][TIMEV2.ordinal()] = PrimitiveType.INVALID_TYPE; + compatibilityMatrix[TIMEV2.ordinal()][TIME.ordinal()] = PrimitiveType.INVALID_TYPE; // Check all of the necessary entries that should be filled. // ignore binary and all @@ -1074,25 +1191,14 @@ public Integer getNumPrecRadix() { PrimitiveType t1 = PrimitiveType.values()[i]; PrimitiveType t2 = PrimitiveType.values()[j]; // DECIMAL, NULL, and INVALID_TYPE are handled separately. - if (t1 == PrimitiveType.INVALID_TYPE || t2 == PrimitiveType.INVALID_TYPE) { - continue; - } - if (t1 == PrimitiveType.NULL_TYPE || t2 == PrimitiveType.NULL_TYPE) { - continue; - } - if (t1 == PrimitiveType.DECIMALV2 || t2 == PrimitiveType.DECIMALV2) { - continue; - } - if (t1 == PrimitiveType.TIME || t2 == PrimitiveType.TIME) { - continue; - } - if (t1 == PrimitiveType.ARRAY || t2 == PrimitiveType.ARRAY) { - continue; - } - if (t1 == PrimitiveType.MAP || t2 == PrimitiveType.MAP) { - continue; - } - if (t1 == PrimitiveType.STRUCT || t2 == PrimitiveType.STRUCT) { + if (t1 == PrimitiveType.INVALID_TYPE || t2 == PrimitiveType.INVALID_TYPE + || t1 == PrimitiveType.NULL_TYPE || t2 == PrimitiveType.NULL_TYPE + || t1 == PrimitiveType.ARRAY || t2 == PrimitiveType.ARRAY + || t1 == PrimitiveType.DECIMALV2 || t2 == PrimitiveType.DECIMALV2 + || t1 == PrimitiveType.TIME || t2 == PrimitiveType.TIME + || t1 == PrimitiveType.TIMEV2 || t2 == PrimitiveType.TIMEV2 + || t1 == PrimitiveType.MAP || t2 == PrimitiveType.MAP + || t1 == PrimitiveType.STRUCT || t2 == PrimitiveType.STRUCT) { continue; } Preconditions.checkNotNull(compatibilityMatrix[i][j]); @@ -1114,6 +1220,7 @@ public Type getResultType() { case DOUBLE: return DOUBLE; case DATE: + case DATEV2: case DATETIME: case TIME: case CHAR: @@ -1122,6 +1229,10 @@ public Type getResultType() { case BITMAP: case QUANTILE_STATE: return VARCHAR; + case DATETIMEV2: + return DEFAULT_DATETIMEV2; + case TIMEV2: + return DEFAULT_TIMEV2; case DECIMALV2: return DECIMALV2; case STRING: @@ -1143,7 +1254,7 @@ public static Type getCmpType(Type t1, Type t2) { PrimitiveType t1ResultType = t1.getResultType().getPrimitiveType(); PrimitiveType t2ResultType = t2.getResultType().getPrimitiveType(); if (canCompareDate(t1.getPrimitiveType(), t2.getPrimitiveType())) { - return Type.DATETIME; + return getDateComparisonResultType((ScalarType) t1, (ScalarType) t2); } // Following logical is compatible with MySQL. @@ -1180,7 +1291,7 @@ public static Type getCmpType(Type t1, Type t2) { return Type.DOUBLE; } - public static boolean canCompareDate(PrimitiveType t1, PrimitiveType t2) { + private static boolean canCompareDate(PrimitiveType t1, PrimitiveType t2) { if (t1.isDateType()) { if (t2.isDateType() || t2.isStringType() || t2.isIntegerType()) { return true; @@ -1196,6 +1307,35 @@ public static boolean canCompareDate(PrimitiveType t1, PrimitiveType t2) { } } + private static Type getDateComparisonResultType(ScalarType t1, ScalarType t2) { + try { + if (t1.isDate() && t2.isDate()) { + return DateLiteral.getDefaultDateType(Type.DATE); + } else if ((t1.isDateV2() && t2.isDate()) || t1.isDate() && t2.isDateV2()) { + return Type.DATEV2; + } else if (t1.isDateV2() && t2.isDateV2()) { + return Type.DATEV2; + } else if (t1.isDatetime() && t2.isDatetime()) { + return DateLiteral.getDefaultDateType(Type.DATETIME); + } else if (t1.isDatetime() && t2.isDatetimeV2()) { + return t2; + } else if (t1.isDatetimeV2() && t2.isDatetime()) { + return t1; + } else if (t1.isDatetimeV2() && t2.isDatetimeV2()) { + return t1.decimalScale() > t2.decimalScale() ? t1 : t2; + } else if (t1.isDatetimeV2()) { + return t1; + } else if (t2.isDatetimeV2()) { + return t2; + } else { + return DateLiteral.getDefaultDateType(Type.DATETIME); + } + } catch (AnalysisException ignored) { + LOG.error("Invalid date type: {} and {}", t1, t2); + } + return null; + } + public Type getMaxResolutionType() { Preconditions.checkState(true, "must implemented"); return null; @@ -1209,6 +1349,7 @@ public Type getNumResultType() { case INT: case BIGINT: case DATE: + case DATEV2: case DATETIME: return Type.BIGINT; case LARGEINT: @@ -1221,6 +1362,10 @@ public Type getNumResultType() { case STRING: case HLL: return Type.DOUBLE; + case DATETIMEV2: + return Type.DEFAULT_DATETIMEV2; + case TIMEV2: + return Type.DEFAULT_TIMEV2; case DECIMALV2: return Type.DECIMALV2; default: diff --git a/fe/fe-core/src/main/java/org/apache/doris/common/Config.java b/fe/fe-core/src/main/java/org/apache/doris/common/Config.java index a10974f42ac6f7..af0494b8ce3f19 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/common/Config.java +++ b/fe/fe-core/src/main/java/org/apache/doris/common/Config.java @@ -1651,4 +1651,7 @@ public class Config extends ConfigBase { @ConfField public static boolean enable_vectorized_load = false; + + @ConfField(mutable = true, masterOnly = true) + public static boolean use_date_v2_by_default = false; } diff --git a/fe/fe-core/src/main/java/org/apache/doris/common/proc/PartitionsProcDir.java b/fe/fe-core/src/main/java/org/apache/doris/common/proc/PartitionsProcDir.java index cd6c768936196f..a34666e0c5a382 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/common/proc/PartitionsProcDir.java +++ b/fe/fe-core/src/main/java/org/apache/doris/common/proc/PartitionsProcDir.java @@ -97,7 +97,20 @@ public boolean filter(String columnName, Comparable element, Map f long leftVal; long rightVal; if (subExpr.getChild(1) instanceof DateLiteral) { - leftVal = (new DateLiteral((String) element, Type.DATETIME)).getLongValue(); + Type type; + switch (subExpr.getChild(1).getType().getPrimitiveType()) { + case DATE: + case DATETIME: + type = Type.DATETIME; + break; + case DATEV2: + case DATETIMEV2: + type = Type.DATETIMEV2; + break; + default: + throw new AnalysisException("Invalid date type: " + subExpr.getChild(1).getType()); + } + leftVal = (new DateLiteral((String) element, type)).getLongValue(); rightVal = ((DateLiteral) subExpr.getChild(1)).getLongValue(); } else { leftVal = Long.parseLong(element.toString()); diff --git a/fe/fe-core/src/main/java/org/apache/doris/common/proc/RollupProcDir.java b/fe/fe-core/src/main/java/org/apache/doris/common/proc/RollupProcDir.java index 28318a87f02444..c3d52787c440e6 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/common/proc/RollupProcDir.java +++ b/fe/fe-core/src/main/java/org/apache/doris/common/proc/RollupProcDir.java @@ -154,7 +154,20 @@ boolean filterResult(String columnName, Comparable element, HashMap properties, D throw new AnalysisException("Invalid storage medium: " + value); } } else if (!hasCooldown && key.equalsIgnoreCase(PROPERTIES_STORAGE_COOLDOWN_TIME)) { - DateLiteral dateLiteral = new DateLiteral(value, Type.DATETIME); + DateLiteral dateLiteral = new DateLiteral(value, DateLiteral.getDefaultDateType(Type.DATETIME)); cooldownTimeStamp = dateLiteral.unixTimestamp(TimeUtils.getTimeZone()); if (cooldownTimeStamp != DataProperty.MAX_COOLDOWN_TIME_MS) { hasCooldown = true; @@ -146,7 +146,7 @@ public static DataProperty analyzeDataProperty(Map properties, D remoteStorageResourceName = value; } } else if (!hasRemoteCooldown && key.equalsIgnoreCase(PROPERTIES_REMOTE_STORAGE_COOLDOWN_TIME)) { - DateLiteral dateLiteral = new DateLiteral(value, Type.DATETIME); + DateLiteral dateLiteral = new DateLiteral(value, DateLiteral.getDefaultDateType(Type.DATETIME)); remoteCooldownTimeStamp = dateLiteral.unixTimestamp(TimeUtils.getTimeZone()); if (remoteCooldownTimeStamp != DataProperty.MAX_COOLDOWN_TIME_MS) { hasRemoteCooldown = true; diff --git a/fe/fe-core/src/main/java/org/apache/doris/common/util/Util.java b/fe/fe-core/src/main/java/org/apache/doris/common/util/Util.java index 4ca18e3ce02e96..81d6742356ba45 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/common/util/Util.java +++ b/fe/fe-core/src/main/java/org/apache/doris/common/util/Util.java @@ -65,6 +65,8 @@ public class Util { TYPE_STRING_MAP.put(PrimitiveType.DOUBLE, "double"); TYPE_STRING_MAP.put(PrimitiveType.DATE, "date"); TYPE_STRING_MAP.put(PrimitiveType.DATETIME, "datetime"); + TYPE_STRING_MAP.put(PrimitiveType.DATEV2, "datev2"); + TYPE_STRING_MAP.put(PrimitiveType.DATETIMEV2, "datetimev2"); TYPE_STRING_MAP.put(PrimitiveType.CHAR, "char(%d)"); TYPE_STRING_MAP.put(PrimitiveType.VARCHAR, "varchar(%d)"); TYPE_STRING_MAP.put(PrimitiveType.STRING, "string"); diff --git a/fe/fe-core/src/main/java/org/apache/doris/external/iceberg/util/DorisTypeToType.java b/fe/fe-core/src/main/java/org/apache/doris/external/iceberg/util/DorisTypeToType.java index a8569befc7baa9..a5d2701ed434e6 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/external/iceberg/util/DorisTypeToType.java +++ b/fe/fe-core/src/main/java/org/apache/doris/external/iceberg/util/DorisTypeToType.java @@ -93,16 +93,18 @@ public Type atomic(org.apache.doris.catalog.Type atomic) { } else if (atomic.getPrimitiveType().equals(PrimitiveType.CHAR) || atomic.getPrimitiveType().equals(PrimitiveType.VARCHAR)) { return Types.StringType.get(); - } else if (atomic.getPrimitiveType().equals(PrimitiveType.DATE)) { + } else if (atomic.getPrimitiveType().equals(PrimitiveType.DATE) + || atomic.getPrimitiveType().equals(PrimitiveType.DATEV2)) { return Types.DateType.get(); - } else if (atomic.getPrimitiveType().equals(PrimitiveType.TIME)) { + } else if (atomic.getPrimitiveType().equals(PrimitiveType.TIME) + || atomic.getPrimitiveType().equals(PrimitiveType.TIMEV2)) { return Types.TimeType.get(); - } else if (atomic.getPrimitiveType().equals(PrimitiveType.DECIMALV2) - || atomic.getPrimitiveType().equals(PrimitiveType.DECIMALV2)) { + } else if (atomic.getPrimitiveType().equals(PrimitiveType.DECIMALV2)) { return Types.DecimalType.of( ((ScalarType) atomic).getScalarPrecision(), ((ScalarType) atomic).getScalarScale()); - } else if (atomic.getPrimitiveType().equals(PrimitiveType.DATETIME)) { + } else if (atomic.getPrimitiveType().equals(PrimitiveType.DATETIME) + || atomic.getPrimitiveType().equals(PrimitiveType.DATETIMEV2)) { return Types.TimestampType.withZone(); } // unsupported type: PrimitiveType.HLL BITMAP BINARY diff --git a/fe/fe-core/src/main/java/org/apache/doris/external/iceberg/util/TypeToDorisType.java b/fe/fe-core/src/main/java/org/apache/doris/external/iceberg/util/TypeToDorisType.java index 926b95c64f1b17..87774fc40b85b5 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/external/iceberg/util/TypeToDorisType.java +++ b/fe/fe-core/src/main/java/org/apache/doris/external/iceberg/util/TypeToDorisType.java @@ -17,8 +17,10 @@ package org.apache.doris.external.iceberg.util; +import org.apache.doris.analysis.DateLiteral; import org.apache.doris.catalog.ScalarType; import org.apache.doris.catalog.Type; +import org.apache.doris.common.AnalysisException; import org.apache.iceberg.Schema; import org.apache.iceberg.types.TypeUtil; @@ -78,9 +80,17 @@ public Type primitive(org.apache.iceberg.types.Type.PrimitiveType primitive) { Types.DecimalType decimal = (Types.DecimalType) primitive; return ScalarType.createDecimalV2Type(decimal.precision(), decimal.scale()); case DATE: - return Type.DATE; + try { + return DateLiteral.getDefaultDateType(Type.DATE); + } catch (AnalysisException e) { + return Type.DATE; + } case TIMESTAMP: - return Type.DATETIME; + try { + return DateLiteral.getDefaultDateType(Type.DATETIME); + } catch (AnalysisException e) { + return Type.DATETIME; + } case STRING: return Type.STRING; // use varchar diff --git a/fe/fe-core/src/main/java/org/apache/doris/httpv2/util/StatementSubmitter.java b/fe/fe-core/src/main/java/org/apache/doris/httpv2/util/StatementSubmitter.java index e29db73d6f6afc..768ca209e361aa 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/httpv2/util/StatementSubmitter.java +++ b/fe/fe-core/src/main/java/org/apache/doris/httpv2/util/StatementSubmitter.java @@ -174,7 +174,8 @@ private ExecutionResultSet generateResultSet(ResultSet rs, long startTime) throw // index start from 1 for (int i = 1; i <= colNum; ++i) { String type = rs.getMetaData().getColumnTypeName(i); - if ("DATE".equalsIgnoreCase(type) || "DATETIME".equalsIgnoreCase(type)) { + if ("DATE".equalsIgnoreCase(type) || "DATETIME".equalsIgnoreCase(type) + || "DATEV2".equalsIgnoreCase(type) || "DATETIMEV2".equalsIgnoreCase(type)) { row.add(rs.getString(i)); } else { row.add(rs.getObject(i)); diff --git a/fe/fe-core/src/main/java/org/apache/doris/load/DeleteHandler.java b/fe/fe-core/src/main/java/org/apache/doris/load/DeleteHandler.java index ef7bd7e9734714..bbd2ea35b250ea 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/load/DeleteHandler.java +++ b/fe/fe-core/src/main/java/org/apache/doris/load/DeleteHandler.java @@ -559,10 +559,14 @@ private void checkDeleteV2(OlapTable table, List partitions, List
 partitions, List
 toDppColumn() {
                     columnType = "DOUBLE";
                     break;
                 case DATE:
+                case DATEV2:
                     columnType = "DATE";
                     break;
                 case DATETIME:
+                case DATETIMEV2:
                     columnType = "DATETIME";
                     break;
                 case CHAR:
diff --git a/fe/fe-core/src/main/jflex/sql_scanner.flex b/fe/fe-core/src/main/jflex/sql_scanner.flex
index 8f3dd68a3549ac..5979977ed9ed8f 100644
--- a/fe/fe-core/src/main/jflex/sql_scanner.flex
+++ b/fe/fe-core/src/main/jflex/sql_scanner.flex
@@ -160,6 +160,7 @@ import org.apache.doris.qe.SqlModeHelper;
         keywordMap.put("databases", new Integer(SqlParserSymbols.KW_DATABASES));
         keywordMap.put("date", new Integer(SqlParserSymbols.KW_DATE));
         keywordMap.put("datetime", new Integer(SqlParserSymbols.KW_DATETIME));
+        keywordMap.put("time", new Integer(SqlParserSymbols.KW_TIME));
         keywordMap.put("day", new Integer(SqlParserSymbols.KW_DAY));
         keywordMap.put("decimal", new Integer(SqlParserSymbols.KW_DECIMAL));
         keywordMap.put("decommission", new Integer(SqlParserSymbols.KW_DECOMMISSION));
diff --git a/fe/fe-core/src/test/java/org/apache/doris/alter/AlterTest.java b/fe/fe-core/src/test/java/org/apache/doris/alter/AlterTest.java
index 293d73341f3b44..6c5639cba9d15e 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/alter/AlterTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/alter/AlterTest.java
@@ -151,6 +151,22 @@ public static void beforeClass() throws Exception {
                 + "DISTRIBUTED BY HASH(k2) BUCKETS 3\n"
                 + "PROPERTIES('replication_num' = '1');");
 
+        createTable("CREATE TABLE test.tbl6\n"
+                + "(\n"
+                + "    k1 datetime(3),\n"
+                + "    k2 time(3),\n"
+                + "    v1 int \n,"
+                + "    v2 datetime(3)\n"
+                + ") ENGINE=OLAP\n"
+                + "UNIQUE KEY (k1,k2)\n"
+                + "PARTITION BY RANGE(k1)\n"
+                + "(\n"
+                + "    PARTITION p1 values less than('2020-02-01 00:00:00'),\n"
+                + "    PARTITION p2 values less than('2020-03-01 00:00:00')\n"
+                + ")\n"
+                + "DISTRIBUTED BY HASH(k2) BUCKETS 3\n"
+                + "PROPERTIES('replication_num' = '1');");
+
         createTable("create external table test.odbc_table\n"
                 + "(  `k1` bigint(20) COMMENT \"\",\n"
                 + "  `k2` datetime COMMENT \"\",\n"
@@ -408,6 +424,86 @@ public void testConflictAlterOperations() throws Exception {
         alterTable(stmt, false);
     }
 
+    @Test
+    public void testAlterDateV2Operations() throws Exception {
+        String stmt = "alter table test.tbl6 add partition p3 values less than('2020-04-01 00:00:00'),"
+                + "add partition p4 values less than('2020-05-01 00:00:00')";
+        alterTable(stmt, true);
+
+        stmt = "alter table test.tbl6 add partition p3 values less than('2020-04-01 00:00:00'), drop partition p4";
+        alterTable(stmt, true);
+
+        stmt = "alter table test.tbl6 drop partition p3, drop partition p4";
+        alterTable(stmt, true);
+
+        stmt = "alter table test.tbl6 drop partition p3, add column k3 datetime(6)";
+        alterTable(stmt, true);
+
+        // no conflict
+        stmt = "alter table test.tbl6 add column k3 int, add column k4 time(6)";
+        alterTable(stmt, false);
+        waitSchemaChangeJobDone(false);
+
+        stmt = "alter table test.tbl6 add rollup r1 (k1, k2)";
+        alterTable(stmt, false);
+        waitSchemaChangeJobDone(true);
+
+        stmt = "alter table test.tbl6 add rollup r2 (k1, k2), r3 (k1, k2)";
+        alterTable(stmt, false);
+        waitSchemaChangeJobDone(true);
+
+        // enable dynamic partition
+        // not adding the `start` property so that it won't drop the origin partition p1, p2 and p3
+        stmt = "alter table test.tbl6 set (\n"
+                + "'dynamic_partition.enable' = 'true',\n"
+                + "'dynamic_partition.time_unit' = 'DAY',\n"
+                + "'dynamic_partition.end' = '3',\n"
+                + "'dynamic_partition.prefix' = 'p',\n"
+                + "'dynamic_partition.buckets' = '3'\n"
+                + " );";
+        alterTable(stmt, false);
+        Database db = Catalog.getCurrentCatalog().getDbOrMetaException("default_cluster:test");
+        OlapTable tbl = (OlapTable) db.getTableOrMetaException("tbl6");
+        Assert.assertTrue(tbl.getTableProperty().getDynamicPartitionProperty().getEnable());
+        Assert.assertEquals(4, tbl.getIndexIdToSchema().size());
+
+        // add partition when dynamic partition is enable
+        stmt = "alter table test.tbl6 add partition p3 values less than('2020-04-01 00:00:00') distributed by"
+                + " hash(k2) buckets 4 PROPERTIES ('replication_num' = '1')";
+        alterTable(stmt, true);
+
+        // add temp partition when dynamic partition is enable
+        stmt = "alter table test.tbl6 add temporary partition tp3 values less than('2020-04-01 00:00:00') distributed"
+                + " by hash(k2) buckets 4 PROPERTIES ('replication_num' = '1')";
+        alterTable(stmt, false);
+        Assert.assertEquals(1, tbl.getTempPartitions().size());
+
+        // disable the dynamic partition
+        stmt = "alter table test.tbl6 set ('dynamic_partition.enable' = 'false')";
+        alterTable(stmt, false);
+        Assert.assertFalse(tbl.getTableProperty().getDynamicPartitionProperty().getEnable());
+
+        // add partition when dynamic partition is disable
+        stmt = "alter table test.tbl6 add partition p3 values less than('2020-04-01 00:00:00') distributed"
+                + " by hash(k2) buckets 4";
+        alterTable(stmt, false);
+
+        // set table's default replication num
+        Assert.assertEquals((short) 1, tbl.getDefaultReplicaAllocation().getTotalReplicaNum());
+        stmt = "alter table test.tbl6 set ('default.replication_num' = '3');";
+        alterTable(stmt, false);
+        Assert.assertEquals((short) 3, tbl.getDefaultReplicaAllocation().getTotalReplicaNum());
+
+        // set range table's real replication num
+        Partition p1 = tbl.getPartition("p1");
+        Assert.assertEquals(Short.valueOf("1"), Short.valueOf(tbl.getPartitionInfo().getReplicaAllocation(p1.getId())
+                .getTotalReplicaNum()));
+        stmt = "alter table test.tbl6 set ('replication_num' = '3');";
+        alterTable(stmt, true);
+        Assert.assertEquals(Short.valueOf("1"), Short.valueOf(tbl.getPartitionInfo().getReplicaAllocation(p1.getId())
+                .getTotalReplicaNum()));
+    }
+
     // test batch update range partitions' properties
     @Test
     public void testBatchUpdatePartitionProperties() throws Exception {
@@ -894,6 +990,48 @@ public void testAlterUniqueTablePartitionColumn() throws Exception {
         alterTable(changeOrderStmt, true);
     }
 
+    @Test
+    public void testAlterDateV2Schema() throws Exception {
+        createTable("CREATE TABLE test.unique_partition_datev2\n"
+                + "(\n"
+                + "    k1 date,\n"
+                + "    k2 datetime(3),\n"
+                + "    k3 datetime,\n"
+                + "    v1 date,\n"
+                + "    v2 datetime(3),\n"
+                + "    v3 datetime,\n"
+                + "    v4 int\n"
+                + ")\n"
+                + "UNIQUE KEY(k1, k2, k3)\n"
+                + "PARTITION BY RANGE(k1)\n"
+                + "(\n"
+                + "    PARTITION p1 values less than('2020-02-01'),\n"
+                + "    PARTITION p2 values less than('2020-03-01')\n"
+                + ")\n"
+                + "DISTRIBUTED BY HASH(k1) BUCKETS 3\n"
+                + "PROPERTIES('replication_num' = '1');");
+
+        // partition key can not be changed.
+        String changeOrderStmt = "ALTER TABLE test.unique_partition_datev2 modify column k1 int key null";
+        alterTable(changeOrderStmt, true);
+        changeOrderStmt = "ALTER TABLE test.unique_partition_datev2 modify column k2 int key null";
+        alterTable(changeOrderStmt, true);
+        changeOrderStmt = "ALTER TABLE test.unique_partition_datev2 modify column k3 int key null";
+        alterTable(changeOrderStmt, true);
+
+        // partition keys which are date type should be changed between each other.
+        changeOrderStmt = "ALTER TABLE test.unique_partition_datev2 modify column k2 datetime key null";
+        alterTable(changeOrderStmt, false);
+        waitSchemaChangeJobDone(false);
+        changeOrderStmt = "ALTER TABLE test.unique_partition_datev2 modify column k3 datetime(3) key null";
+        alterTable(changeOrderStmt, false);
+        waitSchemaChangeJobDone(false);
+        // Change to another precision datetime
+        changeOrderStmt = "ALTER TABLE test.unique_partition_datev2 modify column k3 datetime(6) key null";
+        alterTable(changeOrderStmt, false);
+        waitSchemaChangeJobDone(false);
+    }
+
     private boolean checkAllTabletsExists(List tabletIds) {
         TabletInvertedIndex invertedIndex = Catalog.getCurrentCatalog().getTabletInvertedIndex();
         for (long tabletId : tabletIds) {
diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/AggregateTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/AggregateTest.java
index ce5ef14b55e078..47be42a9bf1912 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/analysis/AggregateTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/AggregateTest.java
@@ -38,8 +38,9 @@ protected void runBeforeAll() throws Exception {
         dorisAssert = new DorisAssert();
         dorisAssert.withDatabase(DB_NAME).useDatabase(DB_NAME);
         String createTableSQL = "create table " + DB_NAME + "." + TABLE_NAME + " (empid int, name varchar, "
-                + "deptno int, salary int, commission int, time DATETIME) "
-                + "distributed by hash(empid) buckets 3 properties('replication_num' = '1');";
+                + "deptno int, salary int, commission int, time_col DATETIME, timev2_col "
+                + " DATETIME(3)) distributed by hash(empid) buckets 3"
+                + " properties('replication_num' = '1');";
         createTable(createTableSQL);
     }
 
@@ -52,11 +53,13 @@ public void testCountDisintctAnalysisException() throws Exception {
 
         // NOT support mix distinct, one DistinctAggregationFunction has one column, the other DistinctAggregationFunction has some columns.
         do {
-            String query = "select count(distinct empid), count(distinct salary), count(distinct empid, salary) from " + DB_NAME + "." + TABLE_NAME;
+            String query = "select count(distinct empid), count(distinct salary), "
+                    + "count(distinct empid, salary) from " + DB_NAME + "." + TABLE_NAME;
             try {
                 UtFrameUtils.parseAndAnalyzeStmt(query, ctx);
             } catch (AnalysisException e) {
-                Assert.assertTrue(e.getMessage().contains("The query contains multi count distinct or sum distinct, each can't have multi columns."));
+                Assert.assertTrue(e.getMessage().contains(
+                        "The query contains multi count distinct or sum distinct, each can't have multi columns."));
                 break;
             } catch (Exception e) {
                 Assert.fail("must be AnalysisException.");
@@ -90,8 +93,18 @@ public void testWindowFunnelAnalysisException() throws Exception {
         ConnectContext ctx = UtFrameUtils.createDefaultCtx();
 
         // normal.
-        { // CHECKSTYLE IGNORE THIS LINE
-            String query = "select empid, window_funnel(1, 'default', time, empid = 1, empid = 2) from "
+        {
+            String query = "select empid, window_funnel(1, 'default', time_col, empid = 1, empid = 2) from "
+                    + DB_NAME + "." + TABLE_NAME + " group by empid";
+            try {
+                UtFrameUtils.parseAndAnalyzeStmt(query, ctx);
+            } catch (Exception e) {
+                Assert.fail("must be AnalysisException.");
+            }
+        }
+
+        {
+            String query = "select empid, window_funnel(1, 'default', timev2_col, empid = 1, empid = 2) from "
                     + DB_NAME + "." + TABLE_NAME + " group by empid";
             try {
                 UtFrameUtils.parseAndAnalyzeStmt(query, ctx);
@@ -102,7 +115,21 @@ public void testWindowFunnelAnalysisException() throws Exception {
 
         // less argument.
         do {
-            String query = "select empid, window_funnel(1, 'default', time) from "
+            String query = "select empid, window_funnel(1, 'default', time_col) from "
+                    + DB_NAME + "." + TABLE_NAME + " group by empid";
+            try {
+                UtFrameUtils.parseAndAnalyzeStmt(query, ctx);
+            } catch (AnalysisException e) {
+                Assert.assertTrue(e.getMessage().contains("function must have at least four params"));
+                break;
+            } catch (Exception e) {
+                Assert.fail("must be AnalysisException.");
+            }
+            Assert.fail("must be AnalysisException.");
+        } while (false);
+
+        do {
+            String query = "select empid, window_funnel(1, 'default', timev2_col) from "
                     + DB_NAME + "." + TABLE_NAME + " group by empid";
             try {
                 UtFrameUtils.parseAndAnalyzeStmt(query, ctx);
@@ -117,12 +144,13 @@ public void testWindowFunnelAnalysisException() throws Exception {
 
         // argument with wrong type.
         do {
-            String query = "select empid, window_funnel('xx', 'default', time, empid = 1) from "
+            String query = "select empid, window_funnel('xx', 'default', time_col, empid = 1) from "
                     + DB_NAME + "." + TABLE_NAME + " group by empid";
             try {
                 UtFrameUtils.parseAndAnalyzeStmt(query, ctx);
             } catch (AnalysisException e) {
-                Assert.assertTrue(e.getMessage().contains("The window params of window_funnel function must be integer"));
+                Assert.assertTrue(
+                        e.getMessage().contains("The window params of window_funnel function must be integer"));
                 break;
             } catch (Exception e) {
                 Assert.fail("must be AnalysisException.");
@@ -131,12 +159,13 @@ public void testWindowFunnelAnalysisException() throws Exception {
         } while (false);
 
         do {
-            String query = "select empid, window_funnel(1, 1, time, empid = 1) from "
+            String query = "select empid, window_funnel('xx', 'default', timev2_col, empid = 1) from "
                     + DB_NAME + "." + TABLE_NAME + " group by empid";
             try {
                 UtFrameUtils.parseAndAnalyzeStmt(query, ctx);
             } catch (AnalysisException e) {
-                Assert.assertTrue(e.getMessage().contains("The mode params of window_funnel function must be integer"));
+                Assert.assertTrue(
+                        e.getMessage().contains("The window params of window_funnel function must be integer"));
                 break;
             } catch (Exception e) {
                 Assert.fail("must be AnalysisException.");
@@ -144,6 +173,35 @@ public void testWindowFunnelAnalysisException() throws Exception {
             Assert.fail("must be AnalysisException.");
         } while (false);
 
+        do {
+            String query = "select empid, window_funnel(1, 1, time_col, empid = 1) from "
+                    + DB_NAME + "." + TABLE_NAME + " group by empid";
+            try {
+                UtFrameUtils.parseAndAnalyzeStmt(query, ctx);
+            } catch (AnalysisException e) {
+                Assert.assertTrue(
+                        e.getMessage().contains("The mode params of window_funnel function must be integer"));
+                break;
+            } catch (Exception e) {
+                Assert.fail("must be AnalysisException.");
+            }
+            Assert.fail("must be AnalysisException.");
+        } while (false);
+
+        do {
+            String query = "select empid, window_funnel(1, 1, timev2_col, empid = 1) from "
+                    + DB_NAME + "." + TABLE_NAME + " group by empid";
+            try {
+                UtFrameUtils.parseAndAnalyzeStmt(query, ctx);
+            } catch (AnalysisException e) {
+                Assert.assertTrue(
+                        e.getMessage().contains("The mode params of window_funnel function must be integer"));
+                break;
+            } catch (Exception e) {
+                Assert.fail("must be AnalysisException.");
+            }
+            Assert.fail("must be AnalysisException.");
+        } while (false);
 
         do {
             String query = "select empid, window_funnel(1, '1', empid, '1') from "
@@ -151,7 +209,23 @@ public void testWindowFunnelAnalysisException() throws Exception {
             try {
                 UtFrameUtils.parseAndAnalyzeStmt(query, ctx);
             } catch (AnalysisException e) {
-                Assert.assertTrue(e.getMessage().contains("The 3rd param of window_funnel function must be DATE or DATETIME"));
+                Assert.assertTrue(
+                        e.getMessage().contains("The 3rd param of window_funnel function must be DATE or DATETIME"));
+                break;
+            } catch (Exception e) {
+                Assert.fail("must be AnalysisException.");
+            }
+            Assert.fail("must be AnalysisException.");
+        } while (false);
+
+        do {
+            String query = "select empid, window_funnel(1, '1', time_col, '1') from "
+                    + DB_NAME + "." + TABLE_NAME + " group by empid";
+            try {
+                UtFrameUtils.parseAndAnalyzeStmt(query, ctx);
+            } catch (AnalysisException e) {
+                Assert.assertTrue(e.getMessage().contains(
+                        "The 4th and subsequent params of window_funnel function must be boolean"));
                 break;
             } catch (Exception e) {
                 Assert.fail("must be AnalysisException.");
@@ -160,12 +234,13 @@ public void testWindowFunnelAnalysisException() throws Exception {
         } while (false);
 
         do {
-            String query = "select empid, window_funnel(1, '1', time, '1') from "
+            String query = "select empid, window_funnel(1, '1', timev2_col, '1') from "
                     + DB_NAME + "." + TABLE_NAME + " group by empid";
             try {
                 UtFrameUtils.parseAndAnalyzeStmt(query, ctx);
             } catch (AnalysisException e) {
-                Assert.assertTrue(e.getMessage().contains("The 4th and subsequent params of window_funnel function must be boolean"));
+                Assert.assertTrue(e.getMessage().contains(
+                        "The 4th and subsequent params of window_funnel function must be boolean"));
                 break;
             } catch (Exception e) {
                 Assert.fail("must be AnalysisException.");
diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/ComparisonPredicateTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/ComparisonPredicateTest.java
index c13b31909eb319..ba7b943ff85547 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/analysis/ComparisonPredicateTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/ComparisonPredicateTest.java
@@ -125,4 +125,46 @@ public void testConvertToRange() {
         Assert.assertFalse(range.hasLowerBound());
     }
 
+    @Test
+    public void testConvertToRangeForDateV2() {
+        SlotRef slotRef = new SlotRef(new TableName("db1", "tb1"), "k1");
+        LiteralExpr dateExpr = new DateLiteral(2022, 5, 19, Type.DATE);
+        LiteralExpr dateV2Expr = new DateLiteral(2022, 5, 19, Type.DATEV2);
+        BinaryPredicate binaryPredicate1 = new BinaryPredicate(BinaryPredicate.Operator.LE, slotRef, dateExpr);
+        BinaryPredicate binaryPredicate2 = new BinaryPredicate(BinaryPredicate.Operator.LE, slotRef, dateV2Expr);
+        Range range1 = binaryPredicate1.convertToRange();
+        Range range2 = binaryPredicate2.convertToRange();
+        Assert.assertEquals(dateExpr, range1.upperEndpoint());
+        Assert.assertEquals(dateV2Expr, range1.upperEndpoint());
+        Assert.assertEquals(BoundType.CLOSED, range1.upperBoundType());
+        Assert.assertFalse(range1.hasLowerBound());
+        Assert.assertEquals(dateExpr, range2.upperEndpoint());
+        Assert.assertEquals(dateV2Expr, range2.upperEndpoint());
+        Assert.assertEquals(BoundType.CLOSED, range2.upperBoundType());
+        Assert.assertFalse(range2.hasLowerBound());
+    }
+
+    @Test
+    public void testConvertToRangeForDateTimeV2() {
+        SlotRef slotRef = new SlotRef(new TableName("db1", "tb1"), "k1");
+        LiteralExpr dateTimeExpr = new DateLiteral(2022, 5, 19, 0, 0, 0, Type.DATETIME);
+        LiteralExpr dateTimeV2Expr1 = new DateLiteral(2022, 5, 19, 0, 0, 0, Type.DEFAULT_DATETIMEV2);
+        LiteralExpr dateTimeV2Expr2 = new DateLiteral(2022, 5, 19, 0, 0, 0, ScalarType.createDatetimeV2Type(6));
+        BinaryPredicate binaryPredicate1 = new BinaryPredicate(BinaryPredicate.Operator.LE, slotRef, dateTimeExpr);
+        BinaryPredicate binaryPredicate2 = new BinaryPredicate(BinaryPredicate.Operator.LE, slotRef, dateTimeV2Expr1);
+        Range range1 = binaryPredicate1.convertToRange();
+        Range range2 = binaryPredicate2.convertToRange();
+
+        Assert.assertEquals(dateTimeExpr, range1.upperEndpoint());
+        Assert.assertEquals(dateTimeV2Expr1, range1.upperEndpoint());
+        Assert.assertEquals(dateTimeV2Expr2, range1.upperEndpoint());
+        Assert.assertEquals(BoundType.CLOSED, range1.upperBoundType());
+        Assert.assertFalse(range1.hasLowerBound());
+
+        Assert.assertEquals(dateTimeExpr, range2.upperEndpoint());
+        Assert.assertEquals(dateTimeV2Expr1, range2.upperEndpoint());
+        Assert.assertEquals(BoundType.CLOSED, range2.upperBoundType());
+        Assert.assertFalse(range2.hasLowerBound());
+        Assert.assertEquals(dateTimeV2Expr2, range2.upperEndpoint());
+    }
 }
diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/DateLiteralTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/DateLiteralTest.java
index 64b55c43d7aa89..db2dbd797defbf 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/analysis/DateLiteralTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/DateLiteralTest.java
@@ -17,6 +17,7 @@
 
 package org.apache.doris.analysis;
 
+import org.apache.doris.catalog.ScalarType;
 import org.apache.doris.catalog.Type;
 import org.apache.doris.common.AnalysisException;
 import org.apache.doris.common.InvalidFormatException;
@@ -163,4 +164,184 @@ public void testCheckRange() {
         }
         Assert.assertFalse(hasException);
     }
+
+    @Test
+    public void testTwoDigitYearForDateV2() {
+        boolean hasException = false;
+        try {
+            DateLiteral literal = new DateLiteral("1997-10-07", Type.DATEV2);
+            Assert.assertEquals(1997, literal.getYear());
+
+            DateLiteral literal2 = new DateLiteral("97-10-07", Type.DATEV2);
+            Assert.assertEquals(1997, literal2.getYear());
+
+            DateLiteral literal3 = new DateLiteral("0097-10-07", Type.DATEV2);
+            Assert.assertEquals(97, literal3.getYear());
+
+            DateLiteral literal4 = new DateLiteral("99-10-07", Type.DATEV2);
+            Assert.assertEquals(1999, literal4.getYear());
+
+            DateLiteral literal5 = new DateLiteral("70-10-07", Type.DATEV2);
+            Assert.assertEquals(1970, literal5.getYear());
+
+            DateLiteral literal6 = new DateLiteral("69-10-07", Type.DATEV2);
+            Assert.assertEquals(2069, literal6.getYear());
+
+            DateLiteral literal7 = new DateLiteral("00-10-07", Type.DATEV2);
+            Assert.assertEquals(2000, literal7.getYear());
+
+        } catch (AnalysisException e) {
+            e.printStackTrace();
+            hasException = true;
+        }
+        Assert.assertFalse(hasException);
+    }
+
+    @Test
+    public void testDateFormatForDateV2() {
+        boolean hasException = false;
+        try {
+            DateLiteral literal = new DateLiteral("1997-10-7", Type.DATEV2);
+            Assert.assertEquals(1997, literal.getYear());
+
+            literal = new DateLiteral("2021-06-1", Type.DATEV2);
+            Assert.assertEquals(2021, literal.getYear());
+            Assert.assertEquals(6, literal.getMonth());
+            Assert.assertEquals(1, literal.getDay());
+
+            literal = new DateLiteral("2022-6-01", Type.DATEV2);
+            Assert.assertEquals(2022, literal.getYear());
+            Assert.assertEquals(6, literal.getMonth());
+            Assert.assertEquals(1, literal.getDay());
+
+            literal = new DateLiteral("2023-6-1", Type.DATEV2);
+            Assert.assertEquals(2023, literal.getYear());
+            Assert.assertEquals(6, literal.getMonth());
+            Assert.assertEquals(1, literal.getDay());
+
+            literal = new DateLiteral("20230601", Type.DATEV2);
+            Assert.assertEquals(2023, literal.getYear());
+            Assert.assertEquals(6, literal.getMonth());
+            Assert.assertEquals(1, literal.getDay());
+        } catch (AnalysisException e) {
+            e.printStackTrace();
+            hasException = true;
+        }
+        Assert.assertFalse(hasException);
+    }
+
+    @Test
+    public void testParseDateTimeToHourORMinuteForDateV2() throws Exception {
+        String s = "2020-12-13 12:13:14";
+        Type type = Type.DATETIMEV2;
+        DateLiteral literal = new DateLiteral(s, type);
+        Assert.assertTrue(literal.toSql().contains("2020-12-13 12:13:14"));
+        s = "2020-12-13 12:13";
+        literal = new DateLiteral(s, type);
+        Assert.assertTrue(literal.toSql().contains("2020-12-13 12:13:00"));
+        s = "2020-12-13 12";
+        literal = new DateLiteral(s, type);
+        Assert.assertTrue(literal.toSql().contains("2020-12-13 12:00:00"));
+    }
+
+    @Test
+    public void testUncheckedCastToForDateV2() {
+        boolean hasException = false;
+        try {
+            // DATEV2 -> DATE/DATETIME/DATETIMEV2
+            DateLiteral literal = new DateLiteral("1997-10-07", Type.DATEV2);
+            Expr castToExpr = literal.uncheckedCastTo(Type.DATE);
+            Assert.assertTrue(castToExpr instanceof DateLiteral);
+            Assert.assertEquals(castToExpr.type, Type.DATE);
+            castToExpr = literal.uncheckedCastTo(Type.DATETIME);
+            Assert.assertTrue(castToExpr instanceof DateLiteral);
+            Assert.assertEquals(castToExpr.type, Type.DATETIME);
+            castToExpr = literal.uncheckedCastTo(Type.DATETIMEV2);
+            Assert.assertTrue(castToExpr instanceof DateLiteral);
+            Assert.assertEquals(castToExpr.type, Type.DATETIMEV2);
+
+            // DATE -> DATEV2/DATETIME/DATETIMEV2
+            literal = new DateLiteral("1997-10-07", Type.DATE);
+            castToExpr = literal.uncheckedCastTo(Type.DATEV2);
+            Assert.assertTrue(castToExpr instanceof DateLiteral);
+            Assert.assertEquals(castToExpr.type, Type.DATEV2);
+            castToExpr = literal.uncheckedCastTo(Type.DATETIME);
+            Assert.assertTrue(castToExpr instanceof DateLiteral);
+            Assert.assertEquals(castToExpr.type, Type.DATETIME);
+            castToExpr = literal.uncheckedCastTo(Type.DATETIMEV2);
+            Assert.assertTrue(castToExpr instanceof DateLiteral);
+            Assert.assertEquals(castToExpr.type, Type.DATETIMEV2);
+
+            // DATETIME -> DATEV2/DATE/DATETIMEV2
+            literal = new DateLiteral("1997-10-07 12:23:23", Type.DATETIME);
+            castToExpr = literal.uncheckedCastTo(Type.DATEV2);
+            Assert.assertTrue(castToExpr instanceof DateLiteral);
+            Assert.assertEquals(castToExpr.type, Type.DATEV2);
+            castToExpr = literal.uncheckedCastTo(Type.DATE);
+            Assert.assertTrue(castToExpr instanceof DateLiteral);
+            Assert.assertEquals(castToExpr.type, Type.DATE);
+            castToExpr = literal.uncheckedCastTo(Type.DATETIMEV2);
+            Assert.assertTrue(castToExpr instanceof DateLiteral);
+            Assert.assertEquals(castToExpr.type, Type.DATETIMEV2);
+
+            // DATETIMEV2 -> DATEV2/DATE/DATETIME
+            literal = new DateLiteral("1997-10-07 12:23:23", Type.DATETIMEV2);
+            castToExpr = literal.uncheckedCastTo(Type.DATEV2);
+            Assert.assertTrue(castToExpr instanceof DateLiteral);
+            Assert.assertEquals(castToExpr.type, Type.DATEV2);
+            castToExpr = literal.uncheckedCastTo(Type.DATE);
+            Assert.assertTrue(castToExpr instanceof DateLiteral);
+            Assert.assertEquals(castToExpr.type, Type.DATE);
+            castToExpr = literal.uncheckedCastTo(Type.DATETIME);
+            Assert.assertTrue(castToExpr instanceof DateLiteral);
+            Assert.assertEquals(castToExpr.type, Type.DATETIME);
+            Type t = ScalarType.createDatetimeV2Type(6);
+            castToExpr = literal.uncheckedCastTo(t);
+            Assert.assertTrue(castToExpr instanceof DateLiteral);
+            Assert.assertEquals(castToExpr.type, t);
+        } catch (AnalysisException e) {
+            e.printStackTrace();
+            hasException = true;
+        }
+        Assert.assertFalse(hasException);
+    }
+
+    @Test
+    public void testCheckDateForDateV2() throws AnalysisException {
+        boolean hasException = false;
+        try {
+            DateLiteral dateLiteral = new DateLiteral();
+            dateLiteral.fromDateFormatStr("%Y%m%d", "19971007", false, Type.DATEV2);
+            Assert.assertFalse(Deencapsulation.invoke(dateLiteral, "checkDate"));
+
+            dateLiteral.fromDateFormatStr("%Y%m%d", "19970007", false, Type.DATEV2);
+            Assert.assertFalse(Deencapsulation.invoke(dateLiteral, "checkDate"));
+
+            dateLiteral.fromDateFormatStr("%Y%m%d", "19971000", false, Type.DATEV2);
+            Assert.assertFalse(Deencapsulation.invoke(dateLiteral, "checkDate"));
+
+            dateLiteral.fromDateFormatStr("%Y%m%d", "20000229", false, Type.DATEV2);
+            Assert.assertFalse(Deencapsulation.invoke(dateLiteral, "checkDate"));
+
+        } catch (InvalidFormatException e) {
+            e.printStackTrace();
+            hasException = true;
+        }
+        Assert.assertFalse(hasException);
+    }
+
+    @Test
+    public void testCheckRangeForDateV2() {
+        boolean hasException = false;
+        try {
+            DateLiteral dateLiteral = new DateLiteral();
+            dateLiteral.fromDateFormatStr("%Y%m%d%H%i%s%f", "20201209123456123456", false, Type.DATETIMEV2);
+            Assert.assertFalse(Deencapsulation.invoke(dateLiteral, "checkRange"));
+
+        } catch (InvalidFormatException e) {
+            e.printStackTrace();
+            hasException = true;
+        }
+        Assert.assertFalse(hasException);
+    }
 }
diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/ExprTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/ExprTest.java
index c8fcd9793ccb00..ad461d93dc70b3 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/analysis/ExprTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/ExprTest.java
@@ -17,6 +17,7 @@
 
 package org.apache.doris.analysis;
 
+import org.apache.doris.catalog.ScalarType;
 import org.apache.doris.catalog.Table;
 import org.apache.doris.catalog.Type;
 import org.apache.doris.common.AnalysisException;
@@ -166,6 +167,10 @@ public void testEqualSets() {
         Expr r2 = new DateLiteral(2020, 10, 21);
         Expr r3 = new DateLiteral(2020, 10, 22);
         Expr r4 = new DateLiteral(2020, 10, 23);
+        Expr r5 = new DateLiteral(2020, 10, 23, Type.DATEV2);
+        Expr r6 = new DateLiteral(2020, 10, 23, 0, 0, 0, Type.DATETIME);
+        Expr r7 = new DateLiteral(2020, 10, 23, 0, 0, 0, Type.DATETIMEV2);
+        Expr r8 = new DateLiteral(2020, 10, 23, 0, 0, 0, ScalarType.createDatetimeV2Type(3));
 
         //list1 equal list2
         List list1 = new ArrayList<>();
@@ -173,9 +178,17 @@ public void testEqualSets() {
         list1.add(r1);
         list1.add(r2);
         list1.add(r3);
+        list1.add(r5);
+        list1.add(r6);
+        list1.add(r7);
+        list1.add(r8);
         list2.add(r1);
         list2.add(r2);
         list2.add(r3);
+        list2.add(r5);
+        list2.add(r6);
+        list2.add(r7);
+        list2.add(r8);
         Assert.assertTrue(Expr.equalSets(list1, list2));
 
         //list3 not equal list4
diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/InPredicateTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/InPredicateTest.java
index 3b688f906929ce..d2f32e37c97959 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/analysis/InPredicateTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/InPredicateTest.java
@@ -17,6 +17,7 @@
 
 package org.apache.doris.analysis;
 
+import org.apache.doris.catalog.Type;
 import org.apache.doris.common.AnalysisException;
 
 import com.clearspring.analytics.util.Lists;
@@ -106,4 +107,84 @@ public void testUnion() throws AnalysisException {
         Assert.assertEquals(1, inPredicate2.getListChildren().size());
         Assert.assertTrue(inPredicate2.contains(literalChild3));
     }
+
+    @Test
+    public void testIntersectionWithDateV2() throws AnalysisException {
+        SlotRef slotRef1 = new SlotRef(new TableName("db1", "tb1"), "k1");
+        LiteralExpr literalChild1 = new DateLiteral(2022, 5, 19, Type.DATE);
+        LiteralExpr literalChild2 = new DateLiteral(2022, 5, 20, Type.DATEV2);
+        List literalChildren1 = Lists.newArrayList();
+        literalChildren1.add(literalChild1);
+        literalChildren1.add(literalChild2);
+        InPredicate inPredicate1 = new InPredicate(slotRef1, literalChildren1, false);
+
+        SlotRef slotRef2 = new SlotRef(new TableName("db1", "tb1"), "k1");
+        LiteralExpr literalChild3 = new DateLiteral(2022, 5, 19, Type.DATEV2);
+        LiteralExpr literalChild4 = new DateLiteral(2022, 5, 21, Type.DATE);
+        List literalChildren2 = Lists.newArrayList();
+        literalChildren2.add(literalChild3);
+        literalChildren2.add(literalChild4);
+        InPredicate inPredicate2 = new InPredicate(slotRef2, literalChildren2, false);
+
+        // check result
+        InPredicate intersection = inPredicate1.intersection(inPredicate2);
+        Assert.assertEquals(slotRef1, intersection.getChild(0));
+        Assert.assertTrue(intersection.isLiteralChildren());
+        Assert.assertEquals(1, intersection.getListChildren().size());
+        Assert.assertEquals(literalChild1, intersection.getChild(1));
+
+        // keep origin predicate
+        Assert.assertTrue(inPredicate1.isLiteralChildren());
+        Assert.assertEquals(2, inPredicate1.getListChildren().size());
+        Assert.assertTrue(inPredicate1.contains(literalChild1));
+        Assert.assertTrue(inPredicate1.contains(literalChild2));
+        Assert.assertTrue(inPredicate2.isLiteralChildren());
+        Assert.assertEquals(2, inPredicate2.getListChildren().size());
+        Assert.assertTrue(inPredicate2.contains(literalChild3));
+        Assert.assertTrue(inPredicate2.contains(literalChild4));
+    }
+
+    /*
+    InPredicate1: k1 in (1,2)
+    InPredicate2: k1 in (1)
+    Union: k1 in (1,2)
+     */
+    @Test
+    public void testUnionWithDateV2() throws AnalysisException {
+        SlotRef slotRef1 = new SlotRef(new TableName("db1", "tb1"), "k1");
+        LiteralExpr literalChild1 = new DateLiteral(2022, 5, 19, Type.DATE);
+        LiteralExpr literalChild2 = new DateLiteral(2022, 5, 20, Type.DATEV2);
+        LiteralExpr literalChild3 = new DateLiteral(2022, 5, 20, 0, 0, 0, Type.DATETIME);
+        List literalChildren1 = Lists.newArrayList();
+        literalChildren1.add(literalChild1);
+        literalChildren1.add(literalChild2);
+        literalChildren1.add(literalChild3);
+        InPredicate inPredicate1 = new InPredicate(slotRef1, literalChildren1, false);
+
+        SlotRef slotRef2 = new SlotRef(new TableName("db1", "tb1"), "k1");
+        LiteralExpr literalChild4 = new DateLiteral(2022, 5, 19, Type.DATE);
+        LiteralExpr literalChild5 = new DateLiteral(2022, 5, 20, 0, 0, 0, Type.DATETIMEV2);
+        List literalChildren2 = Lists.newArrayList();
+        literalChildren2.add(literalChild4);
+        literalChildren2.add(literalChild5);
+        InPredicate inPredicate2 = new InPredicate(slotRef2, literalChildren2, false);
+
+        // check result
+        InPredicate union = inPredicate1.union(inPredicate2);
+        Assert.assertEquals(slotRef1, union.getChild(0));
+        Assert.assertTrue(union.isLiteralChildren());
+        Assert.assertEquals(2, union.getListChildren().size());
+        Assert.assertTrue(union.getListChildren().contains(literalChild1));
+        Assert.assertTrue(union.getListChildren().contains(literalChild2));
+        Assert.assertTrue(union.getListChildren().contains(literalChild5));
+
+        // keep origin predicate
+        Assert.assertTrue(inPredicate1.isLiteralChildren());
+        Assert.assertEquals(3, inPredicate1.getListChildren().size());
+        Assert.assertTrue(inPredicate1.contains(literalChild1));
+        Assert.assertTrue(inPredicate1.contains(literalChild2));
+        Assert.assertTrue(inPredicate2.isLiteralChildren());
+        Assert.assertEquals(2, inPredicate2.getListChildren().size());
+        Assert.assertTrue(inPredicate2.contains(literalChild3));
+    }
 }
diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/LiteralExprCompareTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/LiteralExprCompareTest.java
index 4a0f556ea5dfb4..baf07d8a2db8ba 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/analysis/LiteralExprCompareTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/LiteralExprCompareTest.java
@@ -61,12 +61,24 @@ public void dateFormat1Test() throws AnalysisException {
         Assert.fail();
     }
 
+    @Test(expected = AnalysisException.class)
+    public void dateV2Format1Test() throws AnalysisException {
+        new DateLiteral("2015-02-15 12:12:12", ScalarType.DATEV2);
+        Assert.fail();
+    }
+
     @Test(expected = AnalysisException.class)
     public void dateFormat2Test() throws AnalysisException {
         new DateLiteral("2015-02-15", ScalarType.DATETIME);
         Assert.fail();
     }
 
+    @Test(expected = AnalysisException.class)
+    public void dateV2Format2Test() throws AnalysisException {
+        new DateLiteral("2015-02-15", ScalarType.DATETIMEV2);
+        Assert.fail();
+    }
+
     @Test
     public void dateTest() throws AnalysisException {
         LiteralExpr date1 = new DateLiteral("2015-02-15", ScalarType.DATE);
@@ -121,6 +133,114 @@ public void dateTest() throws AnalysisException {
         Assert.assertTrue(!minDatetime1.equals(datetime1) && -1 == minDatetime1.compareLiteral(datetime1));
     }
 
+    @Test
+    public void dateV2Test() throws AnalysisException {
+        LiteralExpr date1 = new DateLiteral("2015-02-15", ScalarType.DATEV2);
+        LiteralExpr date1Same = new DateLiteral("2015-02-15", ScalarType.DATEV2);
+        LiteralExpr date1Large = new DateLiteral("2015-02-16", ScalarType.DATEV2);
+        LiteralExpr datetime1 = new DateLiteral("2015-02-15 13:14:00", ScalarType.DATETIMEV2);
+        LiteralExpr datetime1Same = new DateLiteral("2015-02-15 13:14:00", ScalarType.DATETIMEV2);
+        LiteralExpr datetime1Large = new DateLiteral("2015-02-15 13:14:15", ScalarType.DATETIMEV2);
+
+        // infinity
+        LiteralExpr maxDate1 = new DateLiteral(ScalarType.DATEV2, true);
+        LiteralExpr maxDate1Same = new DateLiteral(ScalarType.DATEV2, true);
+        LiteralExpr minDate1 = new DateLiteral(ScalarType.DATEV2, false);
+        LiteralExpr minDate1Same = new DateLiteral(ScalarType.DATEV2, false);
+        LiteralExpr maxDatetime1 = new DateLiteral(ScalarType.DATETIMEV2, true);
+        LiteralExpr maxDatetime1Same = new DateLiteral(ScalarType.DATETIMEV2, true);
+        LiteralExpr minDatetime1 = new DateLiteral(ScalarType.DATETIMEV2, false);
+        LiteralExpr minDatetime1Same = new DateLiteral(ScalarType.DATETIMEV2, false);
+        LiteralExpr date8 = new DateLiteral("9999-12-31", ScalarType.DATEV2);
+        LiteralExpr date9 = new DateLiteral("9999-12-31 23:59:59", ScalarType.DATETIMEV2);
+        LiteralExpr date10 = new DateLiteral("0000-01-01", ScalarType.DATEV2);
+        LiteralExpr date11 = new DateLiteral("0000-01-01 00:00:00", ScalarType.DATETIMEV2);
+
+        Assert.assertTrue(date1.equals(date1Same) && date1.compareLiteral(date1Same) == 0);
+        Assert.assertTrue(date1.equals(date1Same) && date1.compareLiteral(date1Same) == 0);
+        Assert.assertTrue(datetime1.equals(datetime1Same) && datetime1.compareLiteral(datetime1Same) == 0);
+        Assert.assertTrue(datetime1.equals(datetime1) && datetime1.compareLiteral(datetime1) == 0);
+
+        // value compare
+        Assert.assertTrue(!date1Large.equals(date1Same) && 1 == date1Large.compareLiteral(date1Same));
+        Assert.assertTrue(!datetime1Large.equals(datetime1Same) && 1 == datetime1Large.compareLiteral(datetime1Same));
+        Assert.assertTrue(!datetime1Same.equals(datetime1Large) && -1 == datetime1Same.compareLiteral(datetime1Large));
+
+        // infinity
+        Assert.assertTrue(maxDate1.equals(maxDate1) && maxDate1.compareLiteral(maxDate1) == 0);
+        Assert.assertTrue(maxDate1.equals(maxDate1Same) && maxDate1.compareLiteral(maxDate1Same) == 0);
+        Assert.assertTrue(minDate1.equals(minDate1) && minDate1.compareLiteral(minDate1) == 0);
+        Assert.assertTrue(minDate1.equals(minDate1Same) && minDate1.compareLiteral(minDate1Same) == 0);
+        Assert.assertTrue(maxDatetime1.equals(maxDatetime1) && maxDatetime1.compareLiteral(maxDatetime1) == 0);
+        Assert.assertTrue(maxDatetime1.equals(maxDatetime1Same) && maxDatetime1.compareLiteral(maxDatetime1Same) == 0);
+        Assert.assertTrue(minDatetime1.equals(minDatetime1) && minDatetime1.compareLiteral(minDatetime1) == 0);
+        Assert.assertTrue(minDatetime1.equals(minDatetime1Same) && minDatetime1.compareLiteral(minDatetime1Same) == 0);
+
+        Assert.assertTrue(maxDate1.equals(date8) && maxDate1.compareLiteral(date8) == 0);
+        Assert.assertTrue(minDate1.equals(date10) && minDate1.compareLiteral(date10) == 0);
+        Assert.assertTrue(maxDatetime1.equals(date9) && maxDatetime1.compareLiteral(date9) == 0);
+        Assert.assertTrue(minDatetime1.equals(date11) && minDatetime1.compareLiteral(date11) == 0);
+
+        Assert.assertTrue(!maxDate1.equals(date1) && 1 == maxDate1.compareLiteral(date1));
+        Assert.assertTrue(!minDate1.equals(date1) && -1 == minDate1.compareLiteral(date1));
+        Assert.assertTrue(!maxDatetime1.equals(datetime1) && 1 == maxDatetime1.compareLiteral(datetime1));
+        Assert.assertTrue(!minDatetime1.equals(datetime1) && -1 == minDatetime1.compareLiteral(datetime1));
+    }
+
+    @Test
+    public void dateCompatibilityTest() throws AnalysisException {
+        LiteralExpr date1 = new DateLiteral("2015-02-15", ScalarType.DATEV2);
+        LiteralExpr date1Same = new DateLiteral("2015-02-15", ScalarType.DATEV2);
+        LiteralExpr date1Large = new DateLiteral("2015-02-16", ScalarType.DATEV2);
+        LiteralExpr datetime1 = new DateLiteral("2015-02-15 13:14:00", ScalarType.DATETIMEV2);
+        LiteralExpr datetime1Same = new DateLiteral("2015-02-15 13:14:00", ScalarType.DATETIMEV2);
+        LiteralExpr datetime1Large = new DateLiteral("2015-02-15 13:14:15", ScalarType.DATETIMEV2);
+
+        // infinity
+        LiteralExpr maxDate1 = new DateLiteral(ScalarType.DATE, true);
+        LiteralExpr maxDate1Same = new DateLiteral(ScalarType.DATE, true);
+        LiteralExpr minDate1 = new DateLiteral(ScalarType.DATE, false);
+        LiteralExpr minDate1Same = new DateLiteral(ScalarType.DATE, false);
+        LiteralExpr maxDatetime1 = new DateLiteral(ScalarType.DATETIME, true);
+        LiteralExpr maxDatetime1Same = new DateLiteral(ScalarType.DATETIME, true);
+        LiteralExpr minDatetime1 = new DateLiteral(ScalarType.DATETIME, false);
+        LiteralExpr minDatetime1Same = new DateLiteral(ScalarType.DATETIME, false);
+        LiteralExpr date8 = new DateLiteral("9999-12-31", ScalarType.DATEV2);
+        LiteralExpr date9 = new DateLiteral("9999-12-31 23:59:59", ScalarType.DATETIMEV2);
+        LiteralExpr date10 = new DateLiteral("0000-01-01", ScalarType.DATEV2);
+        LiteralExpr date11 = new DateLiteral("0000-01-01 00:00:00", ScalarType.DATETIMEV2);
+
+        Assert.assertTrue(date1.equals(date1Same) && date1.compareLiteral(date1Same) == 0);
+        Assert.assertTrue(date1.equals(date1Same) && date1.compareLiteral(date1Same) == 0);
+        Assert.assertTrue(datetime1.equals(datetime1Same) && datetime1.compareLiteral(datetime1Same) == 0);
+        Assert.assertTrue(datetime1.equals(datetime1) && datetime1.compareLiteral(datetime1) == 0);
+
+        // value compare
+        Assert.assertTrue(!date1Large.equals(date1Same) && 1 == date1Large.compareLiteral(date1Same));
+        Assert.assertTrue(!datetime1Large.equals(datetime1Same) && 1 == datetime1Large.compareLiteral(datetime1Same));
+        Assert.assertTrue(!datetime1Same.equals(datetime1Large) && -1 == datetime1Same.compareLiteral(datetime1Large));
+
+        // infinity
+        Assert.assertTrue(maxDate1.equals(maxDate1) && maxDate1.compareLiteral(maxDate1) == 0);
+        Assert.assertTrue(maxDate1.equals(maxDate1Same) && maxDate1.compareLiteral(maxDate1Same) == 0);
+        Assert.assertTrue(minDate1.equals(minDate1) && minDate1.compareLiteral(minDate1) == 0);
+        Assert.assertTrue(minDate1.equals(minDate1Same) && minDate1.compareLiteral(minDate1Same) == 0);
+        Assert.assertTrue(maxDatetime1.equals(maxDatetime1) && maxDatetime1.compareLiteral(maxDatetime1) == 0);
+        Assert.assertTrue(maxDatetime1.equals(maxDatetime1Same) && maxDatetime1.compareLiteral(maxDatetime1Same) == 0);
+        Assert.assertTrue(minDatetime1.equals(minDatetime1) && minDatetime1.compareLiteral(minDatetime1) == 0);
+        Assert.assertTrue(minDatetime1.equals(minDatetime1Same) && minDatetime1.compareLiteral(minDatetime1Same) == 0);
+
+        Assert.assertTrue(maxDate1.equals(date8) && maxDate1.compareLiteral(date8) == 0);
+        Assert.assertTrue(minDate1.equals(date10) && minDate1.compareLiteral(date10) == 0);
+        Assert.assertTrue(maxDatetime1.equals(date9) && maxDatetime1.compareLiteral(date9) == 0);
+        Assert.assertTrue(minDatetime1.equals(date11) && minDatetime1.compareLiteral(date11) == 0);
+
+        Assert.assertTrue(!maxDate1.equals(date1) && 1 == maxDate1.compareLiteral(date1));
+        Assert.assertTrue(!minDate1.equals(date1) && -1 == minDate1.compareLiteral(date1));
+        Assert.assertTrue(!maxDatetime1.equals(datetime1) && 1 == maxDatetime1.compareLiteral(datetime1));
+        Assert.assertTrue(!minDatetime1.equals(datetime1) && -1 == minDatetime1.compareLiteral(datetime1));
+    }
+
     @Test
     public void decimalTest() throws AnalysisException {
         LiteralExpr decimal1 = new DecimalLiteral("1.23456");
diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/QueryStmtTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/QueryStmtTest.java
index f21f291ceb5318..c4c6dac0e5c612 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/analysis/QueryStmtTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/QueryStmtTest.java
@@ -60,6 +60,7 @@ public static void setUp() throws Exception {
                 + "  `citycode` smallint(6) NULL COMMENT \"\",\n"
                 + "  `username` varchar(32) NULL DEFAULT \"\" COMMENT \"\",\n"
                 + "  `workDateTime` datetime NOT NULL COMMENT \"\",\n"
+                + "  `workDateTimeV2` datetime NOT NULL COMMENT \"\",\n"
                 + "  `pv` bigint(20) NULL DEFAULT \"0\" COMMENT \"\"\n"
                 + ") ENGINE=OLAP\n"
                 + "UNIQUE KEY(`siteid`, `citycode`, `username`)\n"
@@ -220,12 +221,17 @@ public void testCollectExprs() throws Exception {
         // expr in subquery associate with column in grandparent level
         sql = "WITH aa AS\n"
                 + "        (SELECT DATE_FORMAT(workDateTime, '%Y-%m') mon,\n"
+                + "                DATE_FORMAT(workDateTimeV2, '%Y-%m') mon1,\n"
                 + "                siteid\n"
                 + "                FROM db1.table1\n"
                 + "                WHERE workDateTime >= concat(year(now())-1, '-01-01 00:00:00')\n"
+                + "                AND workDateTimeV2 >= concat(year(now())-1, '-01-01 00:00:00')\n"
+                + "                AND workDateTimeV2 >= concat(year(now())-1, '-01-01 00:00:00.000000')\n"
                 + "                AND workDateTime < now()\n"
+                + "                AND workDateTimeV2 < now()\n"
                 + "                GROUP BY siteid,\n"
-                + "                DATE_FORMAT(workDateTime, '%Y-%m')),\n"
+                + "                DATE_FORMAT(workDateTime, '%Y-%m'),\n"
+                + "                DATE_FORMAT(workDateTimeV2, '%Y-%m')),\n"
                 + "        bb AS\n"
                 + "        (SELECT mon,\n"
                 + "                count(DISTINCT siteid) total\n"
@@ -233,7 +239,7 @@ public void testCollectExprs() throws Exception {
                 + "                GROUP BY mon),\n"
                 + "        cc AS\n"
                 + "        (SELECT mon,\n"
-                + "                count(DISTINCT siteid) num\n"
+                + "                 count(DISTINCT siteid) num\n"
                 + "                FROM aa\n"
                 + "                GROUP BY mon)\n"
                 + "SELECT bb.mon,\n"
@@ -244,10 +250,10 @@ public void testCollectExprs() throws Exception {
         stmt = (QueryStmt) UtFrameUtils.parseAndAnalyzeStmt(sql, ctx);
         exprsMap.clear();
         stmt.collectExprs(exprsMap);
-        Assert.assertEquals(18, exprsMap.size());
+        Assert.assertEquals(24, exprsMap.size());
         constMap.clear();
         constMap = getConstantExprMap(exprsMap, analyzer);
-        Assert.assertEquals(4, constMap.size());
+        Assert.assertEquals(10, constMap.size());
     }
 
     @Test
diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/RangeCompareTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/RangeCompareTest.java
index 0eb1606511719f..721db3e4585dfb 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/analysis/RangeCompareTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/RangeCompareTest.java
@@ -232,4 +232,20 @@ public void testMergeRangeWithDifferentType() throws AnalysisException {
         }
     }
 
+    @Test
+    public void testMergeRangeWithDifferentType2() throws AnalysisException {
+        LiteralExpr lowerBoundOfRange1 = new DecimalLiteral("3.0");
+        Range range1 = Range.lessThan(lowerBoundOfRange1);
+        LiteralExpr upperBoundOfRange2 = new DateLiteral("2021-01-01", Type.DATEV2);
+        Range range2 = Range.atLeast(upperBoundOfRange2);
+        RangeSet rangeSet = TreeRangeSet.create();
+        rangeSet.add(range1);
+        try {
+            rangeSet.add(range2);
+            Assert.fail();
+        } catch (ClassCastException e) {
+            System.out.println(e);
+        }
+    }
+
 }
diff --git a/fe/fe-core/src/test/java/org/apache/doris/catalog/ColumnTypeTest.java b/fe/fe-core/src/test/java/org/apache/doris/catalog/ColumnTypeTest.java
index 1aded1c260c265..a5c762671d5e9c 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/catalog/ColumnTypeTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/catalog/ColumnTypeTest.java
@@ -115,6 +115,76 @@ public void testDecimal() throws AnalysisException {
         Assert.assertNotEquals(type.getType(), type4.getType());
     }
 
+    @Test
+    public void testDatetimeV2() throws AnalysisException {
+        TypeDef type = TypeDef.createDatetimeV2(3);
+        type.analyze(null);
+        Assert.assertEquals("datetime(3)", type.toString());
+        Assert.assertEquals(PrimitiveType.DATETIMEV2, type.getType().getPrimitiveType());
+        Assert.assertEquals(ScalarType.DATETIME_PRECISION, ((ScalarType) type.getType()).getScalarPrecision());
+        Assert.assertEquals(3, ((ScalarType) type.getType()).getScalarScale());
+
+        // equal type
+        TypeDef type2 = TypeDef.createDatetimeV2(3);
+        Assert.assertEquals(type.getType(), type2.getType());
+
+        // different type
+        TypeDef type3 = TypeDef.createDatetimeV2(6);
+        Assert.assertNotEquals(type.getType(), type3.getType());
+        type3 = TypeDef.createDatetimeV2(0);
+        Assert.assertNotEquals(type.getType(), type3.getType());
+
+        // different type
+        TypeDef type4 = TypeDef.create(PrimitiveType.BIGINT);
+        Assert.assertNotEquals(type.getType(), type4.getType());
+
+        TypeDef type5 = TypeDef.createDatetimeV2(0);
+        TypeDef type6 = TypeDef.create(PrimitiveType.DATETIME);
+        Assert.assertEquals(type5.getType(), type6.getType());
+        Assert.assertNotEquals(type.getType(), type6.getType());
+    }
+
+    @Test
+    public void testDateV2() throws AnalysisException {
+        TypeDef type = TypeDef.create(PrimitiveType.DATE);
+        TypeDef type2 = TypeDef.create(PrimitiveType.DATEV2);
+        type.analyze(null);
+        Assert.assertEquals(type.getType(), type2.getType());
+
+        // different type
+        TypeDef type3 = TypeDef.createDatetimeV2(6);
+        Assert.assertNotEquals(type2.getType(), type3.getType());
+    }
+
+    @Test
+    public void testTimeV2() throws AnalysisException {
+        TypeDef type = TypeDef.createTimeV2(3);
+        type.analyze(null);
+        Assert.assertEquals("time(3)", type.toString());
+        Assert.assertEquals(PrimitiveType.TIMEV2, type.getType().getPrimitiveType());
+        Assert.assertEquals(ScalarType.DATETIME_PRECISION, ((ScalarType) type.getType()).getScalarPrecision());
+        Assert.assertEquals(3, ((ScalarType) type.getType()).getScalarScale());
+
+        // equal type
+        TypeDef type2 = TypeDef.createTimeV2(3);
+        Assert.assertEquals(type.getType(), type2.getType());
+
+        // different type
+        TypeDef type3 = TypeDef.createTimeV2(6);
+        Assert.assertNotEquals(type.getType(), type3.getType());
+        type3 = TypeDef.createTimeV2(0);
+        Assert.assertNotEquals(type.getType(), type3.getType());
+
+        // different type
+        TypeDef type4 = TypeDef.create(PrimitiveType.BIGINT);
+        Assert.assertNotEquals(type.getType(), type4.getType());
+
+        TypeDef type5 = TypeDef.createTimeV2(0);
+        TypeDef type6 = TypeDef.create(PrimitiveType.TIME);
+        Assert.assertEquals(type5.getType(), type6.getType());
+        Assert.assertNotEquals(type.getType(), type6.getType());
+    }
+
     @Test(expected = AnalysisException.class)
     public void testDecimalPreFail() throws AnalysisException {
         TypeDef type = TypeDef.createDecimal(28, 3);
diff --git a/fe/fe-core/src/test/java/org/apache/doris/catalog/RangePartitionInfoTest.java b/fe/fe-core/src/test/java/org/apache/doris/catalog/RangePartitionInfoTest.java
index d45a82e2f3803f..2db7338b8e0bc0 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/catalog/RangePartitionInfoTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/catalog/RangePartitionInfoTest.java
@@ -375,4 +375,71 @@ public void testFixedRange6() throws DdlException, AnalysisException {
             partitionInfo.handleNewSinglePartitionDesc(singlePartitionDesc, partitionId++, false);
         }
     }
+
+    @Test(expected = AnalysisException.class)
+    public void testFixedRange7() throws DdlException, AnalysisException {
+        //add columns
+        Column k1 = new Column("k1", new ScalarType(PrimitiveType.DATEV2), true, null, "", "");
+        Column k2 = new Column("k2", new ScalarType(PrimitiveType.INT), true, null, "", "");
+        Column k3 = new Column("k3", new ScalarType(PrimitiveType.INT), true, null, "", "");
+        partitionColumns.add(k1);
+        partitionColumns.add(k2);
+        partitionColumns.add(k3);
+
+        //add RangePartitionDescs
+        PartitionKeyDesc p1 = PartitionKeyDesc.createLessThan(Lists.newArrayList(new PartitionValue("2019-02-01"),
+                new PartitionValue("100"), new PartitionValue("200")));
+        PartitionKeyDesc p2 = PartitionKeyDesc.createFixed(Lists.newArrayList(new PartitionValue("2020-02-01"),
+                new PartitionValue("100"), new PartitionValue("200")),
+                Lists.newArrayList(new PartitionValue("2020-03-01")));
+        PartitionKeyDesc p3 = PartitionKeyDesc.createLessThan(Lists.newArrayList(new PartitionValue("2021-02-01")));
+
+        singlePartitionDescs.add(new SinglePartitionDesc(false, "p1", p1, null));
+        singlePartitionDescs.add(new SinglePartitionDesc(false, "p2", p2, null));
+        singlePartitionDescs.add(new SinglePartitionDesc(false, "p3", p3, null));
+        partitionInfo = new RangePartitionInfo(partitionColumns);
+        PartitionKeyValueType partitionKeyValueType = PartitionKeyValueType.INVALID;
+        for (SinglePartitionDesc singlePartitionDesc : singlePartitionDescs) {
+            // check partitionType
+            if (partitionKeyValueType == PartitionKeyValueType.INVALID) {
+                partitionKeyValueType = singlePartitionDesc.getPartitionKeyDesc().getPartitionType();
+            } else if (partitionKeyValueType != singlePartitionDesc.getPartitionKeyDesc().getPartitionType()) {
+                throw new AnalysisException("You can only use one of these methods to create partitions");
+            }
+            singlePartitionDesc.analyze(partitionColumns.size(), null);
+            partitionInfo.handleNewSinglePartitionDesc(singlePartitionDesc, 20000L, false);
+        }
+    }
+
+    @Test (expected = DdlException.class)
+    public void testFixedRange8() throws DdlException, AnalysisException {
+        //add columns
+        int columns = 2;
+        Column k1 = new Column("k1", new ScalarType(PrimitiveType.DATEV2), true, null, "", "");
+        partitionColumns.add(k1);
+
+        //add RangePartitionDescs
+        PartitionKeyDesc p1 = PartitionKeyDesc.createFixed(
+                Lists.newArrayList(new PartitionValue("2021-06-01")),
+                Lists.newArrayList(new PartitionValue("2021-06-02")));
+
+        PartitionKeyDesc p2 = PartitionKeyDesc.createFixed(
+                Lists.newArrayList(new PartitionValue("2021-07-01")),
+                Lists.newArrayList(new PartitionValue("2021-08-01")));
+
+        PartitionKeyDesc p3 = PartitionKeyDesc.createFixed(
+                Lists.newArrayList(new PartitionValue("2021-06-01")),
+                Lists.newArrayList(new PartitionValue("2021-07-01")));
+
+        singlePartitionDescs.add(new SinglePartitionDesc(false, "p1", p1, null));
+        singlePartitionDescs.add(new SinglePartitionDesc(false, "p2", p2, null));
+        singlePartitionDescs.add(new SinglePartitionDesc(false, "p3", p3, null));
+        partitionInfo = new RangePartitionInfo(partitionColumns);
+
+        long partitionId = 20000L;
+        for (SinglePartitionDesc singlePartitionDesc : singlePartitionDescs) {
+            singlePartitionDesc.analyze(columns, null);
+            partitionInfo.handleNewSinglePartitionDesc(singlePartitionDesc, partitionId++, false);
+        }
+    }
 }
diff --git a/fe/fe-core/src/test/java/org/apache/doris/catalog/RecoverTest.java b/fe/fe-core/src/test/java/org/apache/doris/catalog/RecoverTest.java
index cafc8236159459..4720803458c978 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/catalog/RecoverTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/catalog/RecoverTest.java
@@ -41,7 +41,7 @@
 
 public class RecoverTest {
 
-    private static String runningDir = "fe/mocked/RecoverTest/" + UUID.randomUUID().toString() + "/";
+    private static String runningDir = "fe/mocked/RecoverTest/" + UUID.randomUUID() + "/";
 
     private static ConnectContext connectContext;
 
@@ -60,7 +60,8 @@ public static void tearDown() {
     }
 
     private static void createDb(String db) throws Exception {
-        CreateDbStmt createDbStmt = (CreateDbStmt) UtFrameUtils.parseAndAnalyzeStmt("create database " + db, connectContext);
+        CreateDbStmt createDbStmt = (CreateDbStmt) UtFrameUtils.parseAndAnalyzeStmt(
+                "create database " + db, connectContext);
         Catalog.getCurrentCatalog().createDb(createDbStmt);
     }
 
@@ -75,7 +76,8 @@ private static void dropDb(String db) throws Exception {
     }
 
     private static void dropTable(String db, String tbl) throws Exception {
-        DropTableStmt dropTableStmt = (DropTableStmt) UtFrameUtils.parseAndAnalyzeStmt("drop table " + db + "." + tbl, connectContext);
+        DropTableStmt dropTableStmt = (DropTableStmt) UtFrameUtils.parseAndAnalyzeStmt(
+                "drop table " + db + "." + tbl, connectContext);
         Catalog.getCurrentCatalog().dropTable(dropTableStmt);
     }
 
@@ -86,12 +88,14 @@ private static void dropPartition(String db, String tbl, String part) throws Exc
     }
 
     private static void recoverDb(String db) throws Exception {
-        RecoverDbStmt recoverDbStmt = (RecoverDbStmt) UtFrameUtils.parseAndAnalyzeStmt("recover database " + db, connectContext);
+        RecoverDbStmt recoverDbStmt = (RecoverDbStmt) UtFrameUtils.parseAndAnalyzeStmt(
+                "recover database " + db, connectContext);
         Catalog.getCurrentCatalog().recoverDatabase(recoverDbStmt);
     }
 
     private static void recoverTable(String db, String tbl) throws Exception {
-        RecoverTableStmt recoverTableStmt = (RecoverTableStmt) UtFrameUtils.parseAndAnalyzeStmt("recover table " + db + "." + tbl, connectContext);
+        RecoverTableStmt recoverTableStmt = (RecoverTableStmt) UtFrameUtils.parseAndAnalyzeStmt(
+                "recover table " + db + "." + tbl, connectContext);
         Catalog.getCurrentCatalog().recoverTable(recoverTableStmt);
     }
 
@@ -102,7 +106,8 @@ private static void recoverPartition(String db, String tbl, String part) throws
     }
 
     private static boolean checkDbExist(String dbName) {
-        return Catalog.getCurrentCatalog().getDb(ClusterNamespace.getFullName(SystemInfoService.DEFAULT_CLUSTER, dbName)).isPresent();
+        return Catalog.getCurrentCatalog().getDb(ClusterNamespace.getFullName(SystemInfoService.DEFAULT_CLUSTER,
+                dbName)).isPresent();
     }
 
     private static boolean checkTableExist(String dbName, String tblName) {
@@ -135,15 +140,13 @@ public void testRecover() throws Exception {
                 + "  `use_time` double SUM NOT NULL COMMENT \"\",\n"
                 + "  `start_times` bigint(20) SUM NOT NULL COMMENT \"\"\n"
                 + ") ENGINE=OLAP\n"
-                + "AGGREGATE KEY(`event_date`, `app_name`, `package_name`, `age`,"
-                + " `gender`, `level`, `city`, `model`, `brand`, `hours`)\n"
-                + "COMMENT \"OLAP\"\n"
+                + "AGGREGATE KEY(`event_date`, `app_name`, `package_name`, `age`, `gender`, `level`, `city`, \n"
+                + " `model`, `brand`, `hours`) COMMENT \"OLAP\"\n"
                 + "PARTITION BY RANGE(`event_date`)\n"
                 + "(PARTITION p1 VALUES [('2020-02-27'), ('2020-03-02')),\n"
                 + "PARTITION p2 VALUES [('2020-03-02'), ('2020-03-07')))\n"
-                + "DISTRIBUTED BY HASH(`event_date`, `app_name`, `package_name`,"
-                + " `age`, `gender`, `level`, `city`, `model`, `brand`, `hours`) BUCKETS 1\n"
-                + "PROPERTIES (\n"
+                + "DISTRIBUTED BY HASH(`event_date`, `app_name`, `package_name`, `age`, `gender`, `level`, `city`, \n"
+                + " `model`, `brand`, `hours`) BUCKETS 1 PROPERTIES (\n"
                 + " \"replication_num\" = \"1\"\n"
                 + ");");
 
@@ -185,15 +188,13 @@ public void testRecover() throws Exception {
                 + "  `use_time` double SUM NOT NULL COMMENT \"\",\n"
                 + "  `start_times` bigint(20) SUM NOT NULL COMMENT \"\"\n"
                 + ") ENGINE=OLAP\n"
-                + "AGGREGATE KEY(`event_date`, `app_name`, `package_name`,"
-                + " `age`, `gender`, `level`, `city`, `model`, `brand`, `hours`)\n"
-                + "COMMENT \"OLAP\"\n"
+                + "AGGREGATE KEY(`event_date`, `app_name`, `package_name`, `age`, `gender`, `level`, \n"
+                + " `city`, `model`, `brand`, `hours`) COMMENT \"OLAP\"\n"
                 + "PARTITION BY RANGE(`event_date`)\n"
                 + "(PARTITION p1 VALUES [('2020-02-27'), ('2020-03-02')),\n"
                 + "PARTITION p2 VALUES [('2020-03-02'), ('2020-03-07')))\n"
-                + "DISTRIBUTED BY HASH(`event_date`, `app_name`, `package_name`,"
-                + " `age`, `gender`, `level`, `city`, `model`, `brand`, `hours`) BUCKETS 1\n"
-                + "PROPERTIES (\n"
+                + "DISTRIBUTED BY HASH(`event_date`, `app_name`, `package_name`, `age`, `gender`, `level`, `city`, \n"
+                + " `model`, `brand`, `hours`) BUCKETS 1 PROPERTIES (\n"
                 + " \"replication_num\" = \"1\"\n"
                 + ");");
         Assert.assertTrue(checkDbExist("test"));
@@ -214,4 +215,96 @@ public void testRecover() throws Exception {
         Assert.assertTrue(checkPartitionExist("test", "table1", "p1"));
     }
 
+    @Test
+    public void testRecover2() throws Exception {
+        createDb("test2");
+        createTable("CREATE TABLE test2.`table2` (\n"
+                + "  `event_date` datetime(3) NOT NULL COMMENT \"\",\n"
+                + "  `app_name` varchar(64) NOT NULL COMMENT \"\",\n"
+                + "  `package_name` varchar(64) NOT NULL COMMENT \"\",\n"
+                + "  `age` varchar(32) NOT NULL COMMENT \"\",\n"
+                + "  `gender` varchar(32) NOT NULL COMMENT \"\",\n"
+                + "  `level` varchar(64) NOT NULL COMMENT \"\",\n"
+                + "  `city` varchar(64) NOT NULL COMMENT \"\",\n"
+                + "  `model` varchar(64) NOT NULL COMMENT \"\",\n"
+                + "  `brand` varchar(64) NOT NULL COMMENT \"\",\n"
+                + "  `hours` varchar(16) NOT NULL COMMENT \"\",\n"
+                + "  `use_num` int(11) SUM NOT NULL COMMENT \"\",\n"
+                + "  `use_time` double SUM NOT NULL COMMENT \"\",\n"
+                + "  `start_times` bigint(20) SUM NOT NULL COMMENT \"\"\n"
+                + ") ENGINE=OLAP\n"
+                + "AGGREGATE KEY(`event_date`, `app_name`, `package_name`, `age`, `gender`, `level`, \n"
+                + "`city`, `model`, `brand`, `hours`) COMMENT \"OLAP\"\n"
+                + "PARTITION BY RANGE(`event_date`)\n"
+                + "(PARTITION p1 VALUES [('2020-02-27 00:00:00'), ('2020-03-02 00:00:00')),\n"
+                + "PARTITION p2 VALUES [('2020-03-02 00:00:00'), ('2020-03-07 00:00:00')))\n"
+                + "DISTRIBUTED BY HASH(`event_date`, `app_name`, `package_name`, `age`, `gender`, `level`, \n"
+                + " `city`, `model`, `brand`, `hours`) BUCKETS 1 PROPERTIES (\n"
+                + " \"replication_num\" = \"1\"\n"
+                + ");");
+
+        Assert.assertTrue(checkDbExist("test2"));
+        Assert.assertTrue(checkTableExist("test2", "table2"));
+
+        dropDb("test2");
+        Assert.assertFalse(checkDbExist("test2"));
+        Assert.assertFalse(checkTableExist("test2", "table2"));
+
+        recoverDb("test2");
+        Assert.assertTrue(checkDbExist("test2"));
+        Assert.assertTrue(checkTableExist("test2", "table2"));
+
+        dropTable("test2", "table2");
+        Assert.assertTrue(checkDbExist("test2"));
+        Assert.assertFalse(checkTableExist("test2", "table2"));
+
+        recoverTable("test2", "table2");
+        Assert.assertTrue(checkDbExist("test2"));
+        Assert.assertTrue(checkTableExist("test2", "table2"));
+
+        dropTable("test2", "table2");
+        Assert.assertTrue(checkDbExist("test2"));
+        Assert.assertFalse(checkTableExist("test2", "table2"));
+
+        createTable("CREATE TABLE test2.`table2` (\n"
+                + "  `event_date` datetime(3) NOT NULL COMMENT \"\",\n"
+                + "  `app_name` varchar(64) NOT NULL COMMENT \"\",\n"
+                + "  `package_name` varchar(64) NOT NULL COMMENT \"\",\n"
+                + "  `age` varchar(32) NOT NULL COMMENT \"\",\n"
+                + "  `gender` varchar(32) NOT NULL COMMENT \"\",\n"
+                + "  `level` varchar(64) NOT NULL COMMENT \"\",\n"
+                + "  `city` varchar(64) NOT NULL COMMENT \"\",\n"
+                + "  `model` varchar(64) NOT NULL COMMENT \"\",\n"
+                + "  `brand` varchar(64) NOT NULL COMMENT \"\",\n"
+                + "  `hours` varchar(16) NOT NULL COMMENT \"\",\n"
+                + "  `use_num` int(11) SUM NOT NULL COMMENT \"\",\n"
+                + "  `use_time` double SUM NOT NULL COMMENT \"\",\n"
+                + "  `start_times` bigint(20) SUM NOT NULL COMMENT \"\"\n"
+                + ") ENGINE=OLAP\n"
+                + "AGGREGATE KEY(`event_date`, `app_name`, `package_name`, `age`, `gender`, `level`, `city`, \n"
+                + "  `model`, `brand`, `hours`) COMMENT \"OLAP\"\n"
+                + "PARTITION BY RANGE(`event_date`)\n"
+                + "(PARTITION p1 VALUES [('2020-02-27 00:00:00'), ('2020-03-02 00:00:00')),\n"
+                + "PARTITION p2 VALUES [('2020-03-02 00:00:00'), ('2020-03-07 00:00:00')))\n"
+                + "DISTRIBUTED BY HASH(`event_date`, `app_name`, `package_name`, `age`, `gender`, `level`, `city`, \n"
+                + " `model`, `brand`, `hours`) BUCKETS 1 PROPERTIES (\n"
+                + " \"replication_num\" = \"1\"\n"
+                + ");");
+        Assert.assertTrue(checkDbExist("test2"));
+        Assert.assertTrue(checkTableExist("test2", "table2"));
+
+        try {
+            recoverTable("test2", "table2");
+            Assert.fail("should not recover succeed");
+        } catch (DdlException e) {
+            e.printStackTrace();
+        }
+
+        Assert.assertTrue(checkPartitionExist("test2", "table2", "p1"));
+        dropPartition("test2", "table2", "p1");
+        Assert.assertFalse(checkPartitionExist("test2", "table2", "p1"));
+
+        recoverPartition("test2", "table2", "p1");
+        Assert.assertTrue(checkPartitionExist("test2", "table2", "p1"));
+    }
 }
diff --git a/fe/fe-core/src/test/java/org/apache/doris/planner/ConstantExpressTest.java b/fe/fe-core/src/test/java/org/apache/doris/planner/ConstantExpressTest.java
index e651166e91e075..d73a106ae6a260 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/planner/ConstantExpressTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/planner/ConstantExpressTest.java
@@ -133,6 +133,14 @@ public void testCast() throws Exception {
         testConstantExpressResult(
                 "select cast ('2020-01-20' as date);",
                 "'2020-01-20'");
+
+        testConstantExpressResult(
+                "select cast ('2020-01-20 00:00:00' as datetime);",
+                "'2020-01-20 00:00:00'");
+
+        testConstantExpressResult(
+                "select cast ('2020-01-20 00:00:00' as datetime(0));",
+                "'2020-01-20 00:00:00'");
     }
 
     @Test
diff --git a/fe/fe-core/src/test/java/org/apache/doris/planner/MaterializedViewFunctionTest.java b/fe/fe-core/src/test/java/org/apache/doris/planner/MaterializedViewFunctionTest.java
index 5f4bf368da3031..6ddae620351ad5 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/planner/MaterializedViewFunctionTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/planner/MaterializedViewFunctionTest.java
@@ -63,20 +63,20 @@ public static void beforeClass() throws Exception {
 
     @Before
     public void beforeMethod() throws Exception {
-        String createTableSQL = "create table " + HR_DB_NAME + "." + EMPS_TABLE_NAME + " (time date, empid int, name varchar, "
-                + "deptno int, salary int, commission int) partition by range (time) "
-                + "(partition p1 values less than MAXVALUE) "
-                + "distributed by hash(time) buckets 3 properties('replication_num' = '1');";
+        String createTableSQL = "create table " + HR_DB_NAME + "." + EMPS_TABLE_NAME + " (time_col date, empid int, "
+                + "name varchar, deptno int, salary int, commission int) partition by range (time_col) "
+                + "(partition p1 values less than MAXVALUE) distributed by hash(time_col) buckets 3"
+                + " properties('replication_num' = '1');";
         dorisAssert.withTable(createTableSQL);
         createTableSQL = "create table " + HR_DB_NAME + "." + DEPTS_TABLE_NAME
-                + " (time date, deptno int, name varchar, cost int) partition by range (time) "
+                + " (time_col date, deptno int, name varchar, cost int) partition by range (time_col) "
                 + "(partition p1 values less than MAXVALUE) "
-                + "distributed by hash(time) buckets 3 properties('replication_num' = '1');";
+                + "distributed by hash(time_col) buckets 3 properties('replication_num' = '1');";
         dorisAssert.withTable(createTableSQL);
         createTableSQL = "create table " + HR_DB_NAME + "." + USER_TAG_TABLE_NAME
-                + " (time date, user_id int, user_name varchar(20), tag_id int) partition by range (time) "
+                + " (time_col date, user_id int, user_name varchar(20), tag_id int) partition by range (time_col) "
                 + " (partition p1 values less than MAXVALUE) "
-                + "distributed by hash(time) buckets 3 properties('replication_num' = '1');";
+                + "distributed by hash(time_col) buckets 3 properties('replication_num' = '1');";
         dorisAssert.withTable(createTableSQL);
     }
 
@@ -434,8 +434,8 @@ public void testOrderByQueryOnOrderByView() throws Exception {
 
     @Test
     public void testQueryOnStar() throws Exception {
-        String createEmpsMVsql = "create materialized view " + EMPS_MV_NAME + " as select time, deptno, empid, name, "
-                + "salary, commission from " + EMPS_TABLE_NAME + " order by time, deptno, empid;";
+        String createEmpsMVsql = "create materialized view " + EMPS_MV_NAME + " as select time_col, deptno,"
+                + "empid, name, salary, commission from " + EMPS_TABLE_NAME + " order by time_col, deptno, empid;";
         String query = "select * from " + EMPS_TABLE_NAME + " where deptno = 1";
         dorisAssert.withMaterializedView(createEmpsMVsql).query(query).explainContains(QUERY_USE_EMPS_MV);
     }
diff --git a/fe/fe-core/src/test/java/org/apache/doris/planner/QueryPlanTest.java b/fe/fe-core/src/test/java/org/apache/doris/planner/QueryPlanTest.java
index 8c92582c9028f4..11f783b5e85c3f 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/planner/QueryPlanTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/planner/QueryPlanTest.java
@@ -68,7 +68,7 @@ protected void runBeforeAll() throws Exception {
         createTable("create table test.test1\n"
                 + "(\n"
                 + "    query_id varchar(48) comment \"Unique query id\",\n"
-                + "    time datetime not null comment \"Query start time\",\n"
+                + "    time_col datetime not null comment \"Query start time\",\n"
                 + "    client_ip varchar(32) comment \"Client IP\",\n"
                 + "    user varchar(64) comment \"User name\",\n"
                 + "    db varchar(96) comment \"Database of this query\",\n"
@@ -82,7 +82,7 @@ protected void runBeforeAll() throws Exception {
                 + "    frontend_ip varchar(32) comment \"Frontend ip of executing this statement\",\n"
                 + "    stmt varchar(2048) comment \"The original statement, trimed if longer than 2048 bytes\"\n"
                 + ")\n"
-                + "partition by range(time) ()\n"
+                + "partition by range(time_col) ()\n"
                 + "distributed by hash(query_id) buckets 1\n"
                 + "properties(\n"
                 + "    \"dynamic_partition.time_unit\" = \"DAY\",\n"
@@ -238,15 +238,14 @@ protected void runBeforeAll() throws Exception {
                 + "  `use_time` double SUM NOT NULL COMMENT \"\",\n"
                 + "  `start_times` bigint(20) SUM NOT NULL COMMENT \"\"\n"
                 + ") ENGINE=OLAP\n"
-                + "AGGREGATE KEY(`event_date`, `app_name`, `package_name`, `age`, `gender`, `level`, `city`, `model`, `brand`, `hours`)\n"
-                +
-                "COMMENT \"OLAP\"\n"
+                + "AGGREGATE KEY(`event_date`, `app_name`, `package_name`, `age`, `gender`, `level`, "
+                + "`city`, `model`, `brand`, `hours`) COMMENT \"OLAP\"\n"
                 + "PARTITION BY RANGE(`event_date`)\n"
                 + "(PARTITION p_20200301 VALUES [('2020-02-27'), ('2020-03-02')),\n"
                 + "PARTITION p_20200306 VALUES [('2020-03-02'), ('2020-03-07')))\n"
-                + "DISTRIBUTED BY HASH(`event_date`, `app_name`, `package_name`, `age`, `gender`, `level`, `city`, `model`, `brand`, `hours`) BUCKETS 1\n"
-                +
-                "PROPERTIES (\n"
+                + "DISTRIBUTED BY HASH(`event_date`, `app_name`, `package_name`, `age`, `gender`, `level`, "
+                + "`city`, `model`, `brand`, `hours`) BUCKETS 1\n"
+                + "PROPERTIES (\n"
                 + " \"replication_num\" = \"1\"\n"
                 + ");");
 
@@ -390,7 +389,8 @@ protected void runBeforeAll() throws Exception {
 
         createView("create view test.tbl_null_column_view AS SELECT *,NULL as add_column  FROM test.test1;");
 
-        createView("create view test.function_view AS SELECT query_id, client_ip, concat(user, db) as concat FROM test.test1;");
+        createView("create view test.function_view AS SELECT query_id, client_ip, concat(user, db) as"
+                + " concat FROM test.test1;");
 
         createTable("create table test.tbl_using_a\n"
                 + "(\n"
@@ -417,7 +417,8 @@ protected void runBeforeAll() throws Exception {
 
     @Test
     public void testFunctionViewGroupingSet() throws Exception {
-        String queryStr = "select query_id, client_ip, concat from test.function_view group by rollup(query_id, client_ip, concat);";
+        String queryStr = "select query_id, client_ip, concat from test.function_view group by rollup("
+                + "query_id, client_ip, concat);";
         assertSQLPlanOrErrorMsgContains(queryStr, "repeat: repeat 3 lines [[], [0], [0, 1], [0, 1, 2, 3]]");
     }
 
@@ -697,8 +698,7 @@ public void testDateTypeEquality() throws Exception {
                 + "(app_name,package_name,age,gender,level,city,model,brand,hours,use_num,use_time,start_times)\n"
                 + "SET\n"
                 + "(event_date = default_value('2020-03-06'))) \n"
-                + "PROPERTIES ( 'max_filter_ratio'='0.0001' );\n"
-                + "";
+                + "PROPERTIES ( 'max_filter_ratio'='0.0001' );\n";
         LoadStmt loadStmt = (LoadStmt) parseAndAnalyzeStmt(loadStr);
         Catalog.getCurrentCatalog().getLoadManager().createLoadJobV1FromStmt(loadStmt, EtlJobType.HADOOP,
                 System.currentTimeMillis());
@@ -867,81 +867,102 @@ public void testConvertCaseWhenToConstant() throws Exception {
         String caseWhenSql = "select "
                 + "case when date_format(now(),'%H%i')  < 123 then 1 else 0 end as col "
                 + "from test.test1 "
-                + "where time = case when date_format(now(),'%H%i')  < 123 then date_format(date_sub(now(),2),'%Y%m%d') else date_format(date_sub(now(),1),'%Y%m%d') end";
-        Assert.assertTrue(!StringUtils.containsIgnoreCase(getSQLPlanOrErrorMsg("explain " + caseWhenSql), "CASE WHEN"));
+                + "where time_col = case when date_format(now(),'%H%i')  < 123 then date_format(date_sub("
+                + "now(),2),'%Y%m%d') else date_format(date_sub(now(),1),'%Y%m%d') end";
+        Assert.assertTrue(!StringUtils.containsIgnoreCase(getSQLPlanOrErrorMsg("explain " + caseWhenSql),
+                "CASE WHEN"));
 
         // test 1: case when then
         // 1.1 multi when in on `case when` and can be converted to constants
         String sql11 = "select case when false then 2 when true then 3 else 0 end as col11;";
-        Assert.assertTrue(StringUtils.containsIgnoreCase(getSQLPlanOrErrorMsg("explain " + sql11), "constant exprs: \n         3"));
+        Assert.assertTrue(StringUtils.containsIgnoreCase(getSQLPlanOrErrorMsg("explain " + sql11),
+                "constant exprs: \n         3"));
 
         // 1.2 multi `when expr` in on `case when` ,`when expr` can not be converted to constants
-        String sql121 = "select case when false then 2 when substr(k7,2,1) then 3 else 0 end as col121 from test.baseall";
+        String sql121 = "select case when false then 2 when substr(k7,2,1) then 3 else 0 end as col121 from"
+                + " test.baseall";
         Assert.assertTrue(StringUtils.containsIgnoreCase(getSQLPlanOrErrorMsg("explain " + sql121),
                 "OUTPUT EXPRS:CASE WHEN substr(`k7`, 2, 1) THEN 3 ELSE 0 END"));
 
         // 1.2.2 when expr which can not be converted to constants in the first
-        String sql122 = "select case when substr(k7,2,1) then 2 when false then 3 else 0 end as col122 from test.baseall";
+        String sql122 = "select case when substr(k7,2,1) then 2 when false then 3 else 0 end as col122"
+                + " from test.baseall";
         Assert.assertTrue(StringUtils.containsIgnoreCase(getSQLPlanOrErrorMsg("explain " + sql122),
                 "OUTPUT EXPRS:CASE WHEN substr(`k7`, 2, 1) THEN 2 WHEN FALSE THEN 3 ELSE 0 END"));
 
         // 1.2.3 test return `then expr` in the middle
         String sql124 = "select case when false then 1 when true then 2 when false then 3 else 'other' end as col124";
-        Assert.assertTrue(StringUtils.containsIgnoreCase(getSQLPlanOrErrorMsg("explain " + sql124), "constant exprs: \n         '2'"));
+        Assert.assertTrue(StringUtils.containsIgnoreCase(getSQLPlanOrErrorMsg("explain " + sql124),
+                "constant exprs: \n         '2'"));
 
         // 1.3 test return null
         String sql3 = "select case when false then 2 end as col3";
-        Assert.assertTrue(StringUtils.containsIgnoreCase(getSQLPlanOrErrorMsg("explain " + sql3), "constant exprs: \n         NULL"));
+        Assert.assertTrue(StringUtils.containsIgnoreCase(getSQLPlanOrErrorMsg("explain " + sql3),
+                "constant exprs: \n         NULL"));
 
         // 1.3.1 test return else expr
         String sql131 = "select case when false then 2 when false then 3 else 4 end as col131";
-        Assert.assertTrue(StringUtils.containsIgnoreCase(getSQLPlanOrErrorMsg("explain " + sql131), "constant exprs: \n         4"));
+        Assert.assertTrue(StringUtils.containsIgnoreCase(getSQLPlanOrErrorMsg("explain " + sql131),
+                "constant exprs: \n         4"));
 
         // 1.4 nest `case when` and can be converted to constants
         String sql14 = "select case when (case when true then true else false end) then 2 when false then 3 else 0 end as col";
-        Assert.assertTrue(StringUtils.containsIgnoreCase(getSQLPlanOrErrorMsg("explain " + sql14), "constant exprs: \n         2"));
+        Assert.assertTrue(StringUtils.containsIgnoreCase(getSQLPlanOrErrorMsg("explain " + sql14),
+                "constant exprs: \n         2"));
 
         // 1.5 nest `case when` and can not be converted to constants
-        String sql15 = "select case when case when substr(k7,2,1) then true else false end then 2 when false then 3 else 0 end as col from test.baseall";
+        String sql15 = "select case when case when substr(k7,2,1) then true else false end then 2 when false then 3"
+                + " else 0 end as col from test.baseall";
         Assert.assertTrue(StringUtils.containsIgnoreCase(getSQLPlanOrErrorMsg("explain " + sql15),
-                "OUTPUT EXPRS:CASE WHEN CASE WHEN substr(`k7`, 2, 1) THEN TRUE ELSE FALSE END THEN 2 WHEN FALSE THEN 3 ELSE 0 END"));
+                "OUTPUT EXPRS:CASE WHEN CASE WHEN substr(`k7`, 2, 1) THEN TRUE ELSE FALSE END THEN 2"
+                        + " WHEN FALSE THEN 3 ELSE 0 END"));
 
         // 1.6 test when expr is null
         String sql16 = "select case when null then 1 else 2 end as col16;";
-        Assert.assertTrue(StringUtils.containsIgnoreCase(getSQLPlanOrErrorMsg("explain " + sql16), "constant exprs: \n         2"));
+        Assert.assertTrue(StringUtils.containsIgnoreCase(getSQLPlanOrErrorMsg("explain " + sql16),
+                "constant exprs: \n         2"));
 
         // test 2: case xxx when then
         // 2.1 test equal
         String sql2 = "select case 1 when 1 then 'a' when 2 then 'b' else 'other' end as col2;";
-        Assert.assertTrue(StringUtils.containsIgnoreCase(getSQLPlanOrErrorMsg("explain " + sql2), "constant exprs: \n         'a'"));
+        Assert.assertTrue(StringUtils.containsIgnoreCase(getSQLPlanOrErrorMsg("explain " + sql2),
+                "constant exprs: \n         'a'"));
 
         // 2.1.2 test not equal
         String sql212 = "select case 'a' when 1 then 'a' when 'a' then 'b' else 'other' end as col212;";
-        Assert.assertTrue(StringUtils.containsIgnoreCase(getSQLPlanOrErrorMsg("explain " + sql212), "constant exprs: \n         'b'"));
+        Assert.assertTrue(StringUtils.containsIgnoreCase(getSQLPlanOrErrorMsg("explain " + sql212),
+                "constant exprs: \n         'b'"));
 
         // 2.2 test return null
         String sql22 = "select case 'a' when 1 then 'a' when 'b' then 'b' end as col22;";
-        Assert.assertTrue(StringUtils.containsIgnoreCase(getSQLPlanOrErrorMsg("explain " + sql22), "constant exprs: \n         NULL"));
+        Assert.assertTrue(StringUtils.containsIgnoreCase(getSQLPlanOrErrorMsg("explain " + sql22),
+                "constant exprs: \n         NULL"));
 
         // 2.2.2 test return else
         String sql222 = "select case 1 when 2 then 'a' when 3 then 'b' else 'other' end as col222;";
-        Assert.assertTrue(StringUtils.containsIgnoreCase(getSQLPlanOrErrorMsg("explain " + sql222), "constant exprs: \n         'other'"));
+        Assert.assertTrue(StringUtils.containsIgnoreCase(getSQLPlanOrErrorMsg("explain " + sql222),
+                "constant exprs: \n         'other'"));
 
         // 2.3 test can not convert to constant,middle when expr is not constant
-        String sql23 = "select case 'a' when 'b' then 'a' when substr(k7,2,1) then 2 when false then 3 else 0 end as col23 from test.baseall";
+        String sql23 = "select case 'a' when 'b' then 'a' when substr(k7,2,1) then 2 when false then 3"
+                + " else 0 end as col23 from test.baseall";
         String a = getSQLPlanOrErrorMsg("explain " + sql23);
         Assert.assertTrue(StringUtils.containsIgnoreCase(a,
                 "OUTPUT EXPRS:CASE 'a' WHEN substr(`k7`, 2, 1) THEN '2' WHEN '0' THEN '3' ELSE '0' END"));
 
         // 2.3.1  first when expr is not constant
-        String sql231 = "select case 'a' when substr(k7,2,1) then 2 when 1 then 'a' when false then 3 else 0 end as col231 from test.baseall";
+        String sql231 = "select case 'a' when substr(k7,2,1) then 2 when 1 then 'a' when false then 3 else 0 end"
+                + " as col231 from test.baseall";
         Assert.assertTrue(StringUtils.containsIgnoreCase(getSQLPlanOrErrorMsg("explain " + sql231),
-                "OUTPUT EXPRS:CASE 'a' WHEN substr(`k7`, 2, 1) THEN '2' WHEN '1' THEN 'a' WHEN '0' THEN '3' ELSE '0' END"));
+                "OUTPUT EXPRS:CASE 'a' WHEN substr(`k7`, 2, 1) THEN '2' WHEN '1' THEN 'a' WHEN '0'"
+                        + " THEN '3' ELSE '0' END"));
 
         // 2.3.2 case expr is not constant
-        String sql232 = "select case k1 when substr(k7,2,1) then 2 when 1 then 'a' when false then 3 else 0 end as col232 from test.baseall";
+        String sql232 = "select case k1 when substr(k7,2,1) then 2 when 1 then 'a' when false then 3 else 0 end"
+                + " as col232 from test.baseall";
         Assert.assertTrue(StringUtils.containsIgnoreCase(getSQLPlanOrErrorMsg("explain " + sql232),
-                "OUTPUT EXPRS:CASE `k1` WHEN substr(`k7`, 2, 1) THEN '2' WHEN '1' THEN 'a' WHEN '0' THEN '3' ELSE '0' END"));
+                "OUTPUT EXPRS:CASE `k1` WHEN substr(`k7`, 2, 1) THEN '2' WHEN '1' THEN 'a' "
+                        + "WHEN '0' THEN '3' ELSE '0' END"));
 
         // 3.1 test float,float in case expr
         String sql31 = "select case cast(100 as float) when 1 then 'a' when 2 then 'b' else 'other' end as col31;";
@@ -950,15 +971,18 @@ public void testConvertCaseWhenToConstant() throws Exception {
 
         // 4.1 test null in case expr return else
         String sql41 = "select case null when 1 then 'a' when 2 then 'b' else 'other' end as col41";
-        Assert.assertTrue(StringUtils.containsIgnoreCase(getSQLPlanOrErrorMsg("explain " + sql41), "constant exprs: \n         'other'"));
+        Assert.assertTrue(StringUtils.containsIgnoreCase(getSQLPlanOrErrorMsg("explain " + sql41),
+                "constant exprs: \n         'other'"));
 
         // 4.1.2 test null in case expr return null
         String sql412 = "select case null when 1 then 'a' when 2 then 'b' end as col41";
-        Assert.assertTrue(StringUtils.containsIgnoreCase(getSQLPlanOrErrorMsg("explain " + sql412), "constant exprs: \n         NULL"));
+        Assert.assertTrue(StringUtils.containsIgnoreCase(getSQLPlanOrErrorMsg("explain " + sql412),
+                "constant exprs: \n         NULL"));
 
         // 4.2.1 test null in when expr
         String sql421 = "select case 'a' when null then 'a' else 'other' end as col421";
-        Assert.assertTrue(StringUtils.containsIgnoreCase(getSQLPlanOrErrorMsg("explain " + sql421), "constant exprs: \n         'other'"));
+        Assert.assertTrue(StringUtils.containsIgnoreCase(getSQLPlanOrErrorMsg("explain " + sql421),
+                "constant exprs: \n         'other'"));
 
         // 5.1 test same type in then expr and else expr
         String sql51 = "select case when 132 then k7 else 'all' end as col51 from test.baseall group by col51";
@@ -976,12 +1000,14 @@ public void testConvertCaseWhenToConstant() throws Exception {
                 "OUTPUT EXPRS: `k1`"));
 
         // 5.4 test return CastExpr with other SlotRef in selectListItem
-        String sql54 = "select k2, case when 2 < 1 then 'all' else k1 end as col54, k7 from test.baseall group by k2, col54, k7";
+        String sql54 = "select k2, case when 2 < 1 then 'all' else k1 end as col54, k7 from test.baseall"
+                + " group by k2, col54, k7";
         Assert.assertTrue(StringUtils.containsIgnoreCase(getSQLPlanOrErrorMsg("explain " + sql54),
                 "OUTPUT EXPRS: `k2` |  `k1` |  `k7`"));
 
         // 5.5 test return CastExpr> with other SlotRef in selectListItem
-        String sql55 = "select case when 2 < 1 then 'all' else cast(k1 as int) end as col55, k7 from test.baseall group by col55, k7";
+        String sql55 = "select case when 2 < 1 then 'all' else cast(k1 as int) end as col55, k7 from"
+                + " test.baseall group by col55, k7";
         Assert.assertTrue(StringUtils.containsIgnoreCase(getSQLPlanOrErrorMsg("explain " + sql55),
                 "OUTPUT EXPRS: CAST(`k1` AS INT) |  `k7`"));
     }
@@ -1011,7 +1037,8 @@ public void testDistinctPushDown() throws Exception {
     @Test
     public void testConstInParitionPrune() throws Exception {
         FeConstants.runningUnitTest = true;
-        String queryStr = "explain select * from (select 'aa' as kk1, sum(id) from test.join1 where dt = 9 group by kk1)tt where kk1 in ('aa');";
+        String queryStr = "explain select * from (select 'aa' as kk1, sum(id) from test.join1 where dt = 9"
+                + " group by kk1)tt where kk1 in ('aa');";
         String explainString = getSQLPlanOrErrorMsg(queryStr);
         FeConstants.runningUnitTest = false;
         Assert.assertTrue(explainString.contains("partitions=1/1"));
@@ -1036,7 +1063,8 @@ public void testOrCompoundPredicateFold() throws Exception {
     public void testColocateJoin() throws Exception {
         FeConstants.runningUnitTest = true;
 
-        String queryStr = "explain select * from test.colocate1 t1, test.colocate2 t2 where t1.k1 = t2.k1 and t1.k2 = t2.k2 and t1.k3 = t2.k3";
+        String queryStr = "explain select * from test.colocate1 t1, test.colocate2 t2 where t1.k1 = t2.k1 and"
+                + " t1.k2 = t2.k2 and t1.k3 = t2.k3";
         String explainString = getSQLPlanOrErrorMsg(queryStr);
         Assert.assertTrue(explainString.contains("colocate: true"));
 
@@ -1105,15 +1133,15 @@ public void testBucketShuffleJoin() throws Exception {
         }
 
         // single partition
-        String queryStr = "explain select * from test.jointest t1, test.bucket_shuffle1 t2"
-                + " where t1.k1 = t2.k1 and t1.k1 = t2.k2";
+        String queryStr = "explain select * from test.jointest t1, test.bucket_shuffle1 t2 where t1.k1 = t2.k1"
+                + " and t1.k1 = t2.k2";
         String explainString = getSQLPlanOrErrorMsg(queryStr);
         Assert.assertTrue(explainString.contains("BUCKET_SHFFULE"));
         Assert.assertTrue(explainString.contains("BUCKET_SHFFULE_HASH_PARTITIONED: `t1`.`k1`, `t1`.`k1`"));
 
         // not bucket shuffle join do not support different type
-        queryStr = "explain select * from test.jointest t1, test.bucket_shuffle1 t2"
-                + " where cast (t1.k1 as tinyint) = t2.k1 and t1.k1 = t2.k2";
+        queryStr = "explain select * from test.jointest t1, test.bucket_shuffle1 t2 where cast (t1.k1 as tinyint)"
+                + " = t2.k1 and t1.k1 = t2.k2";
         explainString = getSQLPlanOrErrorMsg(queryStr);
         Assert.assertTrue(!explainString.contains("BUCKET_SHFFULE"));
 
@@ -1123,37 +1151,36 @@ public void testBucketShuffleJoin() throws Exception {
         Assert.assertTrue(!explainString.contains("BUCKET_SHFFULE"));
 
         // multi partition, should not be bucket shuffle join
-        queryStr = "explain select * from test.jointest t1, test.bucket_shuffle2 t2"
-                + " where t1.k1 = t2.k1 and t1.k1 = t2.k2";
+        queryStr = "explain select * from test.jointest t1, test.bucket_shuffle2 t2 where t1.k1 = t2.k1"
+                + " and t1.k1 = t2.k2";
         explainString = getSQLPlanOrErrorMsg(queryStr);
         Assert.assertTrue(!explainString.contains("BUCKET_SHFFULE"));
 
         // left table is colocate table, should be bucket shuffle
-        queryStr = "explain select * from test.colocate1 t1, test.bucket_shuffle2 t2"
-                + " where t1.k1 = t2.k1 and t1.k1 = t2.k2";
+        queryStr = "explain select * from test.colocate1 t1, test.bucket_shuffle2 t2 where t1.k1 = t2.k1"
+                + " and t1.k1 = t2.k2";
         explainString = getSQLPlanOrErrorMsg(queryStr);
         Assert.assertTrue(!explainString.contains("BUCKET_SHFFULE"));
 
         // support recurse of bucket shuffle join
-        queryStr = "explain select * from test.jointest t1 join test.bucket_shuffle1 t2"
-                + " on t1.k1 = t2.k1 and t1.k1 = t2.k2 join test.colocate1 t3"
-                + " on t2.k1 = t3.k1 and t2.k2 = t3.k2";
+        queryStr = "explain select * from test.jointest t1 join test.bucket_shuffle1 t2 on t1.k1 = t2.k1 and"
+                + " t1.k1 = t2.k2 join test.colocate1 t3 on t2.k1 = t3.k1 and t2.k2 = t3.k2";
         explainString = getSQLPlanOrErrorMsg(queryStr);
         Assert.assertTrue(explainString.contains("BUCKET_SHFFULE_HASH_PARTITIONED: `t1`.`k1`, `t1`.`k1`"));
         Assert.assertTrue(explainString.contains("BUCKET_SHFFULE_HASH_PARTITIONED: `t3`.`k1`, `t3`.`k2`"));
 
         // support recurse of bucket shuffle because t4 join t2 and join column name is same as t2 distribute column name
-        queryStr = "explain select * from test.jointest t1 join test.bucket_shuffle1 t2"
-                + " on t1.k1 = t2.k1 and t1.k1 = t2.k2 join test.colocate1 t3"
-                + " on t2.k1 = t3.k1 join test.jointest t4 on t4.k1 = t2.k1 and t4.k1 = t2.k2";
+        queryStr = "explain select * from test.jointest t1 join test.bucket_shuffle1 t2 on t1.k1 = t2.k1 and"
+                + " t1.k1 = t2.k2 join test.colocate1 t3 on t2.k1 = t3.k1 join test.jointest t4 on t4.k1 = t2.k1 and"
+                + " t4.k1 = t2.k2";
         explainString = getSQLPlanOrErrorMsg(queryStr);
         Assert.assertTrue(explainString.contains("BUCKET_SHFFULE_HASH_PARTITIONED: `t1`.`k1`, `t1`.`k1`"));
         Assert.assertTrue(explainString.contains("BUCKET_SHFFULE_HASH_PARTITIONED: `t4`.`k1`, `t4`.`k1`"));
 
         // some column name in join expr t3 join t4 and t1 distribute column name, so should not be bucket shuffle join
-        queryStr = "explain select * from test.jointest t1 join test.bucket_shuffle1 t2"
-                + " on t1.k1 = t2.k1 and t1.k1 = t2.k2 join test.colocate1 t3"
-                + " on t2.k1 = t3.k1 join test.jointest t4 on t4.k1 = t3.k1 and t4.k2 = t3.k2";
+        queryStr = "explain select * from test.jointest t1 join test.bucket_shuffle1 t2 on t1.k1 = t2.k1 and t1.k1 ="
+                + " t2.k2 join test.colocate1 t3 on t2.k1 = t3.k1 join test.jointest t4 on t4.k1 = t3.k1 and"
+                + " t4.k2 = t3.k2";
         explainString = getSQLPlanOrErrorMsg(queryStr);
         Assert.assertTrue(explainString.contains("BUCKET_SHFFULE_HASH_PARTITIONED: `t1`.`k1`, `t1`.`k1`"));
         Assert.assertTrue(!explainString.contains("BUCKET_SHFFULE_HASH_PARTITIONED: `t4`.`k1`, `t4`.`k1`"));
@@ -1362,7 +1389,8 @@ public void testRuntimeFilterMode() throws Exception {
         explainString = getSQLPlanOrErrorMsg(queryStr);
         Assert.assertFalse(explainString.contains("runtime filter"));
 
-        queryStr = "explain select * from jointest as a where k1 = (select count(1) from jointest as b where a.k1 = b.k1);";
+        queryStr = "explain select * from jointest as a where k1 = (select count(1) from jointest as b"
+                + " where a.k1 = b.k1);";
         Deencapsulation.setField(connectContext.getSessionVariable(), "runtimeFilterMode", "GLOBAL");
         Deencapsulation.setField(connectContext.getSessionVariable(), "runtimeFilterType", 15);
         explainString = getSQLPlanOrErrorMsg(queryStr);
@@ -1411,8 +1439,10 @@ public void testRuntimeFilterType() throws Exception {
 
         Deencapsulation.setField(connectContext.getSessionVariable(), "runtimeFilterType", 7);
         explainString = getSQLPlanOrErrorMsg(queryStr);
-        Assert.assertTrue(explainString.contains("runtime filters: RF000[in] <- `t1`.`k1`, RF001[bloom] <- `t1`.`k1`, RF002[min_max] <- `t1`.`k1`"));
-        Assert.assertTrue(explainString.contains("runtime filters: RF000[in] -> `t2`.`k1`, RF001[bloom] -> `t2`.`k1`, RF002[min_max] -> `t2`.`k1`"));
+        Assert.assertTrue(explainString.contains("runtime filters: RF000[in] <- `t1`.`k1`, RF001[bloom] <- `t1`.`k1`,"
+                + " RF002[min_max] <- `t1`.`k1`"));
+        Assert.assertTrue(explainString.contains("runtime filters: RF000[in] -> `t2`.`k1`, RF001[bloom] -> `t2`.`k1`,"
+                + " RF002[min_max] -> `t2`.`k1`"));
 
         Deencapsulation.setField(connectContext.getSessionVariable(), "runtimeFilterType", 8);
         explainString = getSQLPlanOrErrorMsg(queryStr);
@@ -1535,19 +1565,19 @@ public void testAggregateSatisfyOlapTableDistribution() throws Exception {
     public void testLeadAndLagFunction() throws Exception {
         connectContext.setDatabase("default_cluster:test");
 
-        String queryStr = "explain select time, lead(query_time, 1, NULL) over () as time2 from test.test1";
+        String queryStr = "explain select time_col, lead(query_time, 1, NULL) over () as time2 from test.test1";
         String explainString = getSQLPlanOrErrorMsg(queryStr);
         Assert.assertTrue(explainString.contains("lead(`query_time`, 1, NULL)"));
 
-        queryStr = "explain select time, lead(query_time, 1, 2) over () as time2 from test.test1";
+        queryStr = "explain select time_col, lead(query_time, 1, 2) over () as time2 from test.test1";
         explainString = getSQLPlanOrErrorMsg(queryStr);
         Assert.assertTrue(explainString.contains("lead(`query_time`, 1, 2)"));
 
-        queryStr = "explain select time, lead(time, 1, '2020-01-01 00:00:00') over () as time2 from test.test1";
+        queryStr = "explain select time_col, lead(time_col, 1, '2020-01-01 00:00:00') over () as time2 from test.test1";
         explainString = getSQLPlanOrErrorMsg(queryStr);
-        Assert.assertTrue(explainString.contains("lead(`time`, 1, '2020-01-01 00:00:00')"));
+        Assert.assertTrue(explainString.contains("lead(`time_col`, 1, '2020-01-01 00:00:00')"));
 
-        queryStr = "explain select time, lag(query_time, 1, 2) over () as time2 from test.test1";
+        queryStr = "explain select time_col, lag(query_time, 1, 2) over () as time2 from test.test1";
         explainString = getSQLPlanOrErrorMsg(queryStr);
         Assert.assertTrue(explainString.contains("lag(`query_time`, 1, 2)"));
     }
@@ -1974,6 +2004,10 @@ public void testRewriteDateLiteralRule() throws Exception {
         rewriteDateLiteralRuleTest.testWithIntFormatDate();
         rewriteDateLiteralRuleTest.testWithInvalidFormatDate();
         rewriteDateLiteralRuleTest.testWithStringFormatDate();
+        rewriteDateLiteralRuleTest.testWithDoubleFormatDateV2();
+        rewriteDateLiteralRuleTest.testWithIntFormatDateV2();
+        rewriteDateLiteralRuleTest.testWithInvalidFormatDateV2();
+        rewriteDateLiteralRuleTest.testWithStringFormatDateV2();
         rewriteDateLiteralRuleTest.after();
     }
     // --end--
diff --git a/fe/fe-core/src/test/java/org/apache/doris/rewrite/FEFunctionsTest.java b/fe/fe-core/src/test/java/org/apache/doris/rewrite/FEFunctionsTest.java
index 20baf3d39e64d3..5060fa67f3750e 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/rewrite/FEFunctionsTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/rewrite/FEFunctionsTest.java
@@ -81,20 +81,67 @@ public void unixtimestampTest() {
         }
     }
 
+    @Test
+    public void unixtimestampV2Test() {
+        try {
+            IntLiteral timestamp = FEFunctions.unixTimestamp(new DateLiteral("2018-01-01", Type.DATEV2));
+            Assert.assertEquals(1514736000, timestamp.getValue());
+            timestamp = FEFunctions.unixTimestamp(new DateLiteral("1970-01-01 08:00:00", Type.DATETIMEV2));
+            Assert.assertEquals(0, timestamp.getValue());
+            timestamp = FEFunctions.unixTimestamp(new DateLiteral("1970-01-01 00:00:00", Type.DATETIMEV2));
+            Assert.assertEquals(0, timestamp.getValue());
+            timestamp = FEFunctions.unixTimestamp(new DateLiteral("1969-01-01 00:00:00", Type.DATETIMEV2));
+            Assert.assertEquals(0, timestamp.getValue());
+            timestamp = FEFunctions.unixTimestamp(new DateLiteral("2038-01-19 03:14:07", Type.DATETIMEV2));
+            // CST time zone
+            Assert.assertEquals(Integer.MAX_VALUE - 8 * 3600, timestamp.getValue());
+
+        } catch (AnalysisException e) {
+            e.printStackTrace();
+            Assert.fail();
+        }
+    }
+
     @Test
     public void dateDiffTest() throws AnalysisException {
-        IntLiteral actualResult = FEFunctions.dateDiff(new DateLiteral("2010-11-30 23:59:59", Type.DATETIME), new DateLiteral("2010-12-31", Type.DATE));
+        IntLiteral actualResult = FEFunctions.dateDiff(new DateLiteral("2010-11-30 23:59:59", Type.DATETIME),
+                new DateLiteral("2010-12-31", Type.DATE));
         IntLiteral expectedResult = new IntLiteral(-31);
         Assert.assertEquals(expectedResult, actualResult);
 
-        actualResult = FEFunctions.dateDiff(new DateLiteral("2010-11-30 23:59:50", Type.DATETIME), new DateLiteral("2010-12-30 23:59:59", Type.DATETIME));
+        actualResult = FEFunctions.dateDiff(new DateLiteral("2010-11-30 23:59:50", Type.DATETIME),
+                new DateLiteral("2010-12-30 23:59:59", Type.DATETIME));
+        expectedResult = new IntLiteral(-30);
+        Assert.assertEquals(expectedResult, actualResult);
+    }
+
+    @Test
+    public void dateV2DiffTest() throws AnalysisException {
+        IntLiteral actualResult = FEFunctions.dateDiff(new DateLiteral("2010-11-30 23:59:59", Type.DATETIMEV2),
+                new DateLiteral("2010-12-31", Type.DATEV2));
+        IntLiteral expectedResult = new IntLiteral(-31);
+        Assert.assertEquals(expectedResult, actualResult);
+
+        actualResult = FEFunctions.dateDiff(new DateLiteral("2010-11-30 23:59:59", Type.DATETIMEV2),
+                new DateLiteral("2010-12-31", Type.DATE));
+        expectedResult = new IntLiteral(-31);
+        Assert.assertEquals(expectedResult, actualResult);
+
+        actualResult = FEFunctions.dateDiff(new DateLiteral("2010-11-30 23:59:50", Type.DATETIMEV2),
+                new DateLiteral("2010-12-30 23:59:59", Type.DATETIMEV2));
+        expectedResult = new IntLiteral(-30);
+        Assert.assertEquals(expectedResult, actualResult);
+
+        actualResult = FEFunctions.dateDiff(new DateLiteral("2010-11-30 23:59:50", Type.DATETIMEV2),
+                new DateLiteral("2010-12-30 23:59:59", Type.DATETIME));
         expectedResult = new IntLiteral(-30);
         Assert.assertEquals(expectedResult, actualResult);
     }
 
     @Test
     public void dateAddTest() throws AnalysisException {
-        DateLiteral actualResult = FEFunctions.dateAdd(new DateLiteral("2018-08-08", Type.DATE), new IntLiteral(1));
+        DateLiteral actualResult = FEFunctions.dateAdd(new DateLiteral("2018-08-08", Type.DATE),
+                new IntLiteral(1));
         DateLiteral expectedResult = new DateLiteral("2018-08-09 00:00:00", Type.DATETIME);
         Assert.assertEquals(expectedResult, actualResult);
 
@@ -103,6 +150,33 @@ public void dateAddTest() throws AnalysisException {
         Assert.assertEquals(expectedResult, actualResult);
     }
 
+    @Test
+    public void dateV2AddTest() throws AnalysisException {
+        DateLiteral actualResult = FEFunctions.dateAdd(new DateLiteral("2018-08-08", Type.DATEV2), new IntLiteral(1));
+        DateLiteral expectedResult = new DateLiteral("2018-08-09 00:00:00", Type.DATETIMEV2);
+        Assert.assertEquals(expectedResult, actualResult);
+
+        actualResult = FEFunctions.dateAdd(new DateLiteral("2018-08-08", Type.DATE), new IntLiteral(1));
+        expectedResult = new DateLiteral("2018-08-09 00:00:00", Type.DATETIMEV2);
+        Assert.assertEquals(expectedResult, actualResult);
+
+        actualResult = FEFunctions.dateAdd(new DateLiteral("2018-08-08", Type.DATEV2), new IntLiteral(1));
+        expectedResult = new DateLiteral("2018-08-09 00:00:00", Type.DATETIME);
+        Assert.assertEquals(expectedResult, actualResult);
+
+        actualResult = FEFunctions.dateAdd(new DateLiteral("2018-08-08", Type.DATEV2), new IntLiteral(-1));
+        expectedResult = new DateLiteral("2018-08-07 00:00:00", Type.DATETIMEV2);
+        Assert.assertEquals(expectedResult, actualResult);
+
+        actualResult = FEFunctions.dateAdd(new DateLiteral("2018-08-08", Type.DATE), new IntLiteral(-1));
+        expectedResult = new DateLiteral("2018-08-07 00:00:00", Type.DATETIMEV2);
+        Assert.assertEquals(expectedResult, actualResult);
+
+        actualResult = FEFunctions.dateAdd(new DateLiteral("2018-08-08", Type.DATEV2), new IntLiteral(-1));
+        expectedResult = new DateLiteral("2018-08-07 00:00:00", Type.DATETIME);
+        Assert.assertEquals(expectedResult, actualResult);
+    }
+
     @Test
     public void addDateTest() throws AnalysisException {
         DateLiteral actualResult = FEFunctions.addDate(new DateLiteral("2018-08-08", Type.DATE), new IntLiteral(1));
@@ -115,6 +189,34 @@ public void addDateTest() throws AnalysisException {
 
     }
 
+    @Test
+    public void addDateV2Test() throws AnalysisException {
+        DateLiteral actualResult = FEFunctions.addDate(new DateLiteral("2018-08-08", Type.DATEV2), new IntLiteral(1));
+        DateLiteral expectedResult = new DateLiteral("2018-08-09 00:00:00", Type.DATETIMEV2);
+        Assert.assertEquals(expectedResult, actualResult);
+
+        actualResult = FEFunctions.addDate(new DateLiteral("2018-08-08", Type.DATE), new IntLiteral(1));
+        expectedResult = new DateLiteral("2018-08-09 00:00:00", Type.DATETIMEV2);
+        Assert.assertEquals(expectedResult, actualResult);
+
+        actualResult = FEFunctions.addDate(new DateLiteral("2018-08-08", Type.DATEV2), new IntLiteral(1));
+        expectedResult = new DateLiteral("2018-08-09 00:00:00", Type.DATETIME);
+        Assert.assertEquals(expectedResult, actualResult);
+
+        actualResult = FEFunctions.addDate(new DateLiteral("2018-08-08", Type.DATEV2), new IntLiteral(-1));
+        expectedResult = new DateLiteral("2018-08-07 00:00:00", Type.DATETIMEV2);
+        Assert.assertEquals(expectedResult, actualResult);
+
+        actualResult = FEFunctions.addDate(new DateLiteral("2018-08-08", Type.DATE), new IntLiteral(-1));
+        expectedResult = new DateLiteral("2018-08-07 00:00:00", Type.DATETIMEV2);
+        Assert.assertEquals(expectedResult, actualResult);
+
+        actualResult = FEFunctions.addDate(new DateLiteral("2018-08-08", Type.DATEV2), new IntLiteral(-1));
+        expectedResult = new DateLiteral("2018-08-07 00:00:00", Type.DATETIME);
+        Assert.assertEquals(expectedResult, actualResult);
+
+    }
+
     @Test
     public void daysAddTest() throws AnalysisException {
         DateLiteral actualResult = FEFunctions.daysAdd(new DateLiteral("2018-08-08", Type.DATE), new IntLiteral(1));
@@ -126,6 +228,21 @@ public void daysAddTest() throws AnalysisException {
         Assert.assertEquals(expectedResult, actualResult);
     }
 
+    @Test
+    public void daysAddTest2() throws AnalysisException {
+        DateLiteral actualResult = FEFunctions.daysAdd(new DateLiteral("2018-08-08", Type.DATEV2), new IntLiteral(1));
+        DateLiteral expectedResult = new DateLiteral("2018-08-09", Type.DATEV2);
+        Assert.assertEquals(expectedResult, actualResult);
+
+        actualResult = FEFunctions.daysAdd(new DateLiteral("2018-08-08", Type.DATEV2), new IntLiteral(-1));
+        expectedResult = new DateLiteral("2018-08-07", Type.DATEV2);
+        Assert.assertEquals(expectedResult, actualResult);
+
+        actualResult = FEFunctions.daysAdd(new DateLiteral("2018-08-08", Type.DATE), new IntLiteral(-1));
+        expectedResult = new DateLiteral("2018-08-07", Type.DATEV2);
+        Assert.assertEquals(expectedResult, actualResult);
+    }
+
     @Test
     public void fromUnixTimeTest() throws AnalysisException {
         StringLiteral actualResult = FEFunctions.fromUnixTime(new IntLiteral(100000));
@@ -168,10 +285,53 @@ public void dateFormatUtilTest() {
             Assert.assertEquals("January", FEFunctions.dateFormat(testDate, new StringLiteral("%M")).getStringValue());
             Assert.assertEquals("01", FEFunctions.dateFormat(testDate, new StringLiteral("%m")).getStringValue());
             Assert.assertEquals("PM", FEFunctions.dateFormat(testDate, new StringLiteral("%p")).getStringValue());
-            Assert.assertEquals("01:04:05 PM", FEFunctions.dateFormat(testDate, new StringLiteral("%r")).getStringValue());
+            Assert.assertEquals("01:04:05 PM", FEFunctions.dateFormat(testDate,
+                    new StringLiteral("%r")).getStringValue());
+            Assert.assertEquals("05", FEFunctions.dateFormat(testDate, new StringLiteral("%S")).getStringValue());
+            Assert.assertEquals("05", FEFunctions.dateFormat(testDate, new StringLiteral("%s")).getStringValue());
+            Assert.assertEquals("13:04:05", FEFunctions.dateFormat(testDate,
+                    new StringLiteral("%T")).getStringValue());
+            Assert.assertEquals("02", FEFunctions.dateFormat(testDate, new StringLiteral("%v")).getStringValue());
+            Assert.assertEquals("Tuesday", FEFunctions.dateFormat(testDate, new StringLiteral("%W")).getStringValue());
+            Assert.assertEquals("2001", FEFunctions.dateFormat(testDate, new StringLiteral("%Y")).getStringValue());
+            Assert.assertEquals("01", FEFunctions.dateFormat(testDate, new StringLiteral("%y")).getStringValue());
+            Assert.assertEquals("%", FEFunctions.dateFormat(testDate, new StringLiteral("%%")).getStringValue());
+            Assert.assertEquals("foo", FEFunctions.dateFormat(testDate, new StringLiteral("foo")).getStringValue());
+            Assert.assertEquals("g", FEFunctions.dateFormat(testDate, new StringLiteral("%g")).getStringValue());
+            Assert.assertEquals("4", FEFunctions.dateFormat(testDate, new StringLiteral("%4")).getStringValue());
+            Assert.assertEquals("2001 02", FEFunctions.dateFormat(testDate,
+                    new StringLiteral("%x %v")).getStringValue());
+        } catch (AnalysisException e) {
+            e.printStackTrace();
+        }
+    }
+
+    @Test
+    public void dateV2FormatUtilTest() {
+        try {
+            Locale.setDefault(Locale.ENGLISH);
+            DateLiteral testDate = new DateLiteral("2001-01-09 13:04:05", Type.DATETIMEV2);
+            Assert.assertEquals("Tue", FEFunctions.dateFormat(testDate, new StringLiteral("%a")).getStringValue());
+            Assert.assertEquals("Jan", FEFunctions.dateFormat(testDate, new StringLiteral("%b")).getStringValue());
+            Assert.assertEquals("1", FEFunctions.dateFormat(testDate, new StringLiteral("%c")).getStringValue());
+            Assert.assertEquals("09", FEFunctions.dateFormat(testDate, new StringLiteral("%d")).getStringValue());
+            Assert.assertEquals("9", FEFunctions.dateFormat(testDate, new StringLiteral("%e")).getStringValue());
+            Assert.assertEquals("13", FEFunctions.dateFormat(testDate, new StringLiteral("%H")).getStringValue());
+            Assert.assertEquals("01", FEFunctions.dateFormat(testDate, new StringLiteral("%h")).getStringValue());
+            Assert.assertEquals("01", FEFunctions.dateFormat(testDate, new StringLiteral("%I")).getStringValue());
+            Assert.assertEquals("04", FEFunctions.dateFormat(testDate, new StringLiteral("%i")).getStringValue());
+            Assert.assertEquals("009", FEFunctions.dateFormat(testDate, new StringLiteral("%j")).getStringValue());
+            Assert.assertEquals("13", FEFunctions.dateFormat(testDate, new StringLiteral("%k")).getStringValue());
+            Assert.assertEquals("1", FEFunctions.dateFormat(testDate, new StringLiteral("%l")).getStringValue());
+            Assert.assertEquals("January", FEFunctions.dateFormat(testDate, new StringLiteral("%M")).getStringValue());
+            Assert.assertEquals("01", FEFunctions.dateFormat(testDate, new StringLiteral("%m")).getStringValue());
+            Assert.assertEquals("PM", FEFunctions.dateFormat(testDate, new StringLiteral("%p")).getStringValue());
+            Assert.assertEquals("01:04:05 PM", FEFunctions.dateFormat(testDate,
+                    new StringLiteral("%r")).getStringValue());
             Assert.assertEquals("05", FEFunctions.dateFormat(testDate, new StringLiteral("%S")).getStringValue());
             Assert.assertEquals("05", FEFunctions.dateFormat(testDate, new StringLiteral("%s")).getStringValue());
-            Assert.assertEquals("13:04:05", FEFunctions.dateFormat(testDate, new StringLiteral("%T")).getStringValue());
+            Assert.assertEquals("13:04:05", FEFunctions.dateFormat(testDate,
+                    new StringLiteral("%T")).getStringValue());
             Assert.assertEquals("02", FEFunctions.dateFormat(testDate, new StringLiteral("%v")).getStringValue());
             Assert.assertEquals("Tuesday", FEFunctions.dateFormat(testDate, new StringLiteral("%W")).getStringValue());
             Assert.assertEquals("2001", FEFunctions.dateFormat(testDate, new StringLiteral("%Y")).getStringValue());
@@ -181,6 +341,8 @@ public void dateFormatUtilTest() {
             Assert.assertEquals("g", FEFunctions.dateFormat(testDate, new StringLiteral("%g")).getStringValue());
             Assert.assertEquals("4", FEFunctions.dateFormat(testDate, new StringLiteral("%4")).getStringValue());
             Assert.assertEquals("2001 02", FEFunctions.dateFormat(testDate, new StringLiteral("%x %v")).getStringValue());
+            Assert.assertEquals("2001 02", FEFunctions.dateFormat(testDate,
+                    new StringLiteral("%x %v")).getStringValue());
         } catch (AnalysisException e) {
             e.printStackTrace();
         }
@@ -189,28 +351,55 @@ public void dateFormatUtilTest() {
     @Test
     public void dateParseTest() {
         try {
-            Assert.assertEquals("2019-05-09 00:00:00", FEFunctions.dateParse(new StringLiteral("2019-05-09"), new StringLiteral("%Y-%m-%d %H:%i:%s")).getStringValue());
-            Assert.assertEquals("2013-05-10", FEFunctions.dateParse(new StringLiteral("2013,05,10"), new StringLiteral("%Y,%m,%d")).getStringValue());
-            Assert.assertEquals("2013-05-17 00:35:10", FEFunctions.dateParse(new StringLiteral("2013-05-17 12:35:10"), new StringLiteral("%Y-%m-%d %h:%i:%s")).getStringValue());
-            Assert.assertEquals("2013-05-17 00:35:10", FEFunctions.dateParse(new StringLiteral("2013-05-17 00:35:10"), new StringLiteral("%Y-%m-%d %H:%i:%s")).getStringValue());
-            Assert.assertEquals("2013-05-17 00:35:10", FEFunctions.dateParse(new StringLiteral("2013-05-17 12:35:10 AM"), new StringLiteral("%Y-%m-%d %h:%i:%s %p")).getStringValue());
-            Assert.assertEquals("2013-05-17 12:35:10", FEFunctions.dateParse(new StringLiteral("2013-05-17 12:35:10 PM"), new StringLiteral("%Y-%m-%d %h:%i:%s %p")).getStringValue());
-            Assert.assertEquals("2013-05-17 23:35:10", FEFunctions.dateParse(new StringLiteral("abc 2013-05-17 fff 23:35:10 xyz"), new StringLiteral("abc %Y-%m-%d fff %H:%i:%s xyz")).getStringValue());
-            Assert.assertEquals("2016-01-28 23:45:46", FEFunctions.dateParse(new StringLiteral("28-JAN-16 11.45.46 PM"), new StringLiteral("%d-%b-%y %l.%i.%s %p")).getStringValue());
-            Assert.assertEquals("2019-05-09", FEFunctions.dateParse(new StringLiteral("2019/May/9"), new StringLiteral("%Y/%b/%d")).getStringValue());
-            Assert.assertEquals("2019-05-09", FEFunctions.dateParse(new StringLiteral("2019,129"), new StringLiteral("%Y,%j")).getStringValue());
-            Assert.assertEquals("2019-05-09", FEFunctions.dateParse(new StringLiteral("2019,19,Thursday"), new StringLiteral("%x,%v,%W")).getStringValue());
-            Assert.assertEquals("2019-05-09 12:10:45", FEFunctions.dateParse(new StringLiteral("12:10:45-20190509"), new StringLiteral("%T-%Y%m%d")).getStringValue());
-            Assert.assertEquals("2019-05-09 09:10:45", FEFunctions.dateParse(new StringLiteral("20190509-9:10:45"), new StringLiteral("%Y%m%d-%k:%i:%S")).getStringValue());
-            Assert.assertEquals("0000-00-20", FEFunctions.dateParse(new StringLiteral("2013-05-17"), new StringLiteral("%D")).getStringValue());
-            Assert.assertEquals("0000-00-00", FEFunctions.dateParse(new StringLiteral("2013-05-17"), new StringLiteral("%U")).getStringValue());
-            Assert.assertEquals("0000-00-00", FEFunctions.dateParse(new StringLiteral("2013-05-17"), new StringLiteral("%u")).getStringValue());
-            Assert.assertEquals("0000-00-00", FEFunctions.dateParse(new StringLiteral("2013-05-17"), new StringLiteral("%V")).getStringValue());
-            Assert.assertEquals("0000-00-00", FEFunctions.dateParse(new StringLiteral("2013-05-17"), new StringLiteral("%w")).getStringValue());
-            Assert.assertEquals("0000-00-00", FEFunctions.dateParse(new StringLiteral("2013-05-17"), new StringLiteral("%x")).getStringValue());
-            Assert.assertEquals("0000-00-00", FEFunctions.dateParse(new StringLiteral("2013-05-17"), new StringLiteral("%X")).getStringValue());
-            Assert.assertEquals("2013-05-17 20:07:05", FEFunctions.dateParse(new StringLiteral("2013-05-17 08:07:05 PM"), new StringLiteral("%Y-%m-%d %r")).getStringValue());
-            Assert.assertEquals("2013-05-17 08:07:05", FEFunctions.dateParse(new StringLiteral("2013-05-17 08:07:05"), new StringLiteral("%Y-%m-%d %T")).getStringValue());
+            Assert.assertEquals("2019-05-09 00:00:00", FEFunctions.dateParse(new StringLiteral("2019-05-09"),
+                    new StringLiteral("%Y-%m-%d %H:%i:%s")).getStringValue());
+            Assert.assertEquals("2013-05-10", FEFunctions.dateParse(new StringLiteral("2013,05,10"),
+                    new StringLiteral("%Y,%m,%d")).getStringValue());
+            Assert.assertEquals("2013-05-17 00:35:10", FEFunctions.dateParse(
+                    new StringLiteral("2013-05-17 12:35:10"),
+                    new StringLiteral("%Y-%m-%d %h:%i:%s")).getStringValue());
+            Assert.assertEquals("2013-05-17 00:35:10", FEFunctions.dateParse(new StringLiteral("2013-05-17 00:35:10"),
+                    new StringLiteral("%Y-%m-%d %H:%i:%s")).getStringValue());
+            Assert.assertEquals("2013-05-17 00:35:10", FEFunctions.dateParse(
+                    new StringLiteral("2013-05-17 12:35:10 AM"),
+                    new StringLiteral("%Y-%m-%d %h:%i:%s %p")).getStringValue());
+            Assert.assertEquals("2013-05-17 12:35:10", FEFunctions.dateParse(
+                    new StringLiteral("2013-05-17 12:35:10 PM"),
+                    new StringLiteral("%Y-%m-%d %h:%i:%s %p")).getStringValue());
+            Assert.assertEquals("2013-05-17 23:35:10", FEFunctions.dateParse(
+                    new StringLiteral("abc 2013-05-17 fff 23:35:10 xyz"),
+                    new StringLiteral("abc %Y-%m-%d fff %H:%i:%s xyz")).getStringValue());
+            Assert.assertEquals("2016-01-28 23:45:46", FEFunctions.dateParse(
+                    new StringLiteral("28-JAN-16 11.45.46 PM"),
+                    new StringLiteral("%d-%b-%y %l.%i.%s %p")).getStringValue());
+            Assert.assertEquals("2019-05-09", FEFunctions.dateParse(new StringLiteral("2019/May/9"),
+                    new StringLiteral("%Y/%b/%d")).getStringValue());
+            Assert.assertEquals("2019-05-09", FEFunctions.dateParse(new StringLiteral("2019,129"),
+                    new StringLiteral("%Y,%j")).getStringValue());
+            Assert.assertEquals("2019-05-09", FEFunctions.dateParse(new StringLiteral("2019,19,Thursday"),
+                    new StringLiteral("%x,%v,%W")).getStringValue());
+            Assert.assertEquals("2019-05-09 12:10:45", FEFunctions.dateParse(new StringLiteral("12:10:45-20190509"),
+                    new StringLiteral("%T-%Y%m%d")).getStringValue());
+            Assert.assertEquals("2019-05-09 09:10:45", FEFunctions.dateParse(new StringLiteral("20190509-9:10:45"),
+                    new StringLiteral("%Y%m%d-%k:%i:%S")).getStringValue());
+            Assert.assertEquals("0000-00-20", FEFunctions.dateParse(new StringLiteral("2013-05-17"),
+                    new StringLiteral("%D")).getStringValue());
+            Assert.assertEquals("0000-00-00", FEFunctions.dateParse(new StringLiteral("2013-05-17"),
+                    new StringLiteral("%U")).getStringValue());
+            Assert.assertEquals("0000-00-00", FEFunctions.dateParse(new StringLiteral("2013-05-17"),
+                    new StringLiteral("%u")).getStringValue());
+            Assert.assertEquals("0000-00-00", FEFunctions.dateParse(new StringLiteral("2013-05-17"),
+                    new StringLiteral("%V")).getStringValue());
+            Assert.assertEquals("0000-00-00", FEFunctions.dateParse(new StringLiteral("2013-05-17"),
+                    new StringLiteral("%w")).getStringValue());
+            Assert.assertEquals("0000-00-00", FEFunctions.dateParse(new StringLiteral("2013-05-17"),
+                    new StringLiteral("%x")).getStringValue());
+            Assert.assertEquals("0000-00-00", FEFunctions.dateParse(new StringLiteral("2013-05-17"),
+                    new StringLiteral("%X")).getStringValue());
+            Assert.assertEquals("2013-05-17 20:07:05", FEFunctions.dateParse(
+                    new StringLiteral("2013-05-17 08:07:05 PM"), new StringLiteral("%Y-%m-%d %r")).getStringValue());
+            Assert.assertEquals("2013-05-17 08:07:05", FEFunctions.dateParse(new StringLiteral("2013-05-17 08:07:05"),
+                    new StringLiteral("%Y-%m-%d %T")).getStringValue());
         } catch (AnalysisException e) {
             e.printStackTrace();
             Assert.fail("Junit test dateParse fail");
@@ -235,6 +424,33 @@ public void dateSubTest() throws AnalysisException {
         Assert.assertEquals(expectedResult, actualResult);
     }
 
+    @Test
+    public void dateV2SubTest() throws AnalysisException {
+        DateLiteral actualResult = FEFunctions.dateSub(new DateLiteral("2018-08-08", Type.DATEV2), new IntLiteral(1));
+        DateLiteral expectedResult = new DateLiteral("2018-08-07", Type.DATEV2);
+        Assert.assertEquals(expectedResult, actualResult);
+
+        actualResult = FEFunctions.dateSub(new DateLiteral("2018-08-08", Type.DATE), new IntLiteral(1));
+        expectedResult = new DateLiteral("2018-08-07", Type.DATEV2);
+        Assert.assertEquals(expectedResult, actualResult);
+
+        actualResult = FEFunctions.dateSub(new DateLiteral("2018-08-08", Type.DATEV2), new IntLiteral(1));
+        expectedResult = new DateLiteral("2018-08-07", Type.DATE);
+        Assert.assertEquals(expectedResult, actualResult);
+
+        actualResult = FEFunctions.dateSub(new DateLiteral("2018-08-08", Type.DATEV2), new IntLiteral(-1));
+        expectedResult = new DateLiteral("2018-08-09", Type.DATEV2);
+        Assert.assertEquals(expectedResult, actualResult);
+
+        actualResult = FEFunctions.dateSub(new DateLiteral("2018-08-08", Type.DATEV2), new IntLiteral(-1));
+        expectedResult = new DateLiteral("2018-08-09", Type.DATE);
+        Assert.assertEquals(expectedResult, actualResult);
+
+        actualResult = FEFunctions.dateSub(new DateLiteral("2018-08-08", Type.DATE), new IntLiteral(-1));
+        expectedResult = new DateLiteral("2018-08-09", Type.DATEV2);
+        Assert.assertEquals(expectedResult, actualResult);
+    }
+
     @Test
     public void yearTest() throws AnalysisException {
         IntLiteral actualResult = FEFunctions.year(new DateLiteral("2018-08-08", Type.DATE));
@@ -245,6 +461,26 @@ public void yearTest() throws AnalysisException {
         expectedResult = new IntLiteral(1970, Type.INT);
         Assert.assertEquals(expectedResult, actualResult);
     }
+
+    @Test
+    public void yearTest2() throws AnalysisException {
+        IntLiteral actualResult = FEFunctions.year(new DateLiteral("2018-08-08", Type.DATE));
+        IntLiteral expectedResult = new IntLiteral(2018, Type.INT);
+        Assert.assertEquals(expectedResult, actualResult);
+
+        actualResult = FEFunctions.year(new DateLiteral("2018-08-08", Type.DATEV2));
+        expectedResult = new IntLiteral(2018, Type.INT);
+        Assert.assertEquals(expectedResult, actualResult);
+
+        actualResult = FEFunctions.year(new DateLiteral("1970-01-02 11:46:40", Type.DATETIME));
+        expectedResult = new IntLiteral(1970, Type.INT);
+        Assert.assertEquals(expectedResult, actualResult);
+
+        actualResult = FEFunctions.year(new DateLiteral("1970-01-02 11:46:40", Type.DATETIMEV2));
+        expectedResult = new IntLiteral(1970, Type.INT);
+        Assert.assertEquals(expectedResult, actualResult);
+    }
+
     @Test
     public void monthTest() throws AnalysisException {
         IntLiteral actualResult = FEFunctions.month(new DateLiteral("2018-08-08", Type.DATE));
@@ -256,6 +492,17 @@ public void monthTest() throws AnalysisException {
         Assert.assertEquals(expectedResult, actualResult);
     }
 
+    @Test
+    public void monthTest2() throws AnalysisException {
+        IntLiteral actualResult = FEFunctions.month(new DateLiteral("2018-08-08", Type.DATEV2));
+        IntLiteral expectedResult = new IntLiteral(8, Type.INT);
+        Assert.assertEquals(expectedResult, actualResult);
+
+        actualResult = FEFunctions.month(new DateLiteral("1970-01-02 11:46:40", Type.DATETIMEV2));
+        expectedResult = new IntLiteral(1, Type.INT);
+        Assert.assertEquals(expectedResult, actualResult);
+    }
+
     @Test
     public void dayTest() throws AnalysisException {
         IntLiteral actualResult = FEFunctions.day(new DateLiteral("2018-08-08", Type.DATE));
@@ -267,6 +514,17 @@ public void dayTest() throws AnalysisException {
         Assert.assertEquals(expectedResult, actualResult);
     }
 
+    @Test
+    public void dayTest2() throws AnalysisException {
+        IntLiteral actualResult = FEFunctions.day(new DateLiteral("2018-08-08", Type.DATEV2));
+        IntLiteral expectedResult = new IntLiteral(8, Type.INT);
+        Assert.assertEquals(expectedResult, actualResult);
+
+        actualResult = FEFunctions.day(new DateLiteral("1970-01-02 11:46:40", Type.DATETIMEV2));
+        expectedResult = new IntLiteral(2, Type.INT);
+        Assert.assertEquals(expectedResult, actualResult);
+    }
+
     @Test
     public void floorTest() throws AnalysisException {
         IntLiteral actualResult = FEFunctions.floor(new FloatLiteral(3.3));
@@ -314,7 +572,9 @@ public void addDecimalV2Test() throws AnalysisException {
 
     @Test
     public void addBigIntTest() throws AnalysisException {
-        LargeIntLiteral actualResult = FEFunctions.addBigInt(new LargeIntLiteral("170141183460469231731687303715884105727"), new LargeIntLiteral("-170141183460469231731687303715884105728"));
+        LargeIntLiteral actualResult = FEFunctions.addBigInt(
+                new LargeIntLiteral("170141183460469231731687303715884105727"),
+                new LargeIntLiteral("-170141183460469231731687303715884105728"));
         LargeIntLiteral expectedResult = new LargeIntLiteral("-1");
         Assert.assertEquals(expectedResult, actualResult);
 
@@ -347,7 +607,8 @@ public void subtractDoubleTest() throws AnalysisException {
 
     @Test
     public void subtractDecimalV2Test() throws AnalysisException {
-        DecimalLiteral actualResult = FEFunctions.subtractDecimalV2(new DecimalLiteral("2.2"), new DecimalLiteral("3.3"));
+        DecimalLiteral actualResult = FEFunctions.subtractDecimalV2(new DecimalLiteral("2.2"),
+                new DecimalLiteral("3.3"));
         DecimalLiteral expectedResult = new DecimalLiteral("-1.1");
         Assert.assertEquals(expectedResult, actualResult);
 
@@ -358,7 +619,9 @@ public void subtractDecimalV2Test() throws AnalysisException {
 
     @Test
     public void subtractBigIntTest() throws AnalysisException {
-        LargeIntLiteral actualResult = FEFunctions.subtractBigInt(new LargeIntLiteral("170141183460469231731687303715884105727"), new LargeIntLiteral("170141183460469231731687303715884105728"));
+        LargeIntLiteral actualResult = FEFunctions.subtractBigInt(
+                new LargeIntLiteral("170141183460469231731687303715884105727"),
+                new LargeIntLiteral("170141183460469231731687303715884105728"));
         LargeIntLiteral expectedResult = new LargeIntLiteral("-1");
         Assert.assertEquals(expectedResult, actualResult);
 
@@ -399,7 +662,8 @@ public void multiplyDoubleTest() throws AnalysisException {
 
     @Test
     public void multiplyDecimalV2Test() throws AnalysisException {
-        DecimalLiteral actualResult = FEFunctions.multiplyDecimalV2(new DecimalLiteral("1.1"), new DecimalLiteral("1.0"));
+        DecimalLiteral actualResult = FEFunctions.multiplyDecimalV2(new DecimalLiteral("1.1"),
+                new DecimalLiteral("1.0"));
         DecimalLiteral expectedResult = new DecimalLiteral("1.1");
         Assert.assertEquals(expectedResult, actualResult);
 
@@ -414,7 +678,8 @@ public void multiplyDecimalV2Test() throws AnalysisException {
 
     @Test
     public void multiplyBigIntTest() throws AnalysisException {
-        LargeIntLiteral actualResult = FEFunctions.multiplyBigInt(new LargeIntLiteral("-170141183460469231731687303715884105727"), new LargeIntLiteral("1"));
+        LargeIntLiteral actualResult = FEFunctions.multiplyBigInt(
+                new LargeIntLiteral("-170141183460469231731687303715884105727"), new LargeIntLiteral("1"));
         LargeIntLiteral expectedResult = new LargeIntLiteral("-170141183460469231731687303715884105727");
         Assert.assertEquals(expectedResult, actualResult);
 
@@ -440,7 +705,8 @@ public void divideDoubleTest() throws AnalysisException {
 
     @Test
     public void divideDecimalV2Test() throws AnalysisException {
-        DecimalLiteral actualResult = FEFunctions.divideDecimalV2(new DecimalLiteral("1.1"), new DecimalLiteral("1.0"));
+        DecimalLiteral actualResult = FEFunctions.divideDecimalV2(new DecimalLiteral("1.1"),
+                new DecimalLiteral("1.0"));
         DecimalLiteral expectedResult = new DecimalLiteral("1.1");
         Assert.assertEquals(expectedResult, actualResult);
 
@@ -459,6 +725,16 @@ public void timeDiffTest() throws AnalysisException {
         Assert.assertEquals(2419200, FEFunctions.timeDiff(d3, d2).getLongValue());
     }
 
+    @Test
+    public void timeDiffTest2() throws AnalysisException {
+        DateLiteral d1 = new DateLiteral("1019-02-28 00:00:00", Type.DATETIMEV2);
+        DateLiteral d2 = new DateLiteral("2019-02-28 00:00:00", Type.DATETIME);
+        DateLiteral d3 = new DateLiteral("2019-03-28 00:00:00", Type.DATETIMEV2);
+        Assert.assertEquals(31556995543L, FEFunctions.timeDiff(d2, d1).getLongValue());
+        Assert.assertEquals(31559414743L, FEFunctions.timeDiff(d3, d1).getLongValue());
+        Assert.assertEquals(2419200, FEFunctions.timeDiff(d3, d2).getLongValue());
+    }
+
     @Test
     public void timeNowTest() throws AnalysisException {
         String curTimeString = FEFunctions.curTime().toSqlImpl().replace("'", "");
@@ -510,4 +786,69 @@ public void datePlusAndSubTest() throws AnalysisException {
         Assert.assertEquals(new DateLiteral("2019-11-10 23:59:59", Type.DATETIME),
                 FEFunctions.secondsSub(dateLiteral, new IntLiteral(1)));
     }
+
+    @Test
+    public void dateV2PlusAndSubTest() throws AnalysisException {
+        DateLiteral dateLiteral = new DateLiteral("2019-11-11 00:00:00", Type.DATETIMEV2);
+
+        Assert.assertEquals(new DateLiteral("2020-11-11 00:00:00", Type.DATETIME),
+                FEFunctions.yearsAdd(dateLiteral, new IntLiteral(1)));
+        Assert.assertEquals(new DateLiteral("2020-11-11 00:00:00", Type.DATETIMEV2),
+                FEFunctions.yearsAdd(dateLiteral, new IntLiteral(1)));
+
+        Assert.assertEquals(new DateLiteral("2018-11-11 00:00:00", Type.DATETIME),
+                FEFunctions.yearsSub(dateLiteral, new IntLiteral(1)));
+        Assert.assertEquals(new DateLiteral("2018-11-11 00:00:00", Type.DATETIMEV2),
+                FEFunctions.yearsSub(dateLiteral, new IntLiteral(1)));
+
+        Assert.assertEquals(new DateLiteral("2019-12-11 00:00:00", Type.DATETIME),
+                FEFunctions.monthsAdd(dateLiteral, new IntLiteral(1)));
+        Assert.assertEquals(new DateLiteral("2019-12-11 00:00:00", Type.DATETIMEV2),
+                FEFunctions.monthsAdd(dateLiteral, new IntLiteral(1)));
+
+        Assert.assertEquals(new DateLiteral("2019-10-11 00:00:00", Type.DATETIME),
+                FEFunctions.monthsSub(dateLiteral, new IntLiteral(1)));
+        Assert.assertEquals(new DateLiteral("2019-10-11 00:00:00", Type.DATETIMEV2),
+                FEFunctions.monthsSub(dateLiteral, new IntLiteral(1)));
+
+        Assert.assertEquals(new DateLiteral("2019-11-12 00:00:00", Type.DATETIME),
+                FEFunctions.daysAdd(dateLiteral, new IntLiteral(1)));
+        Assert.assertEquals(new DateLiteral("2019-11-12 00:00:00", Type.DATETIMEV2),
+                FEFunctions.daysAdd(dateLiteral, new IntLiteral(1)));
+
+        Assert.assertEquals(new DateLiteral("2019-11-10 00:00:00", Type.DATETIME),
+                FEFunctions.daysSub(dateLiteral, new IntLiteral(1)));
+        Assert.assertEquals(new DateLiteral("2019-11-10 00:00:00", Type.DATETIMEV2),
+                FEFunctions.daysSub(dateLiteral, new IntLiteral(1)));
+
+        Assert.assertEquals(new DateLiteral("2019-11-11 01:00:00", Type.DATETIME),
+                FEFunctions.hoursAdd(dateLiteral, new IntLiteral(1)));
+        Assert.assertEquals(new DateLiteral("2019-11-11 01:00:00", Type.DATETIMEV2),
+                FEFunctions.hoursAdd(dateLiteral, new IntLiteral(1)));
+
+        Assert.assertEquals(new DateLiteral("2019-11-10 23:00:00", Type.DATETIME),
+                FEFunctions.hoursSub(dateLiteral, new IntLiteral(1)));
+        Assert.assertEquals(new DateLiteral("2019-11-10 23:00:00", Type.DATETIMEV2),
+                FEFunctions.hoursSub(dateLiteral, new IntLiteral(1)));
+
+        Assert.assertEquals(new DateLiteral("2019-11-11 00:01:00", Type.DATETIME),
+                FEFunctions.minutesAdd(dateLiteral, new IntLiteral(1)));
+        Assert.assertEquals(new DateLiteral("2019-11-11 00:01:00", Type.DATETIMEV2),
+                FEFunctions.minutesAdd(dateLiteral, new IntLiteral(1)));
+
+        Assert.assertEquals(new DateLiteral("2019-11-10 23:59:00", Type.DATETIME),
+                FEFunctions.minutesSub(dateLiteral, new IntLiteral(1)));
+        Assert.assertEquals(new DateLiteral("2019-11-10 23:59:00", Type.DATETIMEV2),
+                FEFunctions.minutesSub(dateLiteral, new IntLiteral(1)));
+
+        Assert.assertEquals(new DateLiteral("2019-11-11 00:00:01", Type.DATETIME),
+                FEFunctions.secondsAdd(dateLiteral, new IntLiteral(1)));
+        Assert.assertEquals(new DateLiteral("2019-11-11 00:00:01", Type.DATETIMEV2),
+                FEFunctions.secondsAdd(dateLiteral, new IntLiteral(1)));
+
+        Assert.assertEquals(new DateLiteral("2019-11-10 23:59:59", Type.DATETIME),
+                FEFunctions.secondsSub(dateLiteral, new IntLiteral(1)));
+        Assert.assertEquals(new DateLiteral("2019-11-10 23:59:59", Type.DATETIMEV2),
+                FEFunctions.secondsSub(dateLiteral, new IntLiteral(1)));
+    }
 }
diff --git a/fe/fe-core/src/test/java/org/apache/doris/rewrite/RewriteDateLiteralRuleTest.java b/fe/fe-core/src/test/java/org/apache/doris/rewrite/RewriteDateLiteralRuleTest.java
index 68610859f06ae2..f91568d5144821 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/rewrite/RewriteDateLiteralRuleTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/rewrite/RewriteDateLiteralRuleTest.java
@@ -28,6 +28,7 @@ public class RewriteDateLiteralRuleTest {
     private DorisAssert dorisAssert;
     private static final String DB_NAME = "rewritedaterule";
     private static final String TABLE_NAME_1 = "tb1";
+    private static final String TABLE_NAME_2 = "tb2";
 
     public void before(ConnectContext ctx) throws Exception {
         FeConstants.default_scheduler_interval_millisecond = 10;
@@ -38,6 +39,10 @@ public void before(ConnectContext ctx) throws Exception {
                 + " (k1 datetime, k2 int) "
                 + "distributed by hash(k2) buckets 3 properties('replication_num' = '1');";
         dorisAssert.withTable(createTableSQL);
+        createTableSQL = "create table " + DB_NAME + "." + TABLE_NAME_2
+                + " (k1 datetime(3), k2 int) "
+                + "distributed by hash(k2) buckets 3 properties('replication_num' = '1');";
+        dorisAssert.withTable(createTableSQL);
     }
 
     public void after() throws Exception {
@@ -56,6 +61,18 @@ public void testWithIntFormatDate() throws Exception {
         Assert.assertTrue(planString.contains("`k1` > '2021-03-01 22:33:44'"));
     }
 
+    public void testWithIntFormatDateV2() throws Exception {
+        String query = "select * from " + DB_NAME + ".tb2 where k1 > 20210301";
+        String planString = dorisAssert.query(query).explainQuery();
+        Assert.assertTrue(planString.contains("`k1` > '2021-03-01 00:00:00'"));
+        query = "select k1 > 20210301 from " + DB_NAME + ".tb2";
+        planString = dorisAssert.query(query).explainQuery();
+        Assert.assertTrue(planString.contains("`k1` > '2021-03-01 00:00:00'"));
+        query = "select k1 > 20210301223344 from " + DB_NAME + ".tb2";
+        planString = dorisAssert.query(query).explainQuery();
+        Assert.assertTrue(planString.contains("`k1` > '2021-03-01 22:33:44'"));
+    }
+
     public void testWithStringFormatDate() throws Exception {
         String query = "select * from " + DB_NAME + ".tb1 where k1 > '2021030112334455'";
         String planString = dorisAssert.query(query).explainQuery();
@@ -102,6 +119,52 @@ public void testWithStringFormatDate() throws Exception {
         Assert.assertTrue(planString.contains("`k1` > '2012-03-01 11:22:00'"));
     }
 
+    public void testWithStringFormatDateV2() throws Exception {
+        String query = "select * from " + DB_NAME + ".tb2 where k1 > '2021030112334455'";
+        String planString = dorisAssert.query(query).explainQuery();
+        Assert.assertTrue(planString.contains("`k1` > '2021-03-01 12:33:44'"));
+
+        query = "select k1 > '20210301' from " + DB_NAME + ".tb2";
+        planString = dorisAssert.query(query).explainQuery();
+        Assert.assertTrue(planString.contains("`k1` > '2021-03-01 00:00:00'"));
+
+        query = "select k1 > '20210301233234.34' from " + DB_NAME + ".tb2";
+        planString = dorisAssert.query(query).explainQuery();
+        Assert.assertTrue(planString.contains("`k1` > '2021-03-01 23:32:34'"));
+
+        query = "select * from " + DB_NAME + ".tb2 where k1 > '2021-03-01'";
+        planString = dorisAssert.query(query).explainQuery();
+        Assert.assertTrue(planString.contains("`k1` > '2021-03-01 00:00:00'"));
+
+        query = "select k1 > '2021-03-01 11:22:33' from " + DB_NAME + ".tb2";
+        planString = dorisAssert.query(query).explainQuery();
+        Assert.assertTrue(planString.contains("`k1` > '2021-03-01 11:22:33'"));
+
+        query = "select k1 > '2021-03-01  16:22:33' from " + DB_NAME + ".tb2";
+        planString = dorisAssert.query(query).explainQuery();
+        Assert.assertTrue(planString.contains("`k1` > '2021-03-01 16:22:33'"));
+
+        query = "select k1 > '2021-03-01 11:22' from " + DB_NAME + ".tb2";
+        planString = dorisAssert.query(query).explainQuery();
+        Assert.assertTrue(planString.contains("`k1` > '2021-03-01 11:22:00'"));
+
+        query = "select k1 > '20210301T221133' from " + DB_NAME + ".tb2";
+        planString = dorisAssert.query(query).explainQuery();
+        Assert.assertTrue(planString.contains("`k1` > '2021-03-01 22:11:33'"));
+
+        query = "select k1 > '2021-03-01dd 11:22' from " + DB_NAME + ".tb2";
+        planString = dorisAssert.query(query).explainQuery();
+        Assert.assertTrue(planString.contains("`k1` > '2021-03-01 00:00:00'"));
+
+        query = "select k1 > '80-03-01 11:22' from " + DB_NAME + ".tb2";
+        planString = dorisAssert.query(query).explainQuery();
+        Assert.assertTrue(planString.contains("`k1` > '1980-03-01 11:22:00'"));
+
+        query = "select k1 > '12-03-01 11:22' from " + DB_NAME + ".tb2";
+        planString = dorisAssert.query(query).explainQuery();
+        Assert.assertTrue(planString.contains("`k1` > '2012-03-01 11:22:00'"));
+    }
+
     public void testWithDoubleFormatDate() throws Exception {
         String query = "select * from " + DB_NAME + ".tb1 where k1 > 20210301.22";
         String planString = dorisAssert.query(query).explainQuery();
@@ -112,6 +175,16 @@ public void testWithDoubleFormatDate() throws Exception {
         Assert.assertTrue(planString.contains("`k1` > 2.021033122E7"));
     }
 
+    public void testWithDoubleFormatDateV2() throws Exception {
+        String query = "select * from " + DB_NAME + ".tb2 where k1 > 20210301.22";
+        String planString = dorisAssert.query(query).explainQuery();
+        Assert.assertTrue(planString.contains("`k1` > 2.021030122E7"));
+
+        query = "select k1 > 20210331.22 from " + DB_NAME + ".tb2";
+        planString = dorisAssert.query(query).explainQuery();
+        Assert.assertTrue(planString.contains("`k1` > 2.021033122E7"));
+    }
+
     public void testWithInvalidFormatDate() throws Exception {
         String query = "select * from " + DB_NAME + ".tb1 where k1 > '2021030125334455'";
         try {
@@ -145,4 +218,38 @@ public void testWithInvalidFormatDate() throws Exception {
         plainString = dorisAssert.query(query).explainQuery();
         Assert.assertTrue(plainString.contains("NULL"));
     }
+
+    public void testWithInvalidFormatDateV2() throws Exception {
+        String query = "select * from " + DB_NAME + ".tb2 where k1 > '2021030125334455'";
+        try {
+            dorisAssert.query(query).explainQuery();
+        } catch (AnalysisException e) {
+            Assert.assertTrue(e.getMessage().contains(
+                    "Incorrect datetime value: '2021030125334455' in expression: `k1` > '2021030125334455'"));
+        }
+
+        query = "select k1 > '2021030125334455' from " + DB_NAME + ".tb2";
+        String plainString = dorisAssert.query(query).explainQuery();
+        Assert.assertTrue(plainString.contains("NULL"));
+
+        query = "select * from " + DB_NAME + ".tb2 where k1 > '2021-03-32 23:33:55'";
+        try {
+            dorisAssert.query(query).explainQuery();
+        } catch (AnalysisException e) {
+            Assert.assertTrue(e.getMessage().contains(
+                    "Incorrect datetime value: '2021-03-32 23:33:55' in expression: `k1` > '2021-03-32 23:33:55'"));
+        }
+
+        query = "select * from " + DB_NAME + ".tb2 where k1 > '2021-03- 03 23:33:55'";
+        try {
+            dorisAssert.query(query).explainQuery();
+        } catch (AnalysisException e) {
+            Assert.assertTrue(e.getMessage().contains(
+                    "Incorrect datetime value: '2021-03- 03 23:33:55' in expression: `k1` > '2021-03- 03 23:33:55'"));
+        }
+
+        query = "select k1 > '2021-03- 03 23:33:55' from " + DB_NAME + ".tb2";
+        plainString = dorisAssert.query(query).explainQuery();
+        Assert.assertTrue(plainString.contains("NULL"));
+    }
 }
diff --git a/fe/spark-dpp/src/main/java/org/apache/doris/load/loadv2/dpp/SparkRDDAggregator.java b/fe/spark-dpp/src/main/java/org/apache/doris/load/loadv2/dpp/SparkRDDAggregator.java
index d5b37ec3910ae3..4ec158e6620b6a 100644
--- a/fe/spark-dpp/src/main/java/org/apache/doris/load/loadv2/dpp/SparkRDDAggregator.java
+++ b/fe/spark-dpp/src/main/java/org/apache/doris/load/loadv2/dpp/SparkRDDAggregator.java
@@ -75,6 +75,8 @@ public static SparkRDDAggregator buildAggregator(EtlJobConfig.EtlColumn column)
                     case "decimalv2":
                     case "date":
                     case "datetime":
+                    case "datev2":
+                    case "datetimev2":
                         return new NumberMaxAggregator();
                     case "char":
                     case "varchar":
@@ -95,6 +97,8 @@ public static SparkRDDAggregator buildAggregator(EtlJobConfig.EtlColumn column)
                     case "decimalv2":
                     case "date":
                     case "datetime":
+                    case "datev2":
+                    case "datetimev2":
                         return new NumberMinAggregator();
                     case "char":
                     case "varchar":
diff --git a/gensrc/thrift/Types.thrift b/gensrc/thrift/Types.thrift
index d75376443f104e..aecc20a0693c8e 100644
--- a/gensrc/thrift/Types.thrift
+++ b/gensrc/thrift/Types.thrift
@@ -83,6 +83,9 @@ enum TPrimitiveType {
   STRING,
   ALL,
   QUANTILE_STATE,
+  DATEV2,
+  DATETIMEV2,
+  TIMEV2,
 }
 
 enum TTypeNodeType {
diff --git a/regression-test/suites/correctness/test_last_value_window.groovy b/regression-test/suites/correctness/test_last_value_window.groovy
index 274cdec46d43b2..fab1543d2bbc61 100644
--- a/regression-test/suites/correctness/test_last_value_window.groovy
+++ b/regression-test/suites/correctness/test_last_value_window.groovy
@@ -23,10 +23,10 @@ suite("test_last_value_window") {
     sql """
             CREATE TABLE ${tableName} (
             `myday` INT,
-            `time` VARCHAR(40) NOT NULL,
+            `time_col` VARCHAR(40) NOT NULL,
             `state` INT
             ) ENGINE=OLAP
-            DUPLICATE KEY(`myday`,time,state)
+            DUPLICATE KEY(`myday`,time_col,state)
             COMMENT "OLAP"
             DISTRIBUTED BY HASH(`myday`) BUCKETS 2
             PROPERTIES (
@@ -46,6 +46,6 @@ suite("test_last_value_window") {
     // not_vectorized
     sql """ set enable_vectorized_engine = false; """
 
-    qt_select_default """ select *,last_value(state) over(partition by myday order by time) from ${tableName}; """
+    qt_select_default """ select *,last_value(state) over(partition by myday order by time_col) from ${tableName}; """
 
 }
\ No newline at end of file