Skip to content

Commit

Permalink
Fix the wrong result bug when casting string as datetime with time zo…
Browse files Browse the repository at this point in the history
…ne or illegal chars (#9255) (#9354)

close #8754

Fix the wrong result bug when casting string as datetime with time zone or illegal chars
- func `getFracIndex` ignore time zone.
- func `parseFrac` ignore illegal suffix after microsecond format.

Signed-off-by: Zhigao Tong <[email protected]>

Co-authored-by: TONG,Zhigao <[email protected]>
Co-authored-by: Zhigao Tong <[email protected]>
Co-authored-by: TONG, Zhigao <[email protected]>
  • Loading branch information
ti-chi-bot and solotzg authored Sep 2, 2024
1 parent f63f87a commit 658075d
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 8 deletions.
28 changes: 20 additions & 8 deletions dbms/src/Common/MyTime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ int getFracIndex(const String & format)
int idx = -1;
for (int i = end; i >= 0; i--)
{
if (isPunctuation(format[i]))
if (format[i] != '+' && format[i] != '-' && isPunctuation(format[i]))
{
if (format[i] == '.')
{
Expand Down Expand Up @@ -728,7 +728,7 @@ inline bool numberToDateTime(Int64 number, MyDateTime & result, bool allowZeroDa
}

// returns frac, overflow, matched. eg., "999" fsp=2 will overflow.
std::tuple<UInt32, bool, bool> parseFrac(const String & str, int8_t fsp)
std::tuple<UInt32, bool, bool> parseFrac(const std::string_view str, int8_t fsp)
{
if (str.empty())
{
Expand All @@ -744,15 +744,27 @@ std::tuple<UInt32, bool, bool> parseFrac(const String & str, int8_t fsp)
}
try
{
int len = str.length();
if (fsp >= len)
int end_pos = static_cast<size_t>(fsp) >= str.size() ? str.size() : (fsp + 1);
UInt32 tmp = 0;
int size = 0;
for (int i = 0; i < end_pos; ++i)
{
UInt32 tmp = std::stoul(str);
return {tmp * std::pow(10, 6 - len), false, true};
if (auto c = str[i]; c >= '0' && c <= '9')
{
tmp = tmp * 10 + c - '0';
size++;
}
else
{
break;
}
}

if (fsp >= size)
{
return {tmp * std::pow(10, 6 - size), false, true};
}

// Round when fsp < string length.
UInt32 tmp = std::stoul(str.substr(0, fsp + 1));
tmp = (tmp + 5) / 10;
if (tmp >= std::pow(10, fsp))
{
Expand Down
5 changes: 5 additions & 0 deletions dbms/src/Common/tests/gtest_mytime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@ try
{"2020-10-10 10.10", "2020-10-10 10:10:00.000000"},
{"2018.01.01", "2018-01-01 00:00:00.000000"},
{"2020--12-10 11:11:11..123456", "2020-12-10 11:11:11.123456"},
{"2020-01-01 12:00:00.1234xxxx -0600 PST", "2020-01-01 12:00:00.123400"},
{"2020-01-01 12:00:00.123456-05:00", "2020-01-01 17:00:00.123456"}, // tidb/issues/49555
};
DataTypeMyDateTime type_with_fraction(6);
for (auto & [str, expected] : cases_with_fsp)
Expand Down Expand Up @@ -174,6 +176,9 @@ try
}
DataTypeMyDateTime tp(2);
checkParseMyDateTime("2010-12-31 23:59:59.99999", "2011-01-01 00:00:00.00", tp);
checkParseMyDateTime("2010-12-31 23:59:59.99xxxxx -0600 PST", "2010-12-31 23:59:59.99", tp);
checkParseMyDateTime("2020-01-01 12:00:00.123456 +0600 PST", "2020-01-01 12:00:00.12", tp);
checkParseMyDateTime("2020-01-01 12:00:00.123456 -0600 PST", "2020-01-01 12:00:00.12", tp);
}
catch (Exception & e)
{
Expand Down

0 comments on commit 658075d

Please sign in to comment.