diff --git a/be/src/exprs/timestamp_functions.cpp b/be/src/exprs/timestamp_functions.cpp index e1f8ce6a95..3df58c48da 100644 --- a/be/src/exprs/timestamp_functions.cpp +++ b/be/src/exprs/timestamp_functions.cpp @@ -165,7 +165,10 @@ IntVal TimestampFunctions::day_of_month(FunctionContext* context, const DateTime return IntVal::null(); } const DateTimeValue& ts_value = DateTimeValue::from_datetime_val(ts_val); - return IntVal(ts_value.day()); + if (ts_value.is_valid_date()) { + return IntVal(ts_value.day()); + } + return IntVal::null(); } IntVal TimestampFunctions::day_of_year(FunctionContext* context, const DateTimeVal& ts_val) { diff --git a/be/src/runtime/datetime_value.cpp b/be/src/runtime/datetime_value.cpp index a5880c1889..84938ab687 100644 --- a/be/src/runtime/datetime_value.cpp +++ b/be/src/runtime/datetime_value.cpp @@ -54,15 +54,19 @@ bool DateTimeValue::check_range(uint32_t year, uint32_t month, uint32_t day, uin uint16_t type) { bool time = hour > (type == TIME_TIME ? TIME_MAX_HOUR : 23) || minute > 59 || second > 59 || microsecond > 999999; - return time || check_date(year, month, day); + if (type == TIME_TIME) { + return time; + } else { + return time || check_date(year, month, day); + } } bool DateTimeValue::check_date(uint32_t year, uint32_t month, uint32_t day) { - if (month != 0 && month <= 12 && day > s_days_in_month[month]) { - // Feb 29 in leap year is valid. - if (!(month == 2 && day == 29 && is_leap(year))) return true; + if (month == 2 && day == 29 && doris::is_leap(year)) return false; + if (year > 9999 || month == 0 || month > 12 || day > s_days_in_month[month] || day == 0) { + return true; } - return year > 9999 || month > 12 || day > 31; + return false; } // The interval format is that with no delimiters diff --git a/be/src/runtime/datetime_value.h b/be/src/runtime/datetime_value.h index 36c63df045..b34f0d6dd6 100644 --- a/be/src/runtime/datetime_value.h +++ b/be/src/runtime/datetime_value.h @@ -175,8 +175,18 @@ public: _day(0), _microsecond(0) {} - explicit DateTimeValue(int64_t t) { from_date_int64(t); } - + explicit DateTimeValue(int64_t t) + : _neg(0), + _type(TIME_DATETIME), + _hour(0), + _minute(0), + _second(0), + _year(0), + _month(0), + _day(0), + _microsecond(0) { + from_date_int64(t); + } void set_time(uint32_t year, uint32_t month, uint32_t day, uint32_t hour, uint32_t minute, uint32_t second, uint32_t microsecond); diff --git a/be/test/exprs/timestamp_functions_test.cpp b/be/test/exprs/timestamp_functions_test.cpp index b338830a68..19577c3bd2 100644 --- a/be/test/exprs/timestamp_functions_test.cpp +++ b/be/test/exprs/timestamp_functions_test.cpp @@ -123,16 +123,14 @@ TEST_F(TimestampFunctionsTest, day_of_month_test) { dtv1.set_type(TIME_DATETIME); doris_udf::DateTimeVal tv1; dtv1.to_datetime_val(&tv1); - EXPECT_EQ(false, TimestampFunctions::day_of_month(context, tv1).is_null); - EXPECT_EQ(1, TimestampFunctions::day_of_month(context, tv1).val); + EXPECT_EQ(true, TimestampFunctions::day_of_month(context, tv1).is_null); // 2020-01-00 00:00:00 DateTimeValue dtv2(20200100000000); dtv2.set_type(TIME_DATETIME); doris_udf::DateTimeVal tv2; dtv2.to_datetime_val(&tv2); - EXPECT_EQ(false, TimestampFunctions::day_of_month(context, tv2).is_null); - EXPECT_EQ(0, TimestampFunctions::day_of_month(context, tv2).val); + EXPECT_EQ(true, TimestampFunctions::day_of_month(context, tv2).is_null); // 2020-02-29 00:00:00 DateTimeValue dtv3(20200229000000); diff --git a/be/test/runtime/datetime_value_test.cpp b/be/test/runtime/datetime_value_test.cpp index b1f8c51d46..d71923e8f8 100644 --- a/be/test/runtime/datetime_value_test.cpp +++ b/be/test/runtime/datetime_value_test.cpp @@ -249,15 +249,15 @@ TEST_F(DateTimeValueTest, check_date) { EXPECT_TRUE(value.from_date_int64(19880201)); value._month = 0; - EXPECT_FALSE(DateTimeValue::check_range(value.year(), value.month(), value.day(), value.hour(), - value.minute(), value.second(), value.microsecond(), - value.type())); + EXPECT_TRUE(DateTimeValue::check_range(value.year(), value.month(), value.day(), value.hour(), + value.minute(), value.second(), value.microsecond(), + value.type())); value._month = 2; value._day = 0; - EXPECT_FALSE(DateTimeValue::check_range(value.year(), value.month(), value.day(), value.hour(), - value.minute(), value.second(), value.microsecond(), - value.type())); + EXPECT_TRUE(DateTimeValue::check_range(value.year(), value.month(), value.day(), value.hour(), + value.minute(), value.second(), value.microsecond(), + value.type())); value._year = 1987; value._day = 29; EXPECT_TRUE(DateTimeValue::check_range(value.year(), value.month(), value.day(), value.hour(), diff --git a/regression-test/data/query_p0/sql_functions/cast_function/test_cast_function.out b/regression-test/data/query_p0/sql_functions/cast_function/test_cast_function.out index 6584f8cc9c..6577c6c9fe 100644 --- a/regression-test/data/query_p0/sql_functions/cast_function/test_cast_function.out +++ b/regression-test/data/query_p0/sql_functions/cast_function/test_cast_function.out @@ -5,3 +5,21 @@ -- !sql -- 11 +-- !sql -- +2000-01-01T03:14:17 + +-- !sql -- +\N + +-- !sql -- +1 + +-- !sql -- +11 + +-- !sql -- +2000-01-01T03:14:17 + +-- !sql -- +\N + diff --git a/regression-test/suites/query_p0/sql_functions/cast_function/test_cast_function.groovy b/regression-test/suites/query_p0/sql_functions/cast_function/test_cast_function.groovy index 9371f7ae3b..2c94eb3bb3 100644 --- a/regression-test/suites/query_p0/sql_functions/cast_function/test_cast_function.groovy +++ b/regression-test/suites/query_p0/sql_functions/cast_function/test_cast_function.groovy @@ -20,6 +20,15 @@ suite("test_cast_function") { qt_sql """ select cast (1 as BIGINT) """ qt_sql """ select cast(cast ("11.2" as double) as bigint) """ + qt_sql """ select cast ("0.0101031417" as datetime) """ + qt_sql """ select cast ("0.0000031417" as datetime) """ + + sql """ SET enable_vectorized_engine = FALSE; """ + + qt_sql """ select cast (1 as BIGINT) """ + qt_sql """ select cast(cast ("11.2" as double) as bigint) """ + qt_sql """ select cast ("0.0101031417" as datetime) """ + qt_sql """ select cast ("0.0000031417" as datetime) """ }