1 | #pragma once |
2 | |
3 | #include <AggregateFunctions/IAggregateFunction.h> |
4 | #include <Columns/ColumnNullable.h> |
5 | #include <Common/typeid_cast.h> |
6 | #include <DataTypes/DataTypeNullable.h> |
7 | |
8 | |
9 | namespace DB |
10 | { |
11 | |
12 | namespace ErrorCodes |
13 | { |
14 | extern const int ARGUMENT_OUT_OF_BOUND; |
15 | } |
16 | |
17 | /** |
18 | * -OrDefault and -OrNull combinators for aggregate functions. |
19 | * If there are no input values, return NULL or a default value, accordingly. |
20 | * Use a single additional byte of data after the nested function data: |
21 | * 0 means there was no input, 1 means there was some. |
22 | */ |
23 | template <bool UseNull> |
24 | class AggregateFunctionOrFill final : public IAggregateFunctionHelper<AggregateFunctionOrFill<UseNull>> |
25 | { |
26 | private: |
27 | AggregateFunctionPtr nested_function; |
28 | |
29 | size_t size_of_data; |
30 | DataTypePtr inner_type; |
31 | bool inner_nullable; |
32 | |
33 | public: |
34 | AggregateFunctionOrFill(AggregateFunctionPtr nested_function_, const DataTypes & arguments, const Array & params) |
35 | : IAggregateFunctionHelper<AggregateFunctionOrFill>{arguments, params} |
36 | , nested_function{nested_function_} |
37 | , size_of_data {nested_function->sizeOfData()} |
38 | , inner_type {nested_function->getReturnType()} |
39 | , inner_nullable {inner_type->isNullable()} |
40 | { |
41 | // nothing |
42 | } |
43 | |
44 | String getName() const override |
45 | { |
46 | if constexpr (UseNull) |
47 | return nested_function->getName() + "OrNull" ; |
48 | else |
49 | return nested_function->getName() + "OrDefault" ; |
50 | } |
51 | |
52 | bool isState() const override |
53 | { |
54 | return nested_function->isState(); |
55 | } |
56 | |
57 | bool allocatesMemoryInArena() const override |
58 | { |
59 | return nested_function->allocatesMemoryInArena(); |
60 | } |
61 | |
62 | bool hasTrivialDestructor() const override |
63 | { |
64 | return nested_function->hasTrivialDestructor(); |
65 | } |
66 | |
67 | size_t sizeOfData() const override |
68 | { |
69 | return size_of_data + sizeof(char); |
70 | } |
71 | |
72 | size_t alignOfData() const override |
73 | { |
74 | return nested_function->alignOfData(); |
75 | } |
76 | |
77 | void create(AggregateDataPtr place) const override |
78 | { |
79 | nested_function->create(place); |
80 | |
81 | place[size_of_data] = 0; |
82 | } |
83 | |
84 | void destroy(AggregateDataPtr place) const noexcept override |
85 | { |
86 | nested_function->destroy(place); |
87 | } |
88 | |
89 | void add( |
90 | AggregateDataPtr place, |
91 | const IColumn ** columns, |
92 | size_t row_num, |
93 | Arena * arena) const override |
94 | { |
95 | nested_function->add(place, columns, row_num, arena); |
96 | |
97 | place[size_of_data] = 1; |
98 | } |
99 | |
100 | void merge( |
101 | AggregateDataPtr place, |
102 | ConstAggregateDataPtr rhs, |
103 | Arena * arena) const override |
104 | { |
105 | nested_function->merge(place, rhs, arena); |
106 | } |
107 | |
108 | void serialize( |
109 | ConstAggregateDataPtr place, |
110 | WriteBuffer & buf) const override |
111 | { |
112 | nested_function->serialize(place, buf); |
113 | } |
114 | |
115 | void deserialize( |
116 | AggregateDataPtr place, |
117 | ReadBuffer & buf, |
118 | Arena * arena) const override |
119 | { |
120 | nested_function->deserialize(place, buf, arena); |
121 | } |
122 | |
123 | DataTypePtr getReturnType() const override |
124 | { |
125 | if constexpr (UseNull) |
126 | { |
127 | // -OrNull |
128 | |
129 | if (inner_nullable) |
130 | return inner_type; |
131 | |
132 | return std::make_shared<DataTypeNullable>(inner_type); |
133 | } |
134 | else |
135 | { |
136 | // -OrDefault |
137 | |
138 | return inner_type; |
139 | } |
140 | } |
141 | |
142 | void insertResultInto( |
143 | ConstAggregateDataPtr place, |
144 | IColumn & to) const override |
145 | { |
146 | if (place[size_of_data]) |
147 | { |
148 | if constexpr (UseNull) |
149 | { |
150 | // -OrNull |
151 | |
152 | if (inner_nullable) |
153 | nested_function->insertResultInto(place, to); |
154 | else |
155 | { |
156 | ColumnNullable & col = typeid_cast<ColumnNullable &>(to); |
157 | |
158 | col.getNullMapColumn().insertDefault(); |
159 | nested_function->insertResultInto(place, col.getNestedColumn()); |
160 | } |
161 | } |
162 | else |
163 | { |
164 | // -OrDefault |
165 | |
166 | nested_function->insertResultInto(place, to); |
167 | } |
168 | } |
169 | else |
170 | to.insertDefault(); |
171 | } |
172 | }; |
173 | |
174 | } |
175 | |