diff --git a/be/src/vec/functions/function_timestamp.cpp b/be/src/vec/functions/function_timestamp.cpp index 927d0d8103..8e20d14f79 100644 --- a/be/src/vec/functions/function_timestamp.cpp +++ b/be/src/vec/functions/function_timestamp.cpp @@ -64,16 +64,22 @@ namespace doris::vectorized { +template struct StrToDate { static constexpr auto name = "str_to_date"; static bool is_variadic() { return false; } - static DataTypes get_variadic_argument_types() { return {}; } + static DataTypes get_variadic_argument_types() { + return {std::make_shared(), std::make_shared()}; + } static DataTypePtr get_return_type_impl(const DataTypes& arguments) { - //TODO: it doesn't matter now. maybe sometime we should find the function signature with return_type together - return make_nullable(std::make_shared()); + if constexpr (IsDateType || IsDateV2Type) { + return make_nullable(std::make_shared()); + } + //datetimev2 + return make_nullable(std::make_shared(6)); } static StringRef rewrite_specific_format(const char* raw_str, size_t str_size) { @@ -1266,7 +1272,8 @@ public: } }; -using FunctionStrToDate = FunctionOtherTypesToDateType; +using FunctionStrToDate = FunctionOtherTypesToDateType>; +using FunctionStrToDatetime = FunctionOtherTypesToDateType>; using FunctionMakeDate = FunctionOtherTypesToDateType; using FunctionDateTruncDate = FunctionOtherTypesToDateType>; using FunctionDateTruncDateV2 = FunctionOtherTypesToDateType>; @@ -1275,6 +1282,7 @@ using FunctionDateTruncDatetimeV2 = FunctionOtherTypesToDateType(); + factory.register_function(); factory.register_function(); factory.register_function(); factory.register_function(); diff --git a/be/test/vec/function/function_string_test.cpp b/be/test/vec/function/function_string_test.cpp index e5f4da64eb..5425b0cd08 100644 --- a/be/test/vec/function/function_string_test.cpp +++ b/be/test/vec/function/function_string_test.cpp @@ -1121,25 +1121,6 @@ TEST(function_string_test, function_coalesce_test) { } } -TEST(function_string_test, function_str_to_date_test) { - std::string func_name = "str_to_date"; - InputTypeSet input_types = { - TypeIndex::String, - TypeIndex::String, - }; - DataSet data_set = { - {{Null(), std::string("%Y-%m-%d %H:%i:%s")}, {Null()}}, - {{std::string("2014-12-21 12:34:56"), std::string("%Y-%m-%d %H:%i:%s")}, - str_to_date_time("2014-12-21 12:34:56", false)}, - {{std::string("2014-12-21 12:34%3A56"), std::string("%Y-%m-%d %H:%i%%3A%s")}, - str_to_date_time("2014-12-21 12:34:56", false)}, - {{std::string("11/09/2011"), std::string("%m/%d/%Y")}, - str_to_date_time("2011-11-09", false)}, - {{std::string("2020-09-01"), std::string("%Y-%m-%d %H:%i:%s")}, - str_to_date_time("2020-09-01 00:00:00", false)}}; - static_cast(check_function(func_name, input_types, data_set)); -} - TEST(function_string_test, function_replace) { std::string func_name = "replace"; InputTypeSet input_types = { diff --git a/be/test/vec/function/function_time_test.cpp b/be/test/vec/function/function_time_test.cpp index cf64fd9e55..22566f3f63 100644 --- a/be/test/vec/function/function_time_test.cpp +++ b/be/test/vec/function/function_time_test.cpp @@ -1395,23 +1395,6 @@ TEST(VTimestampFunctionsTest, yearweek_v2_test) { } } -TEST(VTimestampFunctionsTest, str_to_date_test) { - std::string func_name = "str_to_date"; - - InputTypeSet input_types = {TypeIndex::String, TypeIndex::String}; - - { - DataSet data_set = {{{std::string("2021-01-01"), std::string("%Y-%m-%d")}, - str_to_date_time("2021-01-01", false)}, - {{std::string("2022-01-03"), std::string("%Y-%m-%d")}, - str_to_date_time("2022-01-03", false)}, - {{std::string("2021-00-01"), std::string("%Y-%m-%d")}, Null()}, - {{std::string("2021-01-00"), std::string("%Y-%m-%d")}, Null()}}; - - static_cast(check_function(func_name, input_types, data_set)); - } -} - TEST(VTimestampFunctionsTest, from_days_test) { std::string func_name = "from_days"; 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 57730fd44d..05dd3b7f90 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 @@ -1276,9 +1276,20 @@ public class DateLiteral extends LiteralExpr { break; // Micro second case 'f': - tmp = vp + Math.min(6, vend - vp); - intValue = strToLong(value.substring(vp, tmp)); - this.microsecond = (long) (intValue * Math.pow(10, 6 - Math.min(6, vend - vp))); + // FIXME: fix same with BE + tmp = vp; + // when there's still something to the end, fix the scale of ms. + while (tmp < vend && Character.isDigit(value.charAt(tmp))) { + tmp += 1; + } + + if (tmp - vp > 6) { + int tmp2 = vp + 6; + intValue = strToLong(value.substring(vp, tmp2)); + } else { + intValue = strToLong(value.substring(vp, tmp)); + } + this.microsecond = (long) (intValue * Math.pow(10, 6 - Math.min(6, tmp - vp))); timePartUsed = true; microSecondPartUsed = true; vp = tmp; @@ -1476,7 +1487,7 @@ public class DateLiteral extends LiteralExpr { // we think it's stable enough if (datePartUsed) { if (microSecondPartUsed) { - this.type = Type.DATETIMEV2; + this.type = Type.DATETIMEV2_WITH_MAX_SCALAR; } else if (timePartUsed) { this.type = ScalarType.getDefaultDateType(Type.DATETIME); } else { 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 628b514bca..965b579a54 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 @@ -1900,12 +1900,12 @@ public class FunctionCallExpr extends Expr { Expr child1Result = getChild(1).getResultValue(false); if (child1Result instanceof StringLiteral) { if (DateLiteral.hasTimePart(child1Result.getStringValue())) { - this.type = Type.DATETIME; + this.type = Type.DATETIMEV2_WITH_MAX_SCALAR; } else { - this.type = Type.DATE; + this.type = Type.DATEV2; } } else { - this.type = Type.DATETIME; + this.type = Type.DATETIMEV2_WITH_MAX_SCALAR; } } else if (TIME_FUNCTIONS_WITH_PRECISION.contains(fnName.getFunction().toLowerCase()) && fn.getReturnType().isDatetimeV2()) { diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/StrToDate.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/StrToDate.java index 4f512ec09f..1fbf15586d 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/StrToDate.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/StrToDate.java @@ -44,9 +44,9 @@ public class StrToDate extends ScalarFunction implements BinaryExpression, ExplicitlyCastableSignature, AlwaysNullable { public static final List SIGNATURES = ImmutableList.of( - FunctionSignature.ret(DateTimeV2Type.SYSTEM_DEFAULT).args(VarcharType.SYSTEM_DEFAULT, + FunctionSignature.ret(DateTimeV2Type.MAX).args(VarcharType.SYSTEM_DEFAULT, VarcharType.SYSTEM_DEFAULT), - FunctionSignature.ret(DateTimeV2Type.SYSTEM_DEFAULT).args(StringType.INSTANCE, StringType.INSTANCE) + FunctionSignature.ret(DateTimeV2Type.MAX).args(StringType.INSTANCE, StringType.INSTANCE) ); /** @@ -95,6 +95,9 @@ public class StrToDate extends ScalarFunction } } else { returnType = DataType.fromCatalogType(ScalarType.getDefaultDateType(Type.DATETIME)); + if (returnType.isDateTimeV2Type()) { + returnType = DataType.fromCatalogType(Type.DATETIMEV2_WITH_MAX_SCALAR); + } } return signature.withReturnType(returnType); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/rewrite/FEFunctions.java b/fe/fe-core/src/main/java/org/apache/doris/rewrite/FEFunctions.java index cc883e28d0..7442c4c0d0 100755 --- a/fe/fe-core/src/main/java/org/apache/doris/rewrite/FEFunctions.java +++ b/fe/fe-core/src/main/java/org/apache/doris/rewrite/FEFunctions.java @@ -151,7 +151,7 @@ public class FEFunctions { return new StringLiteral(result); } - @FEFunction(name = "str_to_date", argTypes = { "VARCHAR", "VARCHAR" }, returnType = "DATETIME") + @FEFunction(name = "str_to_date", argTypes = { "VARCHAR", "VARCHAR" }, returnType = "DATETIMEV2") public static DateLiteral dateParse(StringLiteral date, StringLiteral fmtLiteral) throws AnalysisException { DateLiteral dateLiteral = new DateLiteral(); try { diff --git a/regression-test/data/query_p0/sql_functions/datetime_functions/test_date_function.out b/regression-test/data/query_p0/sql_functions/datetime_functions/test_date_function.out index 5c61bfc31d..9858f809ea 100644 --- a/regression-test/data/query_p0/sql_functions/datetime_functions/test_date_function.out +++ b/regression-test/data/query_p0/sql_functions/datetime_functions/test_date_function.out @@ -273,10 +273,10 @@ February 2014-12-21T12:34:56 -- !sql -- -2014-12-21T12:34:56 +2014-12-21T12:34:56.789 -- !sql -- -2023-07-05T02:09:55 +2023-07-05T02:09:55.880 -- !sql -- 2004-10-18