More tests for corner cases

This commit is contained in:
Alexander Gololobov 2022-04-07 10:20:38 +02:00
parent 81d150ed43
commit 42d4a84a6f
3 changed files with 94 additions and 20 deletions

View File

@ -196,16 +196,28 @@ protected:
{ {
/// Note that hour, minute and second are checked against 99 to behave consistently with parsing DateTime from String /// Note that hour, minute and second are checked against 99 to behave consistently with parsing DateTime from String
/// E.g. "select cast('1984-01-01 99:99:99' as DateTime);" returns "1984-01-05 04:40:39" /// E.g. "select cast('1984-01-01 99:99:99' as DateTime);" returns "1984-01-05 04:40:39"
if (unlikely(year < DATE_LUT_MIN_YEAR || month < 1 || month > 12 || day_of_month < 1 || day_of_month > 31 || if (unlikely(std::isnan(year) || std::isnan(month) || std::isnan(day_of_month) ||
std::isnan(hour) || std::isnan(minute) || std::isnan(second) ||
year < DATE_LUT_MIN_YEAR || month < 1 || month > 12 || day_of_month < 1 || day_of_month > 31 ||
hour < 0 || hour > 99 || minute < 0 || minute > 99 || second < 0 || second > 99)) hour < 0 || hour > 99 || minute < 0 || minute > 99 || second < 0 || second > 99))
return lut.makeDateTime(DATE_LUT_MIN_YEAR-1, 1, 1, 0, 0, 0); return minDateTime(lut);
if (unlikely(year > DATE_LUT_MAX_YEAR)) if (unlikely(year > DATE_LUT_MAX_YEAR))
return lut.makeDateTime(DATE_LUT_MAX_YEAR+1, 1, 1, 23, 59, 59); return maxDateTime(lut);
return lut.makeDateTime(year, month, day_of_month, hour, minute, second); return lut.makeDateTime(year, month, day_of_month, hour, minute, second);
} }
static Int64 minDateTime(const DateLUTImpl & lut)
{
return lut.makeDateTime(DATE_LUT_MIN_YEAR - 1, 1, 1, 0, 0, 0);
}
static Int64 maxDateTime(const DateLUTImpl & lut)
{
return lut.makeDateTime(DATE_LUT_MAX_YEAR + 1, 1, 1, 23, 59, 59);
}
std::string extractTimezone(const ColumnWithTypeAndName & timezone_argument) const std::string extractTimezone(const ColumnWithTypeAndName & timezone_argument) const
{ {
std::string timezone; std::string timezone;
@ -364,6 +376,8 @@ public:
const auto & date_lut = DateLUT::instance(timezone); const auto & date_lut = DateLUT::instance(timezone);
const auto max_fraction = pow(10, precision) - 1; const auto max_fraction = pow(10, precision) - 1;
const auto min_date_time = minDateTime(date_lut);
const auto max_date_time = maxDateTime(date_lut);
for (size_t i = 0; i < input_rows_count; ++i) for (size_t i = 0; i < input_rows_count; ++i)
{ {
@ -376,11 +390,24 @@ public:
auto date_time = dateTime(year, month, day, hour, minute, second, date_lut); auto date_time = dateTime(year, month, day, hour, minute, second, date_lut);
auto fraction = fraction_data ? (*fraction_data)[i] : 0; double fraction = 0;
if (unlikely(fraction < 0)) if (unlikely(date_time == min_date_time))
fraction = 0; fraction = 0;
else if (unlikely(fraction > max_fraction)) else if (unlikely(date_time == max_date_time))
fraction = max_fraction; fraction = 999999999ll;
else
{
fraction = fraction_data ? (*fraction_data)[i] : 0;
if (unlikely(std::isnan(fraction)))
{
date_time = min_date_time;
fraction = 0;
}
else if (unlikely(fraction < 0))
fraction = 0;
else if (unlikely(fraction > max_fraction))
fraction = max_fraction;
}
result_data[i] = DecimalUtils::decimalFromComponents<DateTime64>(date_time, fraction, precision); result_data[i] = DecimalUtils::decimalFromComponents<DateTime64>(date_time, fraction, precision);
} }

View File

@ -9,7 +9,7 @@ DateTime64(6)
DateTime64(7, \'CET\') DateTime64(7, \'CET\')
DateTime64(7, \'UTC\') DateTime64(7, \'UTC\')
1925-01-01 00:00:00.000000000 1925-01-01 00:00:00.000000000
1925-01-01 00:00:00.999999999 1925-01-01 00:00:00.000000000
2283-11-11 23:59:59.99999999 2283-11-11 23:59:59.99999999
2262-04-11 23:47:16.854775807 2262-04-11 23:47:16.854775807
2262-04-11 23:47:16.85477581 2262-04-11 23:47:16.85477581
@ -30,8 +30,23 @@ DateTime64(7, \'UTC\')
1984-01-02 01:00:00.000000000 1984-01-02 01:00:00.000000000
1984-01-01 01:10:00.000000000 1984-01-01 01:10:00.000000000
1984-01-01 00:01:10.000000000 1984-01-01 00:01:10.000000000
1984-01-01 00:00:00.000000000 1984-01-01 02:03:04.000000005
1983-03-01 00:00:00.000000000 1984-02-29 02:03:04.000000005
1983-03-01 02:03:04.000000005
1984-03-01 02:03:04.000000005
1983-03-02 02:03:04.000000005
1984-03-02 02:03:04.000000005
1983-03-03 02:03:04.000000005
1925-01-01 00:00:00.000000000
1925-01-01 00:00:00.000000000
1925-01-01 00:00:00.000000000
1925-01-01 00:00:00.000000000
1925-01-01 00:00:00.000000000
1925-01-01 00:00:00.000000000
1925-01-01 00:00:00.000000000
1925-01-01 00:00:00.000000000
1984-01-01 02:03:04.000000000
1925-01-01 00:00:00.000000000
1925-01-01 00:00:00.000000000 1925-01-01 00:00:00.000000000
1925-01-01 00:00:00.000000000 1925-01-01 00:00:00.000000000
1925-01-01 00:00:00.000000000 1925-01-01 00:00:00.000000000
@ -39,7 +54,14 @@ DateTime64(7, \'UTC\')
1925-01-01 00:00:00.000000000 1925-01-01 00:00:00.000000000
1925-01-01 00:00:00.000000000 1925-01-01 00:00:00.000000000
1984-01-01 00:00:00.000000000 1984-01-01 00:00:00.000000000
2283-11-11 23:59:59.000 1984-01-01 00:00:00.000000000
1984-01-01 00:00:00.000000000
1984-01-01 00:00:00.000000000
1984-01-01 00:00:00.000000000
1984-01-01 00:00:00.000000000
1984-01-01 00:00:00.000000000
1984-01-01 00:00:00.000000000
2283-11-11 23:59:59.999
1925-01-01 00:00:00.000 1925-01-01 00:00:00.000
1925-01-01 00:00:00.000 1925-01-01 00:00:00.000
1925-01-01 00:00:00.000 1925-01-01 00:00:00.000

View File

@ -40,15 +40,40 @@ select makeDateTime64(1984, 1, 1, 0, 70, 0, 0, 9, 'UTC');
select makeDateTime64(1984, 1, 1, 0, 0, 70, 0, 9, 'UTC'); select makeDateTime64(1984, 1, 1, 0, 0, 70, 0, 9, 'UTC');
select makeDateTime64(1984, 1, 1, 0, 0, 0, 0, 9, 'not a timezone'); -- { serverError 1000 } select makeDateTime64(1984, 1, 1, 0, 0, 0, 0, 9, 'not a timezone'); -- { serverError 1000 }
select makeDateTime64(1984, 1, 1, 0, 0, 0, 0, 9, 'UTC'); select makeDateTime64(1984, 1, 1, 2, 3, 4, 5, 9, 'UTC');
select makeDateTime64(1983, 2, 29, 0, 0, 0, 0, 9, 'UTC'); select makeDateTime64(1984, 2, 29, 2, 3, 4, 5, 9, 'UTC');
select makeDateTime64(-1984, 1, 1, 0, 0, 0, 0, 9, 'UTC'); select makeDateTime64(1983, 2, 29, 2, 3, 4, 5, 9, 'UTC');
select makeDateTime64(1984, -1, 1, 0, 0, 0, 0, 9, 'UTC'); select makeDateTime64(1984, 2, 30, 2, 3, 4, 5, 9, 'UTC');
select makeDateTime64(1984, 1, -1, 0, 0, 0, 0, 9, 'UTC'); select makeDateTime64(1983, 2, 30, 2, 3, 4, 5, 9, 'UTC');
select makeDateTime64(1984, 1, 1, -1, 0, 0, 0, 9, 'UTC'); select makeDateTime64(1984, 2, 31, 2, 3, 4, 5, 9, 'UTC');
select makeDateTime64(1984, 1, 1, 0, -1, 0, 0, 9, 'UTC'); select makeDateTime64(1983, 2, 31, 2, 3, 4, 5, 9, 'UTC');
select makeDateTime64(1984, 1, 1, 0, 0, -1, 0, 9, 'UTC'); select makeDateTime64(1984, 2, 32, 2, 3, 4, 5, 9, 'UTC');
select makeDateTime64(1984, 1, 1, 0, 0, 0, -1, 9, 'UTC'); select makeDateTime64(1983, 2, 32, 2, 3, 4, 5, 9, 'UTC');
select makeDateTime64(-1984, 1, 1, 2, 3, 4, 5, 9, 'UTC');
select makeDateTime64(1984, -1, 1, 2, 3, 4, 5, 9, 'UTC');
select makeDateTime64(1984, 1, -1, 2, 3, 4, 5, 9, 'UTC');
select makeDateTime64(1984, 1, 1, -1, 3, 4, 5, 9, 'UTC');
select makeDateTime64(1984, 1, 1, 2, -1, 4, 5, 9, 'UTC');
select makeDateTime64(1984, 1, 1, 2, 3, -1, 5, 9, 'UTC');
select makeDateTime64(1984, 1, 1, 2, 3, 4, -1, 9, 'UTC');
select makeDateTime64(NaN, 1, 1, 2, 3, 4, 5, 9, 'UTC');
select makeDateTime64(1984, NaN, 1, 2, 3, 4, 5, 9, 'UTC');
select makeDateTime64(1984, 1, NaN, 2, 3, 4, 5, 9, 'UTC');
select makeDateTime64(1984, 1, 1, NaN, 3, 4, 5, 9, 'UTC');
select makeDateTime64(1984, 1, 1, 2, NaN, 4, 5, 9, 'UTC');
select makeDateTime64(1984, 1, 1, 2, 3, NaN, 5, 9, 'UTC');
select makeDateTime64(1984, 1, 1, 2, 3, 4, NaN, 9, 'UTC');
select makeDateTime64(1984.5, 1, 1, 0, 0, 0, 0, 9, 'UTC');
select makeDateTime64(1984, 1.5, 1, 0, 0, 0, 0, 9, 'UTC');
select makeDateTime64(1984, 1, 1.5, 0, 0, 0, 0, 9, 'UTC');
select makeDateTime64(1984, 1, 1, 0.5, 0, 0, 0, 9, 'UTC');
select makeDateTime64(1984, 1, 1, 0, 0.5, 0, 0, 9, 'UTC');
select makeDateTime64(1984, 1, 1, 0, 0, 0.5, 0, 9, 'UTC');
select makeDateTime64(1984, 1, 1, 0, 0, 0, 0.5, 9, 'UTC');
select makeDateTime64(1984, 1, 1, 0, 0, 0, 0, 9.5, 'UTC');
select makeDateTime64(65537, 8, 24, 21, 4, 0); select makeDateTime64(65537, 8, 24, 21, 4, 0);
select makeDateTime64(1991, 65537, 24, 21, 4, 0); select makeDateTime64(1991, 65537, 24, 21, 4, 0);