mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-22 23:52:03 +00:00
Merge branch 'master' into order-by-remerge
This commit is contained in:
commit
042536177d
@ -1,5 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <common/likely.h>
|
#include <common/arithmeticOverflow.h>
|
||||||
#include <Common/typeid_cast.h>
|
#include <Common/typeid_cast.h>
|
||||||
#include <Columns/ColumnDecimal.h>
|
#include <Columns/ColumnDecimal.h>
|
||||||
#include <DataTypes/IDataType.h>
|
#include <DataTypes/IDataType.h>
|
||||||
@ -12,9 +12,9 @@ namespace DB
|
|||||||
|
|
||||||
namespace ErrorCodes
|
namespace ErrorCodes
|
||||||
{
|
{
|
||||||
extern const int LOGICAL_ERROR;
|
|
||||||
extern const int ARGUMENT_OUT_OF_BOUND;
|
extern const int ARGUMENT_OUT_OF_BOUND;
|
||||||
extern const int CANNOT_CONVERT_TYPE;
|
extern const int CANNOT_CONVERT_TYPE;
|
||||||
|
extern const int DECIMAL_OVERFLOW;
|
||||||
}
|
}
|
||||||
|
|
||||||
class Context;
|
class Context;
|
||||||
@ -39,9 +39,7 @@ DataTypePtr createDecimal(UInt64 precision, UInt64 scale);
|
|||||||
/// Int128 38
|
/// Int128 38
|
||||||
/// Operation between two decimals leads to Decimal(P, S), where
|
/// Operation between two decimals leads to Decimal(P, S), where
|
||||||
/// P is one of (9, 18, 38); equals to the maximum precision for the biggest underlying type of operands.
|
/// P is one of (9, 18, 38); equals to the maximum precision for the biggest underlying type of operands.
|
||||||
/// S is maximum scale of operands.
|
/// S is maximum scale of operands. The allowed valuas are [0, precision]
|
||||||
///
|
|
||||||
/// NOTE: It's possible to set scale as a template parameter then most of functions become static.
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class DataTypeDecimal final : public DataTypeWithSimpleSerialization
|
class DataTypeDecimal final : public DataTypeWithSimpleSerialization
|
||||||
{
|
{
|
||||||
@ -156,7 +154,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
const UInt32 precision;
|
const UInt32 precision;
|
||||||
const UInt32 scale; /// TODO: should we support scales out of [0, precision]?
|
const UInt32 scale;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -221,49 +219,86 @@ template <> constexpr bool IsDataTypeDecimal<DataTypeDecimal<Decimal32>> = true;
|
|||||||
template <> constexpr bool IsDataTypeDecimal<DataTypeDecimal<Decimal64>> = true;
|
template <> constexpr bool IsDataTypeDecimal<DataTypeDecimal<Decimal64>> = true;
|
||||||
template <> constexpr bool IsDataTypeDecimal<DataTypeDecimal<Decimal128>> = true;
|
template <> constexpr bool IsDataTypeDecimal<DataTypeDecimal<Decimal128>> = true;
|
||||||
|
|
||||||
|
template <typename DataType> constexpr bool IsDataTypeDecimalOrNumber = IsDataTypeDecimal<DataType> || IsDataTypeNumber<DataType>;
|
||||||
|
|
||||||
template <typename FromDataType, typename ToDataType>
|
template <typename FromDataType, typename ToDataType>
|
||||||
inline std::enable_if_t<IsDataTypeDecimal<FromDataType> && IsDataTypeDecimal<ToDataType>, typename ToDataType::FieldType>
|
inline std::enable_if_t<IsDataTypeDecimal<FromDataType> && IsDataTypeDecimal<ToDataType>, typename ToDataType::FieldType>
|
||||||
convertDecimals(const typename FromDataType::FieldType & value, UInt32 scale_from, UInt32 scale_to)
|
convertDecimals(const typename FromDataType::FieldType & value, UInt32 scale_from, UInt32 scale_to)
|
||||||
{
|
{
|
||||||
ToDataType type_to(ToDataType::maxPrecision(), scale_to);
|
using FromFieldType = typename FromDataType::FieldType;
|
||||||
FromDataType type_from(FromDataType::maxPrecision(), scale_from);
|
using ToFieldType = typename ToDataType::FieldType;
|
||||||
|
using MaxFieldType = std::conditional_t<(sizeof(FromFieldType) > sizeof(ToFieldType)), FromFieldType, ToFieldType>;
|
||||||
|
using MaxNativeType = typename MaxFieldType::NativeType;
|
||||||
|
|
||||||
if (scale_from > scale_to)
|
MaxNativeType converted_value;
|
||||||
|
if (scale_to > scale_from)
|
||||||
{
|
{
|
||||||
typename FromDataType::FieldType factor = type_from.scaleFactorFor(type_to, false);
|
converted_value = DataTypeDecimal<MaxFieldType>::getScaleMultiplier(scale_to - scale_from);
|
||||||
return value / factor;
|
if (common::mulOverflow(static_cast<MaxNativeType>(value), converted_value, converted_value))
|
||||||
|
throw Exception("Decimal convert overflow", ErrorCodes::DECIMAL_OVERFLOW);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
converted_value = value / DataTypeDecimal<MaxFieldType>::getScaleMultiplier(scale_from - scale_to);
|
||||||
|
|
||||||
|
if constexpr (sizeof(FromFieldType) > sizeof(ToFieldType))
|
||||||
{
|
{
|
||||||
typename ToDataType::FieldType factor = type_to.scaleFactorFor(type_from, false);
|
if (converted_value < std::numeric_limits<typename ToFieldType::NativeType>::min() ||
|
||||||
return value * factor;
|
converted_value > std::numeric_limits<typename ToFieldType::NativeType>::max())
|
||||||
|
throw Exception("Decimal convert overflow", ErrorCodes::DECIMAL_OVERFLOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
return converted_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename FromDataType, typename ToDataType>
|
||||||
|
inline std::enable_if_t<IsDataTypeDecimal<FromDataType> && IsDataTypeNumber<ToDataType>, typename ToDataType::FieldType>
|
||||||
|
convertFromDecimal(const typename FromDataType::FieldType & value, UInt32 scale)
|
||||||
|
{
|
||||||
|
using FromFieldType = typename FromDataType::FieldType;
|
||||||
|
using ToFieldType = typename ToDataType::FieldType;
|
||||||
|
|
||||||
|
if constexpr (std::is_floating_point_v<ToFieldType>)
|
||||||
|
return static_cast<ToFieldType>(value) / FromDataType::getScaleMultiplier(scale);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FromFieldType converted_value = convertDecimals<FromDataType, FromDataType>(value, scale, 0);
|
||||||
|
|
||||||
|
if constexpr (sizeof(FromFieldType) > sizeof(ToFieldType) || !std::numeric_limits<ToFieldType>::is_signed)
|
||||||
|
{
|
||||||
|
if constexpr (std::numeric_limits<ToFieldType>::is_signed)
|
||||||
|
{
|
||||||
|
if (converted_value < std::numeric_limits<ToFieldType>::min() ||
|
||||||
|
converted_value > std::numeric_limits<ToFieldType>::max())
|
||||||
|
throw Exception("Decimal convert overflow", ErrorCodes::DECIMAL_OVERFLOW);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
using CastIntType = std::conditional_t<std::is_same_v<ToFieldType, UInt64>, Int128, Int64>;
|
||||||
|
|
||||||
|
if (converted_value < 0 ||
|
||||||
|
converted_value > static_cast<CastIntType>(std::numeric_limits<ToFieldType>::max()))
|
||||||
|
throw Exception("Decimal convert overflow", ErrorCodes::DECIMAL_OVERFLOW);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return converted_value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename FromDataType, typename ToDataType>
|
template <typename FromDataType, typename ToDataType>
|
||||||
inline std::enable_if_t<IsDataTypeDecimal<FromDataType> && !IsDataTypeDecimal<ToDataType>, typename ToDataType::FieldType>
|
inline std::enable_if_t<IsDataTypeNumber<FromDataType> && IsDataTypeDecimal<ToDataType>, typename ToDataType::FieldType>
|
||||||
convertFromDecimal(const typename FromDataType::FieldType & value, UInt32 scale [[maybe_unused]])
|
convertToDecimal(const typename FromDataType::FieldType & value, UInt32 scale)
|
||||||
{
|
{
|
||||||
if (scale > FromDataType::maxPrecision())
|
using FromFieldType = typename FromDataType::FieldType;
|
||||||
throw Exception("Wrong decimal scale", ErrorCodes::LOGICAL_ERROR);
|
|
||||||
|
|
||||||
if constexpr (!std::is_same_v<ToDataType, DataTypeNumber<typename ToDataType::FieldType>>)
|
if constexpr (std::is_floating_point_v<FromFieldType>)
|
||||||
throw Exception("Illegal convertion from decimal", ErrorCodes::CANNOT_CONVERT_TYPE);
|
|
||||||
else
|
|
||||||
return static_cast<typename ToDataType::FieldType>(value) / FromDataType::getScaleMultiplier(scale);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename FromDataType, typename ToDataType>
|
|
||||||
inline std::enable_if_t<!IsDataTypeDecimal<FromDataType> && IsDataTypeDecimal<ToDataType>, typename ToDataType::FieldType>
|
|
||||||
convertToDecimal(const typename FromDataType::FieldType & value, UInt32 scale [[maybe_unused]])
|
|
||||||
{
|
|
||||||
if (scale > ToDataType::maxPrecision())
|
|
||||||
throw Exception("Wrong decimal scale", ErrorCodes::LOGICAL_ERROR);
|
|
||||||
|
|
||||||
if constexpr (!std::is_same_v<FromDataType, DataTypeNumber<typename FromDataType::FieldType>>)
|
|
||||||
throw Exception("Illegal convertion to decimal", ErrorCodes::CANNOT_CONVERT_TYPE);
|
|
||||||
else
|
|
||||||
return value * ToDataType::getScaleMultiplier(scale);
|
return value * ToDataType::getScaleMultiplier(scale);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if constexpr (std::is_same_v<FromFieldType, UInt64>)
|
||||||
|
if (value > static_cast<UInt64>(std::numeric_limits<Int64>::max()))
|
||||||
|
return convertDecimals<DataTypeDecimal<Decimal128>, ToDataType>(value, 0, scale);
|
||||||
|
return convertDecimals<DataTypeDecimal<Decimal64>, ToDataType>(value, 0, scale);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
651
dbms/src/Functions/DateTimeTransforms.h
Normal file
651
dbms/src/Functions/DateTimeTransforms.h
Normal file
@ -0,0 +1,651 @@
|
|||||||
|
#include <Core/Types.h>
|
||||||
|
#include <Common/Exception.h>
|
||||||
|
#include <common/DateLUTImpl.h>
|
||||||
|
#include <Columns/ColumnVector.h>
|
||||||
|
#include <Functions/FunctionHelpers.h>
|
||||||
|
#include <Functions/extractTimeZoneFromFunctionArguments.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace ErrorCodes
|
||||||
|
{
|
||||||
|
extern const int ILLEGAL_TYPE_OF_ARGUMENT;
|
||||||
|
extern const int ILLEGAL_COLUMN;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Transformations.
|
||||||
|
* Represents two functions - from datetime (UInt32) and from date (UInt16).
|
||||||
|
*
|
||||||
|
* 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 for T
|
||||||
|
* (for a fixed value of F, the transformation T is monotonic).
|
||||||
|
*
|
||||||
|
* Or, figuratively, if T is similar to taking the remainder of division, then F is similar to division.
|
||||||
|
*
|
||||||
|
* Example: for transformation 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).
|
||||||
|
*/
|
||||||
|
|
||||||
|
static inline UInt32 dateIsNotSupported(const char * name)
|
||||||
|
{
|
||||||
|
throw Exception("Illegal type Date of argument for function " + std::string(name), ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This factor transformation will say that the function is monotone everywhere.
|
||||||
|
struct ZeroTransform
|
||||||
|
{
|
||||||
|
static inline UInt16 execute(UInt32, const DateLUTImpl &) { return 0; }
|
||||||
|
static inline UInt16 execute(UInt16, const DateLUTImpl &) { return 0; }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ToDateImpl
|
||||||
|
{
|
||||||
|
static constexpr auto name = "toDate";
|
||||||
|
|
||||||
|
static inline UInt16 execute(UInt32 t, const DateLUTImpl & time_zone)
|
||||||
|
{
|
||||||
|
return UInt16(time_zone.toDayNum(t));
|
||||||
|
}
|
||||||
|
static inline UInt16 execute(UInt16 d, const DateLUTImpl &)
|
||||||
|
{
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
using FactorTransform = ZeroTransform;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ToStartOfDayImpl
|
||||||
|
{
|
||||||
|
static constexpr auto name = "toStartOfDay";
|
||||||
|
|
||||||
|
static inline UInt32 execute(UInt32 t, const DateLUTImpl & time_zone)
|
||||||
|
{
|
||||||
|
return time_zone.toDate(t);
|
||||||
|
}
|
||||||
|
static inline UInt32 execute(UInt16, const DateLUTImpl &)
|
||||||
|
{
|
||||||
|
return dateIsNotSupported(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
using FactorTransform = ZeroTransform;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ToMondayImpl
|
||||||
|
{
|
||||||
|
static constexpr auto name = "toMonday";
|
||||||
|
|
||||||
|
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(d));
|
||||||
|
}
|
||||||
|
|
||||||
|
using FactorTransform = ZeroTransform;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ToStartOfMonthImpl
|
||||||
|
{
|
||||||
|
static constexpr auto name = "toStartOfMonth";
|
||||||
|
|
||||||
|
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(d));
|
||||||
|
}
|
||||||
|
|
||||||
|
using FactorTransform = ZeroTransform;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ToStartOfQuarterImpl
|
||||||
|
{
|
||||||
|
static constexpr auto name = "toStartOfQuarter";
|
||||||
|
|
||||||
|
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(d));
|
||||||
|
}
|
||||||
|
|
||||||
|
using FactorTransform = ZeroTransform;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ToStartOfYearImpl
|
||||||
|
{
|
||||||
|
static constexpr auto name = "toStartOfYear";
|
||||||
|
|
||||||
|
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(d));
|
||||||
|
}
|
||||||
|
|
||||||
|
using FactorTransform = ZeroTransform;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct ToTimeImpl
|
||||||
|
{
|
||||||
|
static constexpr auto name = "toTime";
|
||||||
|
|
||||||
|
/// When transforming to time, the date will be equated to 1970-01-02.
|
||||||
|
static inline UInt32 execute(UInt32 t, const DateLUTImpl & time_zone)
|
||||||
|
{
|
||||||
|
return time_zone.toTime(t) + 86400;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline UInt32 execute(UInt16, const DateLUTImpl &)
|
||||||
|
{
|
||||||
|
return dateIsNotSupported(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
using FactorTransform = ToDateImpl;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ToStartOfMinuteImpl
|
||||||
|
{
|
||||||
|
static constexpr auto name = "toStartOfMinute";
|
||||||
|
|
||||||
|
static inline UInt32 execute(UInt32 t, const DateLUTImpl & time_zone)
|
||||||
|
{
|
||||||
|
return time_zone.toStartOfMinute(t);
|
||||||
|
}
|
||||||
|
static inline UInt32 execute(UInt16, const DateLUTImpl &)
|
||||||
|
{
|
||||||
|
return dateIsNotSupported(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
using FactorTransform = ZeroTransform;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ToStartOfFiveMinuteImpl
|
||||||
|
{
|
||||||
|
static constexpr auto name = "toStartOfFiveMinute";
|
||||||
|
|
||||||
|
static inline UInt32 execute(UInt32 t, const DateLUTImpl & time_zone)
|
||||||
|
{
|
||||||
|
return time_zone.toStartOfFiveMinute(t);
|
||||||
|
}
|
||||||
|
static inline UInt32 execute(UInt16, const DateLUTImpl &)
|
||||||
|
{
|
||||||
|
return dateIsNotSupported(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
using FactorTransform = ZeroTransform;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ToStartOfFifteenMinutesImpl
|
||||||
|
{
|
||||||
|
static constexpr auto name = "toStartOfFifteenMinutes";
|
||||||
|
|
||||||
|
static inline UInt32 execute(UInt32 t, const DateLUTImpl & time_zone)
|
||||||
|
{
|
||||||
|
return time_zone.toStartOfFifteenMinutes(t);
|
||||||
|
}
|
||||||
|
static inline UInt32 execute(UInt16, const DateLUTImpl &)
|
||||||
|
{
|
||||||
|
return dateIsNotSupported(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
using FactorTransform = ZeroTransform;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Round to start of half-an-hour length interval with unspecified offset. This transform is specific for Yandex.Metrica.
|
||||||
|
struct TimeSlotImpl
|
||||||
|
{
|
||||||
|
static constexpr auto name = "timeSlot";
|
||||||
|
|
||||||
|
static inline UInt32 execute(UInt32 t, const DateLUTImpl &)
|
||||||
|
{
|
||||||
|
return t / 1800 * 1800;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline UInt32 execute(UInt16, const DateLUTImpl &)
|
||||||
|
{
|
||||||
|
return dateIsNotSupported(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
using FactorTransform = ZeroTransform;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ToStartOfHourImpl
|
||||||
|
{
|
||||||
|
static constexpr auto name = "toStartOfHour";
|
||||||
|
|
||||||
|
static inline UInt32 execute(UInt32 t, const DateLUTImpl & time_zone)
|
||||||
|
{
|
||||||
|
return time_zone.toStartOfHour(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline UInt32 execute(UInt16, const DateLUTImpl &)
|
||||||
|
{
|
||||||
|
return dateIsNotSupported(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
using FactorTransform = ZeroTransform;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ToYearImpl
|
||||||
|
{
|
||||||
|
static constexpr auto name = "toYear";
|
||||||
|
|
||||||
|
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(d));
|
||||||
|
}
|
||||||
|
|
||||||
|
using FactorTransform = ZeroTransform;
|
||||||
|
};
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
return time_zone.toQuarter(DayNum(d));
|
||||||
|
}
|
||||||
|
|
||||||
|
using FactorTransform = ToStartOfYearImpl;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ToMonthImpl
|
||||||
|
{
|
||||||
|
static constexpr auto name = "toMonth";
|
||||||
|
|
||||||
|
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(d));
|
||||||
|
}
|
||||||
|
|
||||||
|
using FactorTransform = ToStartOfYearImpl;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ToDayOfMonthImpl
|
||||||
|
{
|
||||||
|
static constexpr auto name = "toDayOfMonth";
|
||||||
|
|
||||||
|
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(d));
|
||||||
|
}
|
||||||
|
|
||||||
|
using FactorTransform = ToStartOfMonthImpl;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ToDayOfWeekImpl
|
||||||
|
{
|
||||||
|
static constexpr auto name = "toDayOfWeek";
|
||||||
|
|
||||||
|
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(d));
|
||||||
|
}
|
||||||
|
|
||||||
|
using FactorTransform = ToMondayImpl;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ToDayOfYearImpl
|
||||||
|
{
|
||||||
|
static constexpr auto name = "toDayOfYear";
|
||||||
|
|
||||||
|
static inline UInt16 execute(UInt32 t, const DateLUTImpl & time_zone)
|
||||||
|
{
|
||||||
|
return time_zone.toDayOfYear(t);
|
||||||
|
}
|
||||||
|
static inline UInt16 execute(UInt16 d, const DateLUTImpl & time_zone)
|
||||||
|
{
|
||||||
|
return time_zone.toDayOfYear(DayNum(d));
|
||||||
|
}
|
||||||
|
|
||||||
|
using FactorTransform = ToStartOfYearImpl;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ToHourImpl
|
||||||
|
{
|
||||||
|
static constexpr auto name = "toHour";
|
||||||
|
|
||||||
|
static inline UInt8 execute(UInt32 t, const DateLUTImpl & time_zone)
|
||||||
|
{
|
||||||
|
return time_zone.toHour(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline UInt8 execute(UInt16, const DateLUTImpl &)
|
||||||
|
{
|
||||||
|
return dateIsNotSupported(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
using FactorTransform = ToDateImpl;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ToMinuteImpl
|
||||||
|
{
|
||||||
|
static constexpr auto name = "toMinute";
|
||||||
|
|
||||||
|
static inline UInt8 execute(UInt32 t, const DateLUTImpl & time_zone)
|
||||||
|
{
|
||||||
|
return time_zone.toMinute(t);
|
||||||
|
}
|
||||||
|
static inline UInt8 execute(UInt16, const DateLUTImpl &)
|
||||||
|
{
|
||||||
|
return dateIsNotSupported(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
using FactorTransform = ToStartOfHourImpl;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ToSecondImpl
|
||||||
|
{
|
||||||
|
static constexpr auto name = "toSecond";
|
||||||
|
|
||||||
|
static inline UInt8 execute(UInt32 t, const DateLUTImpl & time_zone)
|
||||||
|
{
|
||||||
|
return time_zone.toSecond(t);
|
||||||
|
}
|
||||||
|
static inline UInt8 execute(UInt16, const DateLUTImpl &)
|
||||||
|
{
|
||||||
|
return dateIsNotSupported(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
using FactorTransform = ToStartOfMinuteImpl;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ToISOYearImpl
|
||||||
|
{
|
||||||
|
static constexpr auto name = "toISOYear";
|
||||||
|
|
||||||
|
static inline UInt16 execute(UInt32 t, const DateLUTImpl & time_zone)
|
||||||
|
{
|
||||||
|
return time_zone.toISOYear(time_zone.toDayNum(t));
|
||||||
|
}
|
||||||
|
static inline UInt16 execute(UInt16 d, const DateLUTImpl & time_zone)
|
||||||
|
{
|
||||||
|
return time_zone.toISOYear(DayNum(d));
|
||||||
|
}
|
||||||
|
|
||||||
|
using FactorTransform = ZeroTransform;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ToStartOfISOYearImpl
|
||||||
|
{
|
||||||
|
static constexpr auto name = "toStartOfISOYear";
|
||||||
|
|
||||||
|
static inline UInt16 execute(UInt32 t, const DateLUTImpl & time_zone)
|
||||||
|
{
|
||||||
|
return time_zone.toFirstDayNumOfISOYear(time_zone.toDayNum(t));
|
||||||
|
}
|
||||||
|
static inline UInt16 execute(UInt16 d, const DateLUTImpl & time_zone)
|
||||||
|
{
|
||||||
|
return time_zone.toFirstDayNumOfISOYear(DayNum(d));
|
||||||
|
}
|
||||||
|
|
||||||
|
using FactorTransform = ZeroTransform;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ToISOWeekImpl
|
||||||
|
{
|
||||||
|
static constexpr auto name = "toISOWeek";
|
||||||
|
|
||||||
|
static inline UInt8 execute(UInt32 t, const DateLUTImpl & time_zone)
|
||||||
|
{
|
||||||
|
return time_zone.toISOWeek(time_zone.toDayNum(t));
|
||||||
|
}
|
||||||
|
static inline UInt8 execute(UInt16 d, const DateLUTImpl & time_zone)
|
||||||
|
{
|
||||||
|
return time_zone.toISOWeek(DayNum(d));
|
||||||
|
}
|
||||||
|
|
||||||
|
using FactorTransform = ToISOYearImpl;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ToRelativeYearNumImpl
|
||||||
|
{
|
||||||
|
static constexpr auto name = "toRelativeYearNum";
|
||||||
|
|
||||||
|
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(d));
|
||||||
|
}
|
||||||
|
|
||||||
|
using FactorTransform = ZeroTransform;
|
||||||
|
};
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
return time_zone.toRelativeQuarterNum(DayNum(d));
|
||||||
|
}
|
||||||
|
|
||||||
|
using FactorTransform = ZeroTransform;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ToRelativeMonthNumImpl
|
||||||
|
{
|
||||||
|
static constexpr auto name = "toRelativeMonthNum";
|
||||||
|
|
||||||
|
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(d));
|
||||||
|
}
|
||||||
|
|
||||||
|
using FactorTransform = ZeroTransform;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ToRelativeWeekNumImpl
|
||||||
|
{
|
||||||
|
static constexpr auto name = "toRelativeWeekNum";
|
||||||
|
|
||||||
|
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(d));
|
||||||
|
}
|
||||||
|
|
||||||
|
using FactorTransform = ZeroTransform;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ToRelativeDayNumImpl
|
||||||
|
{
|
||||||
|
static constexpr auto name = "toRelativeDayNum";
|
||||||
|
|
||||||
|
static inline UInt16 execute(UInt32 t, const DateLUTImpl & time_zone)
|
||||||
|
{
|
||||||
|
return time_zone.toDayNum(t);
|
||||||
|
}
|
||||||
|
static inline UInt16 execute(UInt16 d, const DateLUTImpl &)
|
||||||
|
{
|
||||||
|
return static_cast<DayNum>(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
using FactorTransform = ZeroTransform;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct ToRelativeHourNumImpl
|
||||||
|
{
|
||||||
|
static constexpr auto name = "toRelativeHourNum";
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
return time_zone.toRelativeHourNum(DayNum(d));
|
||||||
|
}
|
||||||
|
|
||||||
|
using FactorTransform = ZeroTransform;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ToRelativeMinuteNumImpl
|
||||||
|
{
|
||||||
|
static constexpr auto name = "toRelativeMinuteNum";
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
return time_zone.toRelativeMinuteNum(DayNum(d));
|
||||||
|
}
|
||||||
|
|
||||||
|
using FactorTransform = ZeroTransform;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ToRelativeSecondNumImpl
|
||||||
|
{
|
||||||
|
static constexpr auto name = "toRelativeSecondNum";
|
||||||
|
|
||||||
|
static inline UInt32 execute(UInt32 t, const DateLUTImpl &)
|
||||||
|
{
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
static inline UInt32 execute(UInt16 d, const DateLUTImpl & time_zone)
|
||||||
|
{
|
||||||
|
return time_zone.fromDayNum(DayNum(d));
|
||||||
|
}
|
||||||
|
|
||||||
|
using FactorTransform = ZeroTransform;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ToYYYYMMImpl
|
||||||
|
{
|
||||||
|
static constexpr auto name = "toYYYYMM";
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
return time_zone.toNumYYYYMM(static_cast<DayNum>(d));
|
||||||
|
}
|
||||||
|
|
||||||
|
using FactorTransform = ZeroTransform;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ToYYYYMMDDImpl
|
||||||
|
{
|
||||||
|
static constexpr auto name = "toYYYYMMDD";
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
return time_zone.toNumYYYYMMDD(static_cast<DayNum>(d));
|
||||||
|
}
|
||||||
|
|
||||||
|
using FactorTransform = ZeroTransform;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ToYYYYMMDDhhmmssImpl
|
||||||
|
{
|
||||||
|
static constexpr auto name = "toYYYYMMDDhhmmss";
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
return time_zone.toNumYYYYMMDDhhmmss(time_zone.toDate(static_cast<DayNum>(d)));
|
||||||
|
}
|
||||||
|
|
||||||
|
using FactorTransform = ZeroTransform;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <typename FromType, typename ToType, typename Transform>
|
||||||
|
struct Transformer
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < size; ++i)
|
||||||
|
vec_to[i] = Transform::execute(vec_from[i], time_zone);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <typename FromType, typename ToType, typename Transform>
|
||||||
|
struct DateTimeTransformImpl
|
||||||
|
{
|
||||||
|
static void execute(Block & block, const ColumnNumbers & arguments, size_t result, size_t /*input_rows_count*/)
|
||||||
|
{
|
||||||
|
using Op = Transformer<FromType, ToType, Transform>;
|
||||||
|
|
||||||
|
const DateLUTImpl & time_zone = extractTimeZoneFromFunctionArguments(block, arguments, 1, 0);
|
||||||
|
|
||||||
|
const ColumnPtr source_col = block.getByPosition(arguments[0]).column;
|
||||||
|
if (const auto * sources = checkAndGetColumn<ColumnVector<FromType>>(source_col.get()))
|
||||||
|
{
|
||||||
|
auto col_to = ColumnVector<ToType>::create();
|
||||||
|
Op::vector(sources->getData(), col_to->getData(), time_zone);
|
||||||
|
block.getByPosition(result).column = std::move(col_to);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw Exception("Illegal column " + block.getByPosition(arguments[0]).column->getName()
|
||||||
|
+ " of first argument of function " + Transform::name,
|
||||||
|
ErrorCodes::ILLEGAL_COLUMN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
308
dbms/src/Functions/FunctionDateOrDateTimeAddInterval.h
Normal file
308
dbms/src/Functions/FunctionDateOrDateTimeAddInterval.h
Normal file
@ -0,0 +1,308 @@
|
|||||||
|
#include <common/DateLUTImpl.h>
|
||||||
|
|
||||||
|
#include <DataTypes/DataTypeDate.h>
|
||||||
|
#include <DataTypes/DataTypeDateTime.h>
|
||||||
|
|
||||||
|
#include <Columns/ColumnVector.h>
|
||||||
|
|
||||||
|
#include <Functions/IFunction.h>
|
||||||
|
#include <Functions/FunctionHelpers.h>
|
||||||
|
#include <Functions/extractTimeZoneFromFunctionArguments.h>
|
||||||
|
|
||||||
|
#include <IO/WriteHelpers.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace ErrorCodes
|
||||||
|
{
|
||||||
|
extern const int NUMBER_OF_ARGUMENTS_DOESNT_MATCH;
|
||||||
|
extern const int ILLEGAL_TYPE_OF_ARGUMENT;
|
||||||
|
extern const int ILLEGAL_COLUMN;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct AddSecondsImpl
|
||||||
|
{
|
||||||
|
static constexpr auto name = "addSeconds";
|
||||||
|
|
||||||
|
static inline UInt32 execute(UInt32 t, Int64 delta, const DateLUTImpl &)
|
||||||
|
{
|
||||||
|
return t + delta;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline UInt32 execute(UInt16 d, Int64 delta, const DateLUTImpl & time_zone)
|
||||||
|
{
|
||||||
|
return time_zone.fromDayNum(DayNum(d)) + delta;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct AddMinutesImpl
|
||||||
|
{
|
||||||
|
static constexpr auto name = "addMinutes";
|
||||||
|
|
||||||
|
static inline UInt32 execute(UInt32 t, Int64 delta, const DateLUTImpl &)
|
||||||
|
{
|
||||||
|
return t + delta * 60;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline UInt32 execute(UInt16 d, Int64 delta, const DateLUTImpl & time_zone)
|
||||||
|
{
|
||||||
|
return time_zone.fromDayNum(DayNum(d)) + delta * 60;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct AddHoursImpl
|
||||||
|
{
|
||||||
|
static constexpr auto name = "addHours";
|
||||||
|
|
||||||
|
static inline UInt32 execute(UInt32 t, Int64 delta, const DateLUTImpl &)
|
||||||
|
{
|
||||||
|
return t + delta * 3600;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline UInt32 execute(UInt16 d, Int64 delta, const DateLUTImpl & time_zone)
|
||||||
|
{
|
||||||
|
return time_zone.fromDayNum(DayNum(d)) + delta * 3600;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline UInt16 execute(UInt16 d, Int64 delta, const DateLUTImpl &)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline UInt16 execute(UInt16 d, Int64 delta, const DateLUTImpl &)
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
return time_zone.addMonths(DayNum(d), delta);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
return time_zone.addYears(DayNum(d), delta);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
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"; };
|
||||||
|
|
||||||
|
|
||||||
|
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>;
|
||||||
|
|
||||||
|
const DateLUTImpl & time_zone = extractTimeZoneFromFunctionArguments(block, arguments, 2, 0);
|
||||||
|
|
||||||
|
const ColumnPtr source_col = block.getByPosition(arguments[0]).column;
|
||||||
|
|
||||||
|
if (const auto * sources = checkAndGetColumn<ColumnVector<FromType>>(source_col.get()))
|
||||||
|
{
|
||||||
|
auto col_to = ColumnVector<ToType>::create();
|
||||||
|
|
||||||
|
const IColumn & delta_column = *block.getByPosition(arguments[1]).column;
|
||||||
|
|
||||||
|
if (const auto * delta_const_column = typeid_cast<const ColumnConst *>(&delta_column))
|
||||||
|
Op::vector_constant(sources->getData(), col_to->getData(), delta_const_column->getField().get<Int64>(), time_zone);
|
||||||
|
else
|
||||||
|
Op::vector_vector(sources->getData(), col_to->getData(), delta_column, time_zone);
|
||||||
|
|
||||||
|
block.getByPosition(result).column = std::move(col_to);
|
||||||
|
}
|
||||||
|
else if (const auto * sources = checkAndGetColumnConst<ColumnVector<FromType>>(source_col.get()))
|
||||||
|
{
|
||||||
|
auto col_to = ColumnVector<ToType>::create();
|
||||||
|
Op::constant_vector(sources->template getValue<FromType>(), col_to->getData(), *block.getByPosition(arguments[1]).column, time_zone);
|
||||||
|
block.getByPosition(result).column = std::move(col_to);
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
static FunctionPtr create(const Context &) { return std::make_shared<FunctionDateOrDateTimeAddInterval>(); }
|
||||||
|
|
||||||
|
String getName() const override
|
||||||
|
{
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isVariadic() const override { return true; }
|
||||||
|
size_t getNumberOfArguments() const override { return 0; }
|
||||||
|
|
||||||
|
DataTypePtr getReturnTypeImpl(const ColumnsWithTypeAndName & arguments) const override
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
|
||||||
|
if (!isNumber(arguments[1].type))
|
||||||
|
throw Exception("Second argument for function " + getName() + " (delta) must be number",
|
||||||
|
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
||||||
|
|
||||||
|
if (arguments.size() == 2)
|
||||||
|
{
|
||||||
|
if (!isDateOrDateTime(arguments[0].type))
|
||||||
|
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};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!WhichDataType(arguments[0].type).isDateTime()
|
||||||
|
|| !WhichDataType(arguments[2].type).isString())
|
||||||
|
throw Exception(
|
||||||
|
"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",
|
||||||
|
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (WhichDataType(arguments[0].type).isDate())
|
||||||
|
{
|
||||||
|
if (std::is_same_v<decltype(Transform::execute(DataTypeDate::FieldType(), 0, std::declval<DateLUTImpl>())), UInt16>)
|
||||||
|
return std::make_shared<DataTypeDate>();
|
||||||
|
else
|
||||||
|
return std::make_shared<DataTypeDateTime>(extractTimeZoneNameFromFunctionArguments(arguments, 2, 0));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (std::is_same_v<decltype(Transform::execute(DataTypeDateTime::FieldType(), 0, std::declval<DateLUTImpl>())), UInt16>)
|
||||||
|
return std::make_shared<DataTypeDate>();
|
||||||
|
else
|
||||||
|
return std::make_shared<DataTypeDateTime>(extractTimeZoneNameFromFunctionArguments(arguments, 2, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool useDefaultImplementationForConstants() const override { return true; }
|
||||||
|
ColumnNumbers getArgumentsThatAreAlwaysConstant() const override { return {2}; }
|
||||||
|
|
||||||
|
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result, size_t /*input_rows_count*/) override
|
||||||
|
{
|
||||||
|
const IDataType * from_type = block.getByPosition(arguments[0]).type.get();
|
||||||
|
WhichDataType which(from_type);
|
||||||
|
|
||||||
|
if (which.isDate())
|
||||||
|
DateTimeAddIntervalImpl<DataTypeDate::FieldType, Transform>::execute(block, arguments, result);
|
||||||
|
else if (which.isDateTime())
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
125
dbms/src/Functions/FunctionDateOrDateTimeToSomething.h
Normal file
125
dbms/src/Functions/FunctionDateOrDateTimeToSomething.h
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
#include <DataTypes/DataTypeDate.h>
|
||||||
|
#include <DataTypes/DataTypeDateTime.h>
|
||||||
|
|
||||||
|
#include <Functions/IFunction.h>
|
||||||
|
#include <Functions/extractTimeZoneFromFunctionArguments.h>
|
||||||
|
|
||||||
|
#include <IO/WriteHelpers.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace ErrorCodes
|
||||||
|
{
|
||||||
|
extern const int ILLEGAL_TYPE_OF_ARGUMENT;
|
||||||
|
extern const int NUMBER_OF_ARGUMENTS_DOESNT_MATCH;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// See DateTimeTransforms.h
|
||||||
|
template <typename ToDataType, typename Transform>
|
||||||
|
class FunctionDateOrDateTimeToSomething : public IFunction
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static constexpr auto name = Transform::name;
|
||||||
|
static FunctionPtr create(const 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 ColumnsWithTypeAndName & arguments) const override
|
||||||
|
{
|
||||||
|
if (arguments.size() == 1)
|
||||||
|
{
|
||||||
|
if (!isDateOrDateTime(arguments[0].type))
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
else if (arguments.size() == 2)
|
||||||
|
{
|
||||||
|
if (!WhichDataType(arguments[0].type).isDateTime()
|
||||||
|
|| !WhichDataType(arguments[1].type).isString())
|
||||||
|
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);
|
||||||
|
|
||||||
|
/// For DateTime, if time zone is specified, attach it to type.
|
||||||
|
if (std::is_same_v<ToDataType, DataTypeDateTime>)
|
||||||
|
return std::make_shared<DataTypeDateTime>(extractTimeZoneNameFromFunctionArguments(arguments, 1, 0));
|
||||||
|
else
|
||||||
|
return std::make_shared<ToDataType>();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool useDefaultImplementationForConstants() const override { return true; }
|
||||||
|
ColumnNumbers getArgumentsThatAreAlwaysConstant() const override { return {1}; }
|
||||||
|
|
||||||
|
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) override
|
||||||
|
{
|
||||||
|
const IDataType * from_type = block.getByPosition(arguments[0]).type.get();
|
||||||
|
WhichDataType which(from_type);
|
||||||
|
|
||||||
|
if (which.isDate())
|
||||||
|
DateTimeTransformImpl<DataTypeDate::FieldType, typename ToDataType::FieldType, Transform>::execute(block, arguments, result, input_rows_count);
|
||||||
|
else if (which.isDateTime())
|
||||||
|
DateTimeTransformImpl<DataTypeDateTime::FieldType, typename ToDataType::FieldType, Transform>::execute(block, arguments, result, input_rows_count);
|
||||||
|
else
|
||||||
|
throw Exception("Illegal type " + block.getByPosition(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_v<typename Transform::FactorTransform, ZeroTransform>)
|
||||||
|
{
|
||||||
|
is_monotonic.is_always_monotonic = true;
|
||||||
|
return is_monotonic;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This method is called only if the function has one argument. Therefore, we do not care about the non-local time zone.
|
||||||
|
const DateLUTImpl & date_lut = DateLUT::instance();
|
||||||
|
|
||||||
|
if (left.isNull() || right.isNull())
|
||||||
|
return is_not_monotonic;
|
||||||
|
|
||||||
|
/// The function is monotonous on the [left, right] segment, if the factor transformation returns the same values for them.
|
||||||
|
|
||||||
|
if (checkAndGetDataType<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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -35,8 +35,8 @@
|
|||||||
#include <Interpreters/ExpressionActions.h>
|
#include <Interpreters/ExpressionActions.h>
|
||||||
#include <Functions/IFunction.h>
|
#include <Functions/IFunction.h>
|
||||||
#include <Functions/FunctionsMiscellaneous.h>
|
#include <Functions/FunctionsMiscellaneous.h>
|
||||||
#include <Functions/FunctionsDateTime.h>
|
|
||||||
#include <Functions/FunctionHelpers.h>
|
#include <Functions/FunctionHelpers.h>
|
||||||
|
#include <Functions/DateTimeTransforms.h>
|
||||||
#include <DataTypes/DataTypeWithDictionary.h>
|
#include <DataTypes/DataTypeWithDictionary.h>
|
||||||
#include <Columns/ColumnWithDictionary.h>
|
#include <Columns/ColumnWithDictionary.h>
|
||||||
|
|
||||||
@ -107,6 +107,13 @@ struct ConvertImpl
|
|||||||
using ColVecFrom = std::conditional_t<IsDecimalNumber<FromFieldType>, ColumnDecimal<FromFieldType>, ColumnVector<FromFieldType>>;
|
using ColVecFrom = std::conditional_t<IsDecimalNumber<FromFieldType>, ColumnDecimal<FromFieldType>, ColumnVector<FromFieldType>>;
|
||||||
using ColVecTo = std::conditional_t<IsDecimalNumber<ToFieldType>, ColumnDecimal<ToFieldType>, ColumnVector<ToFieldType>>;
|
using ColVecTo = std::conditional_t<IsDecimalNumber<ToFieldType>, ColumnDecimal<ToFieldType>, ColumnVector<ToFieldType>>;
|
||||||
|
|
||||||
|
if constexpr (IsDataTypeDecimal<FromDataType> || IsDataTypeDecimal<ToDataType>)
|
||||||
|
{
|
||||||
|
if constexpr (!IsDataTypeDecimalOrNumber<FromDataType> || !IsDataTypeDecimalOrNumber<ToDataType>)
|
||||||
|
throw Exception("Illegal column " + named_from.column->getName() + " of first argument of function " + Name::name,
|
||||||
|
ErrorCodes::ILLEGAL_COLUMN);
|
||||||
|
}
|
||||||
|
|
||||||
if (const ColVecFrom * col_from = checkAndGetColumn<ColVecFrom>(named_from.column.get()))
|
if (const ColVecFrom * col_from = checkAndGetColumn<ColVecFrom>(named_from.column.get()))
|
||||||
{
|
{
|
||||||
typename ColVecTo::MutablePtr col_to = nullptr;
|
typename ColVecTo::MutablePtr col_to = nullptr;
|
||||||
@ -125,12 +132,15 @@ struct ConvertImpl
|
|||||||
|
|
||||||
for (size_t i = 0; i < size; ++i)
|
for (size_t i = 0; i < size; ++i)
|
||||||
{
|
{
|
||||||
if constexpr (IsDataTypeDecimal<FromDataType> && IsDataTypeDecimal<ToDataType>)
|
if constexpr (IsDataTypeDecimal<FromDataType> || IsDataTypeDecimal<ToDataType>)
|
||||||
vec_to[i] = convertDecimals<FromDataType, ToDataType>(vec_from[i], vec_from.getScale(), vec_to.getScale());
|
{
|
||||||
else if constexpr (IsDataTypeDecimal<FromDataType>)
|
if constexpr (IsDataTypeDecimal<FromDataType> && IsDataTypeDecimal<ToDataType>)
|
||||||
vec_to[i] = convertFromDecimal<FromDataType, ToDataType>(vec_from[i], vec_from.getScale());
|
vec_to[i] = convertDecimals<FromDataType, ToDataType>(vec_from[i], vec_from.getScale(), vec_to.getScale());
|
||||||
else if constexpr (IsDataTypeDecimal<ToDataType>)
|
else if constexpr (IsDataTypeDecimal<FromDataType> && IsDataTypeNumber<ToDataType>)
|
||||||
vec_to[i] = convertToDecimal<FromDataType, ToDataType>(vec_from[i], vec_to.getScale());
|
vec_to[i] = convertFromDecimal<FromDataType, ToDataType>(vec_from[i], vec_from.getScale());
|
||||||
|
else if constexpr (IsDataTypeNumber<FromDataType> && IsDataTypeDecimal<ToDataType>)
|
||||||
|
vec_to[i] = convertToDecimal<FromDataType, ToDataType>(vec_from[i], vec_to.getScale());
|
||||||
|
}
|
||||||
else
|
else
|
||||||
vec_to[i] = static_cast<ToFieldType>(vec_from[i]);
|
vec_to[i] = static_cast<ToFieldType>(vec_from[i]);
|
||||||
}
|
}
|
||||||
|
@ -1,123 +0,0 @@
|
|||||||
#include <Functions/FunctionFactory.h>
|
|
||||||
#include <Functions/FunctionsDateTime.h>
|
|
||||||
|
|
||||||
namespace DB
|
|
||||||
{
|
|
||||||
|
|
||||||
|
|
||||||
static std::string extractTimeZoneNameFromColumn(const IColumn & column)
|
|
||||||
{
|
|
||||||
const ColumnConst * time_zone_column = checkAndGetColumnConst<ColumnString>(&column);
|
|
||||||
|
|
||||||
if (!time_zone_column)
|
|
||||||
throw Exception("Illegal column " + column.getName()
|
|
||||||
+ " of time zone argument of function, must be constant string",
|
|
||||||
ErrorCodes::ILLEGAL_COLUMN);
|
|
||||||
|
|
||||||
return time_zone_column->getValue<String>();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
std::string extractTimeZoneNameFromFunctionArguments(const ColumnsWithTypeAndName & arguments, size_t time_zone_arg_num, size_t datetime_arg_num)
|
|
||||||
{
|
|
||||||
/// Explicit time zone may be passed in last argument.
|
|
||||||
if (arguments.size() == time_zone_arg_num + 1 && arguments[time_zone_arg_num].column)
|
|
||||||
{
|
|
||||||
return extractTimeZoneNameFromColumn(*arguments[time_zone_arg_num].column);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!arguments.size())
|
|
||||||
return {};
|
|
||||||
|
|
||||||
/// If time zone is attached to an argument of type DateTime.
|
|
||||||
if (const DataTypeDateTime * type = checkAndGetDataType<DataTypeDateTime>(arguments[datetime_arg_num].type.get()))
|
|
||||||
return type->getTimeZone().getTimeZone();
|
|
||||||
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const DateLUTImpl & extractTimeZoneFromFunctionArguments(Block & block, const ColumnNumbers & arguments, size_t time_zone_arg_num, size_t datetime_arg_num)
|
|
||||||
{
|
|
||||||
if (arguments.size() == time_zone_arg_num + 1)
|
|
||||||
return DateLUT::instance(extractTimeZoneNameFromColumn(*block.getByPosition(arguments[time_zone_arg_num]).column));
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!arguments.size())
|
|
||||||
return DateLUT::instance();
|
|
||||||
|
|
||||||
/// If time zone is attached to an argument of type DateTime.
|
|
||||||
if (const DataTypeDateTime * type = checkAndGetDataType<DataTypeDateTime>(block.getByPosition(arguments[datetime_arg_num]).type.get()))
|
|
||||||
return type->getTimeZone();
|
|
||||||
|
|
||||||
return DateLUT::instance();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void registerFunctionsDateTime(FunctionFactory & factory)
|
|
||||||
{
|
|
||||||
factory.registerFunction<FunctionToYear>();
|
|
||||||
factory.registerFunction<FunctionToQuarter>();
|
|
||||||
factory.registerFunction<FunctionToMonth>();
|
|
||||||
factory.registerFunction<FunctionToDayOfMonth>();
|
|
||||||
factory.registerFunction<FunctionToDayOfWeek>();
|
|
||||||
factory.registerFunction<FunctionToDayOfYear>();
|
|
||||||
factory.registerFunction<FunctionToHour>();
|
|
||||||
factory.registerFunction<FunctionToMinute>();
|
|
||||||
factory.registerFunction<FunctionToSecond>();
|
|
||||||
factory.registerFunction<FunctionToStartOfDay>();
|
|
||||||
factory.registerFunction<FunctionToMonday>();
|
|
||||||
factory.registerFunction<FunctionToISOWeek>();
|
|
||||||
factory.registerFunction<FunctionToISOYear>();
|
|
||||||
factory.registerFunction<FunctionToStartOfMonth>();
|
|
||||||
factory.registerFunction<FunctionToStartOfQuarter>();
|
|
||||||
factory.registerFunction<FunctionToStartOfYear>();
|
|
||||||
factory.registerFunction<FunctionToStartOfMinute>();
|
|
||||||
factory.registerFunction<FunctionToStartOfFiveMinute>();
|
|
||||||
factory.registerFunction<FunctionToStartOfFifteenMinutes>();
|
|
||||||
factory.registerFunction<FunctionToStartOfHour>();
|
|
||||||
factory.registerFunction<FunctionToStartOfISOYear>();
|
|
||||||
factory.registerFunction<FunctionToRelativeYearNum>();
|
|
||||||
factory.registerFunction<FunctionToRelativeQuarterNum>();
|
|
||||||
factory.registerFunction<FunctionToRelativeMonthNum>();
|
|
||||||
factory.registerFunction<FunctionToRelativeWeekNum>();
|
|
||||||
factory.registerFunction<FunctionToRelativeDayNum>();
|
|
||||||
factory.registerFunction<FunctionToRelativeHourNum>();
|
|
||||||
factory.registerFunction<FunctionToRelativeMinuteNum>();
|
|
||||||
factory.registerFunction<FunctionToRelativeSecondNum>();
|
|
||||||
factory.registerFunction<FunctionToTime>();
|
|
||||||
factory.registerFunction<FunctionNow>(FunctionFactory::CaseInsensitive);
|
|
||||||
factory.registerFunction<FunctionToday>();
|
|
||||||
factory.registerFunction<FunctionYesterday>();
|
|
||||||
factory.registerFunction<FunctionTimeSlot>();
|
|
||||||
factory.registerFunction<FunctionTimeSlots>();
|
|
||||||
factory.registerFunction<FunctionToYYYYMM>();
|
|
||||||
factory.registerFunction<FunctionToYYYYMMDD>();
|
|
||||||
factory.registerFunction<FunctionToYYYYMMDDhhmmss>();
|
|
||||||
|
|
||||||
factory.registerFunction<FunctionAddSeconds>();
|
|
||||||
factory.registerFunction<FunctionAddMinutes>();
|
|
||||||
factory.registerFunction<FunctionAddHours>();
|
|
||||||
factory.registerFunction<FunctionAddDays>();
|
|
||||||
factory.registerFunction<FunctionAddWeeks>();
|
|
||||||
factory.registerFunction<FunctionAddMonths>();
|
|
||||||
factory.registerFunction<FunctionAddYears>();
|
|
||||||
|
|
||||||
factory.registerFunction<FunctionSubtractSeconds>();
|
|
||||||
factory.registerFunction<FunctionSubtractMinutes>();
|
|
||||||
factory.registerFunction<FunctionSubtractHours>();
|
|
||||||
factory.registerFunction<FunctionSubtractDays>();
|
|
||||||
factory.registerFunction<FunctionSubtractWeeks>();
|
|
||||||
factory.registerFunction<FunctionSubtractMonths>();
|
|
||||||
factory.registerFunction<FunctionSubtractYears>();
|
|
||||||
|
|
||||||
factory.registerFunction<FunctionDateDiff>(FunctionFactory::CaseInsensitive);
|
|
||||||
|
|
||||||
factory.registerFunction<FunctionToTimeZone>();
|
|
||||||
|
|
||||||
|
|
||||||
factory.registerFunction<FunctionFormatDateTime>();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
18
dbms/src/Functions/addDays.cpp
Normal file
18
dbms/src/Functions/addDays.cpp
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#include <Functions/IFunction.h>
|
||||||
|
#include <Functions/FunctionFactory.h>
|
||||||
|
#include <Functions/FunctionDateOrDateTimeAddInterval.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
using FunctionAddDays = FunctionDateOrDateTimeAddInterval<AddDaysImpl>;
|
||||||
|
|
||||||
|
void registerFunctionAddDays(FunctionFactory & factory)
|
||||||
|
{
|
||||||
|
factory.registerFunction<FunctionAddDays>();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
18
dbms/src/Functions/addHours.cpp
Normal file
18
dbms/src/Functions/addHours.cpp
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#include <Functions/IFunction.h>
|
||||||
|
#include <Functions/FunctionFactory.h>
|
||||||
|
#include <Functions/FunctionDateOrDateTimeAddInterval.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
using FunctionAddHours = FunctionDateOrDateTimeAddInterval<AddHoursImpl>;
|
||||||
|
|
||||||
|
void registerFunctionAddHours(FunctionFactory & factory)
|
||||||
|
{
|
||||||
|
factory.registerFunction<FunctionAddHours>();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
18
dbms/src/Functions/addMinutes.cpp
Normal file
18
dbms/src/Functions/addMinutes.cpp
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#include <Functions/IFunction.h>
|
||||||
|
#include <Functions/FunctionFactory.h>
|
||||||
|
#include <Functions/FunctionDateOrDateTimeAddInterval.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
using FunctionAddMinutes = FunctionDateOrDateTimeAddInterval<AddMinutesImpl>;
|
||||||
|
|
||||||
|
void registerFunctionAddMinutes(FunctionFactory & factory)
|
||||||
|
{
|
||||||
|
factory.registerFunction<FunctionAddMinutes>();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
18
dbms/src/Functions/addMonths.cpp
Normal file
18
dbms/src/Functions/addMonths.cpp
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#include <Functions/IFunction.h>
|
||||||
|
#include <Functions/FunctionFactory.h>
|
||||||
|
#include <Functions/FunctionDateOrDateTimeAddInterval.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
using FunctionAddMonths = FunctionDateOrDateTimeAddInterval<AddMonthsImpl>;
|
||||||
|
|
||||||
|
void registerFunctionAddMonths(FunctionFactory & factory)
|
||||||
|
{
|
||||||
|
factory.registerFunction<FunctionAddMonths>();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
18
dbms/src/Functions/addSeconds.cpp
Normal file
18
dbms/src/Functions/addSeconds.cpp
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#include <Functions/IFunction.h>
|
||||||
|
#include <Functions/FunctionFactory.h>
|
||||||
|
#include <Functions/FunctionDateOrDateTimeAddInterval.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
using FunctionAddSeconds = FunctionDateOrDateTimeAddInterval<AddSecondsImpl>;
|
||||||
|
|
||||||
|
void registerFunctionAddSeconds(FunctionFactory & factory)
|
||||||
|
{
|
||||||
|
factory.registerFunction<FunctionAddSeconds>();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
18
dbms/src/Functions/addWeeks.cpp
Normal file
18
dbms/src/Functions/addWeeks.cpp
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#include <Functions/IFunction.h>
|
||||||
|
#include <Functions/FunctionFactory.h>
|
||||||
|
#include <Functions/FunctionDateOrDateTimeAddInterval.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
using FunctionAddWeeks = FunctionDateOrDateTimeAddInterval<AddWeeksImpl>;
|
||||||
|
|
||||||
|
void registerFunctionAddWeeks(FunctionFactory & factory)
|
||||||
|
{
|
||||||
|
factory.registerFunction<FunctionAddWeeks>();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
18
dbms/src/Functions/addYears.cpp
Normal file
18
dbms/src/Functions/addYears.cpp
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#include <Functions/IFunction.h>
|
||||||
|
#include <Functions/FunctionFactory.h>
|
||||||
|
#include <Functions/FunctionDateOrDateTimeAddInterval.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
using FunctionAddYears = FunctionDateOrDateTimeAddInterval<AddYearsImpl>;
|
||||||
|
|
||||||
|
void registerFunctionAddYears(FunctionFactory & factory)
|
||||||
|
{
|
||||||
|
factory.registerFunction<FunctionAddYears>();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
220
dbms/src/Functions/dateDiff.cpp
Normal file
220
dbms/src/Functions/dateDiff.cpp
Normal file
@ -0,0 +1,220 @@
|
|||||||
|
#include <DataTypes/DataTypeDateTime.h>
|
||||||
|
#include <DataTypes/DataTypesNumber.h>
|
||||||
|
#include <Columns/ColumnString.h>
|
||||||
|
#include <Columns/ColumnsNumber.h>
|
||||||
|
|
||||||
|
#include <Functions/IFunction.h>
|
||||||
|
#include <Functions/FunctionHelpers.h>
|
||||||
|
#include <Functions/FunctionFactory.h>
|
||||||
|
#include <Functions/extractTimeZoneFromFunctionArguments.h>
|
||||||
|
#include <Functions/DateTimeTransforms.h>
|
||||||
|
|
||||||
|
#include <IO/WriteHelpers.h>
|
||||||
|
|
||||||
|
#include <common/find_first_symbols.h>
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace ErrorCodes
|
||||||
|
{
|
||||||
|
extern const int NUMBER_OF_ARGUMENTS_DOESNT_MATCH;
|
||||||
|
extern const int ILLEGAL_TYPE_OF_ARGUMENT;
|
||||||
|
extern const int ILLEGAL_COLUMN;
|
||||||
|
extern const int BAD_ARGUMENTS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 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";
|
||||||
|
static FunctionPtr create(const Context &) { return std::make_shared<FunctionDateDiff>(); }
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
if (!isString(arguments[0]))
|
||||||
|
throw Exception("First argument for function " + getName() + " (unit) must be String",
|
||||||
|
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
||||||
|
|
||||||
|
if (!isDateOrDateTime(arguments[1]))
|
||||||
|
throw Exception("Second argument for function " + getName() + " must be Date or DateTime",
|
||||||
|
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
||||||
|
|
||||||
|
if (!isDateOrDateTime(arguments[2]))
|
||||||
|
throw Exception("Third argument for function " + getName() + " must be Date or DateTime",
|
||||||
|
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
||||||
|
|
||||||
|
if (arguments.size() == 4 && !isString(arguments[3]))
|
||||||
|
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}; }
|
||||||
|
|
||||||
|
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) override
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
|
||||||
|
size_t rows = input_rows_count;
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void registerFunctionDateDiff(FunctionFactory & factory)
|
||||||
|
{
|
||||||
|
factory.registerFunction<FunctionDateDiff>(FunctionFactory::CaseInsensitive);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
69
dbms/src/Functions/extractTimeZoneFromFunctionArguments.cpp
Normal file
69
dbms/src/Functions/extractTimeZoneFromFunctionArguments.cpp
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
#include <Functions/extractTimeZoneFromFunctionArguments.h>
|
||||||
|
#include <Functions/FunctionHelpers.h>
|
||||||
|
#include <Core/Block.h>
|
||||||
|
#include <DataTypes/DataTypeDateTime.h>
|
||||||
|
#include <Columns/ColumnString.h>
|
||||||
|
#include <common/DateLUT.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace ErrorCodes
|
||||||
|
{
|
||||||
|
extern const int ILLEGAL_COLUMN;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static std::string extractTimeZoneNameFromColumn(const IColumn & column)
|
||||||
|
{
|
||||||
|
const ColumnConst * time_zone_column = checkAndGetColumnConst<ColumnString>(&column);
|
||||||
|
|
||||||
|
if (!time_zone_column)
|
||||||
|
throw Exception("Illegal column " + column.getName()
|
||||||
|
+ " of time zone argument of function, must be constant string",
|
||||||
|
ErrorCodes::ILLEGAL_COLUMN);
|
||||||
|
|
||||||
|
return time_zone_column->getValue<String>();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::string extractTimeZoneNameFromFunctionArguments(const ColumnsWithTypeAndName & arguments, size_t time_zone_arg_num, size_t datetime_arg_num)
|
||||||
|
{
|
||||||
|
/// Explicit time zone may be passed in last argument.
|
||||||
|
if (arguments.size() == time_zone_arg_num + 1 && arguments[time_zone_arg_num].column)
|
||||||
|
{
|
||||||
|
return extractTimeZoneNameFromColumn(*arguments[time_zone_arg_num].column);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!arguments.size())
|
||||||
|
return {};
|
||||||
|
|
||||||
|
/// If time zone is attached to an argument of type DateTime.
|
||||||
|
if (const DataTypeDateTime * type = checkAndGetDataType<DataTypeDateTime>(arguments[datetime_arg_num].type.get()))
|
||||||
|
return type->getTimeZone().getTimeZone();
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const DateLUTImpl & extractTimeZoneFromFunctionArguments(Block & block, const ColumnNumbers & arguments, size_t time_zone_arg_num, size_t datetime_arg_num)
|
||||||
|
{
|
||||||
|
if (arguments.size() == time_zone_arg_num + 1)
|
||||||
|
return DateLUT::instance(extractTimeZoneNameFromColumn(*block.getByPosition(arguments[time_zone_arg_num]).column));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!arguments.size())
|
||||||
|
return DateLUT::instance();
|
||||||
|
|
||||||
|
/// If time zone is attached to an argument of type DateTime.
|
||||||
|
if (const DataTypeDateTime * type = checkAndGetDataType<DataTypeDateTime>(block.getByPosition(arguments[datetime_arg_num]).type.get()))
|
||||||
|
return type->getTimeZone();
|
||||||
|
|
||||||
|
return DateLUT::instance();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
17
dbms/src/Functions/extractTimeZoneFromFunctionArguments.h
Normal file
17
dbms/src/Functions/extractTimeZoneFromFunctionArguments.h
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#include <string>
|
||||||
|
#include <Core/ColumnNumbers.h>
|
||||||
|
#include <Core/ColumnsWithTypeAndName.h>
|
||||||
|
|
||||||
|
|
||||||
|
class DateLUTImpl;
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
class Block;
|
||||||
|
|
||||||
|
/// Determine working timezone either from optional argument with time zone name or from time zone in DateTime type of argument.
|
||||||
|
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);
|
||||||
|
|
||||||
|
}
|
571
dbms/src/Functions/formatDateTime.cpp
Normal file
571
dbms/src/Functions/formatDateTime.cpp
Normal file
@ -0,0 +1,571 @@
|
|||||||
|
#include <DataTypes/DataTypeString.h>
|
||||||
|
#include <Columns/ColumnString.h>
|
||||||
|
|
||||||
|
#include <Functions/IFunction.h>
|
||||||
|
#include <Functions/FunctionHelpers.h>
|
||||||
|
#include <Functions/FunctionFactory.h>
|
||||||
|
#include <Functions/DateTimeTransforms.h>
|
||||||
|
#include <Functions/extractTimeZoneFromFunctionArguments.h>
|
||||||
|
|
||||||
|
#include <IO/WriteHelpers.h>
|
||||||
|
|
||||||
|
#include <common/DateLUTImpl.h>
|
||||||
|
#include <common/find_first_symbols.h>
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace ErrorCodes
|
||||||
|
{
|
||||||
|
extern const int NUMBER_OF_ARGUMENTS_DOESNT_MATCH;
|
||||||
|
extern const int ILLEGAL_TYPE_OF_ARGUMENT;
|
||||||
|
extern const int NOT_IMPLEMENTED;
|
||||||
|
extern const int ILLEGAL_COLUMN;
|
||||||
|
extern const int BAD_ARGUMENTS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** formatDateTime(time, 'pattern')
|
||||||
|
* Performs formatting of time, according to provided pattern.
|
||||||
|
*
|
||||||
|
* This function is optimized with an assumption, that the resulting strings are fixed width.
|
||||||
|
* (This assumption is fulfilled for currently supported formatting options).
|
||||||
|
*
|
||||||
|
* It is implemented in two steps.
|
||||||
|
* At first step, it creates a pattern of zeros, literal characters, whitespaces, etc.
|
||||||
|
* and quickly fills resulting charater array (string column) with this pattern.
|
||||||
|
* At second step, it walks across the resulting character array and modifies/replaces specific charaters,
|
||||||
|
* by calling some functions by pointers and shifting cursor by specified amount.
|
||||||
|
*
|
||||||
|
* Advantages:
|
||||||
|
* - memcpy is mostly unrolled;
|
||||||
|
* - low number of arithmetic ops due to pre-filled pattern;
|
||||||
|
* - for somewhat reason, function by pointer call is faster than switch/case.
|
||||||
|
*
|
||||||
|
* Possible further optimization options:
|
||||||
|
* - slightly interleave first and second step for better cache locality
|
||||||
|
* (but it has no sense when character array fits in L1d cache);
|
||||||
|
* - avoid indirect function calls and inline functions with JIT compilation.
|
||||||
|
*
|
||||||
|
* Performance on Intel(R) Core(TM) i7-6700 CPU @ 3.40GHz:
|
||||||
|
*
|
||||||
|
* WITH formatDateTime(now() + number, '%H:%M:%S') AS x SELECT count() FROM system.numbers WHERE NOT ignore(x);
|
||||||
|
* - 97 million rows per second per core;
|
||||||
|
*
|
||||||
|
* WITH formatDateTime(toDateTime('2018-01-01 00:00:00') + number, '%F %T') AS x SELECT count() FROM system.numbers WHERE NOT ignore(x)
|
||||||
|
* - 71 million rows per second per core;
|
||||||
|
*
|
||||||
|
* select count() from (select formatDateTime(t, '%m/%d/%Y %H:%M:%S') from (select toDateTime('2018-01-01 00:00:00')+number as t from numbers(100000000)));
|
||||||
|
* - 53 million rows per second per core;
|
||||||
|
*
|
||||||
|
* select count() from (select formatDateTime(t, 'Hello %Y World') from (select toDateTime('2018-01-01 00:00:00')+number as t from numbers(100000000)));
|
||||||
|
* - 138 million rows per second per core;
|
||||||
|
*
|
||||||
|
* PS. We can make this function to return FixedString. Currently it returns String.
|
||||||
|
*/
|
||||||
|
class FunctionFormatDateTime : public IFunction
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
/// Time is either UInt32 for DateTime or UInt16 for Date.
|
||||||
|
template <typename Time>
|
||||||
|
class Action
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using Func = void (*)(char *, Time, const DateLUTImpl &);
|
||||||
|
|
||||||
|
Func func;
|
||||||
|
size_t shift;
|
||||||
|
|
||||||
|
Action(Func func, size_t shift = 0) : func(func), shift(shift) {}
|
||||||
|
|
||||||
|
void perform(char *& target, Time source, const DateLUTImpl & timezone)
|
||||||
|
{
|
||||||
|
func(target, source, timezone);
|
||||||
|
target += shift;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
template <typename T>
|
||||||
|
static inline void writeNumber2(char * p, T v)
|
||||||
|
{
|
||||||
|
static const char digits[201] =
|
||||||
|
"00010203040506070809"
|
||||||
|
"10111213141516171819"
|
||||||
|
"20212223242526272829"
|
||||||
|
"30313233343536373839"
|
||||||
|
"40414243444546474849"
|
||||||
|
"50515253545556575859"
|
||||||
|
"60616263646566676869"
|
||||||
|
"70717273747576777879"
|
||||||
|
"80818283848586878889"
|
||||||
|
"90919293949596979899";
|
||||||
|
|
||||||
|
memcpy(p, &digits[v * 2], 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static inline void writeNumber3(char * p, T v)
|
||||||
|
{
|
||||||
|
writeNumber2(p, v / 10);
|
||||||
|
p[2] += v % 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static inline void writeNumber4(char * p, T v)
|
||||||
|
{
|
||||||
|
writeNumber2(p, v / 100);
|
||||||
|
writeNumber2(p + 2, v % 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
static void noop(char *, Time, const DateLUTImpl &)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void century(char * target, Time source, const DateLUTImpl & timezone)
|
||||||
|
{
|
||||||
|
auto year = ToYearImpl::execute(source, timezone);
|
||||||
|
auto century = year / 100;
|
||||||
|
writeNumber2(target, century);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dayOfMonth(char * target, Time source, const DateLUTImpl & timezone)
|
||||||
|
{
|
||||||
|
writeNumber2(target, ToDayOfMonthImpl::execute(source, timezone));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void americanDate(char * target, Time source, const DateLUTImpl & timezone)
|
||||||
|
{
|
||||||
|
writeNumber2(target, ToMonthImpl::execute(source, timezone));
|
||||||
|
writeNumber2(target + 3, ToDayOfMonthImpl::execute(source, timezone));
|
||||||
|
writeNumber2(target + 6, ToYearImpl::execute(source, timezone) % 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dayOfMonthSpacePadded(char * target, Time source, const DateLUTImpl & timezone)
|
||||||
|
{
|
||||||
|
auto day = ToDayOfMonthImpl::execute(source, timezone);
|
||||||
|
if (day < 10)
|
||||||
|
target[1] += day;
|
||||||
|
else
|
||||||
|
writeNumber2(target, day);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ISO8601Date(char * target, Time source, const DateLUTImpl & timezone)
|
||||||
|
{
|
||||||
|
writeNumber4(target, ToYearImpl::execute(source, timezone));
|
||||||
|
writeNumber2(target + 5, ToMonthImpl::execute(source, timezone));
|
||||||
|
writeNumber2(target + 8, ToDayOfMonthImpl::execute(source, timezone));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dayOfYear(char * target, Time source, const DateLUTImpl & timezone)
|
||||||
|
{
|
||||||
|
writeNumber3(target, ToDayOfYearImpl::execute(source, timezone));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void month(char * target, Time source, const DateLUTImpl & timezone)
|
||||||
|
{
|
||||||
|
writeNumber2(target, ToMonthImpl::execute(source, timezone));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dayOfWeek(char * target, Time source, const DateLUTImpl & timezone)
|
||||||
|
{
|
||||||
|
*target += ToDayOfWeekImpl::execute(source, timezone);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dayOfWeek0To6(char * target, Time source, const DateLUTImpl & timezone)
|
||||||
|
{
|
||||||
|
auto day = ToDayOfWeekImpl::execute(source, timezone);
|
||||||
|
*target += (day == 7 ? 0 : day);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ISO8601Week(char * target, Time source, const DateLUTImpl & timezone)
|
||||||
|
{
|
||||||
|
writeNumber2(target, ToISOWeekImpl::execute(source, timezone));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void year2(char * target, Time source, const DateLUTImpl & timezone)
|
||||||
|
{
|
||||||
|
writeNumber2(target, ToYearImpl::execute(source, timezone) % 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void year4(char * target, Time source, const DateLUTImpl & timezone)
|
||||||
|
{
|
||||||
|
writeNumber4(target, ToYearImpl::execute(source, timezone));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void hour24(char * target, Time source, const DateLUTImpl & timezone)
|
||||||
|
{
|
||||||
|
writeNumber2(target, ToHourImpl::execute(source, timezone));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void hour12(char * target, Time source, const DateLUTImpl & timezone)
|
||||||
|
{
|
||||||
|
auto x = ToHourImpl::execute(source, timezone);
|
||||||
|
writeNumber2(target, x == 0 ? 12 : (x > 12 ? x - 12 : x));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void minute(char * target, Time source, const DateLUTImpl & timezone)
|
||||||
|
{
|
||||||
|
writeNumber2(target, ToMinuteImpl::execute(source, timezone));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void AMPM(char * target, Time source, const DateLUTImpl & timezone)
|
||||||
|
{
|
||||||
|
auto hour = ToHourImpl::execute(source, timezone);
|
||||||
|
if (hour >= 12)
|
||||||
|
*target = 'P';
|
||||||
|
}
|
||||||
|
|
||||||
|
static void hhmm24(char * target, Time source, const DateLUTImpl & timezone)
|
||||||
|
{
|
||||||
|
writeNumber2(target, ToHourImpl::execute(source, timezone));
|
||||||
|
writeNumber2(target + 3, ToMinuteImpl::execute(source, timezone));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void second(char * target, Time source, const DateLUTImpl & timezone)
|
||||||
|
{
|
||||||
|
writeNumber2(target, ToSecondImpl::execute(source, timezone));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ISO8601Time(char * target, Time source, const DateLUTImpl & timezone)
|
||||||
|
{
|
||||||
|
writeNumber2(target, ToHourImpl::execute(source, timezone));
|
||||||
|
writeNumber2(target + 3, ToMinuteImpl::execute(source, timezone));
|
||||||
|
writeNumber2(target + 6, ToSecondImpl::execute(source, timezone));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
static constexpr auto name = "formatDateTime";
|
||||||
|
|
||||||
|
static FunctionPtr create(const Context &) { return std::make_shared<FunctionFormatDateTime>(); }
|
||||||
|
|
||||||
|
String getName() const override
|
||||||
|
{
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool useDefaultImplementationForConstants() const override { return true; }
|
||||||
|
|
||||||
|
ColumnNumbers getArgumentsThatAreAlwaysConstant() const override { return {1, 2}; }
|
||||||
|
|
||||||
|
bool isVariadic() const override { return true; }
|
||||||
|
size_t getNumberOfArguments() const override { return 0; }
|
||||||
|
|
||||||
|
DataTypePtr getReturnTypeImpl(const ColumnsWithTypeAndName & arguments) const override
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
|
||||||
|
if (!WhichDataType(arguments[0].type).isDateOrDateTime())
|
||||||
|
throw Exception("Illegal type " + arguments[0].type->getName() + " of 1 argument of function " + getName() +
|
||||||
|
". Should be a date or a date with time", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
||||||
|
|
||||||
|
if (!WhichDataType(arguments[1].type).isString())
|
||||||
|
throw Exception("Illegal type " + arguments[1].type->getName() + " of 2 argument of function " + getName() + ". Must be String.",
|
||||||
|
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
||||||
|
|
||||||
|
if (arguments.size() == 3)
|
||||||
|
{
|
||||||
|
if (!WhichDataType(arguments[2].type).isString())
|
||||||
|
throw Exception("Illegal type " + arguments[2].type->getName() + " of 3 argument of function " + getName() + ". Must be String.",
|
||||||
|
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::make_shared<DataTypeString>();
|
||||||
|
}
|
||||||
|
|
||||||
|
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result, size_t /*input_rows_count*/) override
|
||||||
|
{
|
||||||
|
if (!executeType<UInt32>(block, arguments, result)
|
||||||
|
&& !executeType<UInt16>(block, arguments, result))
|
||||||
|
throw Exception("Illegal column " + block.getByPosition(arguments[0]).column->getName()
|
||||||
|
+ " of function " + getName() + ", must be Date or DateTime",
|
||||||
|
ErrorCodes::ILLEGAL_COLUMN);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
bool executeType(Block & block, const ColumnNumbers & arguments, size_t result)
|
||||||
|
{
|
||||||
|
if (auto * times = checkAndGetColumn<ColumnVector<T>>(block.getByPosition(arguments[0]).column.get()))
|
||||||
|
{
|
||||||
|
const ColumnConst * pattern_column = checkAndGetColumnConst<ColumnString>(block.getByPosition(arguments[1]).column.get());
|
||||||
|
|
||||||
|
if (!pattern_column)
|
||||||
|
throw Exception("Illegal column " + block.getByPosition(arguments[1]).column->getName()
|
||||||
|
+ " of second ('format') argument of function " + getName()
|
||||||
|
+ ". Must be constant string.",
|
||||||
|
ErrorCodes::ILLEGAL_COLUMN);
|
||||||
|
|
||||||
|
String pattern = pattern_column->getValue<String>();
|
||||||
|
|
||||||
|
std::vector<Action<T>> instructions;
|
||||||
|
String pattern_to_fill = parsePattern(pattern, instructions);
|
||||||
|
size_t result_size = pattern_to_fill.size();
|
||||||
|
|
||||||
|
const DateLUTImpl * time_zone_tmp = nullptr;
|
||||||
|
if (arguments.size() == 3)
|
||||||
|
time_zone_tmp = &extractTimeZoneFromFunctionArguments(block, arguments, 2, 0);
|
||||||
|
else
|
||||||
|
time_zone_tmp = &DateLUT::instance();
|
||||||
|
|
||||||
|
const DateLUTImpl & time_zone = *time_zone_tmp;
|
||||||
|
|
||||||
|
const typename ColumnVector<T>::Container & vec = times->getData();
|
||||||
|
|
||||||
|
auto col_res = ColumnString::create();
|
||||||
|
auto & dst_data = col_res->getChars();
|
||||||
|
auto & dst_offsets = col_res->getOffsets();
|
||||||
|
dst_data.resize(vec.size() * (result_size + 1));
|
||||||
|
dst_offsets.resize(vec.size());
|
||||||
|
|
||||||
|
/// Fill result with literals.
|
||||||
|
{
|
||||||
|
UInt8 * begin = dst_data.data();
|
||||||
|
UInt8 * end = begin + dst_data.size();
|
||||||
|
UInt8 * pos = begin;
|
||||||
|
|
||||||
|
if (pos < end)
|
||||||
|
{
|
||||||
|
memcpy(pos, pattern_to_fill.data(), result_size + 1); /// With zero terminator.
|
||||||
|
pos += result_size + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Fill by copying exponential growing ranges.
|
||||||
|
while (pos < end)
|
||||||
|
{
|
||||||
|
size_t bytes_to_copy = std::min(pos - begin, end - pos);
|
||||||
|
memcpy(pos, begin, bytes_to_copy);
|
||||||
|
pos += bytes_to_copy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto begin = reinterpret_cast<char *>(dst_data.data());
|
||||||
|
auto pos = begin;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < vec.size(); ++i)
|
||||||
|
{
|
||||||
|
for(auto & instruction : instructions)
|
||||||
|
instruction.perform(pos, vec[i], time_zone);
|
||||||
|
|
||||||
|
dst_offsets[i] = pos - begin;
|
||||||
|
}
|
||||||
|
|
||||||
|
dst_data.resize(pos - begin);
|
||||||
|
block.getByPosition(result).column = std::move(col_res);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
String parsePattern(const String & pattern, std::vector<Action<T>> & instructions) const
|
||||||
|
{
|
||||||
|
String result;
|
||||||
|
|
||||||
|
const char * pos = pattern.data();
|
||||||
|
const char * end = pos + pattern.size();
|
||||||
|
|
||||||
|
/// Add shift to previous action; or if there were none, add noop action with shift.
|
||||||
|
auto addShift = [&](size_t amount)
|
||||||
|
{
|
||||||
|
if (instructions.empty())
|
||||||
|
instructions.emplace_back(&Action<T>::noop);
|
||||||
|
instructions.back().shift += amount;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// If the argument was DateTime, add instruction for printing. If it was date, just shift (the buffer is pre-filled with default values).
|
||||||
|
auto addInstructionOrShift = [&](typename Action<T>::Func func [[maybe_unused]], size_t shift)
|
||||||
|
{
|
||||||
|
if constexpr (std::is_same_v<T, UInt32>)
|
||||||
|
instructions.emplace_back(func, shift);
|
||||||
|
else
|
||||||
|
addShift(shift);
|
||||||
|
};
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
const char * percent_pos = find_first_symbols<'%'>(pos, end);
|
||||||
|
|
||||||
|
if (percent_pos < end)
|
||||||
|
{
|
||||||
|
if (pos < percent_pos)
|
||||||
|
{
|
||||||
|
result.append(pos, percent_pos);
|
||||||
|
addShift(percent_pos - pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
pos = percent_pos + 1;
|
||||||
|
|
||||||
|
if (pos >= end)
|
||||||
|
throw Exception("Sign '%' is the last in pattern, if you need it, use '%%'", ErrorCodes::BAD_ARGUMENTS);
|
||||||
|
|
||||||
|
switch (*pos)
|
||||||
|
{
|
||||||
|
// Year, divided by 100, zero-padded
|
||||||
|
case 'C':
|
||||||
|
instructions.emplace_back(&Action<T>::century, 2);
|
||||||
|
result.append("00");
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Day of month, zero-padded (01-31)
|
||||||
|
case 'd':
|
||||||
|
instructions.emplace_back(&Action<T>::dayOfMonth, 2);
|
||||||
|
result.append("00");
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Short MM/DD/YY date, equivalent to %m/%d/%y
|
||||||
|
case 'D':
|
||||||
|
instructions.emplace_back(&Action<T>::americanDate, 8);
|
||||||
|
result.append("00/00/00");
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Day of month, space-padded ( 1-31) 23
|
||||||
|
case 'e':
|
||||||
|
instructions.emplace_back(&Action<T>::dayOfMonthSpacePadded, 2);
|
||||||
|
result.append(" 0");
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Short YYYY-MM-DD date, equivalent to %Y-%m-%d 2001-08-23
|
||||||
|
case 'F':
|
||||||
|
instructions.emplace_back(&Action<T>::ISO8601Date, 10);
|
||||||
|
result.append("0000-00-00");
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Day of the year (001-366) 235
|
||||||
|
case 'j':
|
||||||
|
instructions.emplace_back(&Action<T>::dayOfYear, 3);
|
||||||
|
result.append("000");
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Month as a decimal number (01-12)
|
||||||
|
case 'm':
|
||||||
|
instructions.emplace_back(&Action<T>::month, 2);
|
||||||
|
result.append("00");
|
||||||
|
break;
|
||||||
|
|
||||||
|
// ISO 8601 weekday as number with Monday as 1 (1-7)
|
||||||
|
case 'u':
|
||||||
|
instructions.emplace_back(&Action<T>::dayOfWeek, 1);
|
||||||
|
result.append("0");
|
||||||
|
break;
|
||||||
|
|
||||||
|
// ISO 8601 week number (01-53)
|
||||||
|
case 'V':
|
||||||
|
instructions.emplace_back(&Action<T>::ISO8601Week, 2);
|
||||||
|
result.append("00");
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Weekday as a decimal number with Sunday as 0 (0-6) 4
|
||||||
|
case 'w':
|
||||||
|
instructions.emplace_back(&Action<T>::dayOfWeek0To6, 1);
|
||||||
|
result.append("0");
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Two digits year
|
||||||
|
case 'y':
|
||||||
|
instructions.emplace_back(&Action<T>::year2, 2);
|
||||||
|
result.append("00");
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Four digits year
|
||||||
|
case 'Y':
|
||||||
|
instructions.emplace_back(&Action<T>::year4, 4);
|
||||||
|
result.append("0000");
|
||||||
|
break;
|
||||||
|
|
||||||
|
/// Time components. If the argument is Date, not a DateTime, then this components will have default value.
|
||||||
|
|
||||||
|
// Minute (00-59)
|
||||||
|
case 'M':
|
||||||
|
addInstructionOrShift(&Action<T>::minute, 2);
|
||||||
|
result.append("00");
|
||||||
|
break;
|
||||||
|
|
||||||
|
// AM or PM
|
||||||
|
case 'p':
|
||||||
|
addInstructionOrShift(&Action<T>::AMPM, 2);
|
||||||
|
result.append("AM");
|
||||||
|
break;
|
||||||
|
|
||||||
|
// 24-hour HH:MM time, equivalent to %H:%M 14:55
|
||||||
|
case 'R':
|
||||||
|
addInstructionOrShift(&Action<T>::hhmm24, 5);
|
||||||
|
result.append("00:00");
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Seconds
|
||||||
|
case 'S':
|
||||||
|
addInstructionOrShift(&Action<T>::second, 2);
|
||||||
|
result.append("00");
|
||||||
|
break;
|
||||||
|
|
||||||
|
// ISO 8601 time format (HH:MM:SS), equivalent to %H:%M:%S 14:55:02
|
||||||
|
case 'T':
|
||||||
|
addInstructionOrShift(&Action<T>::ISO8601Time, 8);
|
||||||
|
result.append("00:00:00");
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Hour in 24h format (00-23)
|
||||||
|
case 'H':
|
||||||
|
addInstructionOrShift(&Action<T>::hour24, 2);
|
||||||
|
result.append("00");
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Hour in 12h format (01-12)
|
||||||
|
case 'I':
|
||||||
|
addInstructionOrShift(&Action<T>::hour12, 2);
|
||||||
|
result.append("12");
|
||||||
|
break;
|
||||||
|
|
||||||
|
/// Escaped literal characters.
|
||||||
|
case '%':
|
||||||
|
result += '%';
|
||||||
|
addShift(1);
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
result += '\t';
|
||||||
|
addShift(1);
|
||||||
|
break;
|
||||||
|
case 'n':
|
||||||
|
result += '\n';
|
||||||
|
addShift(1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Unimplemented
|
||||||
|
case 'U': [[fallthrough]];
|
||||||
|
case 'W':
|
||||||
|
throw Exception("Wrong pattern '" + pattern + "', symbol '" + *pos + " is not implemented ' for function " + getName(),
|
||||||
|
ErrorCodes::NOT_IMPLEMENTED);
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw Exception(
|
||||||
|
"Wrong pattern '" + pattern + "', unexpected symbol '" + *pos + "' for function " + getName(), ErrorCodes::ILLEGAL_COLUMN);
|
||||||
|
}
|
||||||
|
|
||||||
|
++pos;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result.append(pos, end);
|
||||||
|
addShift(end + 1 - pos); /// including zero terminator
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void registerFunctionFormatDateTime(FunctionFactory & factory)
|
||||||
|
{
|
||||||
|
factory.registerFunction<FunctionFormatDateTime>();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
44
dbms/src/Functions/now.cpp
Normal file
44
dbms/src/Functions/now.cpp
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
#include <DataTypes/DataTypeDateTime.h>
|
||||||
|
|
||||||
|
#include <Functions/IFunction.h>
|
||||||
|
#include <Functions/FunctionFactory.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
/// Get the current time. (It is a constant, it is evaluated once for the entire query.)
|
||||||
|
class FunctionNow : public IFunction
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static constexpr auto name = "now";
|
||||||
|
static FunctionPtr create(const Context &) { return std::make_shared<FunctionNow>(); }
|
||||||
|
|
||||||
|
String getName() const override
|
||||||
|
{
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t getNumberOfArguments() const override { return 0; }
|
||||||
|
|
||||||
|
DataTypePtr getReturnTypeImpl(const DataTypes & /*arguments*/) const override
|
||||||
|
{
|
||||||
|
return std::make_shared<DataTypeDateTime>();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isDeterministic() const override { return false; }
|
||||||
|
|
||||||
|
void executeImpl(Block & block, const ColumnNumbers &, size_t result, size_t input_rows_count) override
|
||||||
|
{
|
||||||
|
block.getByPosition(result).column = DataTypeDateTime().createColumnConst(
|
||||||
|
input_rows_count,
|
||||||
|
static_cast<UInt64>(time(nullptr)));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void registerFunctionNow(FunctionFactory & factory)
|
||||||
|
{
|
||||||
|
factory.registerFunction<FunctionNow>(FunctionFactory::CaseInsensitive);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
123
dbms/src/Functions/registerFunctionsDateTime.cpp
Normal file
123
dbms/src/Functions/registerFunctionsDateTime.cpp
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
#include <Functions/FunctionFactory.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
void registerFunctionToYear(FunctionFactory &);
|
||||||
|
void registerFunctionToQuarter(FunctionFactory &);
|
||||||
|
void registerFunctionToMonth(FunctionFactory &);
|
||||||
|
void registerFunctionToDayOfMonth(FunctionFactory &);
|
||||||
|
void registerFunctionToDayOfWeek(FunctionFactory &);
|
||||||
|
void registerFunctionToDayOfYear(FunctionFactory &);
|
||||||
|
void registerFunctionToHour(FunctionFactory &);
|
||||||
|
void registerFunctionToMinute(FunctionFactory &);
|
||||||
|
void registerFunctionToSecond(FunctionFactory &);
|
||||||
|
void registerFunctionToStartOfDay(FunctionFactory &);
|
||||||
|
void registerFunctionToMonday(FunctionFactory &);
|
||||||
|
void registerFunctionToISOWeek(FunctionFactory &);
|
||||||
|
void registerFunctionToISOYear(FunctionFactory &);
|
||||||
|
void registerFunctionToStartOfMonth(FunctionFactory &);
|
||||||
|
void registerFunctionToStartOfQuarter(FunctionFactory &);
|
||||||
|
void registerFunctionToStartOfYear(FunctionFactory &);
|
||||||
|
void registerFunctionToStartOfMinute(FunctionFactory &);
|
||||||
|
void registerFunctionToStartOfFiveMinute(FunctionFactory &);
|
||||||
|
void registerFunctionToStartOfFifteenMinutes(FunctionFactory &);
|
||||||
|
void registerFunctionToStartOfHour(FunctionFactory &);
|
||||||
|
void registerFunctionToStartOfISOYear(FunctionFactory &);
|
||||||
|
void registerFunctionToRelativeYearNum(FunctionFactory &);
|
||||||
|
void registerFunctionToRelativeQuarterNum(FunctionFactory &);
|
||||||
|
void registerFunctionToRelativeMonthNum(FunctionFactory &);
|
||||||
|
void registerFunctionToRelativeWeekNum(FunctionFactory &);
|
||||||
|
void registerFunctionToRelativeDayNum(FunctionFactory &);
|
||||||
|
void registerFunctionToRelativeHourNum(FunctionFactory &);
|
||||||
|
void registerFunctionToRelativeMinuteNum(FunctionFactory &);
|
||||||
|
void registerFunctionToRelativeSecondNum(FunctionFactory &);
|
||||||
|
void registerFunctionToTime(FunctionFactory &);
|
||||||
|
void registerFunctionNow(FunctionFactory &);
|
||||||
|
void registerFunctionToday(FunctionFactory &);
|
||||||
|
void registerFunctionYesterday(FunctionFactory &);
|
||||||
|
void registerFunctionTimeSlot(FunctionFactory &);
|
||||||
|
void registerFunctionTimeSlots(FunctionFactory &);
|
||||||
|
void registerFunctionToYYYYMM(FunctionFactory &);
|
||||||
|
void registerFunctionToYYYYMMDD(FunctionFactory &);
|
||||||
|
void registerFunctionToYYYYMMDDhhmmss(FunctionFactory &);
|
||||||
|
void registerFunctionAddSeconds(FunctionFactory &);
|
||||||
|
void registerFunctionAddMinutes(FunctionFactory &);
|
||||||
|
void registerFunctionAddHours(FunctionFactory &);
|
||||||
|
void registerFunctionAddDays(FunctionFactory &);
|
||||||
|
void registerFunctionAddWeeks(FunctionFactory &);
|
||||||
|
void registerFunctionAddMonths(FunctionFactory &);
|
||||||
|
void registerFunctionAddYears(FunctionFactory &);
|
||||||
|
void registerFunctionSubtractSeconds(FunctionFactory &);
|
||||||
|
void registerFunctionSubtractMinutes(FunctionFactory &);
|
||||||
|
void registerFunctionSubtractHours(FunctionFactory &);
|
||||||
|
void registerFunctionSubtractDays(FunctionFactory &);
|
||||||
|
void registerFunctionSubtractWeeks(FunctionFactory &);
|
||||||
|
void registerFunctionSubtractMonths(FunctionFactory &);
|
||||||
|
void registerFunctionSubtractYears(FunctionFactory &);
|
||||||
|
void registerFunctionDateDiff(FunctionFactory &);
|
||||||
|
void registerFunctionToTimeZone(FunctionFactory &);
|
||||||
|
void registerFunctionFormatDateTime(FunctionFactory &);
|
||||||
|
|
||||||
|
|
||||||
|
void registerFunctionsDateTime(FunctionFactory & factory)
|
||||||
|
{
|
||||||
|
registerFunctionToYear(factory);
|
||||||
|
registerFunctionToQuarter(factory);
|
||||||
|
registerFunctionToMonth(factory);
|
||||||
|
registerFunctionToDayOfMonth(factory);
|
||||||
|
registerFunctionToDayOfWeek(factory);
|
||||||
|
registerFunctionToDayOfYear(factory);
|
||||||
|
registerFunctionToHour(factory);
|
||||||
|
registerFunctionToMinute(factory);
|
||||||
|
registerFunctionToSecond(factory);
|
||||||
|
registerFunctionToStartOfDay(factory);
|
||||||
|
registerFunctionToMonday(factory);
|
||||||
|
registerFunctionToISOWeek(factory);
|
||||||
|
registerFunctionToISOYear(factory);
|
||||||
|
registerFunctionToStartOfMonth(factory);
|
||||||
|
registerFunctionToStartOfQuarter(factory);
|
||||||
|
registerFunctionToStartOfYear(factory);
|
||||||
|
registerFunctionToStartOfMinute(factory);
|
||||||
|
registerFunctionToStartOfFiveMinute(factory);
|
||||||
|
registerFunctionToStartOfFifteenMinutes(factory);
|
||||||
|
registerFunctionToStartOfHour(factory);
|
||||||
|
registerFunctionToStartOfISOYear(factory);
|
||||||
|
registerFunctionToRelativeYearNum(factory);
|
||||||
|
registerFunctionToRelativeQuarterNum(factory);
|
||||||
|
registerFunctionToRelativeMonthNum(factory);
|
||||||
|
registerFunctionToRelativeWeekNum(factory);
|
||||||
|
registerFunctionToRelativeDayNum(factory);
|
||||||
|
registerFunctionToRelativeHourNum(factory);
|
||||||
|
registerFunctionToRelativeMinuteNum(factory);
|
||||||
|
registerFunctionToRelativeSecondNum(factory);
|
||||||
|
registerFunctionToTime(factory);
|
||||||
|
registerFunctionNow(factory);
|
||||||
|
registerFunctionToday(factory);
|
||||||
|
registerFunctionYesterday(factory);
|
||||||
|
registerFunctionTimeSlot(factory);
|
||||||
|
registerFunctionTimeSlots(factory);
|
||||||
|
registerFunctionToYYYYMM(factory);
|
||||||
|
registerFunctionToYYYYMMDD(factory);
|
||||||
|
registerFunctionToYYYYMMDDhhmmss(factory);
|
||||||
|
registerFunctionAddSeconds(factory);
|
||||||
|
registerFunctionAddMinutes(factory);
|
||||||
|
registerFunctionAddHours(factory);
|
||||||
|
registerFunctionAddDays(factory);
|
||||||
|
registerFunctionAddWeeks(factory);
|
||||||
|
registerFunctionAddMonths(factory);
|
||||||
|
registerFunctionAddYears(factory);
|
||||||
|
registerFunctionSubtractSeconds(factory);
|
||||||
|
registerFunctionSubtractMinutes(factory);
|
||||||
|
registerFunctionSubtractHours(factory);
|
||||||
|
registerFunctionSubtractDays(factory);
|
||||||
|
registerFunctionSubtractWeeks(factory);
|
||||||
|
registerFunctionSubtractMonths(factory);
|
||||||
|
registerFunctionSubtractYears(factory);
|
||||||
|
registerFunctionDateDiff(factory);
|
||||||
|
registerFunctionToTimeZone(factory);
|
||||||
|
registerFunctionFormatDateTime(factory);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
18
dbms/src/Functions/subtractDays.cpp
Normal file
18
dbms/src/Functions/subtractDays.cpp
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#include <Functions/IFunction.h>
|
||||||
|
#include <Functions/FunctionFactory.h>
|
||||||
|
#include <Functions/FunctionDateOrDateTimeAddInterval.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
using FunctionSubtractDays = FunctionDateOrDateTimeAddInterval<SubtractDaysImpl>;
|
||||||
|
|
||||||
|
void registerFunctionSubtractDays(FunctionFactory & factory)
|
||||||
|
{
|
||||||
|
factory.registerFunction<FunctionSubtractDays>();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
18
dbms/src/Functions/subtractHours.cpp
Normal file
18
dbms/src/Functions/subtractHours.cpp
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#include <Functions/IFunction.h>
|
||||||
|
#include <Functions/FunctionFactory.h>
|
||||||
|
#include <Functions/FunctionDateOrDateTimeAddInterval.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
using FunctionSubtractHours = FunctionDateOrDateTimeAddInterval<SubtractHoursImpl>;
|
||||||
|
|
||||||
|
void registerFunctionSubtractHours(FunctionFactory & factory)
|
||||||
|
{
|
||||||
|
factory.registerFunction<FunctionSubtractHours>();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
18
dbms/src/Functions/subtractMinutes.cpp
Normal file
18
dbms/src/Functions/subtractMinutes.cpp
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#include <Functions/IFunction.h>
|
||||||
|
#include <Functions/FunctionFactory.h>
|
||||||
|
#include <Functions/FunctionDateOrDateTimeAddInterval.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
using FunctionSubtractMinutes = FunctionDateOrDateTimeAddInterval<SubtractMinutesImpl>;
|
||||||
|
|
||||||
|
void registerFunctionSubtractMinutes(FunctionFactory & factory)
|
||||||
|
{
|
||||||
|
factory.registerFunction<FunctionSubtractMinutes>();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
18
dbms/src/Functions/subtractMonths.cpp
Normal file
18
dbms/src/Functions/subtractMonths.cpp
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#include <Functions/IFunction.h>
|
||||||
|
#include <Functions/FunctionFactory.h>
|
||||||
|
#include <Functions/FunctionDateOrDateTimeAddInterval.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
using FunctionSubtractMonths = FunctionDateOrDateTimeAddInterval<SubtractMonthsImpl>;
|
||||||
|
|
||||||
|
void registerFunctionSubtractMonths(FunctionFactory & factory)
|
||||||
|
{
|
||||||
|
factory.registerFunction<FunctionSubtractMonths>();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
18
dbms/src/Functions/subtractSeconds.cpp
Normal file
18
dbms/src/Functions/subtractSeconds.cpp
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#include <Functions/IFunction.h>
|
||||||
|
#include <Functions/FunctionFactory.h>
|
||||||
|
#include <Functions/FunctionDateOrDateTimeAddInterval.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
using FunctionSubtractSeconds = FunctionDateOrDateTimeAddInterval<SubtractSecondsImpl>;
|
||||||
|
|
||||||
|
void registerFunctionSubtractSeconds(FunctionFactory & factory)
|
||||||
|
{
|
||||||
|
factory.registerFunction<FunctionSubtractSeconds>();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
18
dbms/src/Functions/subtractWeeks.cpp
Normal file
18
dbms/src/Functions/subtractWeeks.cpp
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#include <Functions/IFunction.h>
|
||||||
|
#include <Functions/FunctionFactory.h>
|
||||||
|
#include <Functions/FunctionDateOrDateTimeAddInterval.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
using FunctionSubtractWeeks = FunctionDateOrDateTimeAddInterval<SubtractWeeksImpl>;
|
||||||
|
|
||||||
|
void registerFunctionSubtractWeeks(FunctionFactory & factory)
|
||||||
|
{
|
||||||
|
factory.registerFunction<FunctionSubtractWeeks>();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
18
dbms/src/Functions/subtractYears.cpp
Normal file
18
dbms/src/Functions/subtractYears.cpp
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#include <Functions/IFunction.h>
|
||||||
|
#include <Functions/FunctionFactory.h>
|
||||||
|
#include <Functions/FunctionDateOrDateTimeAddInterval.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
using FunctionSubtractYears = FunctionDateOrDateTimeAddInterval<SubtractYearsImpl>;
|
||||||
|
|
||||||
|
void registerFunctionSubtractYears(FunctionFactory & factory)
|
||||||
|
{
|
||||||
|
factory.registerFunction<FunctionSubtractYears>();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
21
dbms/src/Functions/timeSlot.cpp
Normal file
21
dbms/src/Functions/timeSlot.cpp
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#include <Functions/IFunction.h>
|
||||||
|
#include <Functions/FunctionFactory.h>
|
||||||
|
#include <Functions/DateTimeTransforms.h>
|
||||||
|
#include <Functions/FunctionDateOrDateTimeToSomething.h>
|
||||||
|
#include <DataTypes/DataTypesNumber.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
using FunctionTimeSlot = FunctionDateOrDateTimeToSomething<DataTypeUInt32, TimeSlotImpl>;
|
||||||
|
|
||||||
|
void registerFunctionTimeSlot(FunctionFactory & factory)
|
||||||
|
{
|
||||||
|
factory.registerFunction<FunctionTimeSlot>();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
182
dbms/src/Functions/timeSlots.cpp
Normal file
182
dbms/src/Functions/timeSlots.cpp
Normal file
@ -0,0 +1,182 @@
|
|||||||
|
#include <DataTypes/DataTypeDateTime.h>
|
||||||
|
#include <DataTypes/DataTypeArray.h>
|
||||||
|
#include <Columns/ColumnArray.h>
|
||||||
|
#include <Columns/ColumnsNumber.h>
|
||||||
|
|
||||||
|
#include <Functions/IFunction.h>
|
||||||
|
#include <Functions/FunctionFactory.h>
|
||||||
|
#include <Functions/FunctionHelpers.h>
|
||||||
|
#include <Functions/extractTimeZoneFromFunctionArguments.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace ErrorCodes
|
||||||
|
{
|
||||||
|
extern const int NUMBER_OF_ARGUMENTS_DOESNT_MATCH;
|
||||||
|
extern const int ILLEGAL_TYPE_OF_ARGUMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** timeSlots(StartTime, Duration)
|
||||||
|
* - 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.
|
||||||
|
*
|
||||||
|
* This is obsolete function. It was developed for Yandex.Metrica, but no longer used.
|
||||||
|
*/
|
||||||
|
|
||||||
|
template <typename DurationType>
|
||||||
|
struct TimeSlotsImpl
|
||||||
|
{
|
||||||
|
static constexpr UInt32 TIME_SLOT_SIZE = 1800;
|
||||||
|
|
||||||
|
static void vector_vector(
|
||||||
|
const PaddedPODArray<UInt32> & starts, const PaddedPODArray<DurationType> & durations,
|
||||||
|
PaddedPODArray<UInt32> & result_values, ColumnArray::Offsets & result_offsets)
|
||||||
|
{
|
||||||
|
size_t size = starts.size();
|
||||||
|
|
||||||
|
result_offsets.resize(size);
|
||||||
|
result_values.reserve(size);
|
||||||
|
|
||||||
|
ColumnArray::Offset 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 & result_offsets)
|
||||||
|
{
|
||||||
|
size_t size = starts.size();
|
||||||
|
|
||||||
|
result_offsets.resize(size);
|
||||||
|
result_values.reserve(size);
|
||||||
|
|
||||||
|
ColumnArray::Offset 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 & result_offsets)
|
||||||
|
{
|
||||||
|
size_t size = durations.size();
|
||||||
|
|
||||||
|
result_offsets.resize(size);
|
||||||
|
result_values.reserve(size);
|
||||||
|
|
||||||
|
ColumnArray::Offset 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));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class FunctionTimeSlots : public IFunction
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static constexpr auto name = "timeSlots";
|
||||||
|
static FunctionPtr create(const 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 (!WhichDataType(arguments[0]).isDateTime())
|
||||||
|
throw Exception("Illegal type " + arguments[0]->getName() + " of first argument of function " + getName() + ". Must be DateTime.",
|
||||||
|
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
||||||
|
|
||||||
|
if (!WhichDataType(arguments[1]).isUInt32())
|
||||||
|
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, size_t input_rows_count) override
|
||||||
|
{
|
||||||
|
auto starts = checkAndGetColumn<ColumnUInt32>(block.getByPosition(arguments[0]).column.get());
|
||||||
|
auto const_starts = checkAndGetColumnConst<ColumnUInt32>(block.getByPosition(arguments[0]).column.get());
|
||||||
|
|
||||||
|
auto durations = checkAndGetColumn<ColumnUInt32>(block.getByPosition(arguments[1]).column.get());
|
||||||
|
auto const_durations = checkAndGetColumnConst<ColumnUInt32>(block.getByPosition(arguments[1]).column.get());
|
||||||
|
|
||||||
|
auto res = ColumnArray::create(ColumnUInt32::create());
|
||||||
|
ColumnUInt32::Container & res_values = typeid_cast<ColumnUInt32 &>(res->getData()).getData();
|
||||||
|
|
||||||
|
if (starts && durations)
|
||||||
|
{
|
||||||
|
TimeSlotsImpl<UInt32>::vector_vector(starts->getData(), durations->getData(), res_values, res->getOffsets());
|
||||||
|
block.getByPosition(result).column = std::move(res);
|
||||||
|
}
|
||||||
|
else if (starts && const_durations)
|
||||||
|
{
|
||||||
|
TimeSlotsImpl<UInt32>::vector_constant(starts->getData(), const_durations->getValue<UInt32>(), res_values, res->getOffsets());
|
||||||
|
block.getByPosition(result).column = std::move(res);
|
||||||
|
}
|
||||||
|
else if (const_starts && durations)
|
||||||
|
{
|
||||||
|
TimeSlotsImpl<UInt32>::constant_vector(const_starts->getValue<UInt32>(), durations->getData(), res_values, res->getOffsets());
|
||||||
|
block.getByPosition(result).column = std::move(res);
|
||||||
|
}
|
||||||
|
else if (const_starts && const_durations)
|
||||||
|
{
|
||||||
|
Array const_res;
|
||||||
|
TimeSlotsImpl<UInt32>::constant_constant(const_starts->getValue<UInt32>(), const_durations->getValue<UInt32>(), const_res);
|
||||||
|
block.getByPosition(result).column = block.getByPosition(result).type->createColumnConst(input_rows_count, const_res);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw Exception("Illegal columns " + block.getByPosition(arguments[0]).column->getName()
|
||||||
|
+ ", " + block.getByPosition(arguments[1]).column->getName()
|
||||||
|
+ " of arguments of function " + getName(),
|
||||||
|
ErrorCodes::ILLEGAL_COLUMN);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void registerFunctionTimeSlots(FunctionFactory & factory)
|
||||||
|
{
|
||||||
|
factory.registerFunction<FunctionTimeSlots>();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
20
dbms/src/Functions/toDayOfMonth.cpp
Normal file
20
dbms/src/Functions/toDayOfMonth.cpp
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#include <Functions/IFunction.h>
|
||||||
|
#include <Functions/FunctionFactory.h>
|
||||||
|
#include <Functions/DateTimeTransforms.h>
|
||||||
|
#include <Functions/FunctionDateOrDateTimeToSomething.h>
|
||||||
|
#include <DataTypes/DataTypesNumber.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
using FunctionToDayOfMonth = FunctionDateOrDateTimeToSomething<DataTypeUInt8, ToDayOfMonthImpl>;
|
||||||
|
|
||||||
|
void registerFunctionToDayOfMonth(FunctionFactory & factory)
|
||||||
|
{
|
||||||
|
factory.registerFunction<FunctionToDayOfMonth>();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
20
dbms/src/Functions/toDayOfWeek.cpp
Normal file
20
dbms/src/Functions/toDayOfWeek.cpp
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#include <Functions/IFunction.h>
|
||||||
|
#include <Functions/FunctionFactory.h>
|
||||||
|
#include <Functions/DateTimeTransforms.h>
|
||||||
|
#include <Functions/FunctionDateOrDateTimeToSomething.h>
|
||||||
|
#include <DataTypes/DataTypesNumber.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
using FunctionToDayOfWeek = FunctionDateOrDateTimeToSomething<DataTypeUInt8, ToDayOfWeekImpl>;
|
||||||
|
|
||||||
|
void registerFunctionToDayOfWeek(FunctionFactory & factory)
|
||||||
|
{
|
||||||
|
factory.registerFunction<FunctionToDayOfWeek>();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
20
dbms/src/Functions/toDayOfYear.cpp
Normal file
20
dbms/src/Functions/toDayOfYear.cpp
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#include <Functions/IFunction.h>
|
||||||
|
#include <Functions/FunctionFactory.h>
|
||||||
|
#include <Functions/DateTimeTransforms.h>
|
||||||
|
#include <Functions/FunctionDateOrDateTimeToSomething.h>
|
||||||
|
#include <DataTypes/DataTypesNumber.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
using FunctionToDayOfYear = FunctionDateOrDateTimeToSomething<DataTypeUInt16, ToDayOfYearImpl>;
|
||||||
|
|
||||||
|
void registerFunctionToDayOfYear(FunctionFactory & factory)
|
||||||
|
{
|
||||||
|
factory.registerFunction<FunctionToDayOfYear>();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
20
dbms/src/Functions/toHour.cpp
Normal file
20
dbms/src/Functions/toHour.cpp
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#include <Functions/IFunction.h>
|
||||||
|
#include <Functions/FunctionFactory.h>
|
||||||
|
#include <Functions/DateTimeTransforms.h>
|
||||||
|
#include <Functions/FunctionDateOrDateTimeToSomething.h>
|
||||||
|
#include <DataTypes/DataTypesNumber.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
using FunctionToHour = FunctionDateOrDateTimeToSomething<DataTypeUInt8, ToHourImpl>;
|
||||||
|
|
||||||
|
void registerFunctionToHour(FunctionFactory & factory)
|
||||||
|
{
|
||||||
|
factory.registerFunction<FunctionToHour>();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
20
dbms/src/Functions/toISOWeek.cpp
Normal file
20
dbms/src/Functions/toISOWeek.cpp
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#include <Functions/IFunction.h>
|
||||||
|
#include <Functions/FunctionFactory.h>
|
||||||
|
#include <Functions/DateTimeTransforms.h>
|
||||||
|
#include <Functions/FunctionDateOrDateTimeToSomething.h>
|
||||||
|
#include <DataTypes/DataTypesNumber.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
using FunctionToISOWeek = FunctionDateOrDateTimeToSomething<DataTypeUInt8, ToISOWeekImpl>;
|
||||||
|
|
||||||
|
void registerFunctionToISOWeek(FunctionFactory & factory)
|
||||||
|
{
|
||||||
|
factory.registerFunction<FunctionToISOWeek>();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
20
dbms/src/Functions/toISOYear.cpp
Normal file
20
dbms/src/Functions/toISOYear.cpp
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#include <Functions/IFunction.h>
|
||||||
|
#include <Functions/FunctionFactory.h>
|
||||||
|
#include <Functions/DateTimeTransforms.h>
|
||||||
|
#include <Functions/FunctionDateOrDateTimeToSomething.h>
|
||||||
|
#include <DataTypes/DataTypesNumber.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
using FunctionToISOYear = FunctionDateOrDateTimeToSomething<DataTypeUInt16, ToISOYearImpl>;
|
||||||
|
|
||||||
|
void registerFunctionToISOYear(FunctionFactory & factory)
|
||||||
|
{
|
||||||
|
factory.registerFunction<FunctionToISOYear>();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
20
dbms/src/Functions/toMinute.cpp
Normal file
20
dbms/src/Functions/toMinute.cpp
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#include <Functions/IFunction.h>
|
||||||
|
#include <Functions/FunctionFactory.h>
|
||||||
|
#include <Functions/DateTimeTransforms.h>
|
||||||
|
#include <Functions/FunctionDateOrDateTimeToSomething.h>
|
||||||
|
#include <DataTypes/DataTypesNumber.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
using FunctionToMinute = FunctionDateOrDateTimeToSomething<DataTypeUInt8, ToMinuteImpl>;
|
||||||
|
|
||||||
|
void registerFunctionToMinute(FunctionFactory & factory)
|
||||||
|
{
|
||||||
|
factory.registerFunction<FunctionToMinute>();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
20
dbms/src/Functions/toMonday.cpp
Normal file
20
dbms/src/Functions/toMonday.cpp
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#include <Functions/IFunction.h>
|
||||||
|
#include <Functions/FunctionFactory.h>
|
||||||
|
#include <Functions/DateTimeTransforms.h>
|
||||||
|
#include <Functions/FunctionDateOrDateTimeToSomething.h>
|
||||||
|
#include <DataTypes/DataTypesNumber.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
using FunctionToMonday = FunctionDateOrDateTimeToSomething<DataTypeDate, ToMondayImpl>;
|
||||||
|
|
||||||
|
void registerFunctionToMonday(FunctionFactory & factory)
|
||||||
|
{
|
||||||
|
factory.registerFunction<FunctionToMonday>();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
20
dbms/src/Functions/toMonth.cpp
Normal file
20
dbms/src/Functions/toMonth.cpp
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#include <Functions/IFunction.h>
|
||||||
|
#include <Functions/FunctionFactory.h>
|
||||||
|
#include <Functions/DateTimeTransforms.h>
|
||||||
|
#include <Functions/FunctionDateOrDateTimeToSomething.h>
|
||||||
|
#include <DataTypes/DataTypesNumber.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
using FunctionToMonth = FunctionDateOrDateTimeToSomething<DataTypeUInt8, ToMonthImpl>;
|
||||||
|
|
||||||
|
void registerFunctionToMonth(FunctionFactory & factory)
|
||||||
|
{
|
||||||
|
factory.registerFunction<FunctionToMonth>();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
20
dbms/src/Functions/toQuarter.cpp
Normal file
20
dbms/src/Functions/toQuarter.cpp
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#include <Functions/IFunction.h>
|
||||||
|
#include <Functions/FunctionFactory.h>
|
||||||
|
#include <Functions/DateTimeTransforms.h>
|
||||||
|
#include <Functions/FunctionDateOrDateTimeToSomething.h>
|
||||||
|
#include <DataTypes/DataTypesNumber.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
using FunctionToQuarter = FunctionDateOrDateTimeToSomething<DataTypeUInt8, ToQuarterImpl>;
|
||||||
|
|
||||||
|
void registerFunctionToQuarter(FunctionFactory & factory)
|
||||||
|
{
|
||||||
|
factory.registerFunction<FunctionToQuarter>();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
20
dbms/src/Functions/toRelativeDayNum.cpp
Normal file
20
dbms/src/Functions/toRelativeDayNum.cpp
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#include <Functions/IFunction.h>
|
||||||
|
#include <Functions/FunctionFactory.h>
|
||||||
|
#include <Functions/DateTimeTransforms.h>
|
||||||
|
#include <Functions/FunctionDateOrDateTimeToSomething.h>
|
||||||
|
#include <DataTypes/DataTypesNumber.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
using FunctionToRelativeDayNum = FunctionDateOrDateTimeToSomething<DataTypeUInt32, ToRelativeDayNumImpl>;
|
||||||
|
|
||||||
|
void registerFunctionToRelativeDayNum(FunctionFactory & factory)
|
||||||
|
{
|
||||||
|
factory.registerFunction<FunctionToRelativeDayNum>();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
20
dbms/src/Functions/toRelativeHourNum.cpp
Normal file
20
dbms/src/Functions/toRelativeHourNum.cpp
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#include <Functions/IFunction.h>
|
||||||
|
#include <Functions/FunctionFactory.h>
|
||||||
|
#include <Functions/DateTimeTransforms.h>
|
||||||
|
#include <Functions/FunctionDateOrDateTimeToSomething.h>
|
||||||
|
#include <DataTypes/DataTypesNumber.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
using FunctionToRelativeHourNum = FunctionDateOrDateTimeToSomething<DataTypeUInt32, ToRelativeHourNumImpl>;
|
||||||
|
|
||||||
|
void registerFunctionToRelativeHourNum(FunctionFactory & factory)
|
||||||
|
{
|
||||||
|
factory.registerFunction<FunctionToRelativeHourNum>();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
20
dbms/src/Functions/toRelativeMinuteNum.cpp
Normal file
20
dbms/src/Functions/toRelativeMinuteNum.cpp
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#include <Functions/IFunction.h>
|
||||||
|
#include <Functions/FunctionFactory.h>
|
||||||
|
#include <Functions/DateTimeTransforms.h>
|
||||||
|
#include <Functions/FunctionDateOrDateTimeToSomething.h>
|
||||||
|
#include <DataTypes/DataTypesNumber.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
using FunctionToRelativeMinuteNum = FunctionDateOrDateTimeToSomething<DataTypeUInt32, ToRelativeMinuteNumImpl>;
|
||||||
|
|
||||||
|
void registerFunctionToRelativeMinuteNum(FunctionFactory & factory)
|
||||||
|
{
|
||||||
|
factory.registerFunction<FunctionToRelativeMinuteNum>();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
20
dbms/src/Functions/toRelativeMonthNum.cpp
Normal file
20
dbms/src/Functions/toRelativeMonthNum.cpp
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#include <Functions/IFunction.h>
|
||||||
|
#include <Functions/FunctionFactory.h>
|
||||||
|
#include <Functions/DateTimeTransforms.h>
|
||||||
|
#include <Functions/FunctionDateOrDateTimeToSomething.h>
|
||||||
|
#include <DataTypes/DataTypesNumber.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
using FunctionToRelativeMonthNum = FunctionDateOrDateTimeToSomething<DataTypeUInt32, ToRelativeMonthNumImpl>;
|
||||||
|
|
||||||
|
void registerFunctionToRelativeMonthNum(FunctionFactory & factory)
|
||||||
|
{
|
||||||
|
factory.registerFunction<FunctionToRelativeMonthNum>();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
20
dbms/src/Functions/toRelativeQuarterNum.cpp
Normal file
20
dbms/src/Functions/toRelativeQuarterNum.cpp
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#include <Functions/IFunction.h>
|
||||||
|
#include <Functions/FunctionFactory.h>
|
||||||
|
#include <Functions/DateTimeTransforms.h>
|
||||||
|
#include <Functions/FunctionDateOrDateTimeToSomething.h>
|
||||||
|
#include <DataTypes/DataTypesNumber.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
using FunctionToRelativeQuarterNum = FunctionDateOrDateTimeToSomething<DataTypeUInt32, ToRelativeQuarterNumImpl>;
|
||||||
|
|
||||||
|
void registerFunctionToRelativeQuarterNum(FunctionFactory & factory)
|
||||||
|
{
|
||||||
|
factory.registerFunction<FunctionToRelativeQuarterNum>();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
20
dbms/src/Functions/toRelativeSecondNum.cpp
Normal file
20
dbms/src/Functions/toRelativeSecondNum.cpp
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#include <Functions/IFunction.h>
|
||||||
|
#include <Functions/FunctionFactory.h>
|
||||||
|
#include <Functions/DateTimeTransforms.h>
|
||||||
|
#include <Functions/FunctionDateOrDateTimeToSomething.h>
|
||||||
|
#include <DataTypes/DataTypesNumber.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
using FunctionToRelativeSecondNum = FunctionDateOrDateTimeToSomething<DataTypeUInt32, ToRelativeSecondNumImpl>;
|
||||||
|
|
||||||
|
void registerFunctionToRelativeSecondNum(FunctionFactory & factory)
|
||||||
|
{
|
||||||
|
factory.registerFunction<FunctionToRelativeSecondNum>();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
20
dbms/src/Functions/toRelativeWeekNum.cpp
Normal file
20
dbms/src/Functions/toRelativeWeekNum.cpp
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#include <Functions/IFunction.h>
|
||||||
|
#include <Functions/FunctionFactory.h>
|
||||||
|
#include <Functions/DateTimeTransforms.h>
|
||||||
|
#include <Functions/FunctionDateOrDateTimeToSomething.h>
|
||||||
|
#include <DataTypes/DataTypesNumber.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
using FunctionToRelativeWeekNum = FunctionDateOrDateTimeToSomething<DataTypeUInt32, ToRelativeWeekNumImpl>;
|
||||||
|
|
||||||
|
void registerFunctionToRelativeWeekNum(FunctionFactory & factory)
|
||||||
|
{
|
||||||
|
factory.registerFunction<FunctionToRelativeWeekNum>();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
20
dbms/src/Functions/toRelativeYearNum.cpp
Normal file
20
dbms/src/Functions/toRelativeYearNum.cpp
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#include <Functions/IFunction.h>
|
||||||
|
#include <Functions/FunctionFactory.h>
|
||||||
|
#include <Functions/DateTimeTransforms.h>
|
||||||
|
#include <Functions/FunctionDateOrDateTimeToSomething.h>
|
||||||
|
#include <DataTypes/DataTypesNumber.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
using FunctionToRelativeYearNum = FunctionDateOrDateTimeToSomething<DataTypeUInt16, ToRelativeYearNumImpl>;
|
||||||
|
|
||||||
|
void registerFunctionToRelativeYearNum(FunctionFactory & factory)
|
||||||
|
{
|
||||||
|
factory.registerFunction<FunctionToRelativeYearNum>();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
20
dbms/src/Functions/toSecond.cpp
Normal file
20
dbms/src/Functions/toSecond.cpp
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#include <Functions/IFunction.h>
|
||||||
|
#include <Functions/FunctionFactory.h>
|
||||||
|
#include <Functions/DateTimeTransforms.h>
|
||||||
|
#include <Functions/FunctionDateOrDateTimeToSomething.h>
|
||||||
|
#include <DataTypes/DataTypesNumber.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
using FunctionToSecond = FunctionDateOrDateTimeToSomething<DataTypeUInt8, ToSecondImpl>;
|
||||||
|
|
||||||
|
void registerFunctionToSecond(FunctionFactory & factory)
|
||||||
|
{
|
||||||
|
factory.registerFunction<FunctionToSecond>();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
20
dbms/src/Functions/toStartOfDay.cpp
Normal file
20
dbms/src/Functions/toStartOfDay.cpp
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#include <Functions/IFunction.h>
|
||||||
|
#include <Functions/FunctionFactory.h>
|
||||||
|
#include <Functions/DateTimeTransforms.h>
|
||||||
|
#include <Functions/FunctionDateOrDateTimeToSomething.h>
|
||||||
|
#include <DataTypes/DataTypesNumber.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
using FunctionToStartOfDay = FunctionDateOrDateTimeToSomething<DataTypeDateTime, ToStartOfDayImpl>;
|
||||||
|
|
||||||
|
void registerFunctionToStartOfDay(FunctionFactory & factory)
|
||||||
|
{
|
||||||
|
factory.registerFunction<FunctionToStartOfDay>();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
20
dbms/src/Functions/toStartOfFifteenMinutes.cpp
Normal file
20
dbms/src/Functions/toStartOfFifteenMinutes.cpp
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#include <Functions/IFunction.h>
|
||||||
|
#include <Functions/FunctionFactory.h>
|
||||||
|
#include <Functions/DateTimeTransforms.h>
|
||||||
|
#include <Functions/FunctionDateOrDateTimeToSomething.h>
|
||||||
|
#include <DataTypes/DataTypesNumber.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
using FunctionToStartOfFifteenMinutes = FunctionDateOrDateTimeToSomething<DataTypeDateTime, ToStartOfFifteenMinutesImpl>;
|
||||||
|
|
||||||
|
void registerFunctionToStartOfFifteenMinutes(FunctionFactory & factory)
|
||||||
|
{
|
||||||
|
factory.registerFunction<FunctionToStartOfFifteenMinutes>();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
20
dbms/src/Functions/toStartOfFiveMinute.cpp
Normal file
20
dbms/src/Functions/toStartOfFiveMinute.cpp
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#include <Functions/IFunction.h>
|
||||||
|
#include <Functions/FunctionFactory.h>
|
||||||
|
#include <Functions/DateTimeTransforms.h>
|
||||||
|
#include <Functions/FunctionDateOrDateTimeToSomething.h>
|
||||||
|
#include <DataTypes/DataTypesNumber.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
using FunctionToStartOfFiveMinute = FunctionDateOrDateTimeToSomething<DataTypeDateTime, ToStartOfFiveMinuteImpl>;
|
||||||
|
|
||||||
|
void registerFunctionToStartOfFiveMinute(FunctionFactory & factory)
|
||||||
|
{
|
||||||
|
factory.registerFunction<FunctionToStartOfFiveMinute>();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
20
dbms/src/Functions/toStartOfHour.cpp
Normal file
20
dbms/src/Functions/toStartOfHour.cpp
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#include <Functions/IFunction.h>
|
||||||
|
#include <Functions/FunctionFactory.h>
|
||||||
|
#include <Functions/DateTimeTransforms.h>
|
||||||
|
#include <Functions/FunctionDateOrDateTimeToSomething.h>
|
||||||
|
#include <DataTypes/DataTypesNumber.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
using FunctionToStartOfHour = FunctionDateOrDateTimeToSomething<DataTypeDateTime, ToStartOfHourImpl>;
|
||||||
|
|
||||||
|
void registerFunctionToStartOfHour(FunctionFactory & factory)
|
||||||
|
{
|
||||||
|
factory.registerFunction<FunctionToStartOfHour>();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
20
dbms/src/Functions/toStartOfISOYear.cpp
Normal file
20
dbms/src/Functions/toStartOfISOYear.cpp
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#include <Functions/IFunction.h>
|
||||||
|
#include <Functions/FunctionFactory.h>
|
||||||
|
#include <Functions/DateTimeTransforms.h>
|
||||||
|
#include <Functions/FunctionDateOrDateTimeToSomething.h>
|
||||||
|
#include <DataTypes/DataTypesNumber.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
using FunctionToStartOfISOYear = FunctionDateOrDateTimeToSomething<DataTypeDate, ToStartOfISOYearImpl>;
|
||||||
|
|
||||||
|
void registerFunctionToStartOfISOYear(FunctionFactory & factory)
|
||||||
|
{
|
||||||
|
factory.registerFunction<FunctionToStartOfISOYear>();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
20
dbms/src/Functions/toStartOfMinute.cpp
Normal file
20
dbms/src/Functions/toStartOfMinute.cpp
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#include <Functions/IFunction.h>
|
||||||
|
#include <Functions/FunctionFactory.h>
|
||||||
|
#include <Functions/DateTimeTransforms.h>
|
||||||
|
#include <Functions/FunctionDateOrDateTimeToSomething.h>
|
||||||
|
#include <DataTypes/DataTypesNumber.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
using FunctionToStartOfMinute = FunctionDateOrDateTimeToSomething<DataTypeDateTime, ToStartOfMinuteImpl>;
|
||||||
|
|
||||||
|
void registerFunctionToStartOfMinute(FunctionFactory & factory)
|
||||||
|
{
|
||||||
|
factory.registerFunction<FunctionToStartOfMinute>();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
20
dbms/src/Functions/toStartOfMonth.cpp
Normal file
20
dbms/src/Functions/toStartOfMonth.cpp
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#include <Functions/IFunction.h>
|
||||||
|
#include <Functions/FunctionFactory.h>
|
||||||
|
#include <Functions/DateTimeTransforms.h>
|
||||||
|
#include <Functions/FunctionDateOrDateTimeToSomething.h>
|
||||||
|
#include <DataTypes/DataTypesNumber.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
using FunctionToStartOfMonth = FunctionDateOrDateTimeToSomething<DataTypeDate, ToStartOfMonthImpl>;
|
||||||
|
|
||||||
|
void registerFunctionToStartOfMonth(FunctionFactory & factory)
|
||||||
|
{
|
||||||
|
factory.registerFunction<FunctionToStartOfMonth>();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
20
dbms/src/Functions/toStartOfQuarter.cpp
Normal file
20
dbms/src/Functions/toStartOfQuarter.cpp
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#include <Functions/IFunction.h>
|
||||||
|
#include <Functions/FunctionFactory.h>
|
||||||
|
#include <Functions/DateTimeTransforms.h>
|
||||||
|
#include <Functions/FunctionDateOrDateTimeToSomething.h>
|
||||||
|
#include <DataTypes/DataTypesNumber.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
using FunctionToStartOfQuarter = FunctionDateOrDateTimeToSomething<DataTypeDate, ToStartOfQuarterImpl>;
|
||||||
|
|
||||||
|
void registerFunctionToStartOfQuarter(FunctionFactory & factory)
|
||||||
|
{
|
||||||
|
factory.registerFunction<FunctionToStartOfQuarter>();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
20
dbms/src/Functions/toStartOfYear.cpp
Normal file
20
dbms/src/Functions/toStartOfYear.cpp
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#include <Functions/IFunction.h>
|
||||||
|
#include <Functions/FunctionFactory.h>
|
||||||
|
#include <Functions/DateTimeTransforms.h>
|
||||||
|
#include <Functions/FunctionDateOrDateTimeToSomething.h>
|
||||||
|
#include <DataTypes/DataTypesNumber.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
using FunctionToStartOfYear = FunctionDateOrDateTimeToSomething<DataTypeDate, ToStartOfYearImpl>;
|
||||||
|
|
||||||
|
void registerFunctionToStartOfYear(FunctionFactory & factory)
|
||||||
|
{
|
||||||
|
factory.registerFunction<FunctionToStartOfYear>();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
20
dbms/src/Functions/toTime.cpp
Normal file
20
dbms/src/Functions/toTime.cpp
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#include <Functions/IFunction.h>
|
||||||
|
#include <Functions/FunctionFactory.h>
|
||||||
|
#include <Functions/DateTimeTransforms.h>
|
||||||
|
#include <Functions/FunctionDateOrDateTimeToSomething.h>
|
||||||
|
#include <DataTypes/DataTypesNumber.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
using FunctionToTime = FunctionDateOrDateTimeToSomething<DataTypeDateTime, ToTimeImpl>;
|
||||||
|
|
||||||
|
void registerFunctionToTime(FunctionFactory & factory)
|
||||||
|
{
|
||||||
|
factory.registerFunction<FunctionToTime>();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
59
dbms/src/Functions/toTimeZone.cpp
Normal file
59
dbms/src/Functions/toTimeZone.cpp
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
#include <DataTypes/DataTypeDateTime.h>
|
||||||
|
|
||||||
|
#include <Functions/IFunction.h>
|
||||||
|
#include <Functions/FunctionFactory.h>
|
||||||
|
#include <Functions/extractTimeZoneFromFunctionArguments.h>
|
||||||
|
|
||||||
|
#include <IO/WriteHelpers.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace ErrorCodes
|
||||||
|
{
|
||||||
|
extern const int NUMBER_OF_ARGUMENTS_DOESNT_MATCH;
|
||||||
|
extern const int ILLEGAL_TYPE_OF_ARGUMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Just changes time zone information for data type. The calculation is free.
|
||||||
|
class FunctionToTimeZone : public IFunction
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static constexpr auto name = "toTimeZone";
|
||||||
|
static FunctionPtr create(const Context &) { return std::make_shared<FunctionToTimeZone>(); }
|
||||||
|
|
||||||
|
String getName() const override
|
||||||
|
{
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t getNumberOfArguments() const override { return 2; }
|
||||||
|
|
||||||
|
DataTypePtr getReturnTypeImpl(const ColumnsWithTypeAndName & arguments) const override
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
|
||||||
|
if (!WhichDataType(arguments[0].type).isDateTime())
|
||||||
|
throw Exception{"Illegal type " + arguments[0].type->getName() + " of argument of function " + getName() +
|
||||||
|
". Should be DateTime", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT};
|
||||||
|
|
||||||
|
String time_zone_name = extractTimeZoneNameFromFunctionArguments(arguments, 1, 0);
|
||||||
|
return std::make_shared<DataTypeDateTime>(time_zone_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result, size_t /*input_rows_count*/) override
|
||||||
|
{
|
||||||
|
block.getByPosition(result).column = block.getByPosition(arguments[0]).column;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void registerFunctionToTimeZone(FunctionFactory & factory)
|
||||||
|
{
|
||||||
|
factory.registerFunction<FunctionToTimeZone>();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
20
dbms/src/Functions/toYYYYMM.cpp
Normal file
20
dbms/src/Functions/toYYYYMM.cpp
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#include <Functions/IFunction.h>
|
||||||
|
#include <Functions/FunctionFactory.h>
|
||||||
|
#include <Functions/DateTimeTransforms.h>
|
||||||
|
#include <Functions/FunctionDateOrDateTimeToSomething.h>
|
||||||
|
#include <DataTypes/DataTypesNumber.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
using FunctionToYYYYMM = FunctionDateOrDateTimeToSomething<DataTypeUInt32, ToYYYYMMImpl>;
|
||||||
|
|
||||||
|
void registerFunctionToYYYYMM(FunctionFactory & factory)
|
||||||
|
{
|
||||||
|
factory.registerFunction<FunctionToYYYYMM>();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
20
dbms/src/Functions/toYYYYMMDD.cpp
Normal file
20
dbms/src/Functions/toYYYYMMDD.cpp
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#include <Functions/IFunction.h>
|
||||||
|
#include <Functions/FunctionFactory.h>
|
||||||
|
#include <Functions/DateTimeTransforms.h>
|
||||||
|
#include <Functions/FunctionDateOrDateTimeToSomething.h>
|
||||||
|
#include <DataTypes/DataTypesNumber.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
using FunctionToYYYYMMDD = FunctionDateOrDateTimeToSomething<DataTypeUInt32, ToYYYYMMDDImpl>;
|
||||||
|
|
||||||
|
void registerFunctionToYYYYMMDD(FunctionFactory & factory)
|
||||||
|
{
|
||||||
|
factory.registerFunction<FunctionToYYYYMMDD>();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
20
dbms/src/Functions/toYYYYMMDDhhmmss.cpp
Normal file
20
dbms/src/Functions/toYYYYMMDDhhmmss.cpp
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#include <Functions/IFunction.h>
|
||||||
|
#include <Functions/FunctionFactory.h>
|
||||||
|
#include <Functions/DateTimeTransforms.h>
|
||||||
|
#include <Functions/FunctionDateOrDateTimeToSomething.h>
|
||||||
|
#include <DataTypes/DataTypesNumber.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
using FunctionToYYYYMMDDhhmmss = FunctionDateOrDateTimeToSomething<DataTypeUInt64, ToYYYYMMDDhhmmssImpl>;
|
||||||
|
|
||||||
|
void registerFunctionToYYYYMMDDhhmmss(FunctionFactory & factory)
|
||||||
|
{
|
||||||
|
factory.registerFunction<FunctionToYYYYMMDDhhmmss>();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
20
dbms/src/Functions/toYear.cpp
Normal file
20
dbms/src/Functions/toYear.cpp
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#include <Functions/IFunction.h>
|
||||||
|
#include <Functions/FunctionFactory.h>
|
||||||
|
#include <Functions/DateTimeTransforms.h>
|
||||||
|
#include <Functions/FunctionDateOrDateTimeToSomething.h>
|
||||||
|
#include <DataTypes/DataTypesNumber.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
using FunctionToYear = FunctionDateOrDateTimeToSomething<DataTypeUInt16, ToYearImpl>;
|
||||||
|
|
||||||
|
void registerFunctionToYear(FunctionFactory & factory)
|
||||||
|
{
|
||||||
|
factory.registerFunction<FunctionToYear>();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
45
dbms/src/Functions/today.cpp
Normal file
45
dbms/src/Functions/today.cpp
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
#include <common/DateLUT.h>
|
||||||
|
|
||||||
|
#include <DataTypes/DataTypeDate.h>
|
||||||
|
|
||||||
|
#include <Functions/IFunction.h>
|
||||||
|
#include <Functions/FunctionFactory.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
class FunctionToday : public IFunction
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static constexpr auto name = "today";
|
||||||
|
static FunctionPtr create(const Context &) { return std::make_shared<FunctionToday>(); }
|
||||||
|
|
||||||
|
String getName() const override
|
||||||
|
{
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t getNumberOfArguments() const override { return 0; }
|
||||||
|
|
||||||
|
DataTypePtr getReturnTypeImpl(const DataTypes & /*arguments*/) const override
|
||||||
|
{
|
||||||
|
return std::make_shared<DataTypeDate>();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isDeterministic() const override { return false; }
|
||||||
|
|
||||||
|
void executeImpl(Block & block, const ColumnNumbers &, size_t result, size_t input_rows_count) override
|
||||||
|
{
|
||||||
|
block.getByPosition(result).column = DataTypeDate().createColumnConst(
|
||||||
|
input_rows_count,
|
||||||
|
UInt64(DateLUT::instance().toDayNum(time(nullptr))));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void registerFunctionToday(FunctionFactory & factory)
|
||||||
|
{
|
||||||
|
factory.registerFunction<FunctionToday>();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
45
dbms/src/Functions/yesterday.cpp
Normal file
45
dbms/src/Functions/yesterday.cpp
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
#include <common/DateLUT.h>
|
||||||
|
|
||||||
|
#include <DataTypes/DataTypeDate.h>
|
||||||
|
|
||||||
|
#include <Functions/IFunction.h>
|
||||||
|
#include <Functions/FunctionFactory.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
class FunctionYesterday : public IFunction
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static constexpr auto name = "yesterday";
|
||||||
|
static FunctionPtr create(const Context &) { return std::make_shared<FunctionYesterday>(); }
|
||||||
|
|
||||||
|
String getName() const override
|
||||||
|
{
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t getNumberOfArguments() const override { return 0; }
|
||||||
|
|
||||||
|
DataTypePtr getReturnTypeImpl(const DataTypes & /*arguments*/) const override
|
||||||
|
{
|
||||||
|
return std::make_shared<DataTypeDate>();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isDeterministic() const override { return false; }
|
||||||
|
|
||||||
|
void executeImpl(Block & block, const ColumnNumbers &, size_t result, size_t input_rows_count) override
|
||||||
|
{
|
||||||
|
block.getByPosition(result).column = DataTypeDate().createColumnConst(
|
||||||
|
input_rows_count,
|
||||||
|
UInt64(DateLUT::instance().toDayNum(time(nullptr)) - 1));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void registerFunctionYesterday(FunctionFactory & factory)
|
||||||
|
{
|
||||||
|
factory.registerFunction<FunctionYesterday>();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -897,18 +897,18 @@ StoragePtr Context::executeTableFunction(const ASTPtr & table_expression)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
DDLGuard::DDLGuard(Map & map_, std::mutex & guards_mutex_, std::unique_lock<std::mutex> && lock, const String & elem)
|
DDLGuard::DDLGuard(Map & map_, std::unique_lock<std::mutex> guards_lock_, const String & elem)
|
||||||
: map(map_), guards_mutex(guards_mutex_)
|
: map(map_), guards_lock(std::move(guards_lock_))
|
||||||
{
|
{
|
||||||
it = map.emplace(elem, Entry{std::make_unique<std::mutex>(), 0}).first;
|
it = map.emplace(elem, Entry{std::make_unique<std::mutex>(), 0}).first;
|
||||||
++it->second.counter;
|
++it->second.counter;
|
||||||
lock.unlock();
|
guards_lock.unlock();
|
||||||
table_lock = std::unique_lock<std::mutex>(*it->second.mutex);
|
table_lock = std::unique_lock<std::mutex>(*it->second.mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
DDLGuard::~DDLGuard()
|
DDLGuard::~DDLGuard()
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(guards_mutex);
|
guards_lock.lock();
|
||||||
--it->second.counter;
|
--it->second.counter;
|
||||||
if (!it->second.counter)
|
if (!it->second.counter)
|
||||||
{
|
{
|
||||||
@ -920,7 +920,7 @@ DDLGuard::~DDLGuard()
|
|||||||
std::unique_ptr<DDLGuard> Context::getDDLGuard(const String & database, const String & table) const
|
std::unique_ptr<DDLGuard> Context::getDDLGuard(const String & database, const String & table) const
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lock(shared->ddl_guards_mutex);
|
std::unique_lock<std::mutex> lock(shared->ddl_guards_mutex);
|
||||||
return std::make_unique<DDLGuard>(shared->ddl_guards[database], shared->ddl_guards_mutex, std::move(lock), table);
|
return std::make_unique<DDLGuard>(shared->ddl_guards[database], std::move(lock), table);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -481,13 +481,13 @@ public:
|
|||||||
/// NOTE: using std::map here (and not std::unordered_map) to avoid iterator invalidation on insertion.
|
/// NOTE: using std::map here (and not std::unordered_map) to avoid iterator invalidation on insertion.
|
||||||
using Map = std::map<String, Entry>;
|
using Map = std::map<String, Entry>;
|
||||||
|
|
||||||
DDLGuard(Map & map_, std::mutex & guards_mutex_, std::unique_lock<std::mutex> && guards_lock, const String & elem);
|
DDLGuard(Map & map_, std::unique_lock<std::mutex> guards_lock_, const String & elem);
|
||||||
~DDLGuard();
|
~DDLGuard();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Map & map;
|
Map & map;
|
||||||
Map::iterator it;
|
Map::iterator it;
|
||||||
std::mutex & guards_mutex;
|
std::unique_lock<std::mutex> guards_lock;
|
||||||
std::unique_lock<std::mutex> table_lock;
|
std::unique_lock<std::mutex> table_lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -129,3 +129,39 @@
|
|||||||
12345678901234567890123456789012345678
|
12345678901234567890123456789012345678
|
||||||
0.123456789 0.123456789123456789
|
0.123456789 0.123456789123456789
|
||||||
0.12345678901234567890123456789012345678
|
0.12345678901234567890123456789012345678
|
||||||
|
1234567890.0000000000000000000000000000 1234567890.00000000000000000000000000000 1234567890.00000000000000000000000000000
|
||||||
|
1234567890.00000000 1234567890.000000000 1234567890.000000000
|
||||||
|
12345678.0 12345678.00 12345678.00
|
||||||
|
9223372036854775807.000000 9223372036854775807 -9223372036854775807
|
||||||
|
9223372036854775800 9223372036854775800 -9223372036854775800
|
||||||
|
92233720368547758.00 92233720368547758 -92233720368547758
|
||||||
|
2147483647.0000000000 2147483647 -2147483647
|
||||||
|
2147483647.00 2147483647 -2147483647
|
||||||
|
92233720368547757.99 92233720368547757 -92233720368547757
|
||||||
|
2147483640.99 2147483640 -2147483640
|
||||||
|
-0.90000000 0
|
||||||
|
-0.90000000 0
|
||||||
|
-0.90000000 0
|
||||||
|
-0.8000 0
|
||||||
|
-0.8000 0
|
||||||
|
-0.8000 0
|
||||||
|
-0.70 0
|
||||||
|
-0.70 0
|
||||||
|
-0.70 0
|
||||||
|
-0.600000 0
|
||||||
|
-0.600000 0
|
||||||
|
-0.600000 0
|
||||||
|
18446744073709551615 18446744073709551615
|
||||||
|
18446744073709551615.00000000 18446744073709551615
|
||||||
|
4294967295 4294967295
|
||||||
|
4294967295.0000000000 4294967295
|
||||||
|
4294967295 4294967295
|
||||||
|
4294967295.0000 4294967295
|
||||||
|
65535 65535
|
||||||
|
65535.0000000000 65535
|
||||||
|
65535 65535
|
||||||
|
65535.0000 65535
|
||||||
|
2147483647 2147483647
|
||||||
|
-2147483647 -2147483647
|
||||||
|
2147483647 2147483647
|
||||||
|
9223372036854775807 9223372036854775807
|
||||||
|
@ -150,4 +150,94 @@ SELECT CAST('0.123456789', 'Decimal(9,8)'); -- { serverError 69 }
|
|||||||
SELECT CAST('0.123456789123456789', 'Decimal(18,17)'); -- { serverError 69 }
|
SELECT CAST('0.123456789123456789', 'Decimal(18,17)'); -- { serverError 69 }
|
||||||
SELECT CAST('0.12345678901234567890123456789012345678', 'Decimal(38,37)'); -- { serverError 69 }
|
SELECT CAST('0.12345678901234567890123456789012345678', 'Decimal(38,37)'); -- { serverError 69 }
|
||||||
|
|
||||||
|
SELECT toDecimal128('1234567890', 28) AS x, toDecimal128(x, 29), toDecimal128(toDecimal128('1234567890', 28), 29);
|
||||||
|
SELECT toDecimal128(toDecimal128('1234567890', 28), 30); -- { serverError 407 }
|
||||||
|
|
||||||
|
SELECT toDecimal64('1234567890', 8) AS x, toDecimal64(x, 9), toDecimal64(toDecimal64('1234567890', 8), 9);
|
||||||
|
SELECT toDecimal64(toDecimal64('1234567890', 8), 10); -- { serverError 407 }
|
||||||
|
|
||||||
|
SELECT toDecimal32('12345678', 1) AS x, toDecimal32(x, 2), toDecimal32(toDecimal32('12345678', 1), 2);
|
||||||
|
SELECT toDecimal32(toDecimal32('12345678', 1), 3); -- { serverError 407 }
|
||||||
|
|
||||||
|
SELECT toDecimal64(toDecimal64('92233720368547758.1', 1), 2); -- { serverError 407 }
|
||||||
|
SELECT toDecimal64(toDecimal64('-92233720368547758.1', 1), 2); -- { serverError 407 }
|
||||||
|
|
||||||
|
SELECT toDecimal128('9223372036854775807', 6) AS x, toInt64(x), toInt64(-x);
|
||||||
|
SELECT toDecimal128('9223372036854775809', 6) AS x, toInt64(x); -- { serverError 407 }
|
||||||
|
SELECT toDecimal128('9223372036854775809', 6) AS x, toInt64(-x); -- { serverError 407 }
|
||||||
|
SELECT toDecimal64('922337203685477580', 0) * 10 AS x, toInt64(x), toInt64(-x);
|
||||||
|
SELECT toDecimal64(toDecimal64('92233720368547758.0', 1), 2) AS x, toInt64(x), toInt64(-x);
|
||||||
|
|
||||||
|
SELECT toDecimal128('2147483647', 10) AS x, toInt32(x), toInt32(-x);
|
||||||
|
SELECT toDecimal128('2147483649', 10) AS x, toInt32(x), toInt32(-x); -- { serverError 407 }
|
||||||
|
SELECT toDecimal64('2147483647', 2) AS x, toInt32(x), toInt32(-x);
|
||||||
|
SELECT toDecimal64('2147483649', 2) AS x, toInt32(x), toInt32(-x); -- { serverError 407 }
|
||||||
|
|
||||||
|
SELECT toDecimal128('92233720368547757.99', 2) AS x, toInt64(x), toInt64(-x);
|
||||||
|
SELECT toDecimal64('2147483640.99', 2) AS x, toInt32(x), toInt32(-x);
|
||||||
|
|
||||||
|
SELECT toDecimal128('-0.9', 8) AS x, toUInt64(x);
|
||||||
|
SELECT toDecimal64('-0.9', 8) AS x, toUInt64(x);
|
||||||
|
SELECT toDecimal32('-0.9', 8) AS x, toUInt64(x);
|
||||||
|
|
||||||
|
SELECT toDecimal128('-0.8', 4) AS x, toUInt32(x);
|
||||||
|
SELECT toDecimal64('-0.8', 4) AS x, toUInt32(x);
|
||||||
|
SELECT toDecimal32('-0.8', 4) AS x, toUInt32(x);
|
||||||
|
|
||||||
|
SELECT toDecimal128('-0.7', 2) AS x, toUInt16(x);
|
||||||
|
SELECT toDecimal64('-0.7', 2) AS x, toUInt16(x);
|
||||||
|
SELECT toDecimal32('-0.7', 2) AS x, toUInt16(x);
|
||||||
|
|
||||||
|
SELECT toDecimal128('-0.6', 6) AS x, toUInt8(x);
|
||||||
|
SELECT toDecimal64('-0.6', 6) AS x, toUInt8(x);
|
||||||
|
SELECT toDecimal32('-0.6', 6) AS x, toUInt8(x);
|
||||||
|
|
||||||
|
SELECT toDecimal128('-1', 7) AS x, toUInt64(x); -- { serverError 407 }
|
||||||
|
SELECT toDecimal128('-1', 7) AS x, toUInt32(x); -- { serverError 407 }
|
||||||
|
SELECT toDecimal128('-1', 7) AS x, toUInt16(x); -- { serverError 407 }
|
||||||
|
SELECT toDecimal128('-1', 7) AS x, toUInt8(x); -- { serverError 407 }
|
||||||
|
|
||||||
|
SELECT toDecimal64('-1', 5) AS x, toUInt64(x); -- { serverError 407 }
|
||||||
|
SELECT toDecimal64('-1', 5) AS x, toUInt32(x); -- { serverError 407 }
|
||||||
|
SELECT toDecimal64('-1', 5) AS x, toUInt16(x); -- { serverError 407 }
|
||||||
|
SELECT toDecimal64('-1', 5) AS x, toUInt8(x); -- { serverError 407 }
|
||||||
|
|
||||||
|
SELECT toDecimal32('-1', 3) AS x, toUInt64(x); -- { serverError 407 }
|
||||||
|
SELECT toDecimal32('-1', 3) AS x, toUInt32(x); -- { serverError 407 }
|
||||||
|
SELECT toDecimal32('-1', 3) AS x, toUInt16(x); -- { serverError 407 }
|
||||||
|
SELECT toDecimal32('-1', 3) AS x, toUInt8(x); -- { serverError 407 }
|
||||||
|
|
||||||
|
SELECT toDecimal128('18446744073709551615', 0) AS x, toUInt64(x);
|
||||||
|
SELECT toDecimal128('18446744073709551616', 0) AS x, toUInt64(x); -- { serverError 407 }
|
||||||
|
SELECT toDecimal128('18446744073709551615', 8) AS x, toUInt64(x);
|
||||||
|
SELECT toDecimal128('18446744073709551616', 8) AS x, toUInt64(x); -- { serverError 407 }
|
||||||
|
|
||||||
|
SELECT toDecimal128('4294967295', 0) AS x, toUInt32(x);
|
||||||
|
SELECT toDecimal128('4294967296', 0) AS x, toUInt32(x); -- { serverError 407 }
|
||||||
|
SELECT toDecimal128('4294967295', 10) AS x, toUInt32(x);
|
||||||
|
SELECT toDecimal128('4294967296', 10) AS x, toUInt32(x); -- { serverError 407 }
|
||||||
|
SELECT toDecimal64('4294967295', 0) AS x, toUInt32(x);
|
||||||
|
SELECT toDecimal64('4294967296', 0) AS x, toUInt32(x); -- { serverError 407 }
|
||||||
|
SELECT toDecimal64('4294967295', 4) AS x, toUInt32(x);
|
||||||
|
SELECT toDecimal64('4294967296', 4) AS x, toUInt32(x); -- { serverError 407 }
|
||||||
|
|
||||||
|
SELECT toDecimal128('65535', 0) AS x, toUInt16(x);
|
||||||
|
SELECT toDecimal128('65536', 0) AS x, toUInt16(x); -- { serverError 407 }
|
||||||
|
SELECT toDecimal128('65535', 10) AS x, toUInt16(x);
|
||||||
|
SELECT toDecimal128('65536', 10) AS x, toUInt16(x); -- { serverError 407 }
|
||||||
|
SELECT toDecimal64('65535', 0) AS x, toUInt16(x);
|
||||||
|
SELECT toDecimal64('65536', 0) AS x, toUInt16(x); -- { serverError 407 }
|
||||||
|
SELECT toDecimal64('65535', 4) AS x, toUInt16(x);
|
||||||
|
SELECT toDecimal64('65536', 4) AS x, toUInt16(x); -- { serverError 407 }
|
||||||
|
|
||||||
|
SELECT toInt64('2147483647') AS x, toDecimal32(x, 0);
|
||||||
|
SELECT toInt64('-2147483647') AS x, toDecimal32(x, 0);
|
||||||
|
SELECT toUInt64('2147483647') AS x, toDecimal32(x, 0);
|
||||||
|
SELECT toInt64('2147483649') AS x, toDecimal32(x, 0); -- { serverError 407 }
|
||||||
|
SELECT toInt64('-2147483649') AS x, toDecimal32(x, 0); -- { serverError 407 }
|
||||||
|
SELECT toUInt64('2147483649') AS x, toDecimal32(x, 0); -- { serverError 407 }
|
||||||
|
|
||||||
|
SELECT toUInt64('9223372036854775807') AS x, toDecimal64(x, 0);
|
||||||
|
SELECT toUInt64('9223372036854775809') AS x, toDecimal64(x, 0); -- { serverError 407 }
|
||||||
|
|
||||||
DROP TABLE IF EXISTS test.decimal;
|
DROP TABLE IF EXISTS test.decimal;
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
Для поиска без учета регистра используйте функцию `positionCaseInsensitiveUTF8`.
|
Для поиска без учета регистра используйте функцию `positionCaseInsensitiveUTF8`.
|
||||||
|
|
||||||
## match(haystack, pattern)
|
## match(haystack, pattern)
|
||||||
Проверка строки на соответствие регулярному выражению pattern. Регулярное выражение re2.
|
Проверка строки на соответствие регулярному выражению pattern. Регулярное выражение **re2**. Синтаксис регулярных выражений **re2** является более ограниченным по сравнению с регулярными выражениями **Perl** ([подробнее](https://github.com/google/re2/wiki/Syntax)).
|
||||||
Возвращает 0 (если не соответствует) или 1 (если соответствует).
|
Возвращает 0 (если не соответствует) или 1 (если соответствует).
|
||||||
|
|
||||||
Обратите внимание, что для экранирования в регулярном выражении, используется символ `\` (обратный слеш). Этот же символ используется для экранирования в строковых литералах. Поэтому, чтобы экранировать символ в регулярном выражении, необходимо написать в строковом литерале \\ (два обратных слеша).
|
Обратите внимание, что для экранирования в регулярном выражении, используется символ `\` (обратный слеш). Этот же символ используется для экранирования в строковых литералах. Поэтому, чтобы экранировать символ в регулярном выражении, необходимо написать в строковом литерале \\ (два обратных слеша).
|
||||||
|
Loading…
Reference in New Issue
Block a user