aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/clickhouse/src/AggregateFunctions/AggregateFunctionResample.cpp
blob: cc64ed0706561255143e72ca89920b469b63e262 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#include <AggregateFunctions/AggregateFunctionResample.h>

#include <AggregateFunctions/AggregateFunctionCombinatorFactory.h>


namespace DB
{

namespace ErrorCodes
{
    extern const int ILLEGAL_TYPE_OF_ARGUMENT;
    extern const int NUMBER_OF_ARGUMENTS_DOESNT_MATCH;
}

namespace
{

class AggregateFunctionCombinatorResample final : public IAggregateFunctionCombinator
{
public:
    String getName() const override
    {
        return "Resample";
    }

    DataTypes transformArguments(const DataTypes & arguments) const override
    {
        if (arguments.empty())
            throw Exception(ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH,
                    "Incorrect number of arguments for aggregate function with {} suffix", getName());

        return DataTypes(arguments.begin(), arguments.end() - 1);
    }

    Array transformParameters(const Array & params) const override
    {
        if (params.size() < 3)
            throw Exception(ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH,
                    "Incorrect number of parameters for aggregate function with {} suffix", getName());

        return Array(params.begin(), params.end() - 3);
    }

    AggregateFunctionPtr transformAggregateFunction(
        const AggregateFunctionPtr & nested_function,
        const AggregateFunctionProperties &,
        const DataTypes & arguments,
        const Array & params) const override
    {
        WhichDataType which{arguments.back()};

        if (which.isNativeUInt() || which.isDate() || which.isDateTime() || which.isDateTime64())
        {
            UInt64 begin = params[params.size() - 3].safeGet<UInt64>();
            UInt64 end = params[params.size() - 2].safeGet<UInt64>();

            UInt64 step = params[params.size() - 1].safeGet<UInt64>();

            return std::make_shared<AggregateFunctionResample<UInt64>>(
                nested_function,
                begin,
                end,
                step,
                arguments,
                params);
        }

        if (which.isNativeInt() || which.isEnum() || which.isInterval())
        {
            Int64 begin, end;

            // notice: UInt64 -> Int64 may lead to overflow
            if (!params[params.size() - 3].tryGet<Int64>(begin))
                begin = params[params.size() - 3].safeGet<UInt64>();
            if (!params[params.size() - 2].tryGet<Int64>(end))
                end = params[params.size() - 2].safeGet<UInt64>();

            UInt64 step = params[params.size() - 1].safeGet<UInt64>();

            return std::make_shared<AggregateFunctionResample<Int64>>(
                nested_function,
                begin,
                end,
                step,
                arguments,
                params);
        }

        throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT,
                        "Illegal types of argument for aggregate function {}, the type "
                        "of the last argument should be native integer or integer-like", getName());
    }
};

}

void registerAggregateFunctionCombinatorResample(AggregateFunctionCombinatorFactory & factory)
{
    factory.registerCombinator(std::make_shared<AggregateFunctionCombinatorResample>());
}

}