diff --git a/be/src/exprs/timestamp_functions.cpp b/be/src/exprs/timestamp_functions.cpp index 57b5b808f2c9bc..cefd2eb7624b69 100644 --- a/be/src/exprs/timestamp_functions.cpp +++ b/be/src/exprs/timestamp_functions.cpp @@ -203,6 +203,26 @@ DateTimeVal TimestampFunctions::str_to_date(FunctionContext* ctx, const StringVa str.len)) { return DateTimeVal::null(); } + + /// The return type of str_to_date depends on whether the time part is included in the format. + /// If included, it is datetime, otherwise it is date. + /// If the format parameter is not constant, the return type will be datetime. + /// The above judgment has been completed in the FE query planning stage, + /// so here we directly set the value type to the return type set in the query plan. + /// + /// For example: + /// A table with one column k1 varchar, and has 2 lines: + /// "%Y-%m-%d" + /// "%Y-%m-%d %H:%i:%s" + /// Query: + /// SELECT str_to_date("2020-09-01", k1) from tbl; + /// Result will be: + /// 2020-09-01 00:00:00 + /// 2020-09-01 00:00:00 + if (ctx->impl()->get_return_type().type == doris_udf::FunctionContext::Type::TYPE_DATETIME) { + ts_value.to_datetime(); + } + DateTimeVal ts_val; ts_value.to_datetime_val(&ts_val); return ts_val; diff --git a/be/src/udf/udf_internal.h b/be/src/udf/udf_internal.h index ba6f78d3c96a9c..ed6b37de5f387e 100644 --- a/be/src/udf/udf_internal.h +++ b/be/src/udf/udf_internal.h @@ -102,6 +102,8 @@ class FunctionContextImpl { std::string& string_result() { return _string_result; } + const doris_udf::FunctionContext::TypeDesc& get_return_type() const { return _return_type; } + private: friend class doris_udf::FunctionContext; friend class ExprContext; 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 e3fd359430ec27..4025c610272163 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 @@ -498,7 +498,7 @@ public static DateLiteral dateParser(String date, String pattern) throws Analysi dateTime.getHourOfDay(), dateTime.getMinuteOfHour(), dateTime.getSecondOfMinute()); - if(HAS_TIME_PART.matcher(pattern).matches()) { + if (HAS_TIME_PART.matcher(pattern).matches()) { dateLiteral.setType(Type.DATETIME); } else { dateLiteral.setType(Type.DATE); @@ -506,6 +506,10 @@ public static DateLiteral dateParser(String date, String pattern) throws Analysi return dateLiteral; } + public static boolean hasTimePart(String format) { + return HAS_TIME_PART.matcher(format).matches(); + } + //Return the date stored in the dateliteral as pattern format. //eg : "%Y-%m-%d" or "%Y-%m-%d %H:%i:%s" public String dateFormat(String pattern) throws AnalysisException { 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 074d4f7400ad1c..0b0ef1bcc4ee67 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 @@ -646,7 +646,46 @@ public void analyzeImpl(Analyzer analyzer) throws AnalysisException { } } } - this.type = fn.getReturnType(); + + /** + * The return type of str_to_date depends on whether the time part is included in the format. + * If included, it is datetime, otherwise it is date. + * If the format parameter is not constant, the return type will be datetime. + * The above judgment has been completed in the FE query planning stage, + * so here we directly set the value type to the return type set in the query plan. + * + * For example: + * A table with one column k1 varchar, and has 2 lines: + * "%Y-%m-%d" + * "%Y-%m-%d %H:%i:%s" + * Query: + * SELECT str_to_date("2020-09-01", k1) from tbl; + * Result will be: + * 2020-09-01 00:00:00 + * 2020-09-01 00:00:00 + * + * Query: + * SELECT str_to_date("2020-09-01", "%Y-%m-%d"); + * Return type is DATE + * + * Query: + * SELECT str_to_date("2020-09-01", "%Y-%m-%d %H:%i:%s"); + * Return type is DATETIME + */ + if (fn.getFunctionName().getFunction().equals("str_to_date")) { + Expr child1Result = getChild(1).getResultValue(); + if (child1Result instanceof StringLiteral) { + if (DateLiteral.hasTimePart(((StringLiteral) child1Result).getStringValue())) { + this.type = Type.DATETIME; + } else { + this.type = Type.DATE; + } + } else { + this.type = Type.DATETIME; + } + } else { + this.type = fn.getReturnType(); + } } @Override @@ -734,3 +773,4 @@ public int hashCode() { return result; } } +