[Function] Let "str_to_date" return correct type (#5004)

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
This commit is contained in:
Mingyu Chen
2020-12-03 09:33:26 +08:00
committed by GitHub
parent 204c15119f
commit 5215727b45
4 changed files with 68 additions and 2 deletions

View File

@ -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;

View File

@ -102,6 +102,8 @@ public:
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;

View File

@ -498,7 +498,7 @@ public class DateLiteral extends LiteralExpr {
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 class DateLiteral extends LiteralExpr {
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 {

View File

@ -646,7 +646,46 @@ public class FunctionCallExpr extends Expr {
}
}
}
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 class FunctionCallExpr extends Expr {
return result;
}
}