From 0652f9da9685041732d44d120da286a1a58c8ae4 Mon Sep 17 00:00:00 2001 From: Alexey Milovidov Date: Fri, 31 Aug 2012 20:38:05 +0000 Subject: [PATCH] dbms: development [#CONV-2944]. --- dbms/include/DB/Functions/FunctionsDateTime.h | 87 ++++++++++++++++--- dbms/include/DB/IO/WriteHelpers.h | 4 +- dbms/src/Functions/FunctionsLibrary.cpp | 4 + dbms/src/Storages/StorageMergeTree.cpp | 18 ++-- libs/libmysqlxx/include/mysqlxx/DateTime.h | 4 +- 5 files changed, 92 insertions(+), 25 deletions(-) diff --git a/dbms/include/DB/Functions/FunctionsDateTime.h b/dbms/include/DB/Functions/FunctionsDateTime.h index d0953507c82..dcb0b7f34dd 100644 --- a/dbms/include/DB/Functions/FunctionsDateTime.h +++ b/dbms/include/DB/Functions/FunctionsDateTime.h @@ -13,17 +13,18 @@ namespace DB /** Функции работы с датой и временем. * * toYear, toMonth, toDayOfMonth, toDayOfWeek, toHour, toMinute, toSecond, - * toMonday, toStartOfMonth, + * toMonday, toStartOfMonth, toStartOfYear, toStartOfMinute, toStartOfHour * toTime, - * TODO: makeDate, makeDateTime, now, toStartOfMinute, toStartOfHour, toStartOfYear + * now + * TODO: makeDate, makeDateTime * * (toDate - расположена в файле FunctionsConversion.h) * * Возвращаемые типы: * toYear -> UInt16 * toMonth, toDayOfMonth, toDayOfWeek, toHour, toMinute, toSecond -> UInt8 - * toMonday, toStartOfMonth -> Date - * toTime -> DateTime + * toMonday, toStartOfMonth, toStartOfYear -> Date + * toStartOfMinute, toStartOfHour, toTime, now -> DateTime */ struct ToYearImpl @@ -61,7 +62,7 @@ struct ToHourImpl struct ToMinuteImpl { - static inline UInt8 execute(UInt32 t, Yandex::DateLUTSingleton & date_lut) { return date_lut.toMinute(t); } + static inline UInt8 execute(UInt32 t, Yandex::DateLUTSingleton & date_lut) { return date_lut.toMinuteInaccurate(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); @@ -70,7 +71,7 @@ struct ToMinuteImpl struct ToSecondImpl { - static inline UInt8 execute(UInt32 t, Yandex::DateLUTSingleton & date_lut) { return date_lut.toSecond(t); } + static inline UInt8 execute(UInt32 t, Yandex::DateLUTSingleton & date_lut) { return date_lut.toSecondInaccurate(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); @@ -79,16 +80,23 @@ struct ToSecondImpl 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)); } + static inline UInt16 execute(UInt32 t, Yandex::DateLUTSingleton & date_lut) { return date_lut.toFirstDayNumOfWeek(date_lut.toDayNum(t)); } + static inline UInt16 execute(UInt16 d, Yandex::DateLUTSingleton & date_lut) { return date_lut.toFirstDayNumOfWeek(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)); } + static inline UInt16 execute(UInt32 t, Yandex::DateLUTSingleton & date_lut) { return date_lut.toFirstDayNumOfMonth(date_lut.toDayNum(t)); } + static inline UInt16 execute(UInt16 d, Yandex::DateLUTSingleton & date_lut) { return date_lut.toFirstDayNumOfMonth(Yandex::DayNum_t(d)); } }; +struct ToStartOfYearImpl +{ + static inline UInt16 execute(UInt32 t, Yandex::DateLUTSingleton & date_lut) { return date_lut.toFirstDayNumOfYear(date_lut.toDayNum(t)); } + static inline UInt16 execute(UInt16 d, Yandex::DateLUTSingleton & date_lut) { return date_lut.toFirstDayNumOfYear(Yandex::DayNum_t(d)); } +}; + + struct ToTimeImpl { /// При переводе во время, дату будем приравнивать к 1970-01-02. @@ -99,6 +107,24 @@ struct ToTimeImpl } }; +struct ToStartOfMinuteImpl +{ + static inline UInt32 execute(UInt32 t, Yandex::DateLUTSingleton & date_lut) { return date_lut.toStartOfMinute(t); } + static inline UInt32 execute(UInt16 d, Yandex::DateLUTSingleton & date_lut) + { + throw Exception("Illegal type Date of argument for function toStartOfMinute", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); + } +}; + +struct ToStartOfHourImpl +{ + static inline UInt32 execute(UInt32 t, Yandex::DateLUTSingleton & date_lut) { return date_lut.toStartOfHour(t); } + static inline UInt32 execute(UInt16 d, Yandex::DateLUTSingleton & date_lut) + { + throw Exception("Illegal type Date of argument for function toStartOfHour", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); + } +}; + template struct DateTimeTransformImpl @@ -169,6 +195,37 @@ public: }; +/// Получить текущее время. (Оно - константа, вычисляется один раз за весь запрос.) +class FunctionNow : public IFunction +{ +public: + /// Получить имя функции. + String getName() const + { + return "now"; + } + + /// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение. + DataTypePtr getReturnType(const DataTypes & arguments) const + { + if (arguments.size() != 0) + throw Exception("Number of arguments for function " + getName() + " doesn't match: passed " + + Poco::NumberFormatter::format(arguments.size()) + ", should be 0.", + ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH); + + return new DataTypeDateTime; + } + + /// Выполнить функцию над блоком. + void execute(Block & block, const ColumnNumbers & arguments, size_t result) + { + block.getByPosition(result).column = new ColumnConstUInt32( + block.getByPosition(0).column->size(), + time(0)); + } +}; + + struct NameToYear { static const char * get() { return "toYear"; } }; struct NameToMonth { static const char * get() { return "toMonth"; } }; struct NameToDayOfMonth { static const char * get() { return "toDayOfMonth"; } }; @@ -178,6 +235,9 @@ 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 NameToStartOfYear { static const char * get() { return "toStartOfYear"; } }; +struct NameToStartOfMinute { static const char * get() { return "toStartOfMinute"; } }; +struct NameToStartOfHour { static const char * get() { return "toStartOfHour"; } }; struct NameToTime { static const char * get() { return "toTime"; } }; typedef FunctionDateOrDateTimeToSomething FunctionToYear; @@ -187,8 +247,11 @@ typedef FunctionDateOrDateTimeToSomething FunctionToHour; typedef FunctionDateOrDateTimeToSomething FunctionToMinute; typedef FunctionDateOrDateTimeToSomething FunctionToSecond; -typedef FunctionDateOrDateTimeToSomething FunctionToMonday; -typedef FunctionDateOrDateTimeToSomething FunctionToStartOfMonth; +typedef FunctionDateOrDateTimeToSomething FunctionToMonday; +typedef FunctionDateOrDateTimeToSomething FunctionToStartOfMonth; +typedef FunctionDateOrDateTimeToSomething FunctionToStartOfYear; +typedef FunctionDateOrDateTimeToSomething FunctionToStartOfMinute; +typedef FunctionDateOrDateTimeToSomething FunctionToStartOfHour; typedef FunctionDateOrDateTimeToSomething FunctionToTime; } diff --git a/dbms/include/DB/IO/WriteHelpers.h b/dbms/include/DB/IO/WriteHelpers.h index 0f82700ab0b..ff146cdcfce 100644 --- a/dbms/include/DB/IO/WriteHelpers.h +++ b/dbms/include/DB/IO/WriteHelpers.h @@ -309,8 +309,8 @@ inline void writeDateTimeText(time_t datetime, WriteBuffer & buf) s[9] += values.day_of_month % 10; UInt8 hour = date_lut.toHourInaccurate(datetime); - UInt8 minute = date_lut.toMinute(datetime); - UInt8 second = date_lut.toSecond(datetime); + UInt8 minute = date_lut.toMinuteInaccurate(datetime); + UInt8 second = date_lut.toSecondInaccurate(datetime); s[11] += hour / 10; s[12] += hour % 10; diff --git a/dbms/src/Functions/FunctionsLibrary.cpp b/dbms/src/Functions/FunctionsLibrary.cpp index ea448388470..5673cef4702 100644 --- a/dbms/src/Functions/FunctionsLibrary.cpp +++ b/dbms/src/Functions/FunctionsLibrary.cpp @@ -83,7 +83,11 @@ namespace FunctionsLibrary ("toSecond", new FunctionToSecond) ("toMonday", new FunctionToMonday) ("toStartOfMonth", new FunctionToStartOfMonth) + ("toStartOfYear", new FunctionToStartOfYear) + ("toStartOfMinute", new FunctionToStartOfMinute) + ("toStartOfHour", new FunctionToStartOfHour) ("toTime", new FunctionToTime) + ("now", new FunctionNow) ("position", new FunctionPosition) ("positionUTF8", new FunctionPositionUTF8) diff --git a/dbms/src/Storages/StorageMergeTree.cpp b/dbms/src/Storages/StorageMergeTree.cpp index 14857ee6f53..67fb347c6e8 100644 --- a/dbms/src/Storages/StorageMergeTree.cpp +++ b/dbms/src/Storages/StorageMergeTree.cpp @@ -80,8 +80,8 @@ public: typedef std::map BlocksByMonth; BlocksByMonth blocks_by_month; - UInt16 min_month = date_lut.toFirstDayOfMonth(Yandex::DayNum_t(min_date)); - UInt16 max_month = date_lut.toFirstDayOfMonth(Yandex::DayNum_t(max_date)); + UInt16 min_month = date_lut.toFirstDayNumOfMonth(Yandex::DayNum_t(min_date)); + UInt16 max_month = date_lut.toFirstDayNumOfMonth(Yandex::DayNum_t(max_date)); /// Типичный случай - когда месяц один (ничего разделять не нужно). if (min_month == max_month) @@ -90,7 +90,7 @@ public: { for (size_t i = 0; i < rows; ++i) { - UInt16 month = date_lut.toFirstDayOfMonth(Yandex::DayNum_t(dates[i])); + UInt16 month = date_lut.toFirstDayNumOfMonth(Yandex::DayNum_t(dates[i])); BlockWithDateInterval & block_for_month = blocks_by_month[month]; if (!block_for_month.block) @@ -210,8 +210,8 @@ private: new_data_part->name = part_name; new_data_part->size = rows / storage.index_granularity; new_data_part->modification_time = time(0); - new_data_part->left_month = date_lut.toFirstDayOfMonth(new_data_part->left_date); - new_data_part->right_month = date_lut.toFirstDayOfMonth(new_data_part->right_date); + new_data_part->left_month = date_lut.toFirstDayNumOfMonth(new_data_part->left_date); + new_data_part->right_month = date_lut.toFirstDayNumOfMonth(new_data_part->right_date); storage.data_parts.insert(new_data_part); storage.all_data_parts.insert(new_data_part); @@ -1094,8 +1094,8 @@ void StorageMergeTree::loadDataParts() part->modification_time = it->getLastModified().epochTime(); - part->left_month = date_lut.toFirstDayOfMonth(part->left_date); - part->right_month = date_lut.toFirstDayOfMonth(part->right_date); + part->left_month = date_lut.toFirstDayNumOfMonth(part->left_date); + part->right_month = date_lut.toFirstDayNumOfMonth(part->right_date); data_parts.insert(part); } @@ -1367,8 +1367,8 @@ void StorageMergeTree::mergeParts(DataPartPtr left, DataPartPtr right) new_data_part->name = getPartName( new_data_part->left_date, new_data_part->right_date, new_data_part->left, new_data_part->right, new_data_part->level); new_data_part->size = left->size + right->size; - new_data_part->left_month = date_lut.toFirstDayOfMonth(new_data_part->left_date); - new_data_part->right_month = date_lut.toFirstDayOfMonth(new_data_part->right_date); + new_data_part->left_month = date_lut.toFirstDayNumOfMonth(new_data_part->left_date); + new_data_part->right_month = date_lut.toFirstDayNumOfMonth(new_data_part->right_date); /** Читаем из левого и правого куска, сливаем и пишем в новый. * Попутно вычисляем выражение для сортировки. diff --git a/libs/libmysqlxx/include/mysqlxx/DateTime.h b/libs/libmysqlxx/include/mysqlxx/DateTime.h index 61d56bf4247..9d8bc027508 100644 --- a/libs/libmysqlxx/include/mysqlxx/DateTime.h +++ b/libs/libmysqlxx/include/mysqlxx/DateTime.h @@ -50,8 +50,8 @@ private: m_month = values.month; m_day = values.day_of_month; m_hour = date_lut.toHourInaccurate(time); - m_minute = date_lut.toMinute(time); - m_second = date_lut.toSecond(time); + m_minute = date_lut.toMinuteInaccurate(time); + m_second = date_lut.toSecondInaccurate(time); } void init(const char * s, size_t length)