mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-21 23:21:59 +00:00
Fix bugs in DateTime64 parsing
This commit is contained in:
parent
75357ab98d
commit
4ace4b4c75
@ -275,8 +275,11 @@ ReturnType readIntTextImpl(T & x, ReadBuffer & buf)
|
|||||||
switch (*buf.position())
|
switch (*buf.position())
|
||||||
{
|
{
|
||||||
case '+':
|
case '+':
|
||||||
|
{
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case '-':
|
case '-':
|
||||||
|
{
|
||||||
if constexpr (is_signed_v<T>)
|
if constexpr (is_signed_v<T>)
|
||||||
negative = true;
|
negative = true;
|
||||||
else
|
else
|
||||||
@ -287,6 +290,7 @@ ReturnType readIntTextImpl(T & x, ReadBuffer & buf)
|
|||||||
return ReturnType(false);
|
return ReturnType(false);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case '0': [[fallthrough]];
|
case '0': [[fallthrough]];
|
||||||
case '1': [[fallthrough]];
|
case '1': [[fallthrough]];
|
||||||
case '2': [[fallthrough]];
|
case '2': [[fallthrough]];
|
||||||
@ -297,20 +301,27 @@ ReturnType readIntTextImpl(T & x, ReadBuffer & buf)
|
|||||||
case '7': [[fallthrough]];
|
case '7': [[fallthrough]];
|
||||||
case '8': [[fallthrough]];
|
case '8': [[fallthrough]];
|
||||||
case '9':
|
case '9':
|
||||||
|
{
|
||||||
if constexpr (check_overflow == ReadIntTextCheckOverflow::CHECK_OVERFLOW)
|
if constexpr (check_overflow == ReadIntTextCheckOverflow::CHECK_OVERFLOW)
|
||||||
{
|
{
|
||||||
// perform relativelly slow overflow check only when number of decimal digits so far is close to the max for given type.
|
/// Perform relativelly slow overflow check only when
|
||||||
if (buf.count() - initial_pos >= std::numeric_limits<T>::max_digits10)
|
/// number of decimal digits so far is close to the max for given type.
|
||||||
|
/// Example: 20 * 10 will overflow Int8.
|
||||||
|
|
||||||
|
if (buf.count() - initial_pos + 1 >= std::numeric_limits<T>::max_digits10)
|
||||||
{
|
{
|
||||||
if (common::mulOverflow(res, static_cast<decltype(res)>(10), res)
|
T signed_res = res;
|
||||||
|| common::addOverflow(res, static_cast<decltype(res)>(*buf.position() - '0'), res))
|
if (common::mulOverflow<T>(signed_res, 10, signed_res)
|
||||||
|
|| common::addOverflow<T>(signed_res, (*buf.position() - '0'), signed_res))
|
||||||
return ReturnType(false);
|
return ReturnType(false);
|
||||||
|
res = signed_res;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
res *= 10;
|
res *= 10;
|
||||||
res += *buf.position() - '0';
|
res += *buf.position() - '0';
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
@ -318,7 +329,23 @@ ReturnType readIntTextImpl(T & x, ReadBuffer & buf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
end:
|
end:
|
||||||
x = negative ? -res : res;
|
if (!negative)
|
||||||
|
{
|
||||||
|
x = res;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if constexpr (check_overflow == ReadIntTextCheckOverflow::CHECK_OVERFLOW)
|
||||||
|
{
|
||||||
|
x = res;
|
||||||
|
if (common::mulOverflow<T>(x, -1, x))
|
||||||
|
return ReturnType(false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x = -res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return ReturnType(true);
|
return ReturnType(true);
|
||||||
}
|
}
|
||||||
@ -665,9 +692,7 @@ inline ReturnType readDateTimeTextImpl(DateTime64 & datetime64, UInt32 scale, Re
|
|||||||
buf.ignore(1); // skip separator
|
buf.ignore(1); // skip separator
|
||||||
const auto pos_before_fractional = buf.count();
|
const auto pos_before_fractional = buf.count();
|
||||||
if (!tryReadIntText<ReadIntTextCheckOverflow::CHECK_OVERFLOW>(c.fractional, buf))
|
if (!tryReadIntText<ReadIntTextCheckOverflow::CHECK_OVERFLOW>(c.fractional, buf))
|
||||||
{
|
|
||||||
return ReturnType(false);
|
return ReturnType(false);
|
||||||
}
|
|
||||||
|
|
||||||
// Adjust fractional part to the scale, since decimalFromComponents knows nothing
|
// Adjust fractional part to the scale, since decimalFromComponents knows nothing
|
||||||
// about convention of ommiting trailing zero on fractional part
|
// about convention of ommiting trailing zero on fractional part
|
||||||
@ -676,13 +701,15 @@ inline ReturnType readDateTimeTextImpl(DateTime64 & datetime64, UInt32 scale, Re
|
|||||||
// If scale is 3, but we read '12', promote fractional part to '120'.
|
// If scale is 3, but we read '12', promote fractional part to '120'.
|
||||||
// And vice versa: if we read '1234', denote it to '123'.
|
// And vice versa: if we read '1234', denote it to '123'.
|
||||||
const auto fractional_length = static_cast<Int32>(buf.count() - pos_before_fractional);
|
const auto fractional_length = static_cast<Int32>(buf.count() - pos_before_fractional);
|
||||||
if (const auto adjust_scale = static_cast<Int32>(scale) - fractional_length; adjust_scale > 0)
|
|
||||||
|
const auto adjust_scale = static_cast<Int32>(scale) - fractional_length;
|
||||||
|
if (adjust_scale > 0)
|
||||||
{
|
{
|
||||||
c.fractional *= common::exp10_i64(adjust_scale);
|
c.fractional *= common::exp10_i64(adjust_scale);
|
||||||
}
|
}
|
||||||
else if (adjust_scale < 0)
|
else if (adjust_scale < 0)
|
||||||
{
|
{
|
||||||
c.fractional /= common::exp10_i64(-1 * adjust_scale);
|
c.fractional /= common::exp10_i64(-adjust_scale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user