Merge pull request #62335 from Misz606/patch-5

Added nano- micro- milliseconds unit for `date_trunc`
This commit is contained in:
Yarik Briukhovetskyi 2024-04-16 23:16:46 +00:00 committed by GitHub
commit ffeec296a1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 63 additions and 14 deletions

View File

@ -1836,6 +1836,9 @@ Alias: `dateTrunc`.
- `unit` — The type of interval to truncate the result. [String Literal](../syntax.md#syntax-string-literal).
Possible values:
- `nanosecond` - Compatible only with DateTime64
- `microsecond` - Compatible only with DateTime64
- `milisecond` - Compatible only with DateTime64
- `second`
- `minute`
- `hour`

View File

@ -40,7 +40,14 @@ public:
{
/// The first argument is a constant string with the name of datepart.
auto result_type_is_date = false;
enum ResultType
{
Date,
DateTime,
DateTime64,
};
ResultType result_type;
String datepart_param;
auto check_first_argument = [&] {
const ColumnConst * datepart_column = checkAndGetColumnConst<ColumnString>(arguments[0].column.get());
@ -56,13 +63,14 @@ public:
if (!IntervalKind::tryParseString(datepart_param, datepart_kind))
throw Exception(ErrorCodes::BAD_ARGUMENTS, "{} doesn't look like datepart name in {}", datepart_param, getName());
if (datepart_kind == IntervalKind::Kind::Nanosecond || datepart_kind == IntervalKind::Kind::Microsecond
|| datepart_kind == IntervalKind::Kind::Millisecond)
throw Exception(ErrorCodes::BAD_ARGUMENTS, "{} doesn't support {}", getName(), datepart_param);
result_type_is_date = (datepart_kind == IntervalKind::Kind::Year)
|| (datepart_kind == IntervalKind::Kind::Quarter) || (datepart_kind == IntervalKind::Kind::Month)
|| (datepart_kind == IntervalKind::Kind::Week);
if ((datepart_kind == IntervalKind::Kind::Year) || (datepart_kind == IntervalKind::Kind::Quarter)
|| (datepart_kind == IntervalKind::Kind::Month) || (datepart_kind == IntervalKind::Kind::Week))
result_type = ResultType::Date;
else if ((datepart_kind == IntervalKind::Kind::Day) || (datepart_kind == IntervalKind::Kind::Hour)
|| (datepart_kind == IntervalKind::Kind::Minute) || (datepart_kind == IntervalKind::Kind::Second))
result_type = ResultType::DateTime;
else
result_type = ResultType::DateTime64;
};
bool second_argument_is_date = false;
@ -84,7 +92,7 @@ public:
"This argument is optional and must be a constant string with timezone name",
arguments[2].type->getName(), getName());
if (second_argument_is_date && result_type_is_date)
if (second_argument_is_date && result_type == ResultType::Date)
throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT,
"The timezone argument of function {} with datepart '{}' "
"is allowed only when the 2nd argument has the type DateTime",
@ -109,10 +117,21 @@ public:
getName(), arguments.size());
}
if (result_type_is_date)
if (result_type == ResultType::Date)
return std::make_shared<DataTypeDate>();
else
else if (result_type == ResultType::DateTime)
return std::make_shared<DataTypeDateTime>(extractTimeZoneNameFromFunctionArguments(arguments, 2, 1, false));
else
{
size_t scale;
if (datepart_kind == IntervalKind::Kind::Millisecond)
scale = 3;
else if (datepart_kind == IntervalKind::Kind::Microsecond)
scale = 6;
else if (datepart_kind == IntervalKind::Kind::Nanosecond)
scale = 9;
return std::make_shared<DataTypeDateTime64>(scale, extractTimeZoneNameFromFunctionArguments(arguments, 2, 1, false));
}
}
bool useDefaultImplementationForConstants() const override { return true; }

View File

@ -7,3 +7,15 @@
2022-03-01 00:00:00
2022-03-01
2022-02-28
2022-03-01 12:12:12.012000000
2022-03-01 12:12:12.012346
2022-03-01 12:12:12.012
2022-03-01 12:12:12.012300
2022-03-01 12:12:12.012
2022-03-01 12:12:12.012345670
1950-03-01 12:12:12.012000000
1951-03-01 12:12:12.012345
1952-03-01 12:12:12.012
1965-03-01 12:12:12.012300
1966-03-01 12:12:12.012
1967-03-01 12:12:12.012345670

View File

@ -7,6 +7,21 @@ SELECT dateTrunc('Week', toDate('2022-03-01'));
SELECT dateTrunc('day', toDateTime('2022-03-01 12:55:55'));
SELECT dateTrunc('month', toDateTime64('2022-03-01 12:55:55', 2));
SELECT dateTrunc('week', toDate('2022-03-01'));
SELECT dateTrunc('Nanosecond', toDate('2022-03-01')); -- { serverError 36 }
SELECT dateTrunc('MicroSecond', toDate('2022-03-01')); -- { serverError 36 }
SELECT dateTrunc('MILLISECOND', toDate('2022-03-01')); -- { serverError 36 }
SELECT dateTrunc('Nanosecond', toDateTime64('2022-03-01 12:12:12.0123', 3));
SELECT dateTrunc('MicroSecond', toDateTime64('2022-03-01 12:12:12.0123456', 7));
SELECT dateTrunc('MILLISECOND', toDateTime64('2022-03-01 12:12:12.012324251', 9));
SELECT dateTrunc('mICROsECOND', toDateTime64('2022-03-01 12:12:12.0123', 4));
SELECT dateTrunc('mIllISecoNd', toDateTime64('2022-03-01 12:12:12.0123456', 6));
SELECT dateTrunc('NANoSecoND', toDateTime64('2022-03-01 12:12:12.012345678', 8));
SELECT dateTrunc('Nanosecond', toDateTime64('1950-03-01 12:12:12.0123', 3));
SELECT dateTrunc('MicroSecond', toDateTime64('1951-03-01 12:12:12.0123456', 7));
SELECT dateTrunc('MILLISECOND', toDateTime64('1952-03-01 12:12:12.012324251', 9));
SELECT dateTrunc('mICROsECOND', toDateTime64('1965-03-01 12:12:12.0123', 4));
SELECT dateTrunc('mIllISecoNd', toDateTime64('1966-03-01 12:12:12.0123456', 6));
SELECT dateTrunc('NANoSecoND', toDateTime64('1967-03-01 12:12:12.012345678', 8));
SELECT dateTrunc('Nanosecond', toDateTime('2022-03-01')); -- { serverError ILLEGAL_TYPE_OF_ARGUMENT }
SELECT dateTrunc('MicroSecond', toDateTime('2022-03-01')); -- { serverError ILLEGAL_TYPE_OF_ARGUMENT }
SELECT dateTrunc('MILLISECOND', toDateTime('2022-03-01')); -- { serverError ILLEGAL_TYPE_OF_ARGUMENT }
SELECT dateTrunc('Nanosecond', toDate('2022-03-01')); -- { serverError ILLEGAL_TYPE_OF_ARGUMENT }
SELECT dateTrunc('MicroSecond', toDate('2022-03-01')); -- { serverError ILLEGAL_TYPE_OF_ARGUMENT }
SELECT dateTrunc('MILLISECOND', toDate('2022-03-01')); -- { serverError ILLEGAL_TYPE_OF_ARGUMENT }