dbms: development [#CONV-2944].

This commit is contained in:
Alexey Milovidov 2012-08-31 20:38:05 +00:00
parent ec8c0b21fd
commit 0652f9da96
5 changed files with 92 additions and 25 deletions

View File

@ -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 <typename FromType, typename ToType, typename Transform, typename Name>
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<DataTypeUInt16, ToYearImpl, NameToYear> FunctionToYear;
@ -187,8 +247,11 @@ typedef FunctionDateOrDateTimeToSomething<DataTypeUInt8, ToDayOfWeekImpl, NameT
typedef FunctionDateOrDateTimeToSomething<DataTypeUInt8, ToHourImpl, NameToHour> FunctionToHour;
typedef FunctionDateOrDateTimeToSomething<DataTypeUInt8, ToMinuteImpl, NameToMinute> FunctionToMinute;
typedef FunctionDateOrDateTimeToSomething<DataTypeUInt8, ToSecondImpl, NameToSecond> FunctionToSecond;
typedef FunctionDateOrDateTimeToSomething<DataTypeDateTime, ToMondayImpl, NameToMonday> FunctionToMonday;
typedef FunctionDateOrDateTimeToSomething<DataTypeDateTime, ToStartOfMonthImpl, NameToStartOfMonth> FunctionToStartOfMonth;
typedef FunctionDateOrDateTimeToSomething<DataTypeDate, ToMondayImpl, NameToMonday> FunctionToMonday;
typedef FunctionDateOrDateTimeToSomething<DataTypeDate, ToStartOfMonthImpl, NameToStartOfMonth> FunctionToStartOfMonth;
typedef FunctionDateOrDateTimeToSomething<DataTypeDate, ToStartOfYearImpl, NameToStartOfYear> FunctionToStartOfYear;
typedef FunctionDateOrDateTimeToSomething<DataTypeDateTime, ToStartOfMinuteImpl, NameToStartOfMinute> FunctionToStartOfMinute;
typedef FunctionDateOrDateTimeToSomething<DataTypeDateTime, ToStartOfHourImpl, NameToStartOfHour> FunctionToStartOfHour;
typedef FunctionDateOrDateTimeToSomething<DataTypeDateTime, ToTimeImpl, NameToTime> FunctionToTime;
}

View File

@ -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;

View File

@ -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)

View File

@ -80,8 +80,8 @@ public:
typedef std::map<UInt16, BlockWithDateInterval> 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);
/** Читаем из левого и правого куска, сливаем и пишем в новый.
* Попутно вычисляем выражение для сортировки.

View File

@ -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)