2020-01-14 03:08:54 +00:00
|
|
|
#pragma once
|
|
|
|
|
2021-12-21 13:41:53 +00:00
|
|
|
#include <Common/DateLUT.h>
|
2021-06-01 03:01:35 +00:00
|
|
|
#include <DataTypes/DataTypeInterval.h>
|
|
|
|
#include <Functions/IFunction.h>
|
2020-01-14 03:08:54 +00:00
|
|
|
|
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
|
2021-12-10 09:43:44 +00:00
|
|
|
/** Time window functions:
|
2020-01-14 03:08:54 +00:00
|
|
|
*
|
2021-12-07 08:14:00 +00:00
|
|
|
* tumble(time_attr, interval [, timezone])
|
2021-05-29 10:29:38 +00:00
|
|
|
*
|
2021-12-07 08:14:00 +00:00
|
|
|
* tumbleStart(window_id)
|
2021-05-29 10:29:38 +00:00
|
|
|
*
|
2021-12-07 08:14:00 +00:00
|
|
|
* tumbleStart(time_attr, interval [, timezone])
|
2021-05-29 10:29:38 +00:00
|
|
|
*
|
2021-12-07 08:14:00 +00:00
|
|
|
* tumbleEnd(window_id)
|
2021-05-29 10:29:38 +00:00
|
|
|
*
|
2021-12-07 08:14:00 +00:00
|
|
|
* tumbleEnd(time_attr, interval [, timezone])
|
2021-05-29 10:29:38 +00:00
|
|
|
*
|
2021-12-07 08:14:00 +00:00
|
|
|
* hop(time_attr, hop_interval, window_interval [, timezone])
|
2021-05-29 10:29:38 +00:00
|
|
|
*
|
2021-12-07 08:14:00 +00:00
|
|
|
* hopStart(window_id)
|
2021-05-29 10:29:38 +00:00
|
|
|
*
|
2021-12-07 08:14:00 +00:00
|
|
|
* hopStart(time_attr, hop_interval, window_interval [, timezone])
|
2021-05-29 10:29:38 +00:00
|
|
|
*
|
2021-12-07 08:14:00 +00:00
|
|
|
* hopEnd(window_id)
|
2021-05-29 10:29:38 +00:00
|
|
|
*
|
2021-12-07 08:14:00 +00:00
|
|
|
* hopEnd(time_attr, hop_interval, window_interval [, timezone])
|
2021-05-29 10:29:38 +00:00
|
|
|
*
|
2020-01-14 03:08:54 +00:00
|
|
|
*/
|
2021-12-10 09:59:50 +00:00
|
|
|
enum TimeWindowFunctionName
|
2020-01-14 03:08:54 +00:00
|
|
|
{
|
|
|
|
TUMBLE,
|
|
|
|
TUMBLE_START,
|
|
|
|
TUMBLE_END,
|
|
|
|
HOP,
|
|
|
|
HOP_START,
|
2020-06-17 15:06:19 +00:00
|
|
|
HOP_END,
|
|
|
|
WINDOW_ID
|
2020-01-14 03:08:54 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
template <IntervalKind::Kind unit>
|
|
|
|
struct ToStartOfTransform;
|
|
|
|
|
|
|
|
#define TRANSFORM_DATE(INTERVAL_KIND) \
|
|
|
|
template <> \
|
|
|
|
struct ToStartOfTransform<IntervalKind::INTERVAL_KIND> \
|
|
|
|
{ \
|
2022-01-02 23:05:27 +00:00
|
|
|
static auto execute(UInt32 t, UInt64 delta, const DateLUTImpl & time_zone) \
|
2020-01-14 03:08:54 +00:00
|
|
|
{ \
|
|
|
|
return time_zone.toStartOf##INTERVAL_KIND##Interval(time_zone.toDayNum(t), delta); \
|
|
|
|
} \
|
|
|
|
};
|
|
|
|
TRANSFORM_DATE(Year)
|
|
|
|
TRANSFORM_DATE(Quarter)
|
|
|
|
TRANSFORM_DATE(Month)
|
|
|
|
TRANSFORM_DATE(Week)
|
|
|
|
#undef TRANSFORM_DATE
|
|
|
|
|
2020-07-27 09:32:15 +00:00
|
|
|
template <>
|
|
|
|
struct ToStartOfTransform<IntervalKind::Day>
|
|
|
|
{
|
|
|
|
static UInt32 execute(UInt32 t, UInt64 delta, const DateLUTImpl & time_zone)
|
|
|
|
{
|
2022-10-07 10:46:45 +00:00
|
|
|
return static_cast<UInt32>(time_zone.toStartOfDayInterval(time_zone.toDayNum(t), delta));
|
2020-07-26 18:54:09 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2020-01-14 03:08:54 +00:00
|
|
|
#define TRANSFORM_TIME(INTERVAL_KIND) \
|
|
|
|
template <> \
|
|
|
|
struct ToStartOfTransform<IntervalKind::INTERVAL_KIND> \
|
|
|
|
{ \
|
|
|
|
static UInt32 execute(UInt32 t, UInt64 delta, const DateLUTImpl & time_zone) \
|
|
|
|
{ \
|
2022-10-07 10:46:45 +00:00
|
|
|
return static_cast<UInt32>(time_zone.toStartOf##INTERVAL_KIND##Interval(t, delta)); \
|
2020-01-14 03:08:54 +00:00
|
|
|
} \
|
|
|
|
};
|
|
|
|
TRANSFORM_TIME(Hour)
|
|
|
|
TRANSFORM_TIME(Minute)
|
|
|
|
TRANSFORM_TIME(Second)
|
2022-02-07 18:44:14 +00:00
|
|
|
#undef TRANSFORM_TIME
|
2020-01-14 03:08:54 +00:00
|
|
|
|
2022-02-13 14:54:03 +00:00
|
|
|
#define TRANSFORM_SUBSECONDS(INTERVAL_KIND, DEF_SCALE) \
|
|
|
|
template<> \
|
|
|
|
struct ToStartOfTransform<IntervalKind::INTERVAL_KIND> \
|
|
|
|
{ \
|
|
|
|
static Int64 execute(Int64 t, UInt64 delta, const UInt32 scale) \
|
|
|
|
{ \
|
|
|
|
if (scale <= DEF_SCALE) \
|
|
|
|
{ \
|
|
|
|
auto val = t * DecimalUtils::scaleMultiplier<DateTime64>(DEF_SCALE - scale); \
|
|
|
|
if (delta == 1) \
|
|
|
|
return val; \
|
|
|
|
else \
|
|
|
|
return val - (val % delta); \
|
|
|
|
} \
|
|
|
|
else \
|
|
|
|
{ \
|
|
|
|
return t - (t % (delta * DecimalUtils::scaleMultiplier<DateTime64>(scale - DEF_SCALE))) ; \
|
|
|
|
} \
|
|
|
|
} \
|
|
|
|
};
|
|
|
|
TRANSFORM_SUBSECONDS(Millisecond, 3)
|
|
|
|
TRANSFORM_SUBSECONDS(Microsecond, 6)
|
|
|
|
TRANSFORM_SUBSECONDS(Nanosecond, 9)
|
|
|
|
#undef TRANSFORM_SUBSECONDS
|
|
|
|
|
2020-01-14 03:08:54 +00:00
|
|
|
template <IntervalKind::Kind unit>
|
|
|
|
struct AddTime;
|
|
|
|
|
|
|
|
#define ADD_DATE(INTERVAL_KIND) \
|
|
|
|
template <> \
|
|
|
|
struct AddTime<IntervalKind::INTERVAL_KIND> \
|
|
|
|
{ \
|
2022-10-07 10:46:45 +00:00
|
|
|
static inline auto execute(UInt16 d, Int64 delta, const DateLUTImpl & time_zone) \
|
2020-07-26 18:54:09 +00:00
|
|
|
{ \
|
2021-05-28 07:36:19 +00:00
|
|
|
return time_zone.add##INTERVAL_KIND##s(ExtendedDayNum(d), delta); \
|
2020-07-26 18:54:09 +00:00
|
|
|
} \
|
2020-01-14 03:08:54 +00:00
|
|
|
};
|
|
|
|
ADD_DATE(Year)
|
|
|
|
ADD_DATE(Quarter)
|
|
|
|
ADD_DATE(Month)
|
|
|
|
#undef ADD_DATE
|
|
|
|
|
2020-07-27 09:32:15 +00:00
|
|
|
template <>
|
|
|
|
struct AddTime<IntervalKind::Week>
|
2020-07-26 18:54:09 +00:00
|
|
|
{
|
2022-10-07 10:46:45 +00:00
|
|
|
static inline NO_SANITIZE_UNDEFINED ExtendedDayNum execute(UInt16 d, UInt64 delta, const DateLUTImpl &)
|
|
|
|
{
|
|
|
|
return ExtendedDayNum(static_cast<Int32>(d + delta * 7));
|
|
|
|
}
|
2020-07-26 18:54:09 +00:00
|
|
|
};
|
|
|
|
|
2020-01-14 03:08:54 +00:00
|
|
|
#define ADD_TIME(INTERVAL_KIND, INTERVAL) \
|
|
|
|
template <> \
|
|
|
|
struct AddTime<IntervalKind::INTERVAL_KIND> \
|
|
|
|
{ \
|
2022-10-07 10:46:45 +00:00
|
|
|
static inline NO_SANITIZE_UNDEFINED UInt32 execute(UInt32 t, Int64 delta, const DateLUTImpl &) \
|
|
|
|
{ return static_cast<UInt32>(t + delta * INTERVAL); } \
|
2020-01-14 03:08:54 +00:00
|
|
|
};
|
2020-07-26 18:54:09 +00:00
|
|
|
ADD_TIME(Day, 86400)
|
2020-01-14 03:08:54 +00:00
|
|
|
ADD_TIME(Hour, 3600)
|
|
|
|
ADD_TIME(Minute, 60)
|
|
|
|
ADD_TIME(Second, 1)
|
|
|
|
#undef ADD_TIME
|
|
|
|
|
2022-02-13 14:54:03 +00:00
|
|
|
#define ADD_SUBSECONDS(INTERVAL_KIND, DEF_SCALE) \
|
|
|
|
template <> \
|
|
|
|
struct AddTime<IntervalKind::INTERVAL_KIND> \
|
|
|
|
{ \
|
|
|
|
static inline NO_SANITIZE_UNDEFINED Int64 execute(Int64 t, UInt64 delta, const UInt32 scale) \
|
|
|
|
{ \
|
|
|
|
if (scale < DEF_SCALE) \
|
|
|
|
{ \
|
|
|
|
return t + delta * DecimalUtils::scaleMultiplier<DateTime64>(DEF_SCALE - scale); \
|
|
|
|
} \
|
|
|
|
else \
|
|
|
|
return t + delta * DecimalUtils::scaleMultiplier<DateTime64>(scale - DEF_SCALE); \
|
|
|
|
} \
|
|
|
|
};
|
|
|
|
ADD_SUBSECONDS(Millisecond, 3)
|
|
|
|
ADD_SUBSECONDS(Microsecond, 6)
|
|
|
|
ADD_SUBSECONDS(Nanosecond, 9)
|
|
|
|
#undef ADD_SUBSECONDS
|
|
|
|
|
2021-12-10 09:59:50 +00:00
|
|
|
template <TimeWindowFunctionName type>
|
2021-12-10 09:43:44 +00:00
|
|
|
struct TimeWindowImpl
|
2021-05-29 10:29:38 +00:00
|
|
|
{
|
2021-06-01 03:01:35 +00:00
|
|
|
static constexpr auto name = "UNKNOWN";
|
2021-05-29 10:29:38 +00:00
|
|
|
|
2021-06-01 03:01:35 +00:00
|
|
|
static DataTypePtr getReturnType(const ColumnsWithTypeAndName & arguments, const String & function_name);
|
2021-05-29 10:29:38 +00:00
|
|
|
|
2021-06-01 03:01:35 +00:00
|
|
|
static ColumnPtr dispatchForColumns(const ColumnsWithTypeAndName & arguments, const String & function_name);
|
2020-01-14 03:08:54 +00:00
|
|
|
};
|
|
|
|
|
2021-12-10 09:59:50 +00:00
|
|
|
template <TimeWindowFunctionName type>
|
2021-12-10 09:43:44 +00:00
|
|
|
class FunctionTimeWindow : public IFunction
|
2020-01-14 03:08:54 +00:00
|
|
|
{
|
|
|
|
public:
|
2021-12-10 09:43:44 +00:00
|
|
|
static constexpr auto name = TimeWindowImpl<type>::name;
|
|
|
|
static FunctionPtr create(ContextPtr) { return std::make_shared<FunctionTimeWindow>(); }
|
2020-01-14 03:08:54 +00:00
|
|
|
String getName() const override { return name; }
|
2020-02-02 03:54:54 +00:00
|
|
|
bool isVariadic() const override { return true; }
|
|
|
|
size_t getNumberOfArguments() const override { return 0; }
|
2020-01-14 03:08:54 +00:00
|
|
|
bool useDefaultImplementationForConstants() const override { return true; }
|
2020-02-02 03:54:54 +00:00
|
|
|
ColumnNumbers getArgumentsThatAreAlwaysConstant() const override { return {1, 2, 3}; }
|
2021-11-19 13:09:12 +00:00
|
|
|
bool isSuitableForShortCircuitArgumentsExecution(const DataTypesWithConstInfo &) const override { return true; }
|
2020-01-14 03:08:54 +00:00
|
|
|
|
2021-06-01 03:01:35 +00:00
|
|
|
DataTypePtr getReturnTypeImpl(const ColumnsWithTypeAndName & arguments) const override;
|
2020-01-14 03:08:54 +00:00
|
|
|
|
2021-06-01 03:01:35 +00:00
|
|
|
ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr & /*result_type*/, size_t /*input_rows_count*/) const override;
|
2020-01-14 03:08:54 +00:00
|
|
|
};
|
|
|
|
|
2021-12-10 09:43:44 +00:00
|
|
|
using FunctionTumble = FunctionTimeWindow<TUMBLE>;
|
|
|
|
using FunctionTumbleStart = FunctionTimeWindow<TUMBLE_START>;
|
|
|
|
using FunctionTumbleEnd = FunctionTimeWindow<TUMBLE_END>;
|
|
|
|
using FunctionHop = FunctionTimeWindow<HOP>;
|
|
|
|
using FunctionWindowId = FunctionTimeWindow<WINDOW_ID>;
|
|
|
|
using FunctionHopStart = FunctionTimeWindow<HOP_START>;
|
|
|
|
using FunctionHopEnd = FunctionTimeWindow<HOP_END>;
|
2020-01-14 03:08:54 +00:00
|
|
|
}
|