ClickHouse

Форк
0
/
UTCTimestampTransform.cpp 
141 строка · 6.6 Кб
1
#include <Columns/ColumnConst.h>
2
#include <Columns/ColumnsDateTime.h>
3
#include <Columns/ColumnString.h>
4
#include <Columns/ColumnsNumber.h>
5
#include <Columns/IColumn.h>
6
#include <Common/DateLUT.h>
7
#include <Common/LocalDateTime.h>
8
#include <Common/logger_useful.h>
9
#include <Core/DecimalFunctions.h>
10
#include <DataTypes/DataTypeDateTime.h>
11
#include <DataTypes/DataTypeDateTime64.h>
12
#include <DataTypes/DataTypeNullable.h>
13
#include <DataTypes/TimezoneMixin.h>
14
#include <Functions/FunctionFactory.h>
15
#include <Functions/IFunction.h>
16
#include <Functions/FunctionHelpers.h>
17
#include <Interpreters/Context.h>
18

19
namespace DB
20
{
21
namespace ErrorCodes
22
{
23
    extern const int ILLEGAL_COLUMN;
24
    extern const int ILLEGAL_TYPE_OF_ARGUMENT;
25
    extern const int NUMBER_OF_ARGUMENTS_DOESNT_MATCH;
26
}
27

28
namespace
29
{
30
    template <typename Name>
31
    class UTCTimestampTransform : public IFunction
32
    {
33
    public:
34
        static FunctionPtr create(ContextPtr) { return std::make_shared<UTCTimestampTransform>(); }
35
        static constexpr auto name = Name::name;
36

37
        String getName() const override { return name; }
38

39
        size_t getNumberOfArguments() const override { return 2; }
40

41
        bool useDefaultImplementationForConstants() const override { return true; }
42

43
        bool isSuitableForShortCircuitArgumentsExecution(const DataTypesWithConstInfo & /*arguments*/) const override { return true; }
44

45
        ColumnNumbers getArgumentsThatAreAlwaysConstant() const override { return {1}; }
46

47
        DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
48
        {
49
            if (arguments.size() != 2)
50
                throw Exception(ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH, "Function {}'s arguments number must be 2.", name);
51
            WhichDataType which_type_first(arguments[0]);
52
            WhichDataType which_type_second(arguments[1]);
53
            if (!which_type_first.isDateTime() && !which_type_first.isDateTime64())
54
                throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "Function {}'s 1st argument type must be datetime.", name);
55
            if (dynamic_cast<const TimezoneMixin *>(arguments[0].get())->hasExplicitTimeZone())
56
                throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "Function {}'s 1st argument should not have explicit time zone.", name);
57
            if (!which_type_second.isString())
58
                throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "Function {}'s 2nd argument type must be string.", name);
59
            DataTypePtr date_time_type;
60
            if (which_type_first.isDateTime())
61
                date_time_type = std::make_shared<DataTypeDateTime>();
62
            else
63
            {
64
                const DataTypeDateTime64 * date_time_64 = static_cast<const DataTypeDateTime64 *>(arguments[0].get());
65
                date_time_type = std::make_shared<DataTypeDateTime64>(date_time_64->getScale());
66
            }
67
            return date_time_type;
68
        }
69

70
        ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type, size_t) const override
71
        {
72
            if (arguments.size() != 2)
73
                throw Exception(ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH, "Function {}'s arguments number must be 2.", name);
74
            const ColumnWithTypeAndName & arg1 = arguments[0];
75
            const ColumnWithTypeAndName & arg2 = arguments[1];
76
            const auto * time_zone_const_col = checkAndGetColumnConstData<ColumnString>(arg2.column.get());
77
            if (!time_zone_const_col)
78
                throw Exception(ErrorCodes::ILLEGAL_COLUMN, "Illegal column {} of 2nd argument of function {}. Excepted const(String).", arg2.column->getName(), name);
79
            String time_zone_val = time_zone_const_col->getDataAt(0).toString();
80
            auto column = result_type->createColumn();
81
            if (WhichDataType(arg1.type).isDateTime())
82
            {
83
                const auto * date_time_col = checkAndGetColumn<ColumnDateTime>(arg1.column.get());
84
                for (size_t i = 0; i < date_time_col->size(); ++i)
85
                {
86
                    UInt32 date_time_val = date_time_col->getElement(i);
87
                    LocalDateTime date_time(date_time_val, Name::to ? DateLUT::instance("UTC") : DateLUT::instance(time_zone_val));
88
                    time_t time_val = date_time.to_time_t(Name::from ? DateLUT::instance("UTC") : DateLUT::instance(time_zone_val));
89
                    column->insert(time_val);
90
                }
91
            }
92
            else if (WhichDataType(arg1.type).isDateTime64())
93
            {
94
                const auto * date_time_col = checkAndGetColumn<ColumnDateTime64>(arg1.column.get());
95
                const DataTypeDateTime64 * date_time_type = static_cast<const DataTypeDateTime64 *>(arg1.type.get());
96
                Int64 scale_multiplier = DecimalUtils::scaleMultiplier<Int64>(date_time_type->getScale());
97
                for (size_t i = 0; i < date_time_col->size(); ++i)
98
                {
99
                    DateTime64 date_time_val = date_time_col->getElement(i);
100
                    Int64 seconds = date_time_val.value / scale_multiplier;
101
                    Int64 micros = date_time_val.value % scale_multiplier;
102
                    LocalDateTime date_time(seconds, Name::to ? DateLUT::instance("UTC") : DateLUT::instance(time_zone_val));
103
                    time_t time_val = date_time.to_time_t(Name::from ? DateLUT::instance("UTC") : DateLUT::instance(time_zone_val));
104
                    DateTime64 date_time_64(time_val * scale_multiplier + micros);
105
                    column->insert(date_time_64);
106
                }
107
            }
108
            else
109
                throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "Function {}'s 1st argument can only be datetime/datatime64. ", name);
110
            return column;
111
        }
112

113
    };
114

115
    struct NameToUTCTimestamp
116
    {
117
        static constexpr auto name = "toUTCTimestamp";
118
        static constexpr auto from = false;
119
        static constexpr auto to = true;
120
    };
121

122
    struct NameFromUTCTimestamp
123
    {
124
        static constexpr auto name = "fromUTCTimestamp";
125
        static constexpr auto from = true;
126
        static constexpr auto to = false;
127
    };
128

129
    using ToUTCTimestampFunction = UTCTimestampTransform<NameToUTCTimestamp>;
130
    using FromUTCTimestampFunction = UTCTimestampTransform<NameFromUTCTimestamp>;
131
}
132

133
REGISTER_FUNCTION(UTCTimestampTransform)
134
{
135
    factory.registerFunction<ToUTCTimestampFunction>();
136
    factory.registerFunction<FromUTCTimestampFunction>();
137
    factory.registerAlias("to_utc_timestamp", NameToUTCTimestamp::name, FunctionFactory::CaseInsensitive);
138
    factory.registerAlias("from_utc_timestamp", NameFromUTCTimestamp::name, FunctionFactory::CaseInsensitive);
139
}
140

141
}
142

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

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

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

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