updates due to review

This commit is contained in:
Yarik Briukhovetskyi 2024-08-09 19:05:37 +02:00 committed by GitHub
parent 35f19522e7
commit a3d8db6e1e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 24 additions and 59 deletions

View File

@ -55,28 +55,29 @@ SELECT now() as current_date_time, current_date_time + INTERVAL 4 DAY
└─────────────────────┴───────────────────────────────┘
```
也可以同時使用多個間隔:
不同类型的间隔不能合并。 你不能使用诸如 `4 DAY 1 HOUR` 的时间间隔. 以小于或等于时间间隔最小单位的单位来指定间隔,例如,时间间隔 `1 day and an hour` 可以表示为 `25 HOUR``90000 SECOND`.
你不能对 `Interval` 类型的值执行算术运算,但你可以向 `Date``DateTime` 数据类型的值添加不同类型的时间间隔,例如:
``` sql
SELECT now() AS current_date_time, current_date_time + (INTERVAL 4 DAY + INTERVAL 3 HOUR)
SELECT now() AS current_date_time, current_date_time + INTERVAL 4 DAY + INTERVAL 3 HOUR
```
``` text
┌───current_date_time─┬─plus(current_date_time, plus(toIntervalDay(4), toIntervalHour(3)))─┐
│ 2024-08-08 18:31:39 │ 2024-08-12 21:31:39
└─────────────────────┴────────────────────────────────────────────────────────────────────
┌───current_date_time─┬─plus(plus(now(), toIntervalDay(4)), toIntervalHour(3))─┐
│ 2019-10-23 11:16:28 │ 2019-10-27 14:16:28
└─────────────────────┴────────────────────────────────────────────────────────┘
```
並比較不同直數的值:
以下查询将导致异常:
``` sql
SELECT toIntervalMicrosecond(3600000000) = toIntervalHour(1);
select now() AS current_date_time, current_date_time + (INTERVAL 4 DAY + INTERVAL 3 HOUR)
```
``` text
┌─less(toIntervalMicrosecond(179999999), toIntervalMinute(3))─┐
│ 1 │
└─────────────────────────────────────────────────────────────┘
Received exception from server (version 19.14.1):
Code: 43. DB::Exception: Received from localhost:9000. DB::Exception: Wrong argument types for function plus: if one argument is Interval, then another must be Date or DateTime..
```
## 另请参阅 {#see-also}

View File

@ -230,8 +230,7 @@ void convertUInt64toInt64IfPossible(const DataTypes & types, TypeIndexSet & type
DataTypePtr findSmallestIntervalSuperType(const DataTypes &types, TypeIndexSet &types_set)
{
const auto& granularity_map = getGranularityMap();
int min_granularity = std::get<0>(granularity_map.at(IntervalKind::Kind::Year));
auto min_interval = IntervalKind::Kind::Year;
DataTypePtr smallest_type;
bool is_higher_interval = false; // For Years, Quarters and Months
@ -240,18 +239,18 @@ DataTypePtr findSmallestIntervalSuperType(const DataTypes &types, TypeIndexSet &
{
if (const auto * interval_type = typeid_cast<const DataTypeInterval *>(type.get()))
{
int current_granularity = std::get<0>(granularity_map.at(interval_type->getKind()));
if (current_granularity > 8)
auto current_interval = interval_type->getKind().kind;
if (current_interval > IntervalKind::Kind::Week)
is_higher_interval = true;
if (current_granularity < min_granularity)
if (current_interval < min_interval)
{
min_granularity = current_granularity;
min_interval = current_interval;
smallest_type = type;
}
}
}
if (is_higher_interval && min_granularity <= 8)
if (is_higher_interval && min_interval <= IntervalKind::Kind::Week)
throw Exception(ErrorCodes::NO_COMMON_TYPE, "Cannot compare intervals {} and {} because the amount of days in month is not determined", types[0]->getName(), types[1]->getName());
if (smallest_type)

View File

@ -50,24 +50,9 @@ DataTypePtr getLeastSupertypeOrString(const TypeIndexSet & types);
DataTypePtr tryGetLeastSupertype(const TypeIndexSet & types);
/// A map that enumerated all interval kinds in ascending order with a conversion value to a next interval
inline const std::unordered_map<IntervalKind::Kind, std::pair<int, int>> & getGranularityMap()
{
static std::unordered_map<IntervalKind::Kind, std::pair<int, int>> granularity_map =
{
{IntervalKind::Kind::Nanosecond, {1, 1000}},
{IntervalKind::Kind::Microsecond, {2, 1000}},
{IntervalKind::Kind::Millisecond, {3, 1000}},
{IntervalKind::Kind::Second, {4, 60}},
{IntervalKind::Kind::Minute, {5, 60}},
{IntervalKind::Kind::Hour, {6, 24}},
{IntervalKind::Kind::Day, {7, 7}},
{IntervalKind::Kind::Week, {8, 4}},
{IntervalKind::Kind::Month, {9, 3}},
{IntervalKind::Kind::Quarter, {10, 4}},
{IntervalKind::Kind::Year, {11, 1}}
};
return granularity_map;
/// A vector that shows the conversion rates to the next Interval type starting from NanoSecond
static std::vector<int> interval_conversions = {1000, 1000, 1000, 60, 60, 24, 7, 4, 3, 4, 1};
}
}

View File

@ -1582,42 +1582,22 @@ struct ConvertImpl
if (from == to || arguments[0].column->empty())
return arguments[0].column;
const auto &map = getGranularityMap();
Int64 conversion_factor = 1;
Int64 result_value;
int from_position = map.at(from).first;
int to_position = map.at(to).first; // Positions of each interval according to granurality map
int from_position = static_cast<int>(from.kind);
int to_position = static_cast<int>(to.kind); // Positions of each interval according to granurality map
if (from_position < to_position)
{
for (int i = from_position - 1; i <= to_position; ++i)
{
// Find the kind that matches this position
for (const auto &entry : map)
{
if (entry.second.first == i)
{
conversion_factor *= entry.second.second;
break;
}
}
}
conversion_factor *= interval_conversions[i];
result_value = arguments[0].column->getInt(0) / conversion_factor;
}
else
{
for (int i = from_position - 1; i >= to_position; --i)
{
for (const auto &entry : map)
{
if (entry.second.first == i)
{
conversion_factor *= entry.second.second;
break;
}
}
}
conversion_factor *= interval_conversions[i];
result_value = arguments[0].column->getInt(0) * conversion_factor;
}