ClickHouse

Форк
0
/
fromDaysSinceYearZero.cpp 
131 строка · 4.8 Кб
1
#include <Functions/IFunction.h>
2
#include <Columns/ColumnConst.h>
3
#include <Columns/ColumnDecimal.h>
4
#include <DataTypes/DataTypeDate.h>
5
#include <DataTypes/DataTypeDate32.h>
6
#include <Functions/DateTimeTransforms.h>
7
#include <Functions/FunctionFactory.h>
8
#include <Functions/FunctionHelpers.h>
9
#include <Interpreters/castColumn.h>
10

11
#include <Common/DateLUT.h>
12

13
#include <array>
14
#include <cmath>
15

16
namespace DB
17
{
18
namespace ErrorCodes
19
{
20
extern const int ILLEGAL_TYPE_OF_ARGUMENT;
21
extern const int ARGUMENT_OUT_OF_BOUND;
22
}
23

24
namespace
25
{
26

27
struct DateTraits
28
{
29
    static constexpr auto name = "fromDaysSinceYearZero";
30
    using ReturnDataType = DataTypeDate;
31
};
32

33
struct DateTraits32
34
{
35
    static constexpr auto name = "fromDaysSinceYearZero32";
36
    using ReturnDataType = DataTypeDate32;
37
};
38

39
template <typename Traits>
40
class FunctionFromDaysSinceYearZero : public IFunction
41
{
42
public:
43
    static constexpr auto name = Traits::name;
44
    using RawReturnType = typename Traits::ReturnDataType::FieldType;
45

46
    static FunctionPtr create(ContextPtr) { return std::make_shared<FunctionFromDaysSinceYearZero>(); }
47

48
    String getName() const override { return name; }
49
    bool isSuitableForShortCircuitArgumentsExecution(const DataTypesWithConstInfo & /*arguments*/) const override { return true; }
50
    bool useDefaultImplementationForConstants() const override { return true; }
51
    size_t getNumberOfArguments() const override { return 1; }
52

53
    DataTypePtr getReturnTypeImpl(const ColumnsWithTypeAndName & arguments) const override
54
    {
55
        FunctionArgumentDescriptors args{{"days", static_cast<FunctionArgumentDescriptor::TypeValidator>(&isNativeInteger), nullptr, "Integer"}};
56

57
        validateFunctionArgumentTypes(*this, arguments, args);
58

59
        return std::make_shared<typename Traits::ReturnDataType>();
60
    }
61

62
    ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t input_rows_count) const override
63
    {
64
        auto res_column = Traits::ReturnDataType::ColumnType::create(input_rows_count);
65
        const auto & src_column = arguments[0];
66

67
        auto try_type = [&]<typename T>(T)
68
        {
69
            using ColVecType = ColumnVector<T>;
70

71
            if (const ColVecType * col_vec = checkAndGetColumn<ColVecType>(src_column.column.get()))
72
            {
73
                execute<T>(*col_vec, *res_column, input_rows_count);
74
                return true;
75
            }
76
            return false;
77
        };
78

79
        const bool success = try_type(UInt8{}) || try_type(UInt16{}) || try_type(UInt32{}) || try_type(UInt64{})
80
                                || try_type(Int8{}) || try_type(Int16{}) || try_type(Int32{}) || try_type(Int64{});
81

82
        if (!success)
83
            throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "Illegal column while execute function {}", getName());
84

85
        return res_column;
86
    }
87

88
    template <typename T, typename ColVecType, typename ResCol>
89
    void execute(const ColVecType & col, ResCol & result_column, size_t rows_count) const
90
    {
91
        const auto & src_data = col.getData();
92
        auto & dst_data = result_column.getData();
93
        dst_data.resize(rows_count);
94

95
        for (size_t i = 0; i < rows_count; ++i)
96
        {
97
            auto value = src_data[i];
98
            if (value < 0)
99
                throw Exception(ErrorCodes::ARGUMENT_OUT_OF_BOUND, "Expected a non-negative integer, got: {}", std::to_string(value));
100
            /// prevent potential signed integer overflows (aka. undefined behavior) with Date32 results
101
            auto value_uint64 = static_cast<UInt64>(value); /// NOLINT(bugprone-signed-char-misuse,cert-str34-c)
102
            dst_data[i] = static_cast<RawReturnType>(value_uint64 - ToDaysSinceYearZeroImpl::DAYS_BETWEEN_YEARS_0_AND_1970);
103
        }
104
    }
105
};
106

107

108
}
109

110
REGISTER_FUNCTION(FromDaysSinceYearZero)
111
{
112
    factory.registerFunction<FunctionFromDaysSinceYearZero<DateTraits>>(FunctionDocumentation{
113
        .description = R"(
114
Given the number of days passed since 1 January 0000 in the proleptic Gregorian calendar defined by ISO 8601 return a corresponding date.
115
The calculation is the same as in MySQL's FROM_DAYS() function.
116
)",
117
        .examples{{"typical", "SELECT fromDaysSinceYearZero(713569)", "2023-09-08"}},
118
        .categories{"Dates and Times"}});
119

120
    factory.registerFunction<FunctionFromDaysSinceYearZero<DateTraits32>>(FunctionDocumentation{
121
        .description = R"(
122
Given the number of days passed since 1 January 0000 in the proleptic Gregorian calendar defined by ISO 8601 return a corresponding date.
123
The calculation is the same as in MySQL's FROM_DAYS() function.
124
)",
125
        .examples{{"typical", "SELECT fromDaysSinceYearZero32(713569)", "2023-09-08"}},
126
        .categories{"Dates and Times"}});
127

128
    factory.registerAlias("FROM_DAYS", FunctionFromDaysSinceYearZero<DateTraits>::name, FunctionFactory::CaseInsensitive);
129
}
130

131
}
132

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.