2011-10-16 04:17:41 +00:00
|
|
|
#pragma once
|
|
|
|
|
2017-04-01 09:19:00 +00:00
|
|
|
#include <DataTypes/DataTypesNumber.h>
|
|
|
|
#include <DataTypes/DataTypeDate.h>
|
|
|
|
#include <DataTypes/DataTypeDateTime.h>
|
|
|
|
#include <DataTypes/DataTypeArray.h>
|
|
|
|
#include <DataTypes/DataTypeString.h>
|
2012-09-03 04:45:46 +00:00
|
|
|
|
2017-04-01 09:19:00 +00:00
|
|
|
#include <Columns/ColumnsNumber.h>
|
|
|
|
#include <Columns/ColumnConst.h>
|
|
|
|
#include <Columns/ColumnArray.h>
|
|
|
|
#include <Columns/ColumnFixedString.h>
|
2012-09-03 04:45:46 +00:00
|
|
|
|
2017-07-13 20:58:19 +00:00
|
|
|
#include <Common/typeid_cast.h>
|
|
|
|
|
2017-04-01 09:19:00 +00:00
|
|
|
#include <IO/WriteHelpers.h>
|
2017-03-12 10:13:45 +00:00
|
|
|
|
2017-04-01 09:19:00 +00:00
|
|
|
#include <Functions/IFunction.h>
|
2011-10-16 04:17:41 +00:00
|
|
|
|
2017-03-12 10:13:45 +00:00
|
|
|
#include <common/DateLUT.h>
|
|
|
|
|
2015-06-30 15:03:22 +00:00
|
|
|
#include <type_traits>
|
2011-10-16 04:17:41 +00:00
|
|
|
|
2017-03-12 10:13:45 +00:00
|
|
|
|
2011-10-16 04:17:41 +00:00
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
|
2017-06-13 02:06:53 +00:00
|
|
|
namespace ErrorCodes
|
|
|
|
{
|
|
|
|
extern const int NUMBER_OF_ARGUMENTS_DOESNT_MATCH;
|
|
|
|
}
|
|
|
|
|
2017-05-27 15:45:25 +00:00
|
|
|
/** Functions for working with date and time.
|
2011-10-16 04:17:41 +00:00
|
|
|
*
|
|
|
|
* toYear, toMonth, toDayOfMonth, toDayOfWeek, toHour, toMinute, toSecond,
|
2015-06-03 14:27:03 +00:00
|
|
|
* toMonday, toStartOfMonth, toStartOfYear, toStartOfMinute, toStartOfFiveMinute
|
|
|
|
* toStartOfHour, toTime,
|
2017-06-13 02:06:53 +00:00
|
|
|
* now, today, yesterday
|
2012-08-31 20:38:05 +00:00
|
|
|
* TODO: makeDate, makeDateTime
|
2014-06-26 00:58:14 +00:00
|
|
|
*
|
2017-05-27 15:45:25 +00:00
|
|
|
* (toDate - located in FunctionConversion.h file)
|
2011-10-16 04:17:41 +00:00
|
|
|
*
|
2017-05-27 15:45:25 +00:00
|
|
|
* Return types:
|
2011-10-16 04:17:41 +00:00
|
|
|
* toYear -> UInt16
|
|
|
|
* toMonth, toDayOfMonth, toDayOfWeek, toHour, toMinute, toSecond -> UInt8
|
2012-08-31 20:38:05 +00:00
|
|
|
* toMonday, toStartOfMonth, toStartOfYear -> Date
|
|
|
|
* toStartOfMinute, toStartOfHour, toTime, now -> DateTime
|
2012-09-03 04:45:46 +00:00
|
|
|
*
|
2017-05-27 15:45:25 +00:00
|
|
|
* And also:
|
2012-09-03 04:45:46 +00:00
|
|
|
*
|
|
|
|
* timeSlot(EventTime)
|
2017-05-27 15:45:25 +00:00
|
|
|
* - rounds the time to half an hour.
|
2014-06-26 00:58:14 +00:00
|
|
|
*
|
2012-09-03 04:45:46 +00:00
|
|
|
* timeSlots(StartTime, Duration)
|
2017-05-27 15:45:25 +00:00
|
|
|
* - for the time interval beginning at `StartTime` and continuing `Duration` seconds,
|
|
|
|
* returns an array of time points, consisting of rounding down to half an hour of points from this interval.
|
|
|
|
* For example, timeSlots(toDateTime('2012-01-01 12:20:00'), 600) = [toDateTime('2012-01-01 12:00:00'), toDateTime('2012-01-01 12:30:00')].
|
|
|
|
* This is necessary to search for hits that are part of the corresponding visit.
|
2011-10-16 04:17:41 +00:00
|
|
|
*/
|
|
|
|
|
2012-09-03 04:45:46 +00:00
|
|
|
|
|
|
|
#define TIME_SLOT_SIZE 1800
|
|
|
|
|
2017-05-27 15:45:25 +00:00
|
|
|
/** Extra transformations.
|
|
|
|
* Represents two functions - from datetime (UInt32) and from date (UInt16).
|
2015-11-29 11:58:44 +00:00
|
|
|
*
|
2017-05-27 15:45:25 +00:00
|
|
|
* Also, the "factor transformation" F is defined for the T transformation.
|
|
|
|
* This is a transformation of F such that its value identifies the region of monotonicity T
|
|
|
|
* (for a fixed value of F, the transformation T is monotonic).
|
2015-11-29 11:58:44 +00:00
|
|
|
*
|
2017-05-27 15:45:25 +00:00
|
|
|
* Or, figuratively, if T is similar to taking the remainder of division, then F is similar to division.
|
2015-11-29 11:58:44 +00:00
|
|
|
*
|
2017-05-27 15:45:25 +00:00
|
|
|
* Example: to convert T "get the day number in the month" (2015-02-03 -> 3),
|
|
|
|
* factor-transformation F is "round to the nearest month" (2015-02-03 -> 2015-02-01).
|
2015-11-29 11:58:44 +00:00
|
|
|
*/
|
2012-09-03 04:45:46 +00:00
|
|
|
|
2017-05-27 15:45:25 +00:00
|
|
|
/// This factor transformation will say that the function is monotone everywhere.
|
2015-11-29 11:58:44 +00:00
|
|
|
struct ZeroTransform
|
2011-10-16 04:17:41 +00:00
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
static inline UInt16 execute(UInt32 t, const DateLUTImpl & time_zone) { return 0; }
|
|
|
|
static inline UInt16 execute(UInt16 d, const DateLUTImpl & time_zone) { return 0; }
|
2011-10-16 04:17:41 +00:00
|
|
|
};
|
|
|
|
|
2015-11-29 11:58:44 +00:00
|
|
|
struct ToDateImpl
|
2011-10-16 04:17:41 +00:00
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
static inline UInt16 execute(UInt32 t, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
return UInt16(time_zone.toDayNum(t));
|
|
|
|
}
|
|
|
|
static inline UInt16 execute(UInt16 d, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
return d;
|
|
|
|
}
|
2016-12-28 12:10:29 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
using FactorTransform = ZeroTransform;
|
2016-12-28 12:10:29 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct ToStartOfDayImpl
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
static inline UInt32 execute(UInt32 t, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
return time_zone.toDate(t);
|
|
|
|
}
|
|
|
|
static inline UInt16 execute(UInt16 d, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
return d;
|
|
|
|
}
|
2015-11-29 11:58:44 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
using FactorTransform = ZeroTransform;
|
2011-10-16 04:17:41 +00:00
|
|
|
};
|
|
|
|
|
2015-11-29 11:58:44 +00:00
|
|
|
struct ToMondayImpl
|
2011-10-16 04:17:41 +00:00
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
static inline UInt16 execute(UInt32 t, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
return time_zone.toFirstDayNumOfWeek(time_zone.toDayNum(t));
|
|
|
|
}
|
|
|
|
static inline UInt16 execute(UInt16 d, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
return time_zone.toFirstDayNumOfWeek(DayNum_t(d));
|
|
|
|
}
|
2011-10-16 04:17:41 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
using FactorTransform = ZeroTransform;
|
2011-10-16 04:17:41 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct ToStartOfMonthImpl
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
static inline UInt16 execute(UInt32 t, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
return time_zone.toFirstDayNumOfMonth(time_zone.toDayNum(t));
|
|
|
|
}
|
|
|
|
static inline UInt16 execute(UInt16 d, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
return time_zone.toFirstDayNumOfMonth(DayNum_t(d));
|
|
|
|
}
|
2015-11-29 11:58:44 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
using FactorTransform = ZeroTransform;
|
2011-10-16 04:17:41 +00:00
|
|
|
};
|
|
|
|
|
2013-12-20 14:12:20 +00:00
|
|
|
struct ToStartOfQuarterImpl
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
static inline UInt16 execute(UInt32 t, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
return time_zone.toFirstDayNumOfQuarter(time_zone.toDayNum(t));
|
|
|
|
}
|
|
|
|
static inline UInt16 execute(UInt16 d, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
return time_zone.toFirstDayNumOfQuarter(DayNum_t(d));
|
|
|
|
}
|
2015-11-29 11:58:44 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
using FactorTransform = ZeroTransform;
|
2013-12-20 14:12:20 +00:00
|
|
|
};
|
|
|
|
|
2012-08-31 20:38:05 +00:00
|
|
|
struct ToStartOfYearImpl
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
static inline UInt16 execute(UInt32 t, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
return time_zone.toFirstDayNumOfYear(time_zone.toDayNum(t));
|
|
|
|
}
|
|
|
|
static inline UInt16 execute(UInt16 d, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
return time_zone.toFirstDayNumOfYear(DayNum_t(d));
|
|
|
|
}
|
2015-11-29 11:58:44 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
using FactorTransform = ZeroTransform;
|
2012-08-31 20:38:05 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2011-10-16 04:17:41 +00:00
|
|
|
struct ToTimeImpl
|
|
|
|
{
|
2017-05-27 15:45:25 +00:00
|
|
|
/// When transforming to time, the date will be equated to 1970-01-02.
|
2017-04-01 07:20:54 +00:00
|
|
|
static inline UInt32 execute(UInt32 t, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
return time_zone.toTime(t) + 86400;
|
|
|
|
}
|
2015-07-01 14:35:02 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
static inline UInt32 execute(UInt16 d, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
throw Exception("Illegal type Date of argument for function toTime", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
|
|
|
}
|
2015-11-29 11:58:44 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
using FactorTransform = ToDateImpl;
|
2011-10-16 04:17:41 +00:00
|
|
|
};
|
|
|
|
|
2012-08-31 20:38:05 +00:00
|
|
|
struct ToStartOfMinuteImpl
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
static inline UInt32 execute(UInt32 t, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
return time_zone.toStartOfMinuteInaccurate(t);
|
|
|
|
}
|
|
|
|
static inline UInt32 execute(UInt16 d, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
throw Exception("Illegal type Date of argument for function toStartOfMinute", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
|
|
|
}
|
2015-11-29 11:58:44 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
using FactorTransform = ZeroTransform;
|
2012-08-31 20:38:05 +00:00
|
|
|
};
|
|
|
|
|
2015-06-03 14:27:03 +00:00
|
|
|
struct ToStartOfFiveMinuteImpl
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
static inline UInt32 execute(UInt32 t, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
return time_zone.toStartOfFiveMinuteInaccurate(t);
|
|
|
|
}
|
|
|
|
static inline UInt32 execute(UInt16 d, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
throw Exception("Illegal type Date of argument for function toStartOfFiveMinute", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
|
|
|
}
|
2015-11-29 11:58:44 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
using FactorTransform = ZeroTransform;
|
2015-06-03 14:27:03 +00:00
|
|
|
};
|
|
|
|
|
2012-08-31 20:38:05 +00:00
|
|
|
struct ToStartOfHourImpl
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
static inline UInt32 execute(UInt32 t, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
return time_zone.toStartOfHourInaccurate(t);
|
|
|
|
}
|
|
|
|
static inline UInt32 execute(UInt16 d, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
throw Exception("Illegal type Date of argument for function toStartOfHour", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
|
|
|
}
|
2015-11-29 11:58:44 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
using FactorTransform = ZeroTransform;
|
2015-11-29 11:58:44 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct ToYearImpl
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
static inline UInt16 execute(UInt32 t, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
return time_zone.toYear(t);
|
|
|
|
}
|
|
|
|
static inline UInt16 execute(UInt16 d, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
return time_zone.toYear(DayNum_t(d));
|
|
|
|
}
|
2015-11-29 11:58:44 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
using FactorTransform = ZeroTransform;
|
2015-11-29 11:58:44 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct ToMonthImpl
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
static inline UInt8 execute(UInt32 t, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
return time_zone.toMonth(t);
|
|
|
|
}
|
|
|
|
static inline UInt8 execute(UInt16 d, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
return time_zone.toMonth(DayNum_t(d));
|
|
|
|
}
|
2015-11-29 11:58:44 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
using FactorTransform = ToStartOfYearImpl;
|
2015-11-29 11:58:44 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct ToDayOfMonthImpl
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
static inline UInt8 execute(UInt32 t, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
return time_zone.toDayOfMonth(t);
|
|
|
|
}
|
|
|
|
static inline UInt8 execute(UInt16 d, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
return time_zone.toDayOfMonth(DayNum_t(d));
|
|
|
|
}
|
2015-11-29 11:58:44 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
using FactorTransform = ToStartOfMonthImpl;
|
2015-11-29 11:58:44 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct ToDayOfWeekImpl
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
static inline UInt8 execute(UInt32 t, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
return time_zone.toDayOfWeek(t);
|
|
|
|
}
|
|
|
|
static inline UInt8 execute(UInt16 d, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
return time_zone.toDayOfWeek(DayNum_t(d));
|
|
|
|
}
|
2015-11-29 11:58:44 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
using FactorTransform = ToMondayImpl;
|
2015-11-29 11:58:44 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct ToHourImpl
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
static inline UInt8 execute(UInt32 t, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
return time_zone.toHour(t);
|
|
|
|
}
|
|
|
|
static inline UInt8 execute(UInt16 d, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
throw Exception("Illegal type Date of argument for function toHour", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
|
|
|
}
|
2015-11-29 11:58:44 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
using FactorTransform = ToDateImpl;
|
2015-11-29 11:58:44 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct ToMinuteImpl
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
static inline UInt8 execute(UInt32 t, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
return time_zone.toMinuteInaccurate(t);
|
|
|
|
}
|
|
|
|
static inline UInt8 execute(UInt16 d, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
throw Exception("Illegal type Date of argument for function toMinute", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
|
|
|
}
|
2015-11-29 11:58:44 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
using FactorTransform = ToStartOfHourImpl;
|
2015-11-29 11:58:44 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct ToSecondImpl
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
static inline UInt8 execute(UInt32 t, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
return time_zone.toSecondInaccurate(t);
|
|
|
|
}
|
|
|
|
static inline UInt8 execute(UInt16 d, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
throw Exception("Illegal type Date of argument for function toSecond", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
|
|
|
}
|
2015-11-29 11:58:44 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
using FactorTransform = ToStartOfMinuteImpl;
|
2012-08-31 20:38:05 +00:00
|
|
|
};
|
|
|
|
|
2014-01-22 12:27:55 +00:00
|
|
|
struct ToRelativeYearNumImpl
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
static inline UInt16 execute(UInt32 t, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
return time_zone.toYear(t);
|
|
|
|
}
|
|
|
|
static inline UInt16 execute(UInt16 d, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
return time_zone.toYear(DayNum_t(d));
|
|
|
|
}
|
2015-11-29 11:58:44 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
using FactorTransform = ZeroTransform;
|
2014-01-22 12:27:55 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct ToRelativeMonthNumImpl
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
static inline UInt16 execute(UInt32 t, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
return time_zone.toRelativeMonthNum(t);
|
|
|
|
}
|
|
|
|
static inline UInt16 execute(UInt16 d, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
return time_zone.toRelativeMonthNum(DayNum_t(d));
|
|
|
|
}
|
2015-11-29 11:58:44 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
using FactorTransform = ZeroTransform;
|
2014-01-22 12:27:55 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct ToRelativeWeekNumImpl
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
static inline UInt16 execute(UInt32 t, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
return time_zone.toRelativeWeekNum(t);
|
|
|
|
}
|
|
|
|
static inline UInt16 execute(UInt16 d, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
return time_zone.toRelativeWeekNum(DayNum_t(d));
|
|
|
|
}
|
2015-11-29 11:58:44 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
using FactorTransform = ZeroTransform;
|
2014-01-22 12:27:55 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct ToRelativeDayNumImpl
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
static inline UInt16 execute(UInt32 t, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
return time_zone.toDayNum(t);
|
|
|
|
}
|
|
|
|
static inline UInt16 execute(UInt16 d, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
return static_cast<DayNum_t>(d);
|
|
|
|
}
|
2015-11-29 11:58:44 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
using FactorTransform = ZeroTransform;
|
2014-01-22 12:27:55 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
struct ToRelativeHourNumImpl
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
static inline UInt32 execute(UInt32 t, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
return time_zone.toRelativeHourNum(t);
|
|
|
|
}
|
|
|
|
static inline UInt32 execute(UInt16 d, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
throw Exception("Illegal type Date of argument for function toRelativeHourNum", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
|
|
|
}
|
2015-11-29 11:58:44 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
using FactorTransform = ZeroTransform;
|
2014-01-22 12:27:55 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct ToRelativeMinuteNumImpl
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
static inline UInt32 execute(UInt32 t, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
return time_zone.toRelativeMinuteNum(t);
|
|
|
|
}
|
|
|
|
static inline UInt32 execute(UInt16 d, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
throw Exception("Illegal type Date of argument for function toRelativeMinuteNum", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
|
|
|
}
|
2015-11-29 11:58:44 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
using FactorTransform = ZeroTransform;
|
2014-01-22 12:27:55 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct ToRelativeSecondNumImpl
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
static inline UInt32 execute(UInt32 t, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
return t;
|
|
|
|
}
|
|
|
|
static inline UInt32 execute(UInt16 d, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
throw Exception("Illegal type Date of argument for function toRelativeSecondNum", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
|
|
|
}
|
2015-11-29 11:58:44 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
using FactorTransform = ZeroTransform;
|
2014-01-22 12:27:55 +00:00
|
|
|
};
|
|
|
|
|
2015-11-29 11:58:44 +00:00
|
|
|
|
2015-07-01 14:35:02 +00:00
|
|
|
template<typename FromType, typename ToType, typename Transform>
|
2015-07-02 13:35:28 +00:00
|
|
|
struct Transformer
|
2015-06-30 15:03:22 +00:00
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
static void vector(const PaddedPODArray<FromType> & vec_from, PaddedPODArray<ToType> & vec_to, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
size_t size = vec_from.size();
|
|
|
|
vec_to.resize(size);
|
2015-07-02 13:35:28 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
for (size_t i = 0; i < size; ++i)
|
|
|
|
vec_to[i] = Transform::execute(vec_from[i], time_zone);
|
|
|
|
}
|
2015-07-08 17:30:42 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
static void constant(const FromType & from, ToType & to, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
to = Transform::execute(from, time_zone);
|
|
|
|
}
|
2015-07-02 13:35:28 +00:00
|
|
|
};
|
2015-07-01 14:35:02 +00:00
|
|
|
|
2017-01-22 08:33:16 +00:00
|
|
|
|
2015-06-30 15:03:22 +00:00
|
|
|
template <typename FromType, typename ToType, typename Transform, typename Name>
|
|
|
|
struct DateTimeTransformImpl
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
static void execute(Block & block, const ColumnNumbers & arguments, size_t result)
|
|
|
|
{
|
|
|
|
using Op = Transformer<FromType, ToType, Transform>;
|
|
|
|
|
|
|
|
const ColumnPtr source_col = block.safeGetByPosition(arguments[0]).column;
|
|
|
|
const auto * sources = typeid_cast<const ColumnVector<FromType> *>(source_col.get());
|
|
|
|
const auto * const_source = typeid_cast<const ColumnConst<FromType> *>(source_col.get());
|
|
|
|
|
|
|
|
const ColumnConstString * time_zone_column = nullptr;
|
|
|
|
|
|
|
|
if (arguments.size() == 2)
|
|
|
|
{
|
|
|
|
time_zone_column = typeid_cast<const ColumnConstString *>(block.safeGetByPosition(arguments[1]).column.get());
|
|
|
|
|
|
|
|
if (!time_zone_column)
|
|
|
|
throw Exception("Illegal column " + block.safeGetByPosition(arguments[1]).column->getName()
|
|
|
|
+ " of second (time zone) argument of function " + Name::name + ", must be constant string",
|
|
|
|
ErrorCodes::ILLEGAL_COLUMN);
|
|
|
|
}
|
|
|
|
|
|
|
|
const DateLUTImpl & time_zone = time_zone_column
|
|
|
|
? DateLUT::instance(time_zone_column->getData())
|
|
|
|
: DateLUT::instance();
|
|
|
|
|
|
|
|
if (sources)
|
|
|
|
{
|
|
|
|
auto col_to = std::make_shared<ColumnVector<ToType>>();
|
|
|
|
block.safeGetByPosition(result).column = col_to;
|
|
|
|
Op::vector(sources->getData(), col_to->getData(), time_zone);
|
|
|
|
}
|
|
|
|
else if (const_source)
|
|
|
|
{
|
|
|
|
ToType res;
|
|
|
|
Op::constant(const_source->getData(), res, time_zone);
|
|
|
|
block.safeGetByPosition(result).column = std::make_shared<ColumnConst<ToType>>(const_source->size(), res);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
throw Exception("Illegal column " + block.safeGetByPosition(arguments[0]).column->getName()
|
|
|
|
+ " of first argument of function " + Name::name,
|
|
|
|
ErrorCodes::ILLEGAL_COLUMN);
|
|
|
|
}
|
|
|
|
}
|
2011-10-16 04:17:41 +00:00
|
|
|
};
|
|
|
|
|
2017-01-22 08:33:16 +00:00
|
|
|
|
2011-10-16 04:17:41 +00:00
|
|
|
template <typename ToDataType, typename Transform, typename Name>
|
|
|
|
class FunctionDateOrDateTimeToSomething : public IFunction
|
|
|
|
{
|
|
|
|
public:
|
2017-04-01 07:20:54 +00:00
|
|
|
static constexpr auto name = Name::name;
|
|
|
|
static FunctionPtr create(const Context & context) { return std::make_shared<FunctionDateOrDateTimeToSomething>(); };
|
|
|
|
|
|
|
|
String getName() const override
|
|
|
|
{
|
|
|
|
return name;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool isVariadic() const override { return true; }
|
|
|
|
size_t getNumberOfArguments() const override { return 0; }
|
|
|
|
|
|
|
|
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
|
|
|
{
|
|
|
|
if (arguments.size() == 1)
|
|
|
|
{
|
|
|
|
if (!typeid_cast<const DataTypeDate *>(arguments[0].get())
|
|
|
|
&& !typeid_cast<const DataTypeDateTime *>(arguments[0].get()))
|
|
|
|
throw Exception{
|
|
|
|
"Illegal type " + arguments[0]->getName() + " of argument of function " + getName() +
|
|
|
|
". Should be a date or a date with time", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT};
|
|
|
|
}
|
|
|
|
else if (arguments.size() == 2)
|
|
|
|
{
|
|
|
|
if (!typeid_cast<const DataTypeDateTime *>(arguments[0].get())
|
|
|
|
|| !typeid_cast<const DataTypeString *>(arguments[1].get()))
|
|
|
|
throw Exception{
|
|
|
|
"Function " + getName() + " supports 1 or 2 arguments. The 1st argument "
|
|
|
|
"must be of type Date or DateTime. The 2nd argument (optional) must be "
|
|
|
|
"a constant string with timezone name. The timezone argument is allowed "
|
|
|
|
"only when the 1st argument has the type DateTime",
|
|
|
|
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT};
|
|
|
|
}
|
|
|
|
else
|
|
|
|
throw Exception("Number of arguments for function " + getName() + " doesn't match: passed "
|
|
|
|
+ toString(arguments.size()) + ", should be 1 or 2",
|
|
|
|
ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
|
|
|
|
|
|
|
|
return std::make_shared<ToDataType>();
|
|
|
|
}
|
|
|
|
|
|
|
|
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override
|
|
|
|
{
|
|
|
|
IDataType * from_type = block.safeGetByPosition(arguments[0]).type.get();
|
|
|
|
|
|
|
|
if (typeid_cast<const DataTypeDate *>(from_type))
|
|
|
|
DateTimeTransformImpl<DataTypeDate::FieldType, typename ToDataType::FieldType, Transform, Name>::execute(block, arguments, result);
|
|
|
|
else if (typeid_cast<const DataTypeDateTime * >(from_type))
|
|
|
|
DateTimeTransformImpl<DataTypeDateTime::FieldType, typename ToDataType::FieldType, Transform, Name>::execute(block, arguments, result);
|
|
|
|
else
|
|
|
|
throw Exception("Illegal type " + block.safeGetByPosition(arguments[0]).type->getName() + " of argument of function " + getName(),
|
|
|
|
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool hasInformationAboutMonotonicity() const override
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
Monotonicity getMonotonicityForRange(const IDataType & type, const Field & left, const Field & right) const override
|
|
|
|
{
|
|
|
|
IFunction::Monotonicity is_monotonic { true };
|
|
|
|
IFunction::Monotonicity is_not_monotonic;
|
|
|
|
|
|
|
|
if (std::is_same<typename Transform::FactorTransform, ZeroTransform>::value)
|
PKCondition: infer index use with pk subexpression
By default only constraints explicitly matching
primary key expression (or expression wrapped in
a monotonic function) are eligible for part and
range selection. So for example, if index is:
(toStartOfHour(dt), UserID)
Then a query such as this resorts to full scan:
SELECT count() FROM t WHERE dt = now()
Intuitively, only parts with toStartOfHour(now())
could be selected, but it is less trivial to prove.
The primary key currently can be wrapped in a chain
of monotonic functions, so following would work:
toStartOfHour(dt) = toStartOfHour(now()) AND dt = now()
It must be however explicitly stated, if we wanted
to infer that we’d have to know the inverse function,
and prove that the inverse function is monotonic
on given interval. This is not practical as
there is no inverse function that for example undos
rounding, it isn’t strictly monotonic.
There are however functions that don’t transform
output range and preserve monotonicity on the
complete input range, such as rounding or casts
to a same or wider numeric type. This eliminates
the need to find inverse function, as no check for monotonicity over arbitrary interval is needed,
and thus makes this optimisation possible.
2017-07-06 05:39:05 +00:00
|
|
|
{
|
|
|
|
is_monotonic.is_always_monotonic = true;
|
2017-04-01 07:20:54 +00:00
|
|
|
return is_monotonic;
|
PKCondition: infer index use with pk subexpression
By default only constraints explicitly matching
primary key expression (or expression wrapped in
a monotonic function) are eligible for part and
range selection. So for example, if index is:
(toStartOfHour(dt), UserID)
Then a query such as this resorts to full scan:
SELECT count() FROM t WHERE dt = now()
Intuitively, only parts with toStartOfHour(now())
could be selected, but it is less trivial to prove.
The primary key currently can be wrapped in a chain
of monotonic functions, so following would work:
toStartOfHour(dt) = toStartOfHour(now()) AND dt = now()
It must be however explicitly stated, if we wanted
to infer that we’d have to know the inverse function,
and prove that the inverse function is monotonic
on given interval. This is not practical as
there is no inverse function that for example undos
rounding, it isn’t strictly monotonic.
There are however functions that don’t transform
output range and preserve monotonicity on the
complete input range, such as rounding or casts
to a same or wider numeric type. This eliminates
the need to find inverse function, as no check for monotonicity over arbitrary interval is needed,
and thus makes this optimisation possible.
2017-07-06 05:39:05 +00:00
|
|
|
}
|
2017-04-01 07:20:54 +00:00
|
|
|
|
2017-05-27 15:45:25 +00:00
|
|
|
/// This method is called only if the function has one argument. Therefore, we do not care about the non-local time zone.
|
2017-04-01 07:20:54 +00:00
|
|
|
const DateLUTImpl & date_lut = DateLUT::instance();
|
|
|
|
|
|
|
|
if (left.isNull() || right.isNull())
|
|
|
|
return is_not_monotonic;
|
|
|
|
|
2017-05-27 15:45:25 +00:00
|
|
|
/// The function is monotonous on the [left, right] segment, if the factor transformation returns the same values for them.
|
2017-04-01 07:20:54 +00:00
|
|
|
|
|
|
|
if (typeid_cast<const DataTypeDate *>(&type))
|
|
|
|
{
|
|
|
|
return Transform::FactorTransform::execute(UInt16(left.get<UInt64>()), date_lut)
|
|
|
|
== Transform::FactorTransform::execute(UInt16(right.get<UInt64>()), date_lut)
|
|
|
|
? is_monotonic : is_not_monotonic;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return Transform::FactorTransform::execute(UInt32(left.get<UInt64>()), date_lut)
|
|
|
|
== Transform::FactorTransform::execute(UInt32(right.get<UInt64>()), date_lut)
|
|
|
|
? is_monotonic : is_not_monotonic;
|
|
|
|
}
|
|
|
|
}
|
2011-10-16 04:17:41 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2017-05-27 15:45:25 +00:00
|
|
|
/// Get the current time. (It is a constant, it is evaluated once for the entire query.)
|
2012-08-31 20:38:05 +00:00
|
|
|
class FunctionNow : public IFunction
|
|
|
|
{
|
|
|
|
public:
|
2017-04-01 07:20:54 +00:00
|
|
|
static constexpr auto name = "now";
|
|
|
|
static FunctionPtr create(const Context & context) { return std::make_shared<FunctionNow>(); };
|
2014-11-12 17:23:26 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
String getName() const override
|
|
|
|
{
|
|
|
|
return name;
|
|
|
|
}
|
2012-08-31 20:38:05 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
size_t getNumberOfArguments() const override { return 0; }
|
2016-12-29 19:38:10 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
|
|
|
{
|
|
|
|
return std::make_shared<DataTypeDateTime>();
|
|
|
|
}
|
2012-08-31 20:38:05 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override
|
|
|
|
{
|
|
|
|
block.safeGetByPosition(result).column = std::make_shared<ColumnConstUInt32>(
|
|
|
|
block.rows(),
|
|
|
|
time(0));
|
|
|
|
}
|
2012-08-31 20:38:05 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2014-09-04 11:48:07 +00:00
|
|
|
class FunctionToday : public IFunction
|
|
|
|
{
|
|
|
|
public:
|
2017-04-01 07:20:54 +00:00
|
|
|
static constexpr auto name = "today";
|
|
|
|
static FunctionPtr create(const Context & context) { return std::make_shared<FunctionToday>(); };
|
2014-11-12 17:23:26 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
String getName() const override
|
|
|
|
{
|
|
|
|
return name;
|
|
|
|
}
|
2014-09-04 11:48:07 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
size_t getNumberOfArguments() const override { return 0; }
|
2016-12-29 19:38:10 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
|
|
|
{
|
|
|
|
return std::make_shared<DataTypeDate>();
|
|
|
|
}
|
2014-09-04 11:48:07 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override
|
|
|
|
{
|
|
|
|
block.safeGetByPosition(result).column = std::make_shared<ColumnConstUInt16>(
|
|
|
|
block.rows(),
|
|
|
|
DateLUT::instance().toDayNum(time(0)));
|
|
|
|
}
|
2014-09-04 11:48:07 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class FunctionYesterday : public IFunction
|
|
|
|
{
|
|
|
|
public:
|
2017-04-01 07:20:54 +00:00
|
|
|
static constexpr auto name = "yesterday";
|
|
|
|
static FunctionPtr create(const Context & context) { return std::make_shared<FunctionYesterday>(); };
|
2014-11-12 17:23:26 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
String getName() const override
|
|
|
|
{
|
|
|
|
return name;
|
|
|
|
}
|
2014-09-04 11:48:07 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
size_t getNumberOfArguments() const override { return 0; }
|
2016-12-29 19:38:10 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
|
|
|
{
|
|
|
|
return std::make_shared<DataTypeDate>();
|
|
|
|
}
|
2014-09-04 11:48:07 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override
|
|
|
|
{
|
|
|
|
block.safeGetByPosition(result).column = std::make_shared<ColumnConstUInt16>(
|
|
|
|
block.rows(),
|
|
|
|
DateLUT::instance().toDayNum(time(0)) - 1);
|
|
|
|
}
|
2014-09-04 11:48:07 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2012-09-03 04:45:46 +00:00
|
|
|
class FunctionTimeSlot : public IFunction
|
|
|
|
{
|
|
|
|
public:
|
2017-04-01 07:20:54 +00:00
|
|
|
static constexpr auto name = "timeSlot";
|
|
|
|
static FunctionPtr create(const Context & context) { return std::make_shared<FunctionTimeSlot>(); };
|
|
|
|
|
|
|
|
String getName() const override
|
|
|
|
{
|
|
|
|
return name;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t getNumberOfArguments() const override { return 1; }
|
|
|
|
|
|
|
|
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
|
|
|
{
|
|
|
|
if (!typeid_cast<const DataTypeDateTime *>(arguments[0].get()))
|
|
|
|
throw Exception("Illegal type " + arguments[0]->getName() + " of first argument of function " + getName() + ". Must be DateTime.",
|
|
|
|
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
|
|
|
|
|
|
|
return std::make_shared<DataTypeDateTime>();
|
|
|
|
}
|
|
|
|
|
|
|
|
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override
|
|
|
|
{
|
|
|
|
if (const ColumnUInt32 * times = typeid_cast<const ColumnUInt32 *>(block.safeGetByPosition(arguments[0]).column.get()))
|
|
|
|
{
|
|
|
|
auto res = std::make_shared<ColumnUInt32>();
|
|
|
|
ColumnPtr res_holder = res;
|
|
|
|
ColumnUInt32::Container_t & res_vec = res->getData();
|
|
|
|
const ColumnUInt32::Container_t & vec = times->getData();
|
|
|
|
|
|
|
|
size_t size = vec.size();
|
|
|
|
res_vec.resize(size);
|
|
|
|
|
|
|
|
for (size_t i = 0; i < size; ++i)
|
|
|
|
res_vec[i] = vec[i] / TIME_SLOT_SIZE * TIME_SLOT_SIZE;
|
|
|
|
|
|
|
|
block.safeGetByPosition(result).column = res_holder;
|
|
|
|
}
|
|
|
|
else if (const ColumnConstUInt32 * const_times = typeid_cast<const ColumnConstUInt32 *>(block.safeGetByPosition(arguments[0]).column.get()))
|
|
|
|
{
|
|
|
|
block.safeGetByPosition(result).column = std::make_shared<ColumnConstUInt32>(block.rows(), const_times->getData() / TIME_SLOT_SIZE * TIME_SLOT_SIZE);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
throw Exception("Illegal column " + block.safeGetByPosition(arguments[0]).column->getName()
|
|
|
|
+ " of argument of function " + getName(),
|
|
|
|
ErrorCodes::ILLEGAL_COLUMN);
|
|
|
|
}
|
2012-09-03 04:45:46 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
template <typename DurationType>
|
|
|
|
struct TimeSlotsImpl
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
static void vector_vector(
|
|
|
|
const PaddedPODArray<UInt32> & starts, const PaddedPODArray<DurationType> & durations,
|
|
|
|
PaddedPODArray<UInt32> & result_values, ColumnArray::Offsets_t & result_offsets)
|
|
|
|
{
|
|
|
|
size_t size = starts.size();
|
|
|
|
|
|
|
|
result_offsets.resize(size);
|
|
|
|
result_values.reserve(size);
|
|
|
|
|
|
|
|
ColumnArray::Offset_t current_offset = 0;
|
|
|
|
for (size_t i = 0; i < size; ++i)
|
|
|
|
{
|
|
|
|
for (UInt32 value = starts[i] / TIME_SLOT_SIZE; value <= (starts[i] + durations[i]) / TIME_SLOT_SIZE; ++value)
|
|
|
|
{
|
|
|
|
result_values.push_back(value * TIME_SLOT_SIZE);
|
|
|
|
++current_offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
result_offsets[i] = current_offset;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void vector_constant(
|
|
|
|
const PaddedPODArray<UInt32> & starts, DurationType duration,
|
|
|
|
PaddedPODArray<UInt32> & result_values, ColumnArray::Offsets_t & result_offsets)
|
|
|
|
{
|
|
|
|
size_t size = starts.size();
|
|
|
|
|
|
|
|
result_offsets.resize(size);
|
|
|
|
result_values.reserve(size);
|
|
|
|
|
|
|
|
ColumnArray::Offset_t current_offset = 0;
|
|
|
|
for (size_t i = 0; i < size; ++i)
|
|
|
|
{
|
|
|
|
for (UInt32 value = starts[i] / TIME_SLOT_SIZE; value <= (starts[i] + duration) / TIME_SLOT_SIZE; ++value)
|
|
|
|
{
|
|
|
|
result_values.push_back(value * TIME_SLOT_SIZE);
|
|
|
|
++current_offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
result_offsets[i] = current_offset;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void constant_vector(
|
|
|
|
UInt32 start, const PaddedPODArray<DurationType> & durations,
|
|
|
|
PaddedPODArray<UInt32> & result_values, ColumnArray::Offsets_t & result_offsets)
|
|
|
|
{
|
|
|
|
size_t size = durations.size();
|
|
|
|
|
|
|
|
result_offsets.resize(size);
|
|
|
|
result_values.reserve(size);
|
|
|
|
|
|
|
|
ColumnArray::Offset_t current_offset = 0;
|
|
|
|
for (size_t i = 0; i < size; ++i)
|
|
|
|
{
|
|
|
|
for (UInt32 value = start / TIME_SLOT_SIZE; value <= (start + durations[i]) / TIME_SLOT_SIZE; ++value)
|
|
|
|
{
|
|
|
|
result_values.push_back(value * TIME_SLOT_SIZE);
|
|
|
|
++current_offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
result_offsets[i] = current_offset;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void constant_constant(
|
|
|
|
UInt32 start, DurationType duration,
|
|
|
|
Array & result)
|
|
|
|
{
|
|
|
|
for (UInt32 value = start / TIME_SLOT_SIZE; value <= (start + duration) / TIME_SLOT_SIZE; ++value)
|
|
|
|
result.push_back(static_cast<UInt64>(value * TIME_SLOT_SIZE));
|
|
|
|
}
|
2012-09-03 04:45:46 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class FunctionTimeSlots : public IFunction
|
|
|
|
{
|
|
|
|
public:
|
2017-04-01 07:20:54 +00:00
|
|
|
static constexpr auto name = "timeSlots";
|
|
|
|
static FunctionPtr create(const Context & context) { return std::make_shared<FunctionTimeSlots>(); };
|
|
|
|
|
|
|
|
String getName() const override
|
|
|
|
{
|
|
|
|
return name;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t getNumberOfArguments() const override { return 2; }
|
|
|
|
|
|
|
|
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
|
|
|
{
|
|
|
|
if (!typeid_cast<const DataTypeDateTime *>(arguments[0].get()))
|
|
|
|
throw Exception("Illegal type " + arguments[0]->getName() + " of first argument of function " + getName() + ". Must be DateTime.",
|
|
|
|
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
|
|
|
|
|
|
|
if (!typeid_cast<const DataTypeUInt32 *>(arguments[1].get()))
|
|
|
|
throw Exception("Illegal type " + arguments[1]->getName() + " of second argument of function " + getName() + ". Must be UInt32.",
|
|
|
|
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
|
|
|
|
|
|
|
return std::make_shared<DataTypeArray>(std::make_shared<DataTypeDateTime>());
|
|
|
|
}
|
|
|
|
|
|
|
|
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override
|
|
|
|
{
|
|
|
|
const ColumnUInt32 * starts = typeid_cast<const ColumnUInt32 *>(block.safeGetByPosition(arguments[0]).column.get());
|
|
|
|
const ColumnConstUInt32 * const_starts = typeid_cast<const ColumnConstUInt32 *>(block.safeGetByPosition(arguments[0]).column.get());
|
|
|
|
|
|
|
|
const ColumnUInt32 * durations = typeid_cast<const ColumnUInt32 *>(block.safeGetByPosition(arguments[1]).column.get());
|
|
|
|
const ColumnConstUInt32 * const_durations = typeid_cast<const ColumnConstUInt32 *>(block.safeGetByPosition(arguments[1]).column.get());
|
|
|
|
|
|
|
|
auto res = std::make_shared<ColumnArray>(std::make_shared<ColumnUInt32>());
|
|
|
|
ColumnPtr res_holder = res;
|
|
|
|
ColumnUInt32::Container_t & res_values = typeid_cast<ColumnUInt32 &>(res->getData()).getData();
|
|
|
|
|
|
|
|
if (starts && durations)
|
|
|
|
{
|
|
|
|
TimeSlotsImpl<UInt32>::vector_vector(starts->getData(), durations->getData(), res_values, res->getOffsets());
|
|
|
|
block.safeGetByPosition(result).column = res_holder;
|
|
|
|
}
|
|
|
|
else if (starts && const_durations)
|
|
|
|
{
|
|
|
|
TimeSlotsImpl<UInt32>::vector_constant(starts->getData(), const_durations->getData(), res_values, res->getOffsets());
|
|
|
|
block.safeGetByPosition(result).column = res_holder;
|
|
|
|
}
|
|
|
|
else if (const_starts && durations)
|
|
|
|
{
|
|
|
|
TimeSlotsImpl<UInt32>::constant_vector(const_starts->getData(), durations->getData(), res_values, res->getOffsets());
|
|
|
|
block.safeGetByPosition(result).column = res_holder;
|
|
|
|
}
|
|
|
|
else if (const_starts && const_durations)
|
|
|
|
{
|
|
|
|
Array const_res;
|
|
|
|
TimeSlotsImpl<UInt32>::constant_constant(const_starts->getData(), const_durations->getData(), const_res);
|
|
|
|
block.safeGetByPosition(result).column = std::make_shared<ColumnConstArray>(block.rows(), const_res, std::make_shared<DataTypeArray>(std::make_shared<DataTypeDateTime>()));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
throw Exception("Illegal columns " + block.safeGetByPosition(arguments[0]).column->getName()
|
|
|
|
+ ", " + block.safeGetByPosition(arguments[1]).column->getName()
|
|
|
|
+ " of arguments of function " + getName(),
|
|
|
|
ErrorCodes::ILLEGAL_COLUMN);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
struct NameToYear { static constexpr auto name = "toYear"; };
|
|
|
|
struct NameToMonth { static constexpr auto name = "toMonth"; };
|
|
|
|
struct NameToDayOfMonth { static constexpr auto name = "toDayOfMonth"; };
|
|
|
|
struct NameToDayOfWeek { static constexpr auto name = "toDayOfWeek"; };
|
|
|
|
struct NameToHour { static constexpr auto name = "toHour"; };
|
|
|
|
struct NameToMinute { static constexpr auto name = "toMinute"; };
|
|
|
|
struct NameToSecond { static constexpr auto name = "toSecond"; };
|
|
|
|
struct NameToStartOfDay { static constexpr auto name = "toStartOfDay"; };
|
|
|
|
struct NameToMonday { static constexpr auto name = "toMonday"; };
|
|
|
|
struct NameToStartOfMonth { static constexpr auto name = "toStartOfMonth"; };
|
|
|
|
struct NameToStartOfQuarter { static constexpr auto name = "toStartOfQuarter"; };
|
|
|
|
struct NameToStartOfYear { static constexpr auto name = "toStartOfYear"; };
|
|
|
|
struct NameToStartOfMinute { static constexpr auto name = "toStartOfMinute"; };
|
|
|
|
struct NameToStartOfFiveMinute { static constexpr auto name = "toStartOfFiveMinute"; };
|
|
|
|
struct NameToStartOfHour { static constexpr auto name = "toStartOfHour"; };
|
|
|
|
struct NameToTime { static constexpr auto name = "toTime"; };
|
|
|
|
struct NameToRelativeYearNum { static constexpr auto name = "toRelativeYearNum"; };
|
|
|
|
struct NameToRelativeMonthNum { static constexpr auto name = "toRelativeMonthNum"; };
|
|
|
|
struct NameToRelativeWeekNum { static constexpr auto name = "toRelativeWeekNum"; };
|
|
|
|
struct NameToRelativeDayNum { static constexpr auto name = "toRelativeDayNum"; };
|
|
|
|
struct NameToRelativeHourNum { static constexpr auto name = "toRelativeHourNum"; };
|
|
|
|
struct NameToRelativeMinuteNum { static constexpr auto name = "toRelativeMinuteNum"; };
|
|
|
|
struct NameToRelativeSecondNum { static constexpr auto name = "toRelativeSecondNum"; };
|
|
|
|
|
|
|
|
|
|
|
|
using FunctionToYear = FunctionDateOrDateTimeToSomething<DataTypeUInt16, ToYearImpl, NameToYear> ;
|
|
|
|
using FunctionToMonth = FunctionDateOrDateTimeToSomething<DataTypeUInt8, ToMonthImpl, NameToMonth> ;
|
|
|
|
using FunctionToDayOfMonth = FunctionDateOrDateTimeToSomething<DataTypeUInt8, ToDayOfMonthImpl, NameToDayOfMonth> ;
|
|
|
|
using FunctionToDayOfWeek = FunctionDateOrDateTimeToSomething<DataTypeUInt8, ToDayOfWeekImpl, NameToDayOfWeek> ;
|
|
|
|
using FunctionToHour = FunctionDateOrDateTimeToSomething<DataTypeUInt8, ToHourImpl, NameToHour> ;
|
|
|
|
using FunctionToMinute = FunctionDateOrDateTimeToSomething<DataTypeUInt8, ToMinuteImpl, NameToMinute> ;
|
|
|
|
using FunctionToSecond = FunctionDateOrDateTimeToSomething<DataTypeUInt8, ToSecondImpl, NameToSecond> ;
|
|
|
|
using FunctionToStartOfDay = FunctionDateOrDateTimeToSomething<DataTypeDateTime, ToStartOfDayImpl, NameToStartOfDay>;
|
|
|
|
using FunctionToMonday = FunctionDateOrDateTimeToSomething<DataTypeDate, ToMondayImpl, NameToMonday> ;
|
|
|
|
using FunctionToStartOfMonth = FunctionDateOrDateTimeToSomething<DataTypeDate, ToStartOfMonthImpl, NameToStartOfMonth>;
|
|
|
|
using FunctionToStartOfQuarter = FunctionDateOrDateTimeToSomething<DataTypeDate, ToStartOfQuarterImpl, NameToStartOfQuarter> ;
|
|
|
|
using FunctionToStartOfYear = FunctionDateOrDateTimeToSomething<DataTypeDate, ToStartOfYearImpl, NameToStartOfYear> ;
|
|
|
|
using FunctionToStartOfMinute = FunctionDateOrDateTimeToSomething<DataTypeDateTime, ToStartOfMinuteImpl, NameToStartOfMinute>;
|
|
|
|
using FunctionToStartOfFiveMinute = FunctionDateOrDateTimeToSomething<DataTypeDateTime, ToStartOfFiveMinuteImpl, NameToStartOfFiveMinute>;
|
|
|
|
using FunctionToStartOfHour = FunctionDateOrDateTimeToSomething<DataTypeDateTime, ToStartOfHourImpl, NameToStartOfHour> ;
|
|
|
|
using FunctionToTime = FunctionDateOrDateTimeToSomething<DataTypeDateTime, ToTimeImpl, NameToTime> ;
|
|
|
|
|
|
|
|
using FunctionToRelativeYearNum = FunctionDateOrDateTimeToSomething<DataTypeUInt16, ToRelativeYearNumImpl, NameToRelativeYearNum> ;
|
|
|
|
using FunctionToRelativeMonthNum = FunctionDateOrDateTimeToSomething<DataTypeUInt32, ToRelativeMonthNumImpl, NameToRelativeMonthNum> ;
|
|
|
|
using FunctionToRelativeWeekNum = FunctionDateOrDateTimeToSomething<DataTypeUInt32, ToRelativeWeekNumImpl, NameToRelativeWeekNum> ;
|
|
|
|
using FunctionToRelativeDayNum = FunctionDateOrDateTimeToSomething<DataTypeUInt32, ToRelativeDayNumImpl, NameToRelativeDayNum> ;
|
|
|
|
|
|
|
|
using FunctionToRelativeHourNum = FunctionDateOrDateTimeToSomething<DataTypeUInt32, ToRelativeHourNumImpl, NameToRelativeHourNum> ;
|
|
|
|
using FunctionToRelativeMinuteNum = FunctionDateOrDateTimeToSomething<DataTypeUInt32, ToRelativeMinuteNumImpl, NameToRelativeMinuteNum> ;
|
|
|
|
using FunctionToRelativeSecondNum = FunctionDateOrDateTimeToSomething<DataTypeUInt32, ToRelativeSecondNumImpl, NameToRelativeSecondNum> ;
|
2014-01-22 12:27:55 +00:00
|
|
|
|
|
|
|
|
2011-10-16 04:17:41 +00:00
|
|
|
}
|