Merge pull request #11875 from ClickHouse/fix-fpe-datetime64

Fix strange and wrong code around DateTime64
This commit is contained in:
alexey-milovidov 2020-06-24 12:54:04 +03:00 committed by GitHub
commit c2fba5179b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 249 additions and 126 deletions

View File

@ -1477,7 +1477,8 @@ private:
}
else
{
out_logs_buf = std::make_unique<WriteBufferFromFile>(server_logs_file, DBMS_DEFAULT_BUFFER_SIZE, O_WRONLY | O_APPEND | O_CREAT);
out_logs_buf = std::make_unique<WriteBufferFromFile>(
server_logs_file, DBMS_DEFAULT_BUFFER_SIZE, O_WRONLY | O_APPEND | O_CREAT);
wb = out_logs_buf.get();
}
}

View File

@ -20,14 +20,14 @@ inline NO_SANITIZE_UNDEFINED uint64_t intExp2(int x)
return 1ULL << x;
}
inline uint64_t intExp10(int x)
constexpr inline uint64_t intExp10(int x)
{
if (x < 0)
return 0;
if (x > 19)
return std::numeric_limits<uint64_t>::max();
static const uint64_t table[20] =
constexpr uint64_t table[20] =
{
1ULL, 10ULL, 100ULL,
1000ULL, 10000ULL, 100000ULL,
@ -44,9 +44,10 @@ inline uint64_t intExp10(int x)
namespace common
{
inline int exp10_i32(int x)
constexpr inline int exp10_i32(int x)
{
static const int values[] = {
constexpr int values[] =
{
1,
10,
100,
@ -61,74 +62,76 @@ inline int exp10_i32(int x)
return values[x];
}
inline int64_t exp10_i64(int x)
constexpr inline int64_t exp10_i64(int x)
{
static const int64_t values[] = {
1ll,
10ll,
100ll,
1000ll,
10000ll,
100000ll,
1000000ll,
10000000ll,
100000000ll,
1000000000ll,
10000000000ll,
100000000000ll,
1000000000000ll,
10000000000000ll,
100000000000000ll,
1000000000000000ll,
10000000000000000ll,
100000000000000000ll,
1000000000000000000ll
constexpr int64_t values[] =
{
1LL,
10LL,
100LL,
1000LL,
10000LL,
100000LL,
1000000LL,
10000000LL,
100000000LL,
1000000000LL,
10000000000LL,
100000000000LL,
1000000000000LL,
10000000000000LL,
100000000000000LL,
1000000000000000LL,
10000000000000000LL,
100000000000000000LL,
1000000000000000000LL
};
return values[x];
}
inline __int128 exp10_i128(int x)
constexpr inline __int128 exp10_i128(int x)
{
static const __int128 values[] = {
static_cast<__int128>(1ll),
static_cast<__int128>(10ll),
static_cast<__int128>(100ll),
static_cast<__int128>(1000ll),
static_cast<__int128>(10000ll),
static_cast<__int128>(100000ll),
static_cast<__int128>(1000000ll),
static_cast<__int128>(10000000ll),
static_cast<__int128>(100000000ll),
static_cast<__int128>(1000000000ll),
static_cast<__int128>(10000000000ll),
static_cast<__int128>(100000000000ll),
static_cast<__int128>(1000000000000ll),
static_cast<__int128>(10000000000000ll),
static_cast<__int128>(100000000000000ll),
static_cast<__int128>(1000000000000000ll),
static_cast<__int128>(10000000000000000ll),
static_cast<__int128>(100000000000000000ll),
static_cast<__int128>(1000000000000000000ll),
static_cast<__int128>(1000000000000000000ll) * 10ll,
static_cast<__int128>(1000000000000000000ll) * 100ll,
static_cast<__int128>(1000000000000000000ll) * 1000ll,
static_cast<__int128>(1000000000000000000ll) * 10000ll,
static_cast<__int128>(1000000000000000000ll) * 100000ll,
static_cast<__int128>(1000000000000000000ll) * 1000000ll,
static_cast<__int128>(1000000000000000000ll) * 10000000ll,
static_cast<__int128>(1000000000000000000ll) * 100000000ll,
static_cast<__int128>(1000000000000000000ll) * 1000000000ll,
static_cast<__int128>(1000000000000000000ll) * 10000000000ll,
static_cast<__int128>(1000000000000000000ll) * 100000000000ll,
static_cast<__int128>(1000000000000000000ll) * 1000000000000ll,
static_cast<__int128>(1000000000000000000ll) * 10000000000000ll,
static_cast<__int128>(1000000000000000000ll) * 100000000000000ll,
static_cast<__int128>(1000000000000000000ll) * 1000000000000000ll,
static_cast<__int128>(1000000000000000000ll) * 10000000000000000ll,
static_cast<__int128>(1000000000000000000ll) * 100000000000000000ll,
static_cast<__int128>(1000000000000000000ll) * 100000000000000000ll * 10ll,
static_cast<__int128>(1000000000000000000ll) * 100000000000000000ll * 100ll,
static_cast<__int128>(1000000000000000000ll) * 100000000000000000ll * 1000ll
constexpr __int128 values[] =
{
static_cast<__int128>(1LL),
static_cast<__int128>(10LL),
static_cast<__int128>(100LL),
static_cast<__int128>(1000LL),
static_cast<__int128>(10000LL),
static_cast<__int128>(100000LL),
static_cast<__int128>(1000000LL),
static_cast<__int128>(10000000LL),
static_cast<__int128>(100000000LL),
static_cast<__int128>(1000000000LL),
static_cast<__int128>(10000000000LL),
static_cast<__int128>(100000000000LL),
static_cast<__int128>(1000000000000LL),
static_cast<__int128>(10000000000000LL),
static_cast<__int128>(100000000000000LL),
static_cast<__int128>(1000000000000000LL),
static_cast<__int128>(10000000000000000LL),
static_cast<__int128>(100000000000000000LL),
static_cast<__int128>(1000000000000000000LL),
static_cast<__int128>(1000000000000000000LL) * 10LL,
static_cast<__int128>(1000000000000000000LL) * 100LL,
static_cast<__int128>(1000000000000000000LL) * 1000LL,
static_cast<__int128>(1000000000000000000LL) * 10000LL,
static_cast<__int128>(1000000000000000000LL) * 100000LL,
static_cast<__int128>(1000000000000000000LL) * 1000000LL,
static_cast<__int128>(1000000000000000000LL) * 10000000LL,
static_cast<__int128>(1000000000000000000LL) * 100000000LL,
static_cast<__int128>(1000000000000000000LL) * 1000000000LL,
static_cast<__int128>(1000000000000000000LL) * 10000000000LL,
static_cast<__int128>(1000000000000000000LL) * 100000000000LL,
static_cast<__int128>(1000000000000000000LL) * 1000000000000LL,
static_cast<__int128>(1000000000000000000LL) * 10000000000000LL,
static_cast<__int128>(1000000000000000000LL) * 100000000000000LL,
static_cast<__int128>(1000000000000000000LL) * 1000000000000000LL,
static_cast<__int128>(1000000000000000000LL) * 10000000000000000LL,
static_cast<__int128>(1000000000000000000LL) * 100000000000000000LL,
static_cast<__int128>(1000000000000000000LL) * 100000000000000000LL * 10LL,
static_cast<__int128>(1000000000000000000LL) * 100000000000000000LL * 100LL,
static_cast<__int128>(1000000000000000000LL) * 100000000000000000LL * 1000LL
};
return values[x];
}
@ -138,7 +141,7 @@ inline __int128 exp10_i128(int x)
/// intExp10 returning the type T.
template <typename T>
inline T intExp10OfSize(int x)
constexpr inline T intExp10OfSize(int x)
{
if constexpr (sizeof(T) <= 8)
return intExp10(x);

View File

@ -20,19 +20,34 @@
#include <optional>
#include <string>
namespace DB
{
namespace ErrorCodes
{
extern const int ARGUMENT_OUT_OF_BOUND;
}
static constexpr UInt32 max_scale = 9;
DataTypeDateTime64::DataTypeDateTime64(UInt32 scale_, const std::string & time_zone_name)
: DataTypeDecimalBase<DateTime64>(DecimalUtils::maxPrecision<DateTime64>(), scale_),
TimezoneMixin(time_zone_name)
{
if (scale > max_scale)
throw Exception("Scale " + std::to_string(scale) + " is too large for DateTime64. Maximum is up to nanoseconds (9).",
ErrorCodes::ARGUMENT_OUT_OF_BOUND);
}
DataTypeDateTime64::DataTypeDateTime64(UInt32 scale_, const TimezoneMixin & time_zone_info)
: DataTypeDecimalBase<DateTime64>(DecimalUtils::maxPrecision<DateTime64>() - scale_, scale_),
: DataTypeDecimalBase<DateTime64>(DecimalUtils::maxPrecision<DateTime64>(), scale_),
TimezoneMixin(time_zone_info)
{}
{
if (scale > max_scale)
throw Exception("Scale " + std::to_string(scale) + " is too large for DateTime64. Maximum is up to nanoseconds (9).",
ErrorCodes::ARGUMENT_OUT_OF_BOUND);
}
std::string DataTypeDateTime64::doGetName() const
{

View File

@ -72,7 +72,7 @@ public:
{
if (unlikely(precision < 1 || precision > maxPrecision()))
throw Exception("Precision " + std::to_string(precision) + " is out of bounds", ErrorCodes::ARGUMENT_OUT_OF_BOUND);
if (unlikely(scale < 0 || static_cast<UInt32>(scale) > maxPrecision()))
if (unlikely(scale > maxPrecision()))
throw Exception("Scale " + std::to_string(scale) + " is out of bounds", ErrorCodes::ARGUMENT_OUT_OF_BOUND);
}

View File

@ -208,7 +208,7 @@ DataTypePtr getLeastSupertype(const DataTypes & types)
}
}
/// For Date and DateTime, the common type is DateTime. No other types are compatible.
/// For Date and DateTime/DateTime64, the common type is DateTime/DateTime64. No other types are compatible.
{
UInt32 have_date = type_ids.count(TypeIndex::Date);
UInt32 have_datetime = type_ids.count(TypeIndex::DateTime);
@ -218,40 +218,25 @@ DataTypePtr getLeastSupertype(const DataTypes & types)
{
bool all_date_or_datetime = type_ids.size() == (have_date + have_datetime + have_datetime64);
if (!all_date_or_datetime)
throw Exception(getExceptionMessagePrefix(types) + " because some of them are Date/DateTime and some of them are not", ErrorCodes::NO_COMMON_TYPE);
throw Exception(getExceptionMessagePrefix(types) + " because some of them are Date/DateTime/DateTime64 and some of them are not",
ErrorCodes::NO_COMMON_TYPE);
if (have_datetime64 == 0)
{
return std::make_shared<DataTypeDateTime>();
}
// When DateTime64 involved, make sure that supertype has whole-part precision
// big enough to hold max whole-value of any type from `types`.
// That would sacrifice scale when comparing DateTime64 of different scales.
UInt8 max_scale = 0;
UInt32 max_datetime64_whole_precision = 0;
for (const auto & t : types)
{
if (const auto * dt64 = typeid_cast<const DataTypeDateTime64 *>(t.get()))
{
const auto whole_precision = dt64->getPrecision() - dt64->getScale();
max_datetime64_whole_precision = std::max(whole_precision, max_datetime64_whole_precision);
const auto scale = dt64->getScale();
if (scale > max_scale)
max_scale = scale;
}
}
UInt32 least_decimal_precision = 0;
if (have_datetime)
{
least_decimal_precision = leastDecimalPrecisionFor(TypeIndex::UInt32);
}
else if (have_date)
{
least_decimal_precision = leastDecimalPrecisionFor(TypeIndex::UInt16);
}
max_datetime64_whole_precision = std::max(least_decimal_precision, max_datetime64_whole_precision);
const UInt32 scale = DataTypeDateTime64::maxPrecision() - max_datetime64_whole_precision;
return std::make_shared<DataTypeDateTime64>(scale);
return std::make_shared<DataTypeDateTime64>(max_scale);
}
}

View File

@ -86,7 +86,7 @@ TEST_P(LeastSuperTypeTest, getLeastSupertype)
class MostSubtypeTest : public TypeTest {};
TEST_P(MostSubtypeTest, getLeastSupertype)
TEST_P(MostSubtypeTest, getMostSubtype)
{
if (this->expected_type)
{
@ -124,9 +124,7 @@ INSTANTIATE_TEST_SUITE_P(data_type,
{"Date DateTime64(3)", "DateTime64(3)"},
{"DateTime DateTime64(3)", "DateTime64(3)"},
{"DateTime DateTime64(0)", "DateTime64(0)"},
{"DateTime64(9) DateTime64(3)", "DateTime64(3)"},
{"DateTime DateTime64(12)", "DateTime64(8)"},
{"Date DateTime64(15)", "DateTime64(13)"},
{"DateTime64(9) DateTime64(3)", "DateTime64(9)"},
{"String FixedString(32) FixedString(8)", "String"},

View File

@ -275,8 +275,11 @@ ReturnType readIntTextImpl(T & x, ReadBuffer & buf)
switch (*buf.position())
{
case '+':
{
break;
}
case '-':
{
if constexpr (is_signed_v<T>)
negative = true;
else
@ -287,6 +290,7 @@ ReturnType readIntTextImpl(T & x, ReadBuffer & buf)
return ReturnType(false);
}
break;
}
case '0': [[fallthrough]];
case '1': [[fallthrough]];
case '2': [[fallthrough]];
@ -297,20 +301,27 @@ ReturnType readIntTextImpl(T & x, ReadBuffer & buf)
case '7': [[fallthrough]];
case '8': [[fallthrough]];
case '9':
{
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.
if (buf.count() - initial_pos >= std::numeric_limits<T>::max_digits10)
/// Perform relativelly slow overflow check only when
/// 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)
|| common::addOverflow(res, static_cast<decltype(res)>(*buf.position() - '0'), res))
T signed_res = res;
if (common::mulOverflow<T>(signed_res, 10, signed_res)
|| common::addOverflow<T>(signed_res, (*buf.position() - '0'), signed_res))
return ReturnType(false);
res = signed_res;
break;
}
}
res *= 10;
res += *buf.position() - '0';
break;
}
default:
goto end;
}
@ -318,7 +329,23 @@ ReturnType readIntTextImpl(T & x, ReadBuffer & buf)
}
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);
}
@ -658,35 +685,34 @@ inline ReturnType readDateTimeTextImpl(DateTime64 & datetime64, UInt32 scale, Re
return ReturnType(false);
}
DB::DecimalUtils::DecimalComponents<DateTime64::NativeType> c{static_cast<DateTime64::NativeType>(whole), 0};
DB::DecimalUtils::DecimalComponents<DateTime64::NativeType> components{static_cast<DateTime64::NativeType>(whole), 0};
if (!buf.eof() && *buf.position() == '.')
{
buf.ignore(1); // skip separator
const auto pos_before_fractional = buf.count();
if (!tryReadIntText<ReadIntTextCheckOverflow::CHECK_OVERFLOW>(c.fractional, buf))
++buf.position();
/// Read digits, up to 'scale' positions.
for (size_t i = 0; i < scale; ++i)
{
return ReturnType(false);
if (!buf.eof() && isNumericASCII(*buf.position()))
{
components.fractional *= 10;
components.fractional += *buf.position() - '0';
++buf.position();
}
else
{
/// Adjust to scale.
components.fractional *= 10;
}
}
// Adjust fractional part to the scale, since decimalFromComponents knows nothing
// about convention of ommiting trailing zero on fractional part
// and assumes that fractional part value is less than 10^scale.
// If scale is 3, but we read '12', promote fractional part to '120'.
// And vice versa: if we read '1234', denote it to '123'.
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)
{
c.fractional *= common::exp10_i64(adjust_scale);
}
else if (adjust_scale < 0)
{
c.fractional /= common::exp10_i64(-1 * adjust_scale);
}
/// Ignore digits that are out of precision.
while (!buf.eof() && isNumericASCII(*buf.position()))
++buf.position();
}
datetime64 = DecimalUtils::decimalFromComponents<DateTime64>(c, scale);
datetime64 = DecimalUtils::decimalFromComponents<DateTime64>(components, scale);
return ReturnType(true);
}

View File

@ -1,2 +1,2 @@
select now64(10); -- { serverError 407 }
select now64(10); -- { serverError 69 }
select length(toString(now64(9)));

View File

@ -6,7 +6,7 @@ WITH '2020-02-05 14:34:12.333' as S, toDateTime64(S, 3) as DT64 SELECT * WHERE D
WITH '2020-02-05 14:34:12.333' as S, toDateTime64(S, 3) as DT64 SELECT * WHERE materialize(S) = DT64; -- {serverError 43}
SELECT * WHERE toDateTime64(123.345, 3) == 'ABCD'; -- {serverError 53} -- invalid DateTime64 string
SELECT * WHERE toDateTime64(123.345, 3) == '2020-02-05 14:34:12.33333333333333333333333333333333333333333333333333333333'; -- {serverError 53} -- invalid string length
SELECT * WHERE toDateTime64(123.345, 3) == '2020-02-05 14:34:12.33333333333333333333333333333333333333333333333333333333';
SELECT 'in SELECT';
WITH '2020-02-05 14:34:12.333' as S, toDateTime64(S, 3) as DT64 SELECT DT64 = S;

View File

@ -0,0 +1,22 @@
2011-11-11 11:11:11
2011-11-11 11:11:11
2011-11-11 11:11:11
2011-11-11 11:11:11
2011-11-11 11:11:11
2011-11-11 11:11:11
2011-11-11 11:11:11
2011-11-11 11:11:11
2011-11-11 11:11:11
2011-11-11 11:11:11
2011-11-11 11:11:11
2011-11-11 11:11:11
2011-11-11 11:11:11
2011-11-11 11:11:11
2011-11-11 11:11:11
2011-11-11 11:11:11
2011-11-11 11:11:11
2011-11-11 11:11:11
2011-11-11 11:11:11
2011-11-11 11:11:11
2011-11-11 11:11:11
2011-11-11 11:11:11

View File

@ -0,0 +1,71 @@
WITH toDateTime64('2019-09-16 19:20:12.3456789102019-09-16 19:20:12.345678910', 0) AS dt64 SELECT dt64; -- { serverError 6 }
SELECT toDateTime64('2011-11-11 11:11:11.1234567890123456789', 0);
SELECT toDateTime64('2011-11-11 11:11:11.-12345678901234567890', 0); -- { serverError 6 }
SELECT toDateTime64('2011-11-11 11:11:11.1', 0);
SELECT toDateTime64('2011-11-11 11:11:11.11', 0);
SELECT toDateTime64('2011-11-11 11:11:11.111', 0);
SELECT toDateTime64('2011-11-11 11:11:11.1111', 0);
SELECT toDateTime64('2011-11-11 11:11:11.11111', 0);
SELECT toDateTime64('2011-11-11 11:11:11.111111', 0);
SELECT toDateTime64('2011-11-11 11:11:11.1111111', 0);
SELECT toDateTime64('2011-11-11 11:11:11.11111111', 0);
SELECT toDateTime64('2011-11-11 11:11:11.111111111', 0);
SELECT toDateTime64('2011-11-11 11:11:11.1111111111', 0);
SELECT toDateTime64('2011-11-11 11:11:11.11111111111', 0);
SELECT toDateTime64('2011-11-11 11:11:11.111111111111', 0);
SELECT toDateTime64('2011-11-11 11:11:11.1111111111111', 0);
SELECT toDateTime64('2011-11-11 11:11:11.11111111111111', 0);
SELECT toDateTime64('2011-11-11 11:11:11.111111111111111', 0);
SELECT toDateTime64('2011-11-11 11:11:11.1111111111111111', 0);
SELECT toDateTime64('2011-11-11 11:11:11.11111111111111111', 0);
SELECT toDateTime64('2011-11-11 11:11:11.111111111111111111', 0);
SELECT toDateTime64('2011-11-11 11:11:11.1111111111111111111', 0);
SELECT toDateTime64('2011-11-11 11:11:11.11111111111111111111', 0);
SELECT toDateTime64('2011-11-11 11:11:11.111111111111111111111', 0);
SELECT toDateTime64('2011-11-11 11:11:11.-1', 0); -- { serverError 6 }
SELECT toDateTime64('2011-11-11 11:11:11.-11', 0); -- { serverError 6 }
SELECT toDateTime64('2011-11-11 11:11:11.-111', 0); -- { serverError 6 }
SELECT toDateTime64('2011-11-11 11:11:11.-1111', 0); -- { serverError 6 }
SELECT toDateTime64('2011-11-11 11:11:11.-11111', 0); -- { serverError 6 }
SELECT toDateTime64('2011-11-11 11:11:11.-111111', 0); -- { serverError 6 }
SELECT toDateTime64('2011-11-11 11:11:11.-1111111', 0); -- { serverError 6 }
SELECT toDateTime64('2011-11-11 11:11:11.-11111111', 0); -- { serverError 6 }
SELECT toDateTime64('2011-11-11 11:11:11.-111111111', 0); -- { serverError 6 }
SELECT toDateTime64('2011-11-11 11:11:11.-1111111111', 0); -- { serverError 6 }
SELECT toDateTime64('2011-11-11 11:11:11.-11111111111', 0); -- { serverError 6 }
SELECT toDateTime64('2011-11-11 11:11:11.-111111111111', 0); -- { serverError 6 }
SELECT toDateTime64('2011-11-11 11:11:11.-1111111111111', 0); -- { serverError 6 }
SELECT toDateTime64('2011-11-11 11:11:11.-11111111111111', 0); -- { serverError 6 }
SELECT toDateTime64('2011-11-11 11:11:11.-111111111111111', 0); -- { serverError 6 }
SELECT toDateTime64('2011-11-11 11:11:11.-1111111111111111', 0); -- { serverError 6 }
SELECT toDateTime64('2011-11-11 11:11:11.-11111111111111111', 0); -- { serverError 6 }
SELECT toDateTime64('2011-11-11 11:11:11.-111111111111111111', 0); -- { serverError 6 }
SELECT toDateTime64('2011-11-11 11:11:11.-1111111111111111111', 0); -- { serverError 6 }
SELECT toDateTime64('2011-11-11 11:11:11.-11111111111111111111', 0); -- { serverError 6 }
SELECT toDateTime64('2011-11-11 11:11:11.-111111111111111111111', 0); -- { serverError 6 }
SELECT toDateTime64('2011-11-11 11:11:11.+1', 0); -- { serverError 6 }
SELECT toDateTime64('2011-11-11 11:11:11.++11', 10); -- { serverError 69 }
SELECT toDateTime64('2011-11-11 11:11:11.+111', 3); -- { serverError 6 }
SELECT toDateTime64('2011-11-11 11:11:11.+++1111', 5); -- { serverError 6 }
SELECT toDateTime64('2011-11-11 11:11:11.+11111', 7); -- { serverError 6 }
SELECT toDateTime64('2011-11-11 11:11:11.+++++111111', 2); -- { serverError 6 }
SELECT toDateTime64('2011-11-11 11:11:11.+1111111', 1); -- { serverError 6 }
SELECT toDateTime64('2011-11-11 11:11:11.++++++11111111', 8); -- { serverError 6 }
SELECT toDateTime64('2011-11-11 11:11:11.+111111111', 9); -- { serverError 6 }
SELECT toDateTime64('2011-11-11 11:11:11.+++++++1111111111', 6); -- { serverError 6 }
SELECT toDateTime64('2011-11-11 11:11:11.+11111111111', 4); -- { serverError 6 }
SELECT toDateTime64('2011-11-11 11:11:11.++++++++111111111111', 11); -- { serverError 69 }
SELECT toDateTime64('2011-11-11 11:11:11.+1111111111111', 15); -- { serverError 69 }
SELECT toDateTime64('2011-11-11 11:11:11.+++++++++11111111111111', 13); -- { serverError 69 }
SELECT toDateTime64('2011-11-11 11:11:11.+111111111111111', 12); -- { serverError 69 }
SELECT toDateTime64('2011-11-11 11:11:11.++++++++++1111111111111111', 16); -- { serverError 69 }
SELECT toDateTime64('2011-11-11 11:11:11.+11111111111111111', 14); -- { serverError 69 }
SELECT toDateTime64('2011-11-11 11:11:11.+++++++++++111111111111111111', 15); -- { serverError 69 }
SELECT toDateTime64('2011-11-11 11:11:11.+1111111111111111111', 17); -- { serverError 69 }
SELECT toDateTime64('2011-11-11 11:11:11.++++++++++++11111111111111111111', 19); -- { serverError 69 }
SELECT toDateTime64('2011-11-11 11:11:11.+111111111111111111111', 18); -- { serverError 69 }

View File

@ -0,0 +1 @@
['2000-01-01 01:01:01.123000','2000-01-01 01:01:01.123456']

View File

@ -0,0 +1 @@
SELECT [toDateTime64('2000-01-01 01:01:01.123', 3), toDateTime64('2000-01-01 01:01:01.123456', 6)];