2019-06-09 15:19:15 +00:00
|
|
|
#pragma once
|
2021-05-02 19:04:26 +00:00
|
|
|
|
2019-06-09 15:19:15 +00:00
|
|
|
#include <Columns/ColumnVector.h>
|
|
|
|
#include <Columns/ColumnsNumber.h>
|
2021-10-02 07:13:14 +00:00
|
|
|
#include <base/types.h>
|
2019-10-23 12:27:36 +00:00
|
|
|
#include <Core/DecimalFunctions.h>
|
2021-05-24 13:53:14 +00:00
|
|
|
#include <Functions/DateTimeTransforms.h>
|
2019-06-09 15:19:15 +00:00
|
|
|
#include <Functions/FunctionHelpers.h>
|
|
|
|
#include <Functions/extractTimeZoneFromFunctionArguments.h>
|
2021-05-17 07:30:42 +00:00
|
|
|
#include <Functions/IFunction.h>
|
2019-06-09 15:19:15 +00:00
|
|
|
#include <Common/Exception.h>
|
2021-12-21 13:41:53 +00:00
|
|
|
#include <Common/DateLUTImpl.h>
|
2019-06-09 15:19:15 +00:00
|
|
|
|
|
|
|
/// The default mode value to use for the WEEK() function
|
|
|
|
#define DEFAULT_WEEK_MODE 0
|
|
|
|
|
2021-05-02 19:04:26 +00:00
|
|
|
|
2019-06-09 15:19:15 +00:00
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
namespace ErrorCodes
|
|
|
|
{
|
|
|
|
extern const int ILLEGAL_COLUMN;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* CustomWeek Transformations.
|
|
|
|
*/
|
|
|
|
|
2019-06-18 09:48:07 +00:00
|
|
|
struct ToYearWeekImpl
|
2019-06-09 15:19:15 +00:00
|
|
|
{
|
2019-06-18 09:48:07 +00:00
|
|
|
static constexpr auto name = "toYearWeek";
|
2019-06-09 15:19:15 +00:00
|
|
|
|
2020-04-17 13:26:44 +00:00
|
|
|
static inline UInt32 execute(Int64 t, UInt8 week_mode, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
// TODO: ditch toDayNum()
|
|
|
|
YearWeek yw = time_zone.toYearWeek(time_zone.toDayNum(t), week_mode | static_cast<UInt32>(WeekModeFlag::YEAR));
|
|
|
|
return yw.first * 100 + yw.second;
|
|
|
|
}
|
|
|
|
|
2019-06-09 15:19:15 +00:00
|
|
|
static inline UInt32 execute(UInt32 t, UInt8 week_mode, const DateLUTImpl & time_zone)
|
|
|
|
{
|
2019-06-18 09:48:07 +00:00
|
|
|
YearWeek yw = time_zone.toYearWeek(time_zone.toDayNum(t), week_mode | static_cast<UInt32>(WeekModeFlag::YEAR));
|
|
|
|
return yw.first * 100 + yw.second;
|
2019-06-09 15:19:15 +00:00
|
|
|
}
|
2021-07-15 11:41:52 +00:00
|
|
|
static inline UInt32 execute(Int32 d, UInt8 week_mode, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
YearWeek yw = time_zone.toYearWeek(ExtendedDayNum (d), week_mode | static_cast<UInt32>(WeekModeFlag::YEAR));
|
|
|
|
return yw.first * 100 + yw.second;
|
|
|
|
}
|
2019-06-09 15:19:15 +00:00
|
|
|
static inline UInt32 execute(UInt16 d, UInt8 week_mode, const DateLUTImpl & time_zone)
|
|
|
|
{
|
2019-06-18 09:48:07 +00:00
|
|
|
YearWeek yw = time_zone.toYearWeek(DayNum(d), week_mode | static_cast<UInt32>(WeekModeFlag::YEAR));
|
|
|
|
return yw.first * 100 + yw.second;
|
|
|
|
}
|
|
|
|
|
|
|
|
using FactorTransform = ZeroTransform;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct ToStartOfWeekImpl
|
|
|
|
{
|
|
|
|
static constexpr auto name = "toStartOfWeek";
|
|
|
|
|
2022-09-09 13:45:51 +00:00
|
|
|
static inline UInt16 execute(Int64 t, UInt8 week_mode, const DateLUTImpl & time_zone)
|
2020-04-17 13:26:44 +00:00
|
|
|
{
|
2022-08-23 14:13:39 +00:00
|
|
|
if (t < 0)
|
|
|
|
return 0;
|
|
|
|
|
2022-08-25 09:28:15 +00:00
|
|
|
return time_zone.toFirstDayNumOfWeek(DayNum(std::min(Int32(time_zone.toDayNum(t)), Int32(DATE_LUT_MAX_DAY_NUM))), week_mode);
|
2020-04-17 13:26:44 +00:00
|
|
|
}
|
2019-06-18 09:48:07 +00:00
|
|
|
static inline UInt16 execute(UInt32 t, UInt8 week_mode, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
return time_zone.toFirstDayNumOfWeek(time_zone.toDayNum(t), week_mode);
|
|
|
|
}
|
2022-09-09 13:45:51 +00:00
|
|
|
static inline UInt16 execute(Int32 d, UInt8 week_mode, const DateLUTImpl & time_zone)
|
2021-07-15 11:41:52 +00:00
|
|
|
{
|
2022-08-23 14:13:39 +00:00
|
|
|
if (d < 0)
|
|
|
|
return 0;
|
|
|
|
|
2022-08-25 09:28:15 +00:00
|
|
|
return time_zone.toFirstDayNumOfWeek(DayNum(std::min(d, Int32(DATE_LUT_MAX_DAY_NUM))), week_mode);
|
2021-07-15 11:41:52 +00:00
|
|
|
}
|
2019-06-18 09:48:07 +00:00
|
|
|
static inline UInt16 execute(UInt16 d, UInt8 week_mode, const DateLUTImpl & time_zone)
|
|
|
|
{
|
2021-11-08 07:19:31 +00:00
|
|
|
return time_zone.toFirstDayNumOfWeek(DayNum(d), week_mode);
|
2019-06-09 15:19:15 +00:00
|
|
|
}
|
2022-09-09 13:45:51 +00:00
|
|
|
static inline Int64 execute_compat(Int64 t, UInt8 week_mode, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
return time_zone.toFirstDayNumOfWeek(time_zone.toDayNum(t), week_mode);
|
|
|
|
}
|
|
|
|
static inline Int32 execute_compat(Int32 d, UInt8 week_mode, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
return time_zone.toFirstDayNumOfWeek(ExtendedDayNum(d), week_mode);
|
|
|
|
}
|
2019-06-09 15:19:15 +00:00
|
|
|
|
|
|
|
using FactorTransform = ZeroTransform;
|
|
|
|
};
|
|
|
|
|
2021-05-24 13:53:14 +00:00
|
|
|
struct ToWeekImpl
|
|
|
|
{
|
|
|
|
static constexpr auto name = "toWeek";
|
|
|
|
|
|
|
|
static inline UInt8 execute(Int64 t, UInt8 week_mode, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
// TODO: ditch conversion to DayNum, since it doesn't support extended range.
|
|
|
|
YearWeek yw = time_zone.toYearWeek(time_zone.toDayNum(t), week_mode);
|
|
|
|
return yw.second;
|
|
|
|
}
|
|
|
|
static inline UInt8 execute(UInt32 t, UInt8 week_mode, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
YearWeek yw = time_zone.toYearWeek(time_zone.toDayNum(t), week_mode);
|
|
|
|
return yw.second;
|
|
|
|
}
|
2021-07-15 11:41:52 +00:00
|
|
|
static inline UInt8 execute(Int32 d, UInt8 week_mode, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
YearWeek yw = time_zone.toYearWeek(ExtendedDayNum(d), week_mode);
|
|
|
|
return yw.second;
|
|
|
|
}
|
2021-05-24 13:53:14 +00:00
|
|
|
static inline UInt8 execute(UInt16 d, UInt8 week_mode, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
YearWeek yw = time_zone.toYearWeek(DayNum(d), week_mode);
|
|
|
|
return yw.second;
|
|
|
|
}
|
|
|
|
|
|
|
|
using FactorTransform = ToStartOfYearImpl;
|
|
|
|
};
|
|
|
|
|
2022-09-09 13:45:51 +00:00
|
|
|
template <typename FromType, typename ToType, typename Transform, bool is_compat = false>
|
2021-05-24 13:53:14 +00:00
|
|
|
struct WeekTransformer
|
2019-06-09 15:19:15 +00:00
|
|
|
{
|
2021-05-24 13:53:14 +00:00
|
|
|
explicit WeekTransformer(Transform transform_)
|
2019-10-23 12:27:36 +00:00
|
|
|
: transform(std::move(transform_))
|
|
|
|
{}
|
|
|
|
|
|
|
|
template <typename FromVectorType, typename ToVectorType>
|
|
|
|
void
|
|
|
|
vector(const FromVectorType & vec_from, ToVectorType & vec_to, UInt8 week_mode, const DateLUTImpl & time_zone) const
|
2019-06-09 15:19:15 +00:00
|
|
|
{
|
|
|
|
size_t size = vec_from.size();
|
|
|
|
vec_to.resize(size);
|
|
|
|
|
|
|
|
for (size_t i = 0; i < size; ++i)
|
2022-09-09 13:45:51 +00:00
|
|
|
if constexpr (is_compat)
|
|
|
|
vec_to[i] = transform.execute_compat(vec_from[i], week_mode, time_zone);
|
|
|
|
else
|
|
|
|
vec_to[i] = transform.execute(vec_from[i], week_mode, time_zone);
|
2019-06-09 15:19:15 +00:00
|
|
|
}
|
2019-10-23 12:27:36 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
const Transform transform;
|
2019-06-09 15:19:15 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2022-09-09 13:45:51 +00:00
|
|
|
template <typename FromDataType, typename ToDataType, bool is_compat = false>
|
2019-06-09 15:19:15 +00:00
|
|
|
struct CustomWeekTransformImpl
|
|
|
|
{
|
2019-10-23 12:27:36 +00:00
|
|
|
template <typename Transform>
|
2020-11-17 13:24:45 +00:00
|
|
|
static ColumnPtr execute(const ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t /*input_rows_count*/, Transform transform = {})
|
2019-06-09 15:19:15 +00:00
|
|
|
{
|
2022-09-09 13:45:51 +00:00
|
|
|
const auto op = WeekTransformer<typename FromDataType::FieldType, typename ToDataType::FieldType, Transform, is_compat>{std::move(transform)};
|
2019-06-09 15:19:15 +00:00
|
|
|
|
|
|
|
UInt8 week_mode = DEFAULT_WEEK_MODE;
|
|
|
|
if (arguments.size() > 1)
|
|
|
|
{
|
2020-10-17 16:48:53 +00:00
|
|
|
if (const auto * week_mode_column = checkAndGetColumnConst<ColumnUInt8>(arguments[1].column.get()))
|
2019-06-09 15:19:15 +00:00
|
|
|
week_mode = week_mode_column->getValue<UInt8>();
|
|
|
|
}
|
|
|
|
|
2020-10-17 16:48:53 +00:00
|
|
|
const DateLUTImpl & time_zone = extractTimeZoneFromFunctionArguments(arguments, 2, 0);
|
|
|
|
const ColumnPtr source_col = arguments[0].column;
|
2019-10-23 12:27:36 +00:00
|
|
|
if (const auto * sources = checkAndGetColumn<typename FromDataType::ColumnType>(source_col.get()))
|
2019-06-09 15:19:15 +00:00
|
|
|
{
|
2019-10-23 12:27:36 +00:00
|
|
|
auto col_to = ToDataType::ColumnType::create();
|
|
|
|
op.vector(sources->getData(), col_to->getData(), week_mode, time_zone);
|
2020-10-17 16:48:53 +00:00
|
|
|
return col_to;
|
2019-06-09 15:19:15 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
throw Exception(
|
2020-10-17 16:48:53 +00:00
|
|
|
"Illegal column " + arguments[0].column->getName() + " of first argument of function "
|
2019-06-09 15:19:15 +00:00
|
|
|
+ Transform::name,
|
|
|
|
ErrorCodes::ILLEGAL_COLUMN);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|