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>
|
2017-07-21 06:35:58 +00:00
|
|
|
#include <Columns/ColumnString.h>
|
2017-04-01 09:19:00 +00:00
|
|
|
#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>
|
2017-07-21 06:35:58 +00:00
|
|
|
#include <Functions/FunctionHelpers.h>
|
2011-10-16 04:17:41 +00:00
|
|
|
|
2017-03-12 10:13:45 +00:00
|
|
|
#include <common/DateLUT.h>
|
|
|
|
|
2017-12-22 01:54:29 +00:00
|
|
|
#include <Poco/String.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,
|
2017-12-22 10:36:39 +00:00
|
|
|
* toMonday, toStartOfMonth, toStartOfYear, toStartOfMinute, toStartOfFiveMinute, toStartOfFifteenMinutes
|
2015-06-03 14:27:03 +00:00
|
|
|
* 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
|
|
|
|
2017-11-05 05:32:22 +00:00
|
|
|
/// Determine working timezone either from optional argument with time zone name or from time zone in DateTime type of argument.
|
2017-12-22 01:54:29 +00:00
|
|
|
std::string extractTimeZoneNameFromFunctionArguments(const ColumnsWithTypeAndName & arguments, size_t time_zone_arg_num, size_t datetime_arg_num);
|
|
|
|
const DateLUTImpl & extractTimeZoneFromFunctionArguments(Block & block, const ColumnNumbers & arguments, size_t time_zone_arg_num, size_t datetime_arg_num);
|
2017-11-05 05:32:22 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
2012-09-03 04:45:46 +00:00
|
|
|
#define TIME_SLOT_SIZE 1800
|
|
|
|
|
2017-11-05 05:32:22 +00:00
|
|
|
/** Transformations.
|
2017-05-27 15:45:25 +00:00
|
|
|
* 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.
|
2017-11-05 05:32:22 +00:00
|
|
|
* This is a transformation of F such that its value identifies the region of monotonicity for T
|
2017-05-27 15:45:25 +00:00
|
|
|
* (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-11-05 05:32:22 +00:00
|
|
|
* Example: for transformation T "get the day number in the month" (2015-02-03 -> 3),
|
2017-05-27 15:45:25 +00:00
|
|
|
* 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-12-02 02:47:12 +00:00
|
|
|
static inline UInt16 execute(UInt32, const DateLUTImpl &) { return 0; }
|
|
|
|
static inline UInt16 execute(UInt16, const DateLUTImpl &) { 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-10-29 04:18:48 +00:00
|
|
|
static constexpr auto name = "toDate";
|
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
static inline UInt16 execute(UInt32 t, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
return UInt16(time_zone.toDayNum(t));
|
|
|
|
}
|
2017-12-02 02:47:12 +00:00
|
|
|
static inline UInt16 execute(UInt16 d, const DateLUTImpl &)
|
2017-04-01 07:20:54 +00:00
|
|
|
{
|
|
|
|
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-10-29 04:18:48 +00:00
|
|
|
static constexpr auto name = "toStartOfDay";
|
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
static inline UInt32 execute(UInt32 t, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
return time_zone.toDate(t);
|
|
|
|
}
|
2017-12-02 02:47:12 +00:00
|
|
|
static inline UInt32 execute(UInt16, const DateLUTImpl &)
|
2017-04-01 07:20:54 +00:00
|
|
|
{
|
2017-11-05 05:17:48 +00:00
|
|
|
throw Exception("Illegal type Date of argument for function toStartOfDay", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
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-10-29 04:18:48 +00:00
|
|
|
static constexpr auto name = "toMonday";
|
|
|
|
|
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)
|
|
|
|
{
|
2018-05-25 13:29:15 +00:00
|
|
|
return time_zone.toFirstDayNumOfWeek(DayNum(d));
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
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-10-29 04:18:48 +00:00
|
|
|
static constexpr auto name = "toStartOfMonth";
|
|
|
|
|
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)
|
|
|
|
{
|
2018-05-25 13:29:15 +00:00
|
|
|
return time_zone.toFirstDayNumOfMonth(DayNum(d));
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
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-10-29 04:18:48 +00:00
|
|
|
static constexpr auto name = "toStartOfQuarter";
|
|
|
|
|
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)
|
|
|
|
{
|
2018-05-25 13:29:15 +00:00
|
|
|
return time_zone.toFirstDayNumOfQuarter(DayNum(d));
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
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-10-29 04:18:48 +00:00
|
|
|
static constexpr auto name = "toStartOfYear";
|
|
|
|
|
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)
|
|
|
|
{
|
2018-05-25 13:29:15 +00:00
|
|
|
return time_zone.toFirstDayNumOfYear(DayNum(d));
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
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-10-29 04:18:48 +00:00
|
|
|
static constexpr auto name = "toTime";
|
|
|
|
|
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-12-02 02:47:12 +00:00
|
|
|
static inline UInt32 execute(UInt16, const DateLUTImpl &)
|
2017-04-01 07:20:54 +00:00
|
|
|
{
|
|
|
|
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-10-29 04:18:48 +00:00
|
|
|
static constexpr auto name = "toStartOfMinute";
|
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
static inline UInt32 execute(UInt32 t, const DateLUTImpl & time_zone)
|
|
|
|
{
|
2017-10-29 00:51:40 +00:00
|
|
|
return time_zone.toStartOfMinute(t);
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
2017-12-02 02:47:12 +00:00
|
|
|
static inline UInt32 execute(UInt16, const DateLUTImpl &)
|
2017-04-01 07:20:54 +00:00
|
|
|
{
|
|
|
|
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-10-29 04:18:48 +00:00
|
|
|
static constexpr auto name = "toStartOfFiveMinute";
|
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
static inline UInt32 execute(UInt32 t, const DateLUTImpl & time_zone)
|
|
|
|
{
|
2017-10-29 00:51:40 +00:00
|
|
|
return time_zone.toStartOfFiveMinute(t);
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
2017-12-02 02:47:12 +00:00
|
|
|
static inline UInt32 execute(UInt16, const DateLUTImpl &)
|
2017-04-01 07:20:54 +00:00
|
|
|
{
|
|
|
|
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
|
|
|
};
|
|
|
|
|
2017-12-22 10:36:39 +00:00
|
|
|
struct ToStartOfFifteenMinutesImpl
|
|
|
|
{
|
|
|
|
static constexpr auto name = "toStartOfFifteenMinutes";
|
|
|
|
|
|
|
|
static inline UInt32 execute(UInt32 t, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
return time_zone.toStartOfFifteenMinutes(t);
|
|
|
|
}
|
2017-12-22 19:26:56 +00:00
|
|
|
static inline UInt32 execute(UInt16, const DateLUTImpl &)
|
2017-12-22 10:36:39 +00:00
|
|
|
{
|
|
|
|
throw Exception("Illegal type Date of argument for function toStartOfFifteenMinutes", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
|
|
|
}
|
|
|
|
|
|
|
|
using FactorTransform = ZeroTransform;
|
|
|
|
};
|
|
|
|
|
2012-08-31 20:38:05 +00:00
|
|
|
struct ToStartOfHourImpl
|
|
|
|
{
|
2017-10-29 04:18:48 +00:00
|
|
|
static constexpr auto name = "toStartOfHour";
|
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
static inline UInt32 execute(UInt32 t, const DateLUTImpl & time_zone)
|
|
|
|
{
|
2017-10-29 00:51:40 +00:00
|
|
|
return time_zone.toStartOfHour(t);
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
2017-10-29 00:51:40 +00:00
|
|
|
|
2017-12-02 02:47:12 +00:00
|
|
|
static inline UInt32 execute(UInt16, const DateLUTImpl &)
|
2017-04-01 07:20:54 +00:00
|
|
|
{
|
|
|
|
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-10-29 04:18:48 +00:00
|
|
|
static constexpr auto name = "toYear";
|
|
|
|
|
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)
|
|
|
|
{
|
2018-05-25 13:29:15 +00:00
|
|
|
return time_zone.toYear(DayNum(d));
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
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
|
|
|
};
|
|
|
|
|
2017-12-22 01:54:29 +00:00
|
|
|
struct ToQuarterImpl
|
|
|
|
{
|
|
|
|
static constexpr auto name = "toQuarter";
|
|
|
|
|
|
|
|
static inline UInt8 execute(UInt32 t, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
return time_zone.toQuarter(t);
|
|
|
|
}
|
|
|
|
static inline UInt8 execute(UInt16 d, const DateLUTImpl & time_zone)
|
|
|
|
{
|
2018-05-25 13:29:15 +00:00
|
|
|
return time_zone.toQuarter(DayNum(d));
|
2017-12-22 01:54:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
using FactorTransform = ToStartOfYearImpl;
|
|
|
|
};
|
|
|
|
|
2015-11-29 11:58:44 +00:00
|
|
|
struct ToMonthImpl
|
|
|
|
{
|
2017-10-29 04:18:48 +00:00
|
|
|
static constexpr auto name = "toMonth";
|
|
|
|
|
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)
|
|
|
|
{
|
2018-05-25 13:29:15 +00:00
|
|
|
return time_zone.toMonth(DayNum(d));
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
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-10-29 04:18:48 +00:00
|
|
|
static constexpr auto name = "toDayOfMonth";
|
|
|
|
|
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)
|
|
|
|
{
|
2018-05-25 13:29:15 +00:00
|
|
|
return time_zone.toDayOfMonth(DayNum(d));
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
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-10-29 04:18:48 +00:00
|
|
|
static constexpr auto name = "toDayOfWeek";
|
|
|
|
|
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)
|
|
|
|
{
|
2018-05-25 13:29:15 +00:00
|
|
|
return time_zone.toDayOfWeek(DayNum(d));
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
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-10-29 04:18:48 +00:00
|
|
|
static constexpr auto name = "toHour";
|
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
static inline UInt8 execute(UInt32 t, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
return time_zone.toHour(t);
|
|
|
|
}
|
2017-10-29 00:51:40 +00:00
|
|
|
|
2017-12-02 02:47:12 +00:00
|
|
|
static inline UInt8 execute(UInt16, const DateLUTImpl &)
|
2017-04-01 07:20:54 +00:00
|
|
|
{
|
|
|
|
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-10-29 04:18:48 +00:00
|
|
|
static constexpr auto name = "toMinute";
|
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
static inline UInt8 execute(UInt32 t, const DateLUTImpl & time_zone)
|
|
|
|
{
|
2017-10-29 00:51:40 +00:00
|
|
|
return time_zone.toMinute(t);
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
2017-12-02 02:47:12 +00:00
|
|
|
static inline UInt8 execute(UInt16, const DateLUTImpl &)
|
2017-04-01 07:20:54 +00:00
|
|
|
{
|
|
|
|
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-10-29 04:18:48 +00:00
|
|
|
static constexpr auto name = "toSecond";
|
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
static inline UInt8 execute(UInt32 t, const DateLUTImpl & time_zone)
|
|
|
|
{
|
2017-10-29 00:51:40 +00:00
|
|
|
return time_zone.toSecond(t);
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
2017-12-02 02:47:12 +00:00
|
|
|
static inline UInt8 execute(UInt16, const DateLUTImpl &)
|
2017-04-01 07:20:54 +00:00
|
|
|
{
|
|
|
|
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-10-29 04:18:48 +00:00
|
|
|
static constexpr auto name = "toRelativeYearNum";
|
|
|
|
|
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)
|
|
|
|
{
|
2018-05-25 13:29:15 +00:00
|
|
|
return time_zone.toYear(DayNum(d));
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
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
|
|
|
};
|
|
|
|
|
2017-12-22 01:54:29 +00:00
|
|
|
struct ToRelativeQuarterNumImpl
|
|
|
|
{
|
|
|
|
static constexpr auto name = "toRelativeQuarterNum";
|
|
|
|
|
|
|
|
static inline UInt16 execute(UInt32 t, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
return time_zone.toRelativeQuarterNum(t);
|
|
|
|
}
|
|
|
|
static inline UInt16 execute(UInt16 d, const DateLUTImpl & time_zone)
|
|
|
|
{
|
2018-05-25 13:29:15 +00:00
|
|
|
return time_zone.toRelativeQuarterNum(DayNum(d));
|
2017-12-22 01:54:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
using FactorTransform = ZeroTransform;
|
|
|
|
};
|
|
|
|
|
2014-01-22 12:27:55 +00:00
|
|
|
struct ToRelativeMonthNumImpl
|
|
|
|
{
|
2017-10-29 04:18:48 +00:00
|
|
|
static constexpr auto name = "toRelativeMonthNum";
|
|
|
|
|
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)
|
|
|
|
{
|
2018-05-25 13:29:15 +00:00
|
|
|
return time_zone.toRelativeMonthNum(DayNum(d));
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
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-10-29 04:18:48 +00:00
|
|
|
static constexpr auto name = "toRelativeWeekNum";
|
|
|
|
|
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)
|
|
|
|
{
|
2018-05-25 13:29:15 +00:00
|
|
|
return time_zone.toRelativeWeekNum(DayNum(d));
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
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-10-29 04:18:48 +00:00
|
|
|
static constexpr auto name = "toRelativeDayNum";
|
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
static inline UInt16 execute(UInt32 t, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
return time_zone.toDayNum(t);
|
|
|
|
}
|
2017-12-02 02:47:12 +00:00
|
|
|
static inline UInt16 execute(UInt16 d, const DateLUTImpl &)
|
2017-04-01 07:20:54 +00:00
|
|
|
{
|
2018-05-25 13:29:15 +00:00
|
|
|
return static_cast<DayNum>(d);
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
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-10-29 04:18:48 +00:00
|
|
|
static constexpr auto name = "toRelativeHourNum";
|
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
static inline UInt32 execute(UInt32 t, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
return time_zone.toRelativeHourNum(t);
|
|
|
|
}
|
2017-12-22 01:54:29 +00:00
|
|
|
static inline UInt32 execute(UInt16 d, const DateLUTImpl & time_zone)
|
2017-04-01 07:20:54 +00:00
|
|
|
{
|
2018-05-25 13:29:15 +00:00
|
|
|
return time_zone.toRelativeHourNum(DayNum(d));
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
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-10-29 04:18:48 +00:00
|
|
|
static constexpr auto name = "toRelativeMinuteNum";
|
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
static inline UInt32 execute(UInt32 t, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
return time_zone.toRelativeMinuteNum(t);
|
|
|
|
}
|
2017-12-22 01:54:29 +00:00
|
|
|
static inline UInt32 execute(UInt16 d, const DateLUTImpl & time_zone)
|
2017-04-01 07:20:54 +00:00
|
|
|
{
|
2018-05-25 13:29:15 +00:00
|
|
|
return time_zone.toRelativeMinuteNum(DayNum(d));
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
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-10-29 04:18:48 +00:00
|
|
|
static constexpr auto name = "toRelativeSecondNum";
|
|
|
|
|
2017-12-02 02:47:12 +00:00
|
|
|
static inline UInt32 execute(UInt32 t, const DateLUTImpl &)
|
2017-04-01 07:20:54 +00:00
|
|
|
{
|
|
|
|
return t;
|
|
|
|
}
|
2017-12-22 01:54:29 +00:00
|
|
|
static inline UInt32 execute(UInt16 d, const DateLUTImpl & time_zone)
|
2017-04-01 07:20:54 +00:00
|
|
|
{
|
2018-05-25 13:29:15 +00:00
|
|
|
return time_zone.fromDayNum(DayNum(d));
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
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
|
|
|
};
|
|
|
|
|
2017-07-21 14:22:53 +00:00
|
|
|
struct ToYYYYMMImpl
|
|
|
|
{
|
2017-10-29 04:18:48 +00:00
|
|
|
static constexpr auto name = "toYYYYMM";
|
|
|
|
|
2017-07-21 14:22:53 +00:00
|
|
|
static inline UInt32 execute(UInt32 t, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
return time_zone.toNumYYYYMM(t);
|
|
|
|
}
|
|
|
|
static inline UInt32 execute(UInt16 d, const DateLUTImpl & time_zone)
|
|
|
|
{
|
2018-05-25 13:29:15 +00:00
|
|
|
return time_zone.toNumYYYYMM(static_cast<DayNum>(d));
|
2017-07-21 14:22:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
using FactorTransform = ZeroTransform;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct ToYYYYMMDDImpl
|
|
|
|
{
|
2017-10-29 04:18:48 +00:00
|
|
|
static constexpr auto name = "toYYYYMMDD";
|
|
|
|
|
2017-07-21 14:22:53 +00:00
|
|
|
static inline UInt32 execute(UInt32 t, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
return time_zone.toNumYYYYMMDD(t);
|
|
|
|
}
|
|
|
|
static inline UInt32 execute(UInt16 d, const DateLUTImpl & time_zone)
|
|
|
|
{
|
2018-05-25 13:29:15 +00:00
|
|
|
return time_zone.toNumYYYYMMDD(static_cast<DayNum>(d));
|
2017-07-21 14:22:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
using FactorTransform = ZeroTransform;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct ToYYYYMMDDhhmmssImpl
|
|
|
|
{
|
2017-10-29 04:18:48 +00:00
|
|
|
static constexpr auto name = "toYYYYMMDDhhmmss";
|
|
|
|
|
2017-07-21 14:22:53 +00:00
|
|
|
static inline UInt64 execute(UInt32 t, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
return time_zone.toNumYYYYMMDDhhmmss(t);
|
|
|
|
}
|
|
|
|
static inline UInt64 execute(UInt16 d, const DateLUTImpl & time_zone)
|
|
|
|
{
|
2018-05-25 13:29:15 +00:00
|
|
|
return time_zone.toNumYYYYMMDDhhmmss(time_zone.toDate(static_cast<DayNum>(d)));
|
2017-07-21 14:22:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
using FactorTransform = ZeroTransform;
|
|
|
|
};
|
|
|
|
|
2015-11-29 11:58:44 +00:00
|
|
|
|
2017-09-15 12:16:12 +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-02 13:35:28 +00:00
|
|
|
};
|
2015-07-01 14:35:02 +00:00
|
|
|
|
2017-01-22 08:33:16 +00:00
|
|
|
|
2017-10-29 04:18:48 +00:00
|
|
|
template <typename FromType, typename ToType, typename Transform>
|
2015-06-30 15:03:22 +00:00
|
|
|
struct DateTimeTransformImpl
|
|
|
|
{
|
2018-04-24 07:16:39 +00:00
|
|
|
static void execute(Block & block, const ColumnNumbers & arguments, size_t result, size_t /*input_rows_count*/)
|
2017-04-01 07:20:54 +00:00
|
|
|
{
|
|
|
|
using Op = Transformer<FromType, ToType, Transform>;
|
|
|
|
|
2017-12-22 01:54:29 +00:00
|
|
|
const DateLUTImpl & time_zone = extractTimeZoneFromFunctionArguments(block, arguments, 1, 0);
|
2017-04-01 07:20:54 +00:00
|
|
|
|
2017-10-29 04:18:48 +00:00
|
|
|
const ColumnPtr source_col = block.getByPosition(arguments[0]).column;
|
|
|
|
if (const auto * sources = checkAndGetColumn<ColumnVector<FromType>>(source_col.get()))
|
2017-04-01 07:20:54 +00:00
|
|
|
{
|
2017-12-14 01:43:19 +00:00
|
|
|
auto col_to = ColumnVector<ToType>::create();
|
2017-04-01 07:20:54 +00:00
|
|
|
Op::vector(sources->getData(), col_to->getData(), time_zone);
|
2017-12-16 04:59:32 +00:00
|
|
|
block.getByPosition(result).column = std::move(col_to);
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-07-21 06:35:58 +00:00
|
|
|
throw Exception("Illegal column " + block.getByPosition(arguments[0]).column->getName()
|
2017-10-29 04:18:48 +00:00
|
|
|
+ " of first argument of function " + Transform::name,
|
2017-04-01 07:20:54 +00:00
|
|
|
ErrorCodes::ILLEGAL_COLUMN);
|
|
|
|
}
|
|
|
|
}
|
2011-10-16 04:17:41 +00:00
|
|
|
};
|
|
|
|
|
2017-01-22 08:33:16 +00:00
|
|
|
|
2017-10-29 04:18:48 +00:00
|
|
|
template <typename ToDataType, typename Transform>
|
2011-10-16 04:17:41 +00:00
|
|
|
class FunctionDateOrDateTimeToSomething : public IFunction
|
|
|
|
{
|
|
|
|
public:
|
2017-10-29 04:18:48 +00:00
|
|
|
static constexpr auto name = Transform::name;
|
2018-08-26 00:50:48 +00:00
|
|
|
static FunctionPtr create(const Context &) { return std::make_shared<FunctionDateOrDateTimeToSomething>(); }
|
2017-04-01 07:20:54 +00:00
|
|
|
|
|
|
|
String getName() const override
|
|
|
|
{
|
|
|
|
return name;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool isVariadic() const override { return true; }
|
|
|
|
size_t getNumberOfArguments() const override { return 0; }
|
|
|
|
|
2018-02-02 08:33:36 +00:00
|
|
|
DataTypePtr getReturnTypeImpl(const ColumnsWithTypeAndName & arguments) const override
|
2017-04-01 07:20:54 +00:00
|
|
|
{
|
|
|
|
if (arguments.size() == 1)
|
|
|
|
{
|
2018-09-07 14:37:26 +00:00
|
|
|
if (!isDateOrDateTime(arguments[0].type))
|
2018-05-07 02:01:11 +00:00
|
|
|
throw Exception("Illegal type " + arguments[0].type->getName() + " of argument of function " + getName() +
|
|
|
|
". Should be a date or a date with time", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
|
|
|
else if (arguments.size() == 2)
|
|
|
|
{
|
2018-09-07 14:37:26 +00:00
|
|
|
if (!WhichDataType(arguments[0].type).isDateTime()
|
|
|
|
|| !WhichDataType(arguments[1].type).isString())
|
2018-05-07 02:01:11 +00:00
|
|
|
throw Exception(
|
2017-04-01 07:20:54 +00:00
|
|
|
"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",
|
2018-05-07 02:01:11 +00:00
|
|
|
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
|
|
|
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);
|
|
|
|
|
2017-11-05 05:32:22 +00:00
|
|
|
/// For DateTime, if time zone is specified, attach it to type.
|
2017-12-25 04:01:46 +00:00
|
|
|
if (std::is_same_v<ToDataType, DataTypeDateTime>)
|
2018-02-02 08:33:36 +00:00
|
|
|
return std::make_shared<DataTypeDateTime>(extractTimeZoneNameFromFunctionArguments(arguments, 1, 0));
|
2017-11-05 05:32:22 +00:00
|
|
|
else
|
2018-02-02 08:33:36 +00:00
|
|
|
return std::make_shared<ToDataType>();
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
|
|
|
|
2017-07-23 08:40:43 +00:00
|
|
|
bool useDefaultImplementationForConstants() const override { return true; }
|
|
|
|
ColumnNumbers getArgumentsThatAreAlwaysConstant() const override { return {1}; }
|
|
|
|
|
2018-04-24 07:16:39 +00:00
|
|
|
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) override
|
2017-04-01 07:20:54 +00:00
|
|
|
{
|
2017-10-29 04:18:48 +00:00
|
|
|
const IDataType * from_type = block.getByPosition(arguments[0]).type.get();
|
2018-09-07 14:37:26 +00:00
|
|
|
WhichDataType which(from_type);
|
2017-04-01 07:20:54 +00:00
|
|
|
|
2018-09-07 14:37:26 +00:00
|
|
|
if (which.isDate())
|
2018-04-24 07:16:39 +00:00
|
|
|
DateTimeTransformImpl<DataTypeDate::FieldType, typename ToDataType::FieldType, Transform>::execute(block, arguments, result, input_rows_count);
|
2018-09-07 14:37:26 +00:00
|
|
|
else if (which.isDateTime())
|
2018-04-24 07:16:39 +00:00
|
|
|
DateTimeTransformImpl<DataTypeDateTime::FieldType, typename ToDataType::FieldType, Transform>::execute(block, arguments, result, input_rows_count);
|
2017-04-01 07:20:54 +00:00
|
|
|
else
|
2017-07-21 06:35:58 +00:00
|
|
|
throw Exception("Illegal type " + block.getByPosition(arguments[0]).type->getName() + " of argument of function " + getName(),
|
2017-04-01 07:20:54 +00:00
|
|
|
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;
|
|
|
|
|
2017-12-25 04:01:46 +00:00
|
|
|
if (std::is_same_v<typename Transform::FactorTransform, ZeroTransform>)
|
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
|
|
|
|
2017-07-21 06:35:58 +00:00
|
|
|
if (checkAndGetDataType<DataTypeDate>(&type))
|
2017-04-01 07:20:54 +00:00
|
|
|
{
|
|
|
|
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-10-29 04:18:48 +00:00
|
|
|
struct AddSecondsImpl
|
|
|
|
{
|
|
|
|
static constexpr auto name = "addSeconds";
|
|
|
|
|
2017-12-02 02:47:12 +00:00
|
|
|
static inline UInt32 execute(UInt32 t, Int64 delta, const DateLUTImpl &)
|
2017-10-29 04:18:48 +00:00
|
|
|
{
|
|
|
|
return t + delta;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline UInt32 execute(UInt16 d, Int64 delta, const DateLUTImpl & time_zone)
|
|
|
|
{
|
2018-05-25 13:29:15 +00:00
|
|
|
return time_zone.fromDayNum(DayNum(d)) + delta;
|
2017-10-29 04:18:48 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
struct AddMinutesImpl
|
|
|
|
{
|
|
|
|
static constexpr auto name = "addMinutes";
|
|
|
|
|
2017-12-02 02:47:12 +00:00
|
|
|
static inline UInt32 execute(UInt32 t, Int64 delta, const DateLUTImpl &)
|
2017-10-29 04:18:48 +00:00
|
|
|
{
|
|
|
|
return t + delta * 60;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline UInt32 execute(UInt16 d, Int64 delta, const DateLUTImpl & time_zone)
|
|
|
|
{
|
2018-05-25 13:29:15 +00:00
|
|
|
return time_zone.fromDayNum(DayNum(d)) + delta * 60;
|
2017-10-29 04:18:48 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
struct AddHoursImpl
|
|
|
|
{
|
|
|
|
static constexpr auto name = "addHours";
|
|
|
|
|
2017-12-02 02:47:12 +00:00
|
|
|
static inline UInt32 execute(UInt32 t, Int64 delta, const DateLUTImpl &)
|
2017-10-29 04:18:48 +00:00
|
|
|
{
|
|
|
|
return t + delta * 3600;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline UInt32 execute(UInt16 d, Int64 delta, const DateLUTImpl & time_zone)
|
|
|
|
{
|
2018-05-25 13:29:15 +00:00
|
|
|
return time_zone.fromDayNum(DayNum(d)) + delta * 3600;
|
2017-10-29 04:18:48 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
struct AddDaysImpl
|
|
|
|
{
|
|
|
|
static constexpr auto name = "addDays";
|
|
|
|
|
|
|
|
static inline UInt32 execute(UInt32 t, Int64 delta, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
return time_zone.addDays(t, delta);
|
|
|
|
}
|
|
|
|
|
2017-12-02 02:47:12 +00:00
|
|
|
static inline UInt16 execute(UInt16 d, Int64 delta, const DateLUTImpl &)
|
2017-10-29 04:18:48 +00:00
|
|
|
{
|
|
|
|
return d + delta;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
struct AddWeeksImpl
|
|
|
|
{
|
|
|
|
static constexpr auto name = "addWeeks";
|
|
|
|
|
|
|
|
static inline UInt32 execute(UInt32 t, Int64 delta, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
return time_zone.addWeeks(t, delta);
|
|
|
|
}
|
|
|
|
|
2017-12-02 02:47:12 +00:00
|
|
|
static inline UInt16 execute(UInt16 d, Int64 delta, const DateLUTImpl &)
|
2017-10-29 04:18:48 +00:00
|
|
|
{
|
|
|
|
return d + delta * 7;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
struct AddMonthsImpl
|
|
|
|
{
|
|
|
|
static constexpr auto name = "addMonths";
|
|
|
|
|
|
|
|
static inline UInt32 execute(UInt32 t, Int64 delta, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
return time_zone.addMonths(t, delta);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline UInt16 execute(UInt16 d, Int64 delta, const DateLUTImpl & time_zone)
|
|
|
|
{
|
2018-05-25 13:29:15 +00:00
|
|
|
return time_zone.addMonths(DayNum(d), delta);
|
2017-10-29 04:18:48 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
struct AddYearsImpl
|
|
|
|
{
|
|
|
|
static constexpr auto name = "addYears";
|
|
|
|
|
|
|
|
static inline UInt32 execute(UInt32 t, Int64 delta, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
return time_zone.addYears(t, delta);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline UInt16 execute(UInt16 d, Int64 delta, const DateLUTImpl & time_zone)
|
|
|
|
{
|
2018-05-25 13:29:15 +00:00
|
|
|
return time_zone.addYears(DayNum(d), delta);
|
2017-10-29 04:18:48 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2017-10-30 05:26:31 +00:00
|
|
|
|
|
|
|
template <typename Transform>
|
|
|
|
struct SubtractIntervalImpl
|
|
|
|
{
|
|
|
|
static inline UInt32 execute(UInt32 t, Int64 delta, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
return Transform::execute(t, -delta, time_zone);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline UInt16 execute(UInt16 d, Int64 delta, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
return Transform::execute(d, -delta, time_zone);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
struct SubtractSecondsImpl : SubtractIntervalImpl<AddSecondsImpl> { static constexpr auto name = "subtractSeconds"; };
|
|
|
|
struct SubtractMinutesImpl : SubtractIntervalImpl<AddMinutesImpl> { static constexpr auto name = "subtractMinutes"; };
|
|
|
|
struct SubtractHoursImpl : SubtractIntervalImpl<AddHoursImpl> { static constexpr auto name = "subtractHours"; };
|
|
|
|
struct SubtractDaysImpl : SubtractIntervalImpl<AddDaysImpl> { static constexpr auto name = "subtractDays"; };
|
|
|
|
struct SubtractWeeksImpl : SubtractIntervalImpl<AddWeeksImpl> { static constexpr auto name = "subtractWeeks"; };
|
|
|
|
struct SubtractMonthsImpl : SubtractIntervalImpl<AddMonthsImpl> { static constexpr auto name = "subtractMonths"; };
|
|
|
|
struct SubtractYearsImpl : SubtractIntervalImpl<AddYearsImpl> { static constexpr auto name = "subtractYears"; };
|
|
|
|
|
|
|
|
|
2017-10-29 04:18:48 +00:00
|
|
|
template <typename FromType, typename ToType, typename Transform>
|
|
|
|
struct Adder
|
|
|
|
{
|
|
|
|
static void vector_vector(const PaddedPODArray<FromType> & vec_from, PaddedPODArray<ToType> & vec_to, const IColumn & delta, 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], delta.getInt(i), time_zone);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void vector_constant(const PaddedPODArray<FromType> & vec_from, PaddedPODArray<ToType> & vec_to, Int64 delta, 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], delta, time_zone);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void constant_vector(const FromType & from, PaddedPODArray<ToType> & vec_to, const IColumn & delta, const DateLUTImpl & time_zone)
|
|
|
|
{
|
|
|
|
size_t size = delta.size();
|
|
|
|
vec_to.resize(size);
|
|
|
|
|
|
|
|
for (size_t i = 0; i < size; ++i)
|
|
|
|
vec_to[i] = Transform::execute(from, delta.getInt(i), time_zone);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
template <typename FromType, typename Transform>
|
|
|
|
struct DateTimeAddIntervalImpl
|
|
|
|
{
|
|
|
|
static void execute(Block & block, const ColumnNumbers & arguments, size_t result)
|
|
|
|
{
|
|
|
|
using ToType = decltype(Transform::execute(FromType(), 0, std::declval<DateLUTImpl>()));
|
|
|
|
using Op = Adder<FromType, ToType, Transform>;
|
|
|
|
|
2017-12-22 01:54:29 +00:00
|
|
|
const DateLUTImpl & time_zone = extractTimeZoneFromFunctionArguments(block, arguments, 2, 0);
|
2017-10-29 04:18:48 +00:00
|
|
|
|
|
|
|
const ColumnPtr source_col = block.getByPosition(arguments[0]).column;
|
|
|
|
|
|
|
|
if (const auto * sources = checkAndGetColumn<ColumnVector<FromType>>(source_col.get()))
|
|
|
|
{
|
2017-12-14 01:43:19 +00:00
|
|
|
auto col_to = ColumnVector<ToType>::create();
|
2017-10-29 04:18:48 +00:00
|
|
|
|
|
|
|
const IColumn & delta_column = *block.getByPosition(arguments[1]).column;
|
|
|
|
|
|
|
|
if (const auto * delta_const_column = typeid_cast<const ColumnConst *>(&delta_column))
|
2017-11-05 05:32:22 +00:00
|
|
|
Op::vector_constant(sources->getData(), col_to->getData(), delta_const_column->getField().get<Int64>(), time_zone);
|
2017-10-29 04:18:48 +00:00
|
|
|
else
|
|
|
|
Op::vector_vector(sources->getData(), col_to->getData(), delta_column, time_zone);
|
2017-12-16 05:21:04 +00:00
|
|
|
|
|
|
|
block.getByPosition(result).column = std::move(col_to);
|
2017-10-29 04:18:48 +00:00
|
|
|
}
|
|
|
|
else if (const auto * sources = checkAndGetColumnConst<ColumnVector<FromType>>(source_col.get()))
|
|
|
|
{
|
2017-12-14 01:43:19 +00:00
|
|
|
auto col_to = ColumnVector<ToType>::create();
|
2017-10-29 04:18:48 +00:00
|
|
|
Op::constant_vector(sources->template getValue<FromType>(), col_to->getData(), *block.getByPosition(arguments[1]).column, time_zone);
|
2017-12-16 05:21:04 +00:00
|
|
|
block.getByPosition(result).column = std::move(col_to);
|
2017-10-29 04:18:48 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
throw Exception("Illegal column " + block.getByPosition(arguments[0]).column->getName()
|
|
|
|
+ " of first argument of function " + Transform::name,
|
|
|
|
ErrorCodes::ILLEGAL_COLUMN);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
template <typename Transform>
|
|
|
|
class FunctionDateOrDateTimeAddInterval : public IFunction
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
static constexpr auto name = Transform::name;
|
2018-08-26 00:50:48 +00:00
|
|
|
static FunctionPtr create(const Context &) { return std::make_shared<FunctionDateOrDateTimeAddInterval>(); }
|
2017-10-29 04:18:48 +00:00
|
|
|
|
|
|
|
String getName() const override
|
|
|
|
{
|
|
|
|
return name;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool isVariadic() const override { return true; }
|
|
|
|
size_t getNumberOfArguments() const override { return 0; }
|
|
|
|
|
2018-02-02 08:33:36 +00:00
|
|
|
DataTypePtr getReturnTypeImpl(const ColumnsWithTypeAndName & arguments) const override
|
2017-10-29 04:18:48 +00:00
|
|
|
{
|
|
|
|
if (arguments.size() != 2 && arguments.size() != 3)
|
|
|
|
throw Exception("Number of arguments for function " + getName() + " doesn't match: passed "
|
|
|
|
+ toString(arguments.size()) + ", should be 2 or 3",
|
|
|
|
ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
|
|
|
|
|
2018-09-07 14:37:26 +00:00
|
|
|
if (!isNumber(arguments[1].type))
|
2017-10-29 04:18:48 +00:00
|
|
|
throw Exception("Second argument for function " + getName() + " (delta) must be number",
|
|
|
|
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
|
|
|
|
|
|
|
if (arguments.size() == 2)
|
|
|
|
{
|
2018-09-07 14:37:26 +00:00
|
|
|
if (!isDateOrDateTime(arguments[0].type))
|
2018-05-07 02:01:11 +00:00
|
|
|
throw Exception{"Illegal type " + arguments[0].type->getName() + " of argument of function " + getName() +
|
2017-10-29 04:18:48 +00:00
|
|
|
". Should be a date or a date with time", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT};
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-09-07 14:37:26 +00:00
|
|
|
if (!WhichDataType(arguments[0].type).isDateTime()
|
|
|
|
|| !WhichDataType(arguments[2].type).isString())
|
2018-05-07 02:01:11 +00:00
|
|
|
throw Exception(
|
2017-10-29 04:18:48 +00:00
|
|
|
"Function " + getName() + " supports 2 or 3 arguments. The 1st argument "
|
|
|
|
"must be of type Date or DateTime. The 2nd argument must be number. "
|
|
|
|
"The 3rd argument (optional) must be "
|
|
|
|
"a constant string with timezone name. The timezone argument is allowed "
|
|
|
|
"only when the 1st argument has the type DateTime",
|
2018-05-07 02:01:11 +00:00
|
|
|
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
2017-10-29 04:18:48 +00:00
|
|
|
}
|
|
|
|
|
2018-09-07 14:37:26 +00:00
|
|
|
if (WhichDataType(arguments[0].type).isDate())
|
2017-11-05 05:32:22 +00:00
|
|
|
{
|
2017-12-25 04:01:46 +00:00
|
|
|
if (std::is_same_v<decltype(Transform::execute(DataTypeDate::FieldType(), 0, std::declval<DateLUTImpl>())), UInt16>)
|
2018-02-02 08:33:36 +00:00
|
|
|
return std::make_shared<DataTypeDate>();
|
2017-11-05 05:32:22 +00:00
|
|
|
else
|
2018-02-02 08:33:36 +00:00
|
|
|
return std::make_shared<DataTypeDateTime>(extractTimeZoneNameFromFunctionArguments(arguments, 2, 0));
|
2017-11-05 05:32:22 +00:00
|
|
|
}
|
2017-10-29 04:18:48 +00:00
|
|
|
else
|
2017-11-05 05:32:22 +00:00
|
|
|
{
|
2017-12-25 04:01:46 +00:00
|
|
|
if (std::is_same_v<decltype(Transform::execute(DataTypeDateTime::FieldType(), 0, std::declval<DateLUTImpl>())), UInt16>)
|
2018-02-02 08:33:36 +00:00
|
|
|
return std::make_shared<DataTypeDate>();
|
2017-11-05 05:32:22 +00:00
|
|
|
else
|
2018-02-02 08:33:36 +00:00
|
|
|
return std::make_shared<DataTypeDateTime>(extractTimeZoneNameFromFunctionArguments(arguments, 2, 0));
|
2017-11-05 05:32:22 +00:00
|
|
|
}
|
2017-10-29 04:18:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool useDefaultImplementationForConstants() const override { return true; }
|
|
|
|
ColumnNumbers getArgumentsThatAreAlwaysConstant() const override { return {2}; }
|
|
|
|
|
2018-04-24 07:16:39 +00:00
|
|
|
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result, size_t /*input_rows_count*/) override
|
2017-10-29 04:18:48 +00:00
|
|
|
{
|
|
|
|
const IDataType * from_type = block.getByPosition(arguments[0]).type.get();
|
2018-09-07 14:37:26 +00:00
|
|
|
WhichDataType which(from_type);
|
2017-10-29 04:18:48 +00:00
|
|
|
|
2018-09-07 14:37:26 +00:00
|
|
|
if (which.isDate())
|
2017-10-29 04:18:48 +00:00
|
|
|
DateTimeAddIntervalImpl<DataTypeDate::FieldType, Transform>::execute(block, arguments, result);
|
2018-09-07 14:37:26 +00:00
|
|
|
else if (which.isDateTime())
|
2017-10-29 04:18:48 +00:00
|
|
|
DateTimeAddIntervalImpl<DataTypeDateTime::FieldType, Transform>::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);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2017-12-22 01:54:29 +00:00
|
|
|
/** dateDiff('unit', t1, t2, [timezone])
|
|
|
|
* t1 and t2 can be Date or DateTime
|
|
|
|
*
|
|
|
|
* If timezone is specified, it applied to both arguments.
|
|
|
|
* If not, timezones from datatypes t1 and t2 are used.
|
|
|
|
* If that timezones are not the same, the result is unspecified.
|
|
|
|
*
|
|
|
|
* Timezone matters because days can have different length.
|
|
|
|
*/
|
|
|
|
class FunctionDateDiff : public IFunction
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
static constexpr auto name = "dateDiff";
|
2018-08-26 00:50:48 +00:00
|
|
|
static FunctionPtr create(const Context &) { return std::make_shared<FunctionDateDiff>(); }
|
2017-12-22 01:54:29 +00:00
|
|
|
|
|
|
|
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() != 3 && arguments.size() != 4)
|
|
|
|
throw Exception("Number of arguments for function " + getName() + " doesn't match: passed "
|
|
|
|
+ toString(arguments.size()) + ", should be 3 or 4",
|
|
|
|
ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
|
|
|
|
|
2018-09-07 14:37:26 +00:00
|
|
|
if (!isString(arguments[0]))
|
2017-12-22 01:54:29 +00:00
|
|
|
throw Exception("First argument for function " + getName() + " (unit) must be String",
|
|
|
|
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
|
|
|
|
2018-09-07 14:37:26 +00:00
|
|
|
if (!isDateOrDateTime(arguments[1]))
|
2017-12-22 01:54:29 +00:00
|
|
|
throw Exception("Second argument for function " + getName() + " must be Date or DateTime",
|
|
|
|
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
|
|
|
|
2018-09-07 14:37:26 +00:00
|
|
|
if (!isDateOrDateTime(arguments[2]))
|
2017-12-22 01:54:29 +00:00
|
|
|
throw Exception("Third argument for function " + getName() + " must be Date or DateTime",
|
|
|
|
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
|
|
|
|
2018-09-07 14:37:26 +00:00
|
|
|
if (arguments.size() == 4 && !isString(arguments[3]))
|
2017-12-22 01:54:29 +00:00
|
|
|
throw Exception("Fourth argument for function " + getName() + " (timezone) must be String",
|
|
|
|
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
|
|
|
|
|
|
|
return std::make_shared<DataTypeInt64>();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool useDefaultImplementationForConstants() const override { return true; }
|
|
|
|
ColumnNumbers getArgumentsThatAreAlwaysConstant() const override { return {0, 3}; }
|
|
|
|
|
2018-04-24 07:16:39 +00:00
|
|
|
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) override
|
2017-12-22 01:54:29 +00:00
|
|
|
{
|
|
|
|
auto * unit_column = checkAndGetColumnConst<ColumnString>(block.getByPosition(arguments[0]).column.get());
|
|
|
|
if (!unit_column)
|
|
|
|
throw Exception("First argument for function " + getName() + " must be constant String", ErrorCodes::ILLEGAL_COLUMN);
|
|
|
|
|
|
|
|
String unit = Poco::toLower(unit_column->getValue<String>());
|
|
|
|
|
|
|
|
const IColumn & x = *block.getByPosition(arguments[1]).column;
|
|
|
|
const IColumn & y = *block.getByPosition(arguments[2]).column;
|
|
|
|
|
2018-04-24 07:16:39 +00:00
|
|
|
size_t rows = input_rows_count;
|
2017-12-22 01:54:29 +00:00
|
|
|
auto res = ColumnInt64::create(rows);
|
|
|
|
|
|
|
|
const DateLUTImpl & timezone_x = extractTimeZoneFromFunctionArguments(block, arguments, 3, 1);
|
|
|
|
const DateLUTImpl & timezone_y = extractTimeZoneFromFunctionArguments(block, arguments, 3, 2);
|
|
|
|
|
|
|
|
if (unit == "year" || unit == "yy" || unit == "yyyy")
|
|
|
|
dispatchForColumns<ToRelativeYearNumImpl>(x, y, timezone_x, timezone_y, res->getData());
|
|
|
|
else if (unit == "quarter" || unit == "qq" || unit == "q")
|
|
|
|
dispatchForColumns<ToRelativeQuarterNumImpl>(x, y, timezone_x, timezone_y, res->getData());
|
|
|
|
else if (unit == "month" || unit == "mm" || unit == "m")
|
|
|
|
dispatchForColumns<ToRelativeMonthNumImpl>(x, y, timezone_x, timezone_y, res->getData());
|
|
|
|
else if (unit == "week" || unit == "wk" || unit == "ww")
|
|
|
|
dispatchForColumns<ToRelativeWeekNumImpl>(x, y, timezone_x, timezone_y, res->getData());
|
|
|
|
else if (unit == "day" || unit == "dd" || unit == "d")
|
|
|
|
dispatchForColumns<ToRelativeDayNumImpl>(x, y, timezone_x, timezone_y, res->getData());
|
|
|
|
else if (unit == "hour" || unit == "hh")
|
|
|
|
dispatchForColumns<ToRelativeHourNumImpl>(x, y, timezone_x, timezone_y, res->getData());
|
|
|
|
else if (unit == "minute" || unit == "mi" || unit == "n")
|
|
|
|
dispatchForColumns<ToRelativeMinuteNumImpl>(x, y, timezone_x, timezone_y, res->getData());
|
|
|
|
else if (unit == "second" || unit == "ss" || unit == "s")
|
|
|
|
dispatchForColumns<ToRelativeSecondNumImpl>(x, y, timezone_x, timezone_y, res->getData());
|
|
|
|
else
|
|
|
|
throw Exception("Function " + getName() + " does not support '" + unit + "' unit", ErrorCodes::BAD_ARGUMENTS);
|
|
|
|
|
|
|
|
block.getByPosition(result).column = std::move(res);
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
template <typename Transform>
|
|
|
|
void dispatchForColumns(
|
|
|
|
const IColumn & x, const IColumn & y,
|
|
|
|
const DateLUTImpl & timezone_x, const DateLUTImpl & timezone_y,
|
|
|
|
ColumnInt64::Container & result)
|
|
|
|
{
|
|
|
|
if (auto * x_vec = checkAndGetColumn<ColumnUInt16>(&x))
|
|
|
|
dispatchForSecondColumn<Transform>(*x_vec, y, timezone_x, timezone_y, result);
|
|
|
|
else if (auto * x_vec = checkAndGetColumn<ColumnUInt32>(&x))
|
|
|
|
dispatchForSecondColumn<Transform>(*x_vec, y, timezone_x, timezone_y, result);
|
|
|
|
else if (auto * x_const = checkAndGetColumnConst<ColumnUInt16>(&x))
|
|
|
|
dispatchConstForSecondColumn<Transform>(x_const->getValue<UInt16>(), y, timezone_x, timezone_y, result);
|
|
|
|
else if (auto * x_const = checkAndGetColumnConst<ColumnUInt32>(&x))
|
|
|
|
dispatchConstForSecondColumn<Transform>(x_const->getValue<UInt32>(), y, timezone_x, timezone_y, result);
|
|
|
|
else
|
|
|
|
throw Exception("Illegal column for first argument of function " + getName() + ", must be Date or DateTime", ErrorCodes::ILLEGAL_COLUMN);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename Transform, typename T1>
|
|
|
|
void dispatchForSecondColumn(
|
|
|
|
const ColumnVector<T1> & x, const IColumn & y,
|
|
|
|
const DateLUTImpl & timezone_x, const DateLUTImpl & timezone_y,
|
|
|
|
ColumnInt64::Container & result)
|
|
|
|
{
|
|
|
|
if (auto * y_vec = checkAndGetColumn<ColumnUInt16>(&y))
|
|
|
|
vector_vector<Transform>(x, *y_vec, timezone_x, timezone_y, result);
|
|
|
|
else if (auto * y_vec = checkAndGetColumn<ColumnUInt32>(&y))
|
|
|
|
vector_vector<Transform>(x, *y_vec, timezone_x, timezone_y, result);
|
|
|
|
else if (auto * y_const = checkAndGetColumnConst<ColumnUInt16>(&y))
|
|
|
|
vector_constant<Transform>(x, y_const->getValue<UInt16>(), timezone_x, timezone_y, result);
|
|
|
|
else if (auto * y_const = checkAndGetColumnConst<ColumnUInt32>(&y))
|
|
|
|
vector_constant<Transform>(x, y_const->getValue<UInt32>(), timezone_x, timezone_y, result);
|
|
|
|
else
|
|
|
|
throw Exception("Illegal column for second argument of function " + getName() + ", must be Date or DateTime", ErrorCodes::ILLEGAL_COLUMN);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename Transform, typename T1>
|
|
|
|
void dispatchConstForSecondColumn(
|
|
|
|
T1 x, const IColumn & y,
|
|
|
|
const DateLUTImpl & timezone_x, const DateLUTImpl & timezone_y,
|
|
|
|
ColumnInt64::Container & result)
|
|
|
|
{
|
|
|
|
if (auto * y_vec = checkAndGetColumn<ColumnUInt16>(&y))
|
|
|
|
constant_vector<Transform>(x, *y_vec, timezone_x, timezone_y, result);
|
|
|
|
else if (auto * y_vec = checkAndGetColumn<ColumnUInt32>(&y))
|
|
|
|
constant_vector<Transform>(x, *y_vec, timezone_x, timezone_y, result);
|
|
|
|
else
|
|
|
|
throw Exception("Illegal column for second argument of function " + getName() + ", must be Date or DateTime", ErrorCodes::ILLEGAL_COLUMN);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename Transform, typename T1, typename T2>
|
|
|
|
void vector_vector(
|
|
|
|
const ColumnVector<T1> & x, const ColumnVector<T2> & y,
|
|
|
|
const DateLUTImpl & timezone_x, const DateLUTImpl & timezone_y,
|
|
|
|
ColumnInt64::Container & result)
|
|
|
|
{
|
|
|
|
const auto & x_data = x.getData();
|
|
|
|
const auto & y_data = y.getData();
|
|
|
|
for (size_t i = 0, size = x.size(); i < size; ++i)
|
|
|
|
result[i] = calculate<Transform>(x_data[i], y_data[i], timezone_x, timezone_y);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename Transform, typename T1, typename T2>
|
|
|
|
void vector_constant(
|
|
|
|
const ColumnVector<T1> & x, T2 y,
|
|
|
|
const DateLUTImpl & timezone_x, const DateLUTImpl & timezone_y,
|
|
|
|
ColumnInt64::Container & result)
|
|
|
|
{
|
|
|
|
const auto & x_data = x.getData();
|
|
|
|
for (size_t i = 0, size = x.size(); i < size; ++i)
|
|
|
|
result[i] = calculate<Transform>(x_data[i], y, timezone_x, timezone_y);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename Transform, typename T1, typename T2>
|
|
|
|
void constant_vector(
|
|
|
|
T1 x, const ColumnVector<T2> & y,
|
|
|
|
const DateLUTImpl & timezone_x, const DateLUTImpl & timezone_y,
|
|
|
|
ColumnInt64::Container & result)
|
|
|
|
{
|
|
|
|
const auto & y_data = y.getData();
|
|
|
|
for (size_t i = 0, size = y.size(); i < size; ++i)
|
|
|
|
result[i] = calculate<Transform>(x, y_data[i], timezone_x, timezone_y);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename Transform, typename T1, typename T2>
|
|
|
|
Int64 calculate(T1 x, T2 y, const DateLUTImpl & timezone_x, const DateLUTImpl & timezone_y)
|
|
|
|
{
|
|
|
|
return Int64(Transform::execute(y, timezone_y))
|
|
|
|
- Int64(Transform::execute(x, timezone_x));
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
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";
|
2018-08-26 00:50:48 +00:00
|
|
|
static FunctionPtr create(const 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-12-02 02:47:12 +00:00
|
|
|
DataTypePtr getReturnTypeImpl(const DataTypes & /*arguments*/) const override
|
2017-04-01 07:20:54 +00:00
|
|
|
{
|
|
|
|
return std::make_shared<DataTypeDateTime>();
|
|
|
|
}
|
2012-08-31 20:38:05 +00:00
|
|
|
|
2018-08-08 11:26:18 +00:00
|
|
|
bool isDeterministic() const override { return false; }
|
2018-02-21 17:05:21 +00:00
|
|
|
|
2018-04-24 07:16:39 +00:00
|
|
|
void executeImpl(Block & block, const ColumnNumbers &, size_t result, size_t input_rows_count) override
|
2017-04-01 07:20:54 +00:00
|
|
|
{
|
2017-12-10 22:44:04 +00:00
|
|
|
block.getByPosition(result).column = DataTypeUInt32().createColumnConst(
|
2018-04-24 07:16:39 +00:00
|
|
|
input_rows_count,
|
2017-12-18 04:07:26 +00:00
|
|
|
static_cast<UInt64>(time(nullptr)));
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
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";
|
2018-08-26 00:50:48 +00:00
|
|
|
static FunctionPtr create(const 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-12-02 02:47:12 +00:00
|
|
|
DataTypePtr getReturnTypeImpl(const DataTypes & /*arguments*/) const override
|
2017-04-01 07:20:54 +00:00
|
|
|
{
|
|
|
|
return std::make_shared<DataTypeDate>();
|
|
|
|
}
|
2014-09-04 11:48:07 +00:00
|
|
|
|
2018-08-08 11:26:18 +00:00
|
|
|
bool isDeterministic() const override { return false; }
|
2018-02-21 17:05:21 +00:00
|
|
|
|
2018-04-24 07:16:39 +00:00
|
|
|
void executeImpl(Block & block, const ColumnNumbers &, size_t result, size_t input_rows_count) override
|
2017-04-01 07:20:54 +00:00
|
|
|
{
|
2017-12-10 22:44:04 +00:00
|
|
|
block.getByPosition(result).column = DataTypeUInt16().createColumnConst(
|
2018-04-24 07:16:39 +00:00
|
|
|
input_rows_count,
|
2017-12-18 04:07:26 +00:00
|
|
|
UInt64(DateLUT::instance().toDayNum(time(nullptr))));
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
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";
|
2018-08-26 00:50:48 +00:00
|
|
|
static FunctionPtr create(const 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-12-02 02:47:12 +00:00
|
|
|
DataTypePtr getReturnTypeImpl(const DataTypes & /*arguments*/) const override
|
2017-04-01 07:20:54 +00:00
|
|
|
{
|
|
|
|
return std::make_shared<DataTypeDate>();
|
|
|
|
}
|
2014-09-04 11:48:07 +00:00
|
|
|
|
2018-08-08 11:26:18 +00:00
|
|
|
bool isDeterministic() const override { return false; }
|
2018-02-21 17:05:21 +00:00
|
|
|
|
2018-04-24 07:16:39 +00:00
|
|
|
void executeImpl(Block & block, const ColumnNumbers &, size_t result, size_t input_rows_count) override
|
2017-04-01 07:20:54 +00:00
|
|
|
{
|
2017-12-10 22:44:04 +00:00
|
|
|
block.getByPosition(result).column = DataTypeUInt16().createColumnConst(
|
2018-04-24 07:16:39 +00:00
|
|
|
input_rows_count,
|
2017-12-18 04:07:26 +00:00
|
|
|
UInt64(DateLUT::instance().toDayNum(time(nullptr)) - 1));
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
2014-09-04 11:48:07 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2017-11-05 05:32:22 +00:00
|
|
|
/// Just changes time zone information for data type. The calculation is free.
|
|
|
|
class FunctionToTimeZone : public IFunction
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
static constexpr auto name = "toTimeZone";
|
2018-08-26 00:50:48 +00:00
|
|
|
static FunctionPtr create(const Context &) { return std::make_shared<FunctionToTimeZone>(); }
|
2017-11-05 05:32:22 +00:00
|
|
|
|
|
|
|
String getName() const override
|
|
|
|
{
|
|
|
|
return name;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t getNumberOfArguments() const override { return 2; }
|
|
|
|
|
2018-02-02 08:33:36 +00:00
|
|
|
DataTypePtr getReturnTypeImpl(const ColumnsWithTypeAndName & arguments) const override
|
2017-11-05 05:32:22 +00:00
|
|
|
{
|
|
|
|
if (arguments.size() != 2)
|
|
|
|
throw Exception("Number of arguments for function " + getName() + " doesn't match: passed "
|
|
|
|
+ toString(arguments.size()) + ", should be 2",
|
|
|
|
ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
|
|
|
|
|
2018-09-07 14:37:26 +00:00
|
|
|
if (!WhichDataType(arguments[0].type).isDateTime())
|
2018-05-07 02:01:11 +00:00
|
|
|
throw Exception{"Illegal type " + arguments[0].type->getName() + " of argument of function " + getName() +
|
2017-11-05 05:32:22 +00:00
|
|
|
". Should be DateTime", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT};
|
|
|
|
|
2017-12-22 01:54:29 +00:00
|
|
|
String time_zone_name = extractTimeZoneNameFromFunctionArguments(arguments, 1, 0);
|
2018-02-02 08:33:36 +00:00
|
|
|
return std::make_shared<DataTypeDateTime>(time_zone_name);
|
2017-11-05 05:32:22 +00:00
|
|
|
}
|
|
|
|
|
2018-04-24 07:16:39 +00:00
|
|
|
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result, size_t /*input_rows_count*/) override
|
2017-11-05 05:32:22 +00:00
|
|
|
{
|
|
|
|
block.getByPosition(result).column = block.getByPosition(arguments[0]).column;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
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";
|
2018-08-26 00:50:48 +00:00
|
|
|
static FunctionPtr create(const Context &) { return std::make_shared<FunctionTimeSlot>(); }
|
2017-04-01 07:20:54 +00:00
|
|
|
|
|
|
|
String getName() const override
|
|
|
|
{
|
|
|
|
return name;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t getNumberOfArguments() const override { return 1; }
|
|
|
|
|
|
|
|
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
|
|
|
{
|
2018-09-07 14:37:26 +00:00
|
|
|
if (!WhichDataType(arguments[0]).isDateTime())
|
2017-04-01 07:20:54 +00:00
|
|
|
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>();
|
|
|
|
}
|
|
|
|
|
2017-07-23 08:40:43 +00:00
|
|
|
bool useDefaultImplementationForConstants() const override { return true; }
|
|
|
|
|
2018-04-24 07:16:39 +00:00
|
|
|
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result, size_t /*input_rows_count*/) override
|
2017-04-01 07:20:54 +00:00
|
|
|
{
|
2017-07-21 06:35:58 +00:00
|
|
|
if (const ColumnUInt32 * times = typeid_cast<const ColumnUInt32 *>(block.getByPosition(arguments[0]).column.get()))
|
2017-04-01 07:20:54 +00:00
|
|
|
{
|
2017-12-14 01:43:19 +00:00
|
|
|
auto res = ColumnUInt32::create();
|
2017-12-15 21:32:25 +00:00
|
|
|
ColumnUInt32::Container & res_vec = res->getData();
|
|
|
|
const ColumnUInt32::Container & vec = times->getData();
|
2017-04-01 07:20:54 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
|
2017-12-16 04:59:32 +00:00
|
|
|
block.getByPosition(result).column = std::move(res);
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
|
|
|
else
|
2017-07-21 06:35:58 +00:00
|
|
|
throw Exception("Illegal column " + block.getByPosition(arguments[0]).column->getName()
|
2017-04-01 07:20:54 +00:00
|
|
|
+ " 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,
|
2017-12-15 21:32:25 +00:00
|
|
|
PaddedPODArray<UInt32> & result_values, ColumnArray::Offsets & result_offsets)
|
2017-04-01 07:20:54 +00:00
|
|
|
{
|
|
|
|
size_t size = starts.size();
|
|
|
|
|
|
|
|
result_offsets.resize(size);
|
|
|
|
result_values.reserve(size);
|
|
|
|
|
2017-12-15 21:32:25 +00:00
|
|
|
ColumnArray::Offset current_offset = 0;
|
2017-04-01 07:20:54 +00:00
|
|
|
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,
|
2017-12-15 21:32:25 +00:00
|
|
|
PaddedPODArray<UInt32> & result_values, ColumnArray::Offsets & result_offsets)
|
2017-04-01 07:20:54 +00:00
|
|
|
{
|
|
|
|
size_t size = starts.size();
|
|
|
|
|
|
|
|
result_offsets.resize(size);
|
|
|
|
result_values.reserve(size);
|
|
|
|
|
2017-12-15 21:32:25 +00:00
|
|
|
ColumnArray::Offset current_offset = 0;
|
2017-04-01 07:20:54 +00:00
|
|
|
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,
|
2017-12-15 21:32:25 +00:00
|
|
|
PaddedPODArray<UInt32> & result_values, ColumnArray::Offsets & result_offsets)
|
2017-04-01 07:20:54 +00:00
|
|
|
{
|
|
|
|
size_t size = durations.size();
|
|
|
|
|
|
|
|
result_offsets.resize(size);
|
|
|
|
result_values.reserve(size);
|
|
|
|
|
2017-12-15 21:32:25 +00:00
|
|
|
ColumnArray::Offset current_offset = 0;
|
2017-04-01 07:20:54 +00:00
|
|
|
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";
|
2018-08-26 00:50:48 +00:00
|
|
|
static FunctionPtr create(const Context &) { return std::make_shared<FunctionTimeSlots>(); }
|
2017-04-01 07:20:54 +00:00
|
|
|
|
|
|
|
String getName() const override
|
|
|
|
{
|
|
|
|
return name;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t getNumberOfArguments() const override { return 2; }
|
|
|
|
|
|
|
|
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
|
|
|
{
|
2018-09-07 14:37:26 +00:00
|
|
|
if (!WhichDataType(arguments[0]).isDateTime())
|
2017-04-01 07:20:54 +00:00
|
|
|
throw Exception("Illegal type " + arguments[0]->getName() + " of first argument of function " + getName() + ". Must be DateTime.",
|
|
|
|
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
|
|
|
|
2018-09-07 14:37:26 +00:00
|
|
|
if (!WhichDataType(arguments[1]).isUInt32())
|
2017-04-01 07:20:54 +00:00
|
|
|
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>());
|
|
|
|
}
|
|
|
|
|
2018-04-24 07:16:39 +00:00
|
|
|
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) override
|
2017-04-01 07:20:54 +00:00
|
|
|
{
|
2017-07-21 06:35:58 +00:00
|
|
|
auto starts = checkAndGetColumn<ColumnUInt32>(block.getByPosition(arguments[0]).column.get());
|
|
|
|
auto const_starts = checkAndGetColumnConst<ColumnUInt32>(block.getByPosition(arguments[0]).column.get());
|
2017-04-01 07:20:54 +00:00
|
|
|
|
2017-07-21 06:35:58 +00:00
|
|
|
auto durations = checkAndGetColumn<ColumnUInt32>(block.getByPosition(arguments[1]).column.get());
|
|
|
|
auto const_durations = checkAndGetColumnConst<ColumnUInt32>(block.getByPosition(arguments[1]).column.get());
|
2017-04-01 07:20:54 +00:00
|
|
|
|
2017-12-14 01:43:19 +00:00
|
|
|
auto res = ColumnArray::create(ColumnUInt32::create());
|
2017-12-15 21:32:25 +00:00
|
|
|
ColumnUInt32::Container & res_values = typeid_cast<ColumnUInt32 &>(res->getData()).getData();
|
2017-04-01 07:20:54 +00:00
|
|
|
|
|
|
|
if (starts && durations)
|
|
|
|
{
|
|
|
|
TimeSlotsImpl<UInt32>::vector_vector(starts->getData(), durations->getData(), res_values, res->getOffsets());
|
2017-12-16 04:59:32 +00:00
|
|
|
block.getByPosition(result).column = std::move(res);
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
|
|
|
else if (starts && const_durations)
|
|
|
|
{
|
2017-07-21 06:35:58 +00:00
|
|
|
TimeSlotsImpl<UInt32>::vector_constant(starts->getData(), const_durations->getValue<UInt32>(), res_values, res->getOffsets());
|
2017-12-16 04:59:32 +00:00
|
|
|
block.getByPosition(result).column = std::move(res);
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
|
|
|
else if (const_starts && durations)
|
|
|
|
{
|
2017-07-21 06:35:58 +00:00
|
|
|
TimeSlotsImpl<UInt32>::constant_vector(const_starts->getValue<UInt32>(), durations->getData(), res_values, res->getOffsets());
|
2017-12-16 04:59:32 +00:00
|
|
|
block.getByPosition(result).column = std::move(res);
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
|
|
|
else if (const_starts && const_durations)
|
|
|
|
{
|
|
|
|
Array const_res;
|
2017-07-21 06:35:58 +00:00
|
|
|
TimeSlotsImpl<UInt32>::constant_constant(const_starts->getValue<UInt32>(), const_durations->getValue<UInt32>(), const_res);
|
2018-04-24 07:16:39 +00:00
|
|
|
block.getByPosition(result).column = block.getByPosition(result).type->createColumnConst(input_rows_count, const_res);
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
|
|
|
else
|
2017-07-21 06:35:58 +00:00
|
|
|
throw Exception("Illegal columns " + block.getByPosition(arguments[0]).column->getName()
|
|
|
|
+ ", " + block.getByPosition(arguments[1]).column->getName()
|
2017-04-01 07:20:54 +00:00
|
|
|
+ " of arguments of function " + getName(),
|
|
|
|
ErrorCodes::ILLEGAL_COLUMN);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2017-10-29 04:18:48 +00:00
|
|
|
using FunctionToYear = FunctionDateOrDateTimeToSomething<DataTypeUInt16, ToYearImpl>;
|
2017-12-22 01:54:29 +00:00
|
|
|
using FunctionToQuarter = FunctionDateOrDateTimeToSomething<DataTypeUInt8, ToQuarterImpl>;
|
2017-10-29 04:18:48 +00:00
|
|
|
using FunctionToMonth = FunctionDateOrDateTimeToSomething<DataTypeUInt8, ToMonthImpl>;
|
|
|
|
using FunctionToDayOfMonth = FunctionDateOrDateTimeToSomething<DataTypeUInt8, ToDayOfMonthImpl>;
|
|
|
|
using FunctionToDayOfWeek = FunctionDateOrDateTimeToSomething<DataTypeUInt8, ToDayOfWeekImpl>;
|
|
|
|
using FunctionToHour = FunctionDateOrDateTimeToSomething<DataTypeUInt8, ToHourImpl>;
|
|
|
|
using FunctionToMinute = FunctionDateOrDateTimeToSomething<DataTypeUInt8, ToMinuteImpl>;
|
|
|
|
using FunctionToSecond = FunctionDateOrDateTimeToSomething<DataTypeUInt8, ToSecondImpl>;
|
|
|
|
using FunctionToStartOfDay = FunctionDateOrDateTimeToSomething<DataTypeDateTime, ToStartOfDayImpl>;
|
|
|
|
using FunctionToMonday = FunctionDateOrDateTimeToSomething<DataTypeDate, ToMondayImpl>;
|
|
|
|
using FunctionToStartOfMonth = FunctionDateOrDateTimeToSomething<DataTypeDate, ToStartOfMonthImpl>;
|
|
|
|
using FunctionToStartOfQuarter = FunctionDateOrDateTimeToSomething<DataTypeDate, ToStartOfQuarterImpl>;
|
|
|
|
using FunctionToStartOfYear = FunctionDateOrDateTimeToSomething<DataTypeDate, ToStartOfYearImpl>;
|
|
|
|
using FunctionToStartOfMinute = FunctionDateOrDateTimeToSomething<DataTypeDateTime, ToStartOfMinuteImpl>;
|
|
|
|
using FunctionToStartOfFiveMinute = FunctionDateOrDateTimeToSomething<DataTypeDateTime, ToStartOfFiveMinuteImpl>;
|
2017-12-22 10:36:39 +00:00
|
|
|
using FunctionToStartOfFifteenMinutes = FunctionDateOrDateTimeToSomething<DataTypeDateTime, ToStartOfFifteenMinutesImpl>;
|
2017-10-29 04:18:48 +00:00
|
|
|
using FunctionToStartOfHour = FunctionDateOrDateTimeToSomething<DataTypeDateTime, ToStartOfHourImpl>;
|
|
|
|
using FunctionToTime = FunctionDateOrDateTimeToSomething<DataTypeDateTime, ToTimeImpl>;
|
|
|
|
|
|
|
|
using FunctionToRelativeYearNum = FunctionDateOrDateTimeToSomething<DataTypeUInt16, ToRelativeYearNumImpl>;
|
2017-12-22 01:54:29 +00:00
|
|
|
using FunctionToRelativeQuarterNum = FunctionDateOrDateTimeToSomething<DataTypeUInt32, ToRelativeQuarterNumImpl>;
|
2017-10-29 04:18:48 +00:00
|
|
|
using FunctionToRelativeMonthNum = FunctionDateOrDateTimeToSomething<DataTypeUInt32, ToRelativeMonthNumImpl>;
|
|
|
|
using FunctionToRelativeWeekNum = FunctionDateOrDateTimeToSomething<DataTypeUInt32, ToRelativeWeekNumImpl>;
|
|
|
|
using FunctionToRelativeDayNum = FunctionDateOrDateTimeToSomething<DataTypeUInt32, ToRelativeDayNumImpl>;
|
|
|
|
using FunctionToRelativeHourNum = FunctionDateOrDateTimeToSomething<DataTypeUInt32, ToRelativeHourNumImpl>;
|
|
|
|
using FunctionToRelativeMinuteNum = FunctionDateOrDateTimeToSomething<DataTypeUInt32, ToRelativeMinuteNumImpl>;
|
|
|
|
using FunctionToRelativeSecondNum = FunctionDateOrDateTimeToSomething<DataTypeUInt32, ToRelativeSecondNumImpl>;
|
|
|
|
|
|
|
|
using FunctionToYYYYMM = FunctionDateOrDateTimeToSomething<DataTypeUInt32, ToYYYYMMImpl>;
|
|
|
|
using FunctionToYYYYMMDD = FunctionDateOrDateTimeToSomething<DataTypeUInt32, ToYYYYMMDDImpl>;
|
|
|
|
using FunctionToYYYYMMDDhhmmss = FunctionDateOrDateTimeToSomething<DataTypeUInt64, ToYYYYMMDDhhmmssImpl>;
|
|
|
|
|
|
|
|
using FunctionAddSeconds = FunctionDateOrDateTimeAddInterval<AddSecondsImpl>;
|
|
|
|
using FunctionAddMinutes = FunctionDateOrDateTimeAddInterval<AddMinutesImpl>;
|
|
|
|
using FunctionAddHours = FunctionDateOrDateTimeAddInterval<AddHoursImpl>;
|
|
|
|
using FunctionAddDays = FunctionDateOrDateTimeAddInterval<AddDaysImpl>;
|
|
|
|
using FunctionAddWeeks = FunctionDateOrDateTimeAddInterval<AddWeeksImpl>;
|
|
|
|
using FunctionAddMonths = FunctionDateOrDateTimeAddInterval<AddMonthsImpl>;
|
|
|
|
using FunctionAddYears = FunctionDateOrDateTimeAddInterval<AddYearsImpl>;
|
2014-01-22 12:27:55 +00:00
|
|
|
|
2017-10-30 05:26:31 +00:00
|
|
|
using FunctionSubtractSeconds = FunctionDateOrDateTimeAddInterval<SubtractSecondsImpl>;
|
|
|
|
using FunctionSubtractMinutes = FunctionDateOrDateTimeAddInterval<SubtractMinutesImpl>;
|
|
|
|
using FunctionSubtractHours = FunctionDateOrDateTimeAddInterval<SubtractHoursImpl>;
|
|
|
|
using FunctionSubtractDays = FunctionDateOrDateTimeAddInterval<SubtractDaysImpl>;
|
|
|
|
using FunctionSubtractWeeks = FunctionDateOrDateTimeAddInterval<SubtractWeeksImpl>;
|
|
|
|
using FunctionSubtractMonths = FunctionDateOrDateTimeAddInterval<SubtractMonthsImpl>;
|
|
|
|
using FunctionSubtractYears = FunctionDateOrDateTimeAddInterval<SubtractYearsImpl>;
|
|
|
|
|
2011-10-16 04:17:41 +00:00
|
|
|
}
|