From f9cadfa3d0d0870e03127afed2698093c5315e88 Mon Sep 17 00:00:00 2001 From: birdstorm Date: Wed, 16 Nov 2022 13:26:49 +0800 Subject: [PATCH] add overflow test Signed-off-by: birdstorm --- dbms/src/Common/MyTime.cpp | 78 +++++++++++++---------- dbms/src/Common/StringUtils/StringUtils.h | 2 +- dbms/src/Common/tests/gtest_mytime.cpp | 2 + 3 files changed, 46 insertions(+), 36 deletions(-) diff --git a/dbms/src/Common/MyTime.cpp b/dbms/src/Common/MyTime.cpp index 08fc2665d95..c00a41b375f 100644 --- a/dbms/src/Common/MyTime.cpp +++ b/dbms/src/Common/MyTime.cpp @@ -594,6 +594,39 @@ bool noNeedCheckTime(Int32, Int32, Int32, Int32, Int32, Int32) return true; } +UInt64 addSeconds(UInt64 t, Int64 delta) +{ + // todo support zero date + if (t == 0) + { + return t; + } + MyDateTime my_time(t); + Int64 current_second = my_time.hour * MyTimeBase::SECOND_IN_ONE_HOUR + my_time.minute * MyTimeBase::SECOND_IN_ONE_MINUTE + my_time.second; + current_second += delta; + if (current_second >= 0) + { + Int64 days = current_second / MyTimeBase::SECOND_IN_ONE_DAY; + current_second = current_second % MyTimeBase::SECOND_IN_ONE_DAY; + if (days != 0) + addDays(my_time, days); + } + else + { + Int64 days = (-current_second) / MyTimeBase::SECOND_IN_ONE_DAY; + if ((-current_second) % MyTimeBase::SECOND_IN_ONE_DAY != 0) + { + days++; + } + current_second += days * MyTimeBase::SECOND_IN_ONE_DAY; + addDays(my_time, -days); + } + my_time.hour = current_second / MyTimeBase::SECOND_IN_ONE_HOUR; + my_time.minute = (current_second % MyTimeBase::SECOND_IN_ONE_HOUR) / MyTimeBase::SECOND_IN_ONE_MINUTE; + my_time.second = current_second % MyTimeBase::SECOND_IN_ONE_MINUTE; + return my_time.toPackedUInt(); +} + // Return true if the time is invalid. inline bool getDatetime(const Int64 & num, MyDateTime & result) { @@ -995,11 +1028,12 @@ std::pair parseMyDateTimeAndJudgeIsDate(const String & str, int8_t } UInt32 micro_second = 0; - if (hhmmss && !frac_str.empty()) + bool overflow; + if (hhmmss) { // If input string is "20170118.999", without hhmmss, fsp is meaningless. // TODO: this case is not only meaningless, but erroneous, please confirm. - bool overflow, matched; + bool matched; std::tie(micro_second, overflow, matched) = parseFrac(frac_str, fsp); if (!matched) { @@ -1014,6 +1048,13 @@ std::pair parseMyDateTimeAndJudgeIsDate(const String & str, int8_t MyDateTime result(year, month, day, hour, minute, second, micro_second); + if (overflow) + { + // fraction part overflow, add one second to result + MyDateTime tmp(addSeconds(result.toPackedUInt(), 1)); + result = tmp; + } + if (has_tz) { if (!hhmmss) @@ -1596,39 +1637,6 @@ bool toCoreTimeChecked(const UInt64 & year, const UInt64 & month, const UInt64 & return false; } -UInt64 addSeconds(UInt64 t, Int64 delta) -{ - // todo support zero date - if (t == 0) - { - return t; - } - MyDateTime my_time(t); - Int64 current_second = my_time.hour * MyTimeBase::SECOND_IN_ONE_HOUR + my_time.minute * MyTimeBase::SECOND_IN_ONE_MINUTE + my_time.second; - current_second += delta; - if (current_second >= 0) - { - Int64 days = current_second / MyTimeBase::SECOND_IN_ONE_DAY; - current_second = current_second % MyTimeBase::SECOND_IN_ONE_DAY; - if (days != 0) - addDays(my_time, days); - } - else - { - Int64 days = (-current_second) / MyTimeBase::SECOND_IN_ONE_DAY; - if ((-current_second) % MyTimeBase::SECOND_IN_ONE_DAY != 0) - { - days++; - } - current_second += days * MyTimeBase::SECOND_IN_ONE_DAY; - addDays(my_time, -days); - } - my_time.hour = current_second / MyTimeBase::SECOND_IN_ONE_HOUR; - my_time.minute = (current_second % MyTimeBase::SECOND_IN_ONE_HOUR) / MyTimeBase::SECOND_IN_ONE_MINUTE; - my_time.second = current_second % MyTimeBase::SECOND_IN_ONE_MINUTE; - return my_time.toPackedUInt(); -} - void fillMonthAndDay(int day_num, int & month, int & day, const int * accumulated_days_per_month) { month = day_num / 31; diff --git a/dbms/src/Common/StringUtils/StringUtils.h b/dbms/src/Common/StringUtils/StringUtils.h index 47c35a2fb2e..b66648cb827 100644 --- a/dbms/src/Common/StringUtils/StringUtils.h +++ b/dbms/src/Common/StringUtils/StringUtils.h @@ -244,4 +244,4 @@ inline std::tuple number(const std::string & str) { return {0, 0, false}; } -} \ No newline at end of file +} diff --git a/dbms/src/Common/tests/gtest_mytime.cpp b/dbms/src/Common/tests/gtest_mytime.cpp index 10f356711c7..5f005adbe07 100644 --- a/dbms/src/Common/tests/gtest_mytime.cpp +++ b/dbms/src/Common/tests/gtest_mytime.cpp @@ -121,6 +121,8 @@ try { checkParseMyDateTime(str, expected, type_with_fraction); } + DataTypeMyDateTime tp(2); + checkParseMyDateTime("2010-12-31 23:59:59.99999", "2011-01-01 00:00:00.00", tp); } catch (Exception & e) {