#pragma once #include #include #include #include #include #include #include #include /// The default mode value to use for the WEEK() function #define DEFAULT_WEEK_MODE 0 namespace DB { namespace ErrorCodes { extern const int ILLEGAL_TYPE_OF_ARGUMENT; extern const int ILLEGAL_COLUMN; } /** * CustomWeek Transformations. */ static inline UInt32 dateIsNotSupported(const char * name) { throw Exception("Illegal type Date of argument for function " + std::string(name), ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); } /// This factor transformation will say that the function is monotone everywhere. struct ZeroTransform { static inline UInt16 execute(UInt32, UInt8, const DateLUTImpl &) { return 0; } static inline UInt16 execute(UInt16, UInt8, const DateLUTImpl &) { return 0; } }; struct ToWeekImpl { static constexpr auto name = "toWeek"; 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; } 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 = ZeroTransform; }; struct ToYearWeekImpl { static constexpr auto name = "toYearWeek"; static inline UInt32 execute(UInt32 t, UInt8 week_mode, const DateLUTImpl & time_zone) { YearWeek yw = time_zone.toYearWeek(time_zone.toDayNum(t), week_mode | static_cast(WeekModeFlag::YEAR)); return yw.first * 100 + yw.second; } static inline UInt32 execute(UInt16 d, UInt8 week_mode, const DateLUTImpl & time_zone) { YearWeek yw = time_zone.toYearWeek(DayNum(d), week_mode | static_cast(WeekModeFlag::YEAR)); return yw.first * 100 + yw.second; } using FactorTransform = ZeroTransform; }; struct ToStartOfWeekImpl { static constexpr auto name = "toStartOfWeek"; static inline UInt16 execute(UInt32 t, UInt8 week_mode, const DateLUTImpl & time_zone) { return time_zone.toFirstDayNumOfWeek(time_zone.toDayNum(t), week_mode); } static inline UInt16 execute(UInt16 d, UInt8 week_mode, const DateLUTImpl & time_zone) { return time_zone.toFirstDayNumOfWeek(DayNum(d), week_mode); } using FactorTransform = ZeroTransform; }; template struct Transformer { static void vector(const PaddedPODArray & vec_from, PaddedPODArray & vec_to, UInt8 week_mode, const DateLUTImpl & time_zone) { size_t size = vec_from.size(); vec_to.resize(size); for (size_t i = 0; i < size; ++i) vec_to[i] = Transform::execute(vec_from[i], week_mode, time_zone); } }; template struct CustomWeekTransformImpl { static void execute(Block & block, const ColumnNumbers & arguments, size_t result, size_t /*input_rows_count*/) { using Op = Transformer; UInt8 week_mode = DEFAULT_WEEK_MODE; if (arguments.size() > 1) { if (const auto week_mode_column = checkAndGetColumnConst(block.getByPosition(arguments[1]).column.get())) week_mode = week_mode_column->getValue(); } const DateLUTImpl & time_zone = extractTimeZoneFromFunctionArguments(block, arguments, 2, 0); const ColumnPtr source_col = block.getByPosition(arguments[0]).column; if (const auto * sources = checkAndGetColumn>(source_col.get())) { auto col_to = ColumnVector::create(); Op::vector(sources->getData(), col_to->getData(), week_mode, time_zone); block.getByPosition(result).column = std::move(col_to); } else { throw Exception( "Illegal column " + block.getByPosition(arguments[0]).column->getName() + " of first argument of function " + Transform::name, ErrorCodes::ILLEGAL_COLUMN); } } }; }