This is an automated email from the ASF dual-hosted git repository. yiguolei pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/master by this push: new abd2eb4fa1 [Bug](date function) Fix bug for date format %T (#11729) abd2eb4fa1 is described below commit abd2eb4fa148a3c88d9a78b29a2289d161c73b67 Author: Gabriel <gabrielleeb...@gmail.com> AuthorDate: Fri Aug 12 19:29:58 2022 +0800 [Bug](date function) Fix bug for date format %T (#11729) * [Bug](date function) Fix bug for date format %T --- be/src/vec/runtime/vdatetime_value.cpp | 99 ++++++++++++++-------- be/src/vec/runtime/vdatetime_value.h | 20 +++-- .../datetime_functions/test_date_function.out | 3 + .../datetime_functions/test_date_function.groovy | 1 + 4 files changed, 81 insertions(+), 42 deletions(-) diff --git a/be/src/vec/runtime/vdatetime_value.cpp b/be/src/vec/runtime/vdatetime_value.cpp index 315851c454..04dd72b8d4 100644 --- a/be/src/vec/runtime/vdatetime_value.cpp +++ b/be/src/vec/runtime/vdatetime_value.cpp @@ -48,7 +48,11 @@ uint8_t mysql_week_mode(uint32_t mode) { bool VecDateTimeValue::check_range(uint32_t year, uint32_t month, uint32_t day, uint32_t hour, uint32_t minute, uint32_t second, uint16_t type) { bool time = hour > (type == TIME_TIME ? TIME_MAX_HOUR : 23) || minute > 59 || second > 59; - return time || check_date(year, month, day); + if (type == TIME_TIME) { + return time; + } else { + return time || check_date(year, month, day); + } } bool VecDateTimeValue::check_date(uint32_t year, uint32_t month, uint32_t day) { @@ -1316,22 +1320,32 @@ bool VecDateTimeValue::from_date_format_str(const char* format, int format_len, val = tmp; date_part_used = true; break; - case 'r': - if (!from_date_format_str("%I:%i:%S %p", 11, val, val_end - val, &tmp)) { + case 'r': { + VecDateTimeValue tmp_val; + if (!tmp_val.from_date_format_str("%I:%i:%S %p", 11, val, val_end - val, &tmp)) { return false; } + this->_hour = tmp_val._hour; + this->_minute = tmp_val._minute; + this->_second = tmp_val._second; val = tmp; time_part_used = true; already_set_time_part = true; break; - case 'T': - if (!from_date_format_str("%H:%i:%S", 8, val, val_end - val, &tmp)) { + } + case 'T': { + VecDateTimeValue tmp_val; + if (!tmp_val.from_date_format_str("%H:%i:%S", 8, val, val_end - val, &tmp)) { return false; } + this->_hour = tmp_val._hour; + this->_minute = tmp_val._minute; + this->_second = tmp_val._second; time_part_used = true; already_set_time_part = true; val = tmp; break; + } case '.': while (val < val_end && ispunct(*val)) { val++; @@ -1679,13 +1693,19 @@ std::size_t hash_value(VecDateTimeValue const& value) { template <typename T> bool DateV2Value<T>::is_invalid(uint32_t year, uint32_t month, uint32_t day, uint8_t hour, - uint8_t minute, uint8_t second, uint32_t microsecond) { + uint8_t minute, uint8_t second, uint32_t microsecond, + bool only_time_part) { if (hour > 24 || minute >= 60 || second >= 60 || microsecond > 999999) { return true; } + if (only_time_part) { + return false; + } + if (year < MIN_YEAR || year > MAX_YEAR) { + return true; + } if (month == 2 && day == 29 && doris::is_leap(year)) return false; - if (year < MIN_YEAR || year > MAX_YEAR || month == 0 || month > 12 || - day > s_days_in_month[month] || day == 0) { + if (month == 0 || month > 12 || day > s_days_in_month[month] || day == 0) { return true; } return false; @@ -2061,22 +2081,41 @@ bool DateV2Value<T>::from_date_format_str(const char* format, int format_len, co val = tmp; date_part_used = true; break; - case 'r': - if (!from_date_format_str("%I:%i:%S %p", 11, val, val_end - val, &tmp)) { + case 'r': { + if constexpr (is_datetime) { + DateV2Value<DateTimeV2ValueType> tmp_val; + if (!tmp_val.from_date_format_str("%I:%i:%S %p", 11, val, val_end - val, + &tmp)) { + return false; + } + this->date_v2_value_.hour_ = tmp_val.hour(); + this->date_v2_value_.minute_ = tmp_val.minute(); + this->date_v2_value_.second_ = tmp_val.second(); + val = tmp; + time_part_used = true; + already_set_time_part = true; + break; + } else { return false; } - val = tmp; - time_part_used = true; - already_set_time_part = true; - break; - case 'T': - if (!from_date_format_str("%H:%i:%S", 8, val, val_end - val, &tmp)) { + } + case 'T': { + if constexpr (is_datetime) { + DateV2Value<DateTimeV2ValueType> tmp_val; + if (!tmp_val.from_date_format_str("%H:%i:%S", 8, val, val_end - val, &tmp)) { + return false; + } + this->date_v2_value_.hour_ = tmp_val.hour(); + this->date_v2_value_.minute_ = tmp_val.minute(); + this->date_v2_value_.second_ = tmp_val.second(); + time_part_used = true; + already_set_time_part = true; + val = tmp; + break; + } else { return false; } - time_part_used = true; - already_set_time_part = true; - val = tmp; - break; + } case '.': while (val < val_end && ispunct(*val)) { val++; @@ -2156,20 +2195,9 @@ bool DateV2Value<T>::from_date_format_str(const char* format, int format_len, co LOG(WARNING) << "Microsecond is not allowed for date type!"; return false; } - if (!date_part_used) { - LOG(WARNING) << "Time type is not supported yet!"; - return false; - } - } else { - if (date_part_used) { - if (time_part_used) { - if constexpr (!is_datetime) { - LOG(WARNING) << "Time part is not allowed for date type!"; - return false; - } - } - } else { - LOG(WARNING) << "Time type is not supported yet!"; + } else if (time_part_used) { + if constexpr (!is_datetime) { + LOG(WARNING) << "Time part is not allowed for date type!"; return false; } } @@ -2228,7 +2256,8 @@ bool DateV2Value<T>::from_date_format_str(const char* format, int format_len, co } } if constexpr (is_datetime) { - return check_range_and_set_time(year, month, day, hour, minute, second, microsecond); + return check_range_and_set_time(year, month, day, hour, minute, second, microsecond, + time_part_used && !date_part_used); } else { return check_range_and_set_time(year, month, day, 0, 0, 0, 0); } diff --git a/be/src/vec/runtime/vdatetime_value.h b/be/src/vec/runtime/vdatetime_value.h index 1a384e20aa..0ac9ccf074 100644 --- a/be/src/vec/runtime/vdatetime_value.h +++ b/be/src/vec/runtime/vdatetime_value.h @@ -815,14 +815,20 @@ public: // Return true if range or date is invalid static bool is_invalid(uint32_t year, uint32_t month, uint32_t day, uint8_t hour, - uint8_t minute, uint8_t second, uint32_t microsecond); + uint8_t minute, uint8_t second, uint32_t microsecond, + bool only_time_part = false); bool check_range_and_set_time(uint16_t year, uint8_t month, uint8_t day, uint8_t hour, - uint8_t minute, uint8_t second, uint32_t microsecond) { - if (is_invalid(year, month, day, hour, minute, second, microsecond)) { + uint8_t minute, uint8_t second, uint32_t microsecond, + bool only_time_part = false) { + if (is_invalid(year, month, day, hour, minute, second, microsecond, only_time_part)) { return false; } - set_time(year, month, day, hour, minute, second, microsecond); + if (only_time_part) { + set_time(0, 0, 0, hour, minute, second, microsecond); + } else { + set_time(year, month, day, hour, minute, second, microsecond); + } return true; }; @@ -1134,6 +1140,9 @@ public: } }; + bool from_date_format_str(const char* format, int format_len, const char* value, int value_len, + const char** sub_val_end); + private: static uint8_t calc_week(const uint32_t& day_nr, const uint16_t& year, const uint8_t& month, const uint8_t& day, uint8_t mode, uint16_t* to_year, @@ -1145,9 +1154,6 @@ private: // Helper to set max, min, zero void set_zero(); - bool from_date_format_str(const char* format, int format_len, const char* value, int value_len, - const char** sub_val_end); - union { T date_v2_value_; underlying_value int_val_; diff --git a/regression-test/data/query/sql_functions/datetime_functions/test_date_function.out b/regression-test/data/query/sql_functions/datetime_functions/test_date_function.out index ee492a41b2..902bfc5147 100644 --- a/regression-test/data/query/sql_functions/datetime_functions/test_date_function.out +++ b/regression-test/data/query/sql_functions/datetime_functions/test_date_function.out @@ -353,3 +353,6 @@ true -- !sql -- \N +-- !sql -- +2022-07-12T20:00:45 + diff --git a/regression-test/suites/query/sql_functions/datetime_functions/test_date_function.groovy b/regression-test/suites/query/sql_functions/datetime_functions/test_date_function.groovy index 6f915f44a1..b5387f8205 100644 --- a/regression-test/suites/query/sql_functions/datetime_functions/test_date_function.groovy +++ b/regression-test/suites/query/sql_functions/datetime_functions/test_date_function.groovy @@ -293,4 +293,5 @@ suite("test_date_function", "query") { qt_sql """ select date_format('2022-08-04', '%X %V %w'); """ qt_sql """ select STR_TO_DATE('Tue Jul 12 20:00:45 CST 2022', '%a %b %e %H:%i:%s %Y'); """ + qt_sql """ select STR_TO_DATE('Tue Jul 12 20:00:45 CST 2022', '%a %b %e %T CST %Y'); """ } --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org For additional commands, e-mail: commits-h...@doris.apache.org