#pragma once #include #include #include #include #include namespace DB { /** Функции работы с датой и временем. * * toYear, toMonth, toDayOfMonth, toDayOfWeek, toHour, toMinute, toSecond, * toMonday, toStartOfMonth, * toTime, * TODO: makeDate, makeDateTime * * (toDate - расположена в файле FunctionsConversion.h) * * Возвращаемые типы: * toYear -> UInt16 * toMonth, toDayOfMonth, toDayOfWeek, toHour, toMinute, toSecond -> UInt8 * toMonday, toStartOfMonth -> Date * toTime -> DateTime */ struct ToYearImpl { static inline UInt16 execute(UInt32 t, Yandex::DateLUTSingleton & date_lut) { return date_lut.toYear(t); } static inline UInt16 execute(UInt16 d, Yandex::DateLUTSingleton & date_lut) { return date_lut.toYear(Yandex::DayNum_t(d)); } }; struct ToMonthImpl { static inline UInt8 execute(UInt32 t, Yandex::DateLUTSingleton & date_lut) { return date_lut.toMonth(t); } static inline UInt8 execute(UInt16 d, Yandex::DateLUTSingleton & date_lut) { return date_lut.toMonth(Yandex::DayNum_t(d)); } }; struct ToDayOfMonthImpl { static inline UInt8 execute(UInt32 t, Yandex::DateLUTSingleton & date_lut) { return date_lut.toDayOfMonth(t); } static inline UInt8 execute(UInt16 d, Yandex::DateLUTSingleton & date_lut) { return date_lut.toDayOfMonth(Yandex::DayNum_t(d)); } }; struct ToDayOfWeekImpl { static inline UInt8 execute(UInt32 t, Yandex::DateLUTSingleton & date_lut) { return date_lut.toDayOfWeek(t); } static inline UInt8 execute(UInt16 d, Yandex::DateLUTSingleton & date_lut) { return date_lut.toDayOfWeek(Yandex::DayNum_t(d)); } }; struct ToHourImpl { static inline UInt8 execute(UInt32 t, Yandex::DateLUTSingleton & date_lut) { return date_lut.toHourInaccurate(t); } static inline UInt8 execute(UInt16 d, Yandex::DateLUTSingleton & date_lut) { throw Exception("Illegal type Date of argument for function toHour", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); } }; struct ToMinuteImpl { static inline UInt8 execute(UInt32 t, Yandex::DateLUTSingleton & date_lut) { return date_lut.toMinute(t); } static inline UInt8 execute(UInt16 d, Yandex::DateLUTSingleton & date_lut) { throw Exception("Illegal type Date of argument for function toMinute", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); } }; struct ToSecondImpl { static inline UInt8 execute(UInt32 t, Yandex::DateLUTSingleton & date_lut) { return date_lut.toSecond(t); } static inline UInt8 execute(UInt16 d, Yandex::DateLUTSingleton & date_lut) { throw Exception("Illegal type Date of argument for function toSecond", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); } }; struct ToMondayImpl { static inline UInt32 execute(UInt32 t, Yandex::DateLUTSingleton & date_lut) { return date_lut.toWeek(t); } static inline UInt32 execute(UInt16 d, Yandex::DateLUTSingleton & date_lut) { return date_lut.toWeek(Yandex::DayNum_t(d)); } }; struct ToStartOfMonthImpl { static inline UInt32 execute(UInt32 t, Yandex::DateLUTSingleton & date_lut) { return date_lut.toFirstDayOfMonth(t); } static inline UInt32 execute(UInt16 d, Yandex::DateLUTSingleton & date_lut) { return date_lut.toFirstDayOfMonth(Yandex::DayNum_t(d)); } }; struct ToTimeImpl { /// При переводе во время, дату будем приравнивать к 1970-01-02. static inline UInt32 execute(UInt32 t, Yandex::DateLUTSingleton & date_lut) { return t - date_lut.toDate(t) + 75600; } static inline UInt32 execute(UInt16 d, Yandex::DateLUTSingleton & date_lut) { throw Exception("Illegal type Date of argument for function toTime", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); } }; template struct DateTimeTransformImpl { static void execute(Block & block, const ColumnNumbers & arguments, size_t result) { Yandex::DateLUTSingleton & date_lut = Yandex::DateLUTSingleton::instance(); if (const ColumnVector * col_from = dynamic_cast *>(&*block.getByPosition(arguments[0]).column)) { ColumnVector * col_to = new ColumnVector; block.getByPosition(result).column = col_to; const typename ColumnVector::Container_t & vec_from = col_from->getData(); typename ColumnVector::Container_t & vec_to = col_to->getData(); 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], date_lut); } else if (const ColumnConst * col_from = dynamic_cast *>(&*block.getByPosition(arguments[0]).column)) { block.getByPosition(result).column = new ColumnConst(col_from->size(), Transform::execute(col_from->getData(), date_lut)); } else throw Exception("Illegal column " + block.getByPosition(arguments[0]).column->getName() + " of first argument of function " + Name::get(), ErrorCodes::ILLEGAL_COLUMN); } }; template class FunctionDateOrDateTimeToSomething : public IFunction { public: /// Получить имя функции. String getName() const { return Name::get(); } /// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение. DataTypePtr getReturnType(const DataTypes & arguments) const { if (arguments.size() != 1) throw Exception("Number of arguments for function " + getName() + " doesn't match: passed " + Poco::NumberFormatter::format(arguments.size()) + ", should be 1.", ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH); return new ToDataType; } /// Выполнить функцию над блоком. void execute(Block & block, const ColumnNumbers & arguments, size_t result) { IDataType * from_type = &*block.getByPosition(arguments[0]).type; if (dynamic_cast(from_type)) DateTimeTransformImpl::execute(block, arguments, result); else if (dynamic_cast(from_type)) DateTimeTransformImpl::execute(block, arguments, result); else throw Exception("Illegal type " + block.getByPosition(arguments[0]).type->getName() + " of argument of function " + getName(), ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); } }; struct NameToYear { static const char * get() { return "toYear"; } }; struct NameToMonth { static const char * get() { return "toMonth"; } }; struct NameToDayOfMonth { static const char * get() { return "toDayOfMonth"; } }; struct NameToDayOfWeek { static const char * get() { return "toDayOfWeek"; } }; struct NameToHour { static const char * get() { return "toHour"; } }; struct NameToMinute { static const char * get() { return "toMinute"; } }; struct NameToSecond { static const char * get() { return "toSecond"; } }; struct NameToMonday { static const char * get() { return "toMonday"; } }; struct NameToStartOfMonth { static const char * get() { return "toStartOfMonth"; } }; struct NameToTime { static const char * get() { return "toTime"; } }; typedef FunctionDateOrDateTimeToSomething FunctionToYear; typedef FunctionDateOrDateTimeToSomething FunctionToMonth; typedef FunctionDateOrDateTimeToSomething FunctionToDayOfMonth; typedef FunctionDateOrDateTimeToSomething FunctionToDayOfWeek; typedef FunctionDateOrDateTimeToSomething FunctionToHour; typedef FunctionDateOrDateTimeToSomething FunctionToMinute; typedef FunctionDateOrDateTimeToSomething FunctionToSecond; typedef FunctionDateOrDateTimeToSomething FunctionToMonday; typedef FunctionDateOrDateTimeToSomething FunctionToStartOfMonth; typedef FunctionDateOrDateTimeToSomething FunctionToTime; }