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
9namespace DB
10{
11
12namespace 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 */
23template <bool UseNull>
24class AggregateFunctionOrFill final : public IAggregateFunctionHelper<AggregateFunctionOrFill<UseNull>>
25{
26private:
27 AggregateFunctionPtr nested_function;
28
29 size_t size_of_data;
30 DataTypePtr inner_type;
31 bool inner_nullable;
32
33public:
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