1#include <AggregateFunctions/AggregateFunctionFactory.h>
2#include <AggregateFunctions/AggregateFunctionGroupArrayMoving.h>
3#include <AggregateFunctions/Helpers.h>
4#include <AggregateFunctions/FactoryHelpers.h>
5#include <DataTypes/DataTypeDate.h>
6#include <DataTypes/DataTypeDateTime.h>
7#include "registerAggregateFunctions.h"
8
9
10namespace DB
11{
12
13namespace ErrorCodes
14{
15 extern const int NUMBER_OF_ARGUMENTS_DOESNT_MATCH;
16 extern const int BAD_ARGUMENTS;
17}
18
19namespace
20{
21
22template <typename T, typename Tlimit_num_elems>
23struct MovingSum
24{
25 using DataType = MovingSumData<T>;
26 using Function = MovingImpl<T, Tlimit_num_elems, DataType>;
27};
28
29template <typename T, typename Tlimit_num_elems>
30struct MovingAvg
31{
32 using DataType = MovingAvgData<T>;
33 using Function = MovingImpl<T, Tlimit_num_elems, DataType>;
34};
35
36template <typename T, typename Tlimit_num_elems> using MovingSumTemplate = typename MovingSum<T, Tlimit_num_elems>::Function;
37template <typename T, typename Tlimit_num_elems> using MovingAvgTemplate = typename MovingAvg<T, Tlimit_num_elems>::Function;
38
39template <template <typename, typename> class Function, typename has_limit, typename ... TArgs>
40inline AggregateFunctionPtr createAggregateFunctionMovingImpl(const std::string & name, const DataTypePtr & argument_type, TArgs ... args)
41{
42 AggregateFunctionPtr res;
43
44 if (isDecimal(argument_type))
45 res.reset(createWithDecimalType<Function, has_limit>(*argument_type, argument_type, std::forward<TArgs>(args)...));
46 else
47 res.reset(createWithNumericType<Function, has_limit>(*argument_type, argument_type, std::forward<TArgs>(args)...));
48
49 if (!res)
50 throw Exception("Illegal type " + argument_type->getName() + " of argument for aggregate function " + name,
51 ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
52
53 return res;
54}
55
56template <template <typename, typename> class Function>
57AggregateFunctionPtr createAggregateFunctionMoving(const std::string & name, const DataTypes & argument_types, const Array & parameters)
58{
59 assertUnary(name, argument_types);
60
61 bool limit_size = false;
62
63 UInt64 max_elems = std::numeric_limits<UInt64>::max();
64
65 if (parameters.empty())
66 {
67 // cumulative sum without parameter
68 }
69 else if (parameters.size() == 1)
70 {
71 auto type = parameters[0].getType();
72 if (type != Field::Types::Int64 && type != Field::Types::UInt64)
73 throw Exception("Parameter for aggregate function " + name + " should be positive number", ErrorCodes::BAD_ARGUMENTS);
74
75 if ((type == Field::Types::Int64 && parameters[0].get<Int64>() < 0) ||
76 (type == Field::Types::UInt64 && parameters[0].get<UInt64>() == 0))
77 throw Exception("Parameter for aggregate function " + name + " should be positive number", ErrorCodes::BAD_ARGUMENTS);
78
79 limit_size = true;
80 max_elems = parameters[0].get<UInt64>();
81 }
82 else
83 throw Exception("Incorrect number of parameters for aggregate function " + name + ", should be 0 or 1",
84 ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
85
86 if (!limit_size)
87 return createAggregateFunctionMovingImpl<Function, std::false_type>(name, argument_types[0]);
88 else
89 return createAggregateFunctionMovingImpl<Function, std::true_type>(name, argument_types[0], max_elems);
90}
91
92}
93
94
95void registerAggregateFunctionMoving(AggregateFunctionFactory & factory)
96{
97 factory.registerFunction("groupArrayMovingSum", createAggregateFunctionMoving<MovingSumTemplate>);
98 factory.registerFunction("groupArrayMovingAvg", createAggregateFunctionMoving<MovingAvgTemplate>);
99}
100
101}
102