1 | #pragma once |
2 | |
3 | #include <AggregateFunctions/AggregateFunctionFactory.h> |
4 | #include <Columns/ColumnAggregateFunction.h> |
5 | #include <Columns/ColumnArray.h> |
6 | #include <Columns/ColumnConst.h> |
7 | #include <Columns/ColumnVector.h> |
8 | #include <Columns/ColumnsNumber.h> |
9 | #include <DataTypes/DataTypeAggregateFunction.h> |
10 | #include <DataTypes/DataTypeArray.h> |
11 | #include <DataTypes/DataTypesNumber.h> |
12 | #include <Functions/FunctionHelpers.h> |
13 | #include <Functions/IFunctionImpl.h> |
14 | #include <Common/typeid_cast.h> |
15 | #include <Common/assert_cast.h> |
16 | |
17 | // TODO include this last because of a broken roaring header. See the comment |
18 | // inside. |
19 | #include <AggregateFunctions/AggregateFunctionGroupBitmapData.h> |
20 | |
21 | namespace DB |
22 | { |
23 | namespace ErrorCodes |
24 | { |
25 | extern const int LOGICAL_ERROR; |
26 | extern const int NUMBER_OF_ARGUMENTS_DOESNT_MATCH; |
27 | } |
28 | |
29 | /** Bitmap functions. |
30 | * Build a bitmap from integer array: |
31 | * bitmapBuild: integer[] -> bitmap |
32 | * |
33 | * Convert bitmap to integer array: |
34 | * bitmapToArray: bitmap -> integer[] |
35 | * |
36 | * Retrun the smallest value in the set: |
37 | * bitmapMin: bitmap -> integer |
38 | * |
39 | * Retrun the greatest value in the set: |
40 | * bitmapMax: bitmap -> integer |
41 | * |
42 | * Return subset in specified range (not include the range_end): |
43 | * bitmapSubsetInRange: bitmap,integer,integer -> bitmap |
44 | * |
45 | * Return subset of the smallest `limit` values in set which is no smaller than `range_start`. |
46 | * bitmapSubsetLimit: bitmap,integer,integer -> bitmap |
47 | * |
48 | * Transform an array of values in a bitmap to another array of values, the result is a new bitmap. |
49 | * bitmapTransform: bitmap,integer[],integer[] -> bitmap |
50 | * |
51 | * Two bitmap and calculation: |
52 | * bitmapAnd: bitmap,bitmap -> bitmap |
53 | * |
54 | * Two bitmap or calculation: |
55 | * bitmapOr: bitmap,bitmap -> bitmap |
56 | * |
57 | * Two bitmap xor calculation: |
58 | * bitmapXor: bitmap,bitmap -> bitmap |
59 | * |
60 | * Two bitmap andnot calculation: |
61 | * bitmapAndnot: bitmap,bitmap -> bitmap |
62 | * |
63 | * Retrun bitmap cardinality: |
64 | * bitmapCardinality: bitmap -> integer |
65 | * |
66 | * Two bitmap and calculation, return cardinality: |
67 | * bitmapAndCardinality: bitmap,bitmap -> integer |
68 | * |
69 | * Two bitmap or calculation, return cardinality: |
70 | * bitmapOrCardinality: bitmap,bitmap -> integer |
71 | * |
72 | * Two bitmap xor calculation, return cardinality: |
73 | * bitmapXorCardinality: bitmap,bitmap -> integer |
74 | * |
75 | * Two bitmap andnot calculation, return cardinality: |
76 | * bitmapAndnotCardinality: bitmap,bitmap -> integer |
77 | * |
78 | * Determine if a bitmap contains the given integer: |
79 | * bitmapContains: bitmap,integer -> bool |
80 | * |
81 | * Judge if a bitmap is superset of the another one: |
82 | * bitmapHasAll: bitmap,bitmap -> bool |
83 | * |
84 | * Judge if the intersection of two bitmap is nonempty: |
85 | * bitmapHasAny: bitmap,bitmap -> bool |
86 | */ |
87 | |
88 | template <typename Name> |
89 | class FunctionBitmapBuildImpl : public IFunction |
90 | { |
91 | public: |
92 | static constexpr auto name = Name::name; |
93 | |
94 | static FunctionPtr create(const Context &) { return std::make_shared<FunctionBitmapBuildImpl>(); } |
95 | |
96 | String getName() const override { return name; } |
97 | |
98 | bool isVariadic() const override { return false; } |
99 | |
100 | size_t getNumberOfArguments() const override { return 1; } |
101 | |
102 | DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override |
103 | { |
104 | if (arguments[0]->onlyNull()) |
105 | return arguments[0]; |
106 | |
107 | auto array_type = typeid_cast<const DataTypeArray *>(arguments[0].get()); |
108 | if (!array_type) |
109 | throw Exception( |
110 | "First argument for function " + getName() + " must be an array but it has type " + arguments[0]->getName() + "." , |
111 | ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); |
112 | |
113 | auto nested_type = array_type->getNestedType(); |
114 | DataTypes argument_types = {nested_type}; |
115 | Array params_row; |
116 | AggregateFunctionPtr bitmap_function |
117 | = AggregateFunctionFactory::instance().get(AggregateFunctionGroupBitmapData<UInt32>::name(), argument_types, params_row); |
118 | |
119 | return std::make_shared<DataTypeAggregateFunction>(bitmap_function, argument_types, params_row); |
120 | } |
121 | |
122 | bool useDefaultImplementationForConstants() const override { return true; } |
123 | |
124 | void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result, size_t /* input_rows_count */) override |
125 | { |
126 | const IDataType * from_type = block.getByPosition(arguments[0]).type.get(); |
127 | auto array_type = typeid_cast<const DataTypeArray *>(from_type); |
128 | auto nested_type = array_type->getNestedType(); |
129 | |
130 | DataTypes argument_types = {nested_type}; |
131 | |
132 | WhichDataType which(nested_type); |
133 | if (which.isUInt8()) |
134 | executeBitmapData<UInt8>(block, argument_types, arguments, result); |
135 | else if (which.isUInt16()) |
136 | executeBitmapData<UInt16>(block, argument_types, arguments, result); |
137 | else if (which.isUInt32()) |
138 | executeBitmapData<UInt32>(block, argument_types, arguments, result); |
139 | else if (which.isUInt64()) |
140 | executeBitmapData<UInt64>(block, argument_types, arguments, result); |
141 | else |
142 | throw Exception( |
143 | "Unexpected type " + from_type->getName() + " of argument of function " + getName(), ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); |
144 | } |
145 | |
146 | private: |
147 | template <typename T> |
148 | void executeBitmapData(Block & block, DataTypes & argument_types, const ColumnNumbers & arguments, size_t result) |
149 | { |
150 | // input data |
151 | const ColumnArray * array = typeid_cast<const ColumnArray *>(block.getByPosition(arguments[0]).column.get()); |
152 | ColumnPtr mapped = array->getDataPtr(); |
153 | const ColumnArray::Offsets & offsets = array->getOffsets(); |
154 | const ColumnVector<T> * column = checkAndGetColumn<ColumnVector<T>>(&*mapped); |
155 | const typename ColumnVector<T>::Container & input_data = column->getData(); |
156 | |
157 | // output data |
158 | Array params_row; |
159 | AggregateFunctionPtr bitmap_function |
160 | = AggregateFunctionFactory::instance().get(AggregateFunctionGroupBitmapData<UInt32>::name(), argument_types, params_row); |
161 | auto col_to = ColumnAggregateFunction::create(bitmap_function); |
162 | col_to->reserve(offsets.size()); |
163 | |
164 | size_t pos = 0; |
165 | for (size_t i = 0; i < offsets.size(); ++i) |
166 | { |
167 | col_to->insertDefault(); |
168 | AggregateFunctionGroupBitmapData<T> & bitmap_data |
169 | = *reinterpret_cast<AggregateFunctionGroupBitmapData<T> *>(col_to->getData()[i]); |
170 | for (; pos < offsets[i]; ++pos) |
171 | { |
172 | bitmap_data.rbs.add(input_data[pos]); |
173 | } |
174 | } |
175 | block.getByPosition(result).column = std::move(col_to); |
176 | } |
177 | }; |
178 | |
179 | template <typename Name> |
180 | class FunctionBitmapToArrayImpl : public IFunction |
181 | { |
182 | public: |
183 | static constexpr auto name = Name::name; |
184 | |
185 | static FunctionPtr create(const Context &) { return std::make_shared<FunctionBitmapToArrayImpl>(); } |
186 | |
187 | String getName() const override { return name; } |
188 | |
189 | bool isVariadic() const override { return false; } |
190 | |
191 | size_t getNumberOfArguments() const override { return 1; } |
192 | |
193 | DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override |
194 | { |
195 | const DataTypeAggregateFunction * bitmap_type = typeid_cast<const DataTypeAggregateFunction *>(arguments[0].get()); |
196 | if (!(bitmap_type && bitmap_type->getFunctionName() == AggregateFunctionGroupBitmapData<UInt32>::name())) |
197 | throw Exception( |
198 | "First argument for function " + getName() + " must be a bitmap but it has type " + arguments[0]->getName() + "." , |
199 | ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); |
200 | |
201 | const DataTypePtr data_type = bitmap_type->getArgumentsDataTypes()[0]; |
202 | |
203 | return std::make_shared<DataTypeArray>(data_type); |
204 | } |
205 | |
206 | bool useDefaultImplementationForConstants() const override { return true; } |
207 | |
208 | void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) override |
209 | { |
210 | // input data |
211 | const auto & return_type = block.getByPosition(result).type; |
212 | auto res_ptr = return_type->createColumn(); |
213 | ColumnArray & res = assert_cast<ColumnArray &>(*res_ptr); |
214 | |
215 | IColumn & res_data = res.getData(); |
216 | ColumnArray::Offsets & res_offsets = res.getOffsets(); |
217 | |
218 | const IDataType * from_type = block.getByPosition(arguments[0]).type.get(); |
219 | const DataTypeAggregateFunction * aggr_type = typeid_cast<const DataTypeAggregateFunction *>(from_type); |
220 | WhichDataType which(aggr_type->getArgumentsDataTypes()[0]); |
221 | if (which.isUInt8()) |
222 | executeIntType<UInt8>(block, arguments, input_rows_count, res_data, res_offsets); |
223 | else if (which.isUInt16()) |
224 | executeIntType<UInt16>(block, arguments, input_rows_count, res_data, res_offsets); |
225 | else if (which.isUInt32()) |
226 | executeIntType<UInt32>(block, arguments, input_rows_count, res_data, res_offsets); |
227 | else if (which.isUInt64()) |
228 | executeIntType<UInt64>(block, arguments, input_rows_count, res_data, res_offsets); |
229 | else |
230 | throw Exception( |
231 | "Unexpected type " + from_type->getName() + " of argument of function " + getName(), ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); |
232 | |
233 | block.getByPosition(result).column = std::move(res_ptr); |
234 | } |
235 | |
236 | private: |
237 | using ToType = UInt64; |
238 | |
239 | template <typename T> |
240 | void executeIntType( |
241 | Block & block, const ColumnNumbers & arguments, size_t input_rows_count, IColumn & res_data_col, ColumnArray::Offsets & res_offsets) |
242 | const |
243 | { |
244 | const ColumnAggregateFunction * column |
245 | = typeid_cast<const ColumnAggregateFunction *>(block.getByPosition(arguments[0]).column.get()); |
246 | |
247 | PaddedPODArray<T> & res_data = typeid_cast<ColumnVector<T> &>(res_data_col).getData(); |
248 | ColumnArray::Offset res_offset = 0; |
249 | |
250 | for (size_t i = 0; i < input_rows_count; ++i) |
251 | { |
252 | const AggregateFunctionGroupBitmapData<T> & bitmap_data_1 |
253 | = *reinterpret_cast<const AggregateFunctionGroupBitmapData<T> *>(column->getData()[i]); |
254 | UInt64 count = bitmap_data_1.rbs.rb_to_array(res_data); |
255 | res_offset += count; |
256 | res_offsets.emplace_back(res_offset); |
257 | } |
258 | } |
259 | }; |
260 | |
261 | template <typename Impl> |
262 | class FunctionBitmapSubset : public IFunction |
263 | { |
264 | public: |
265 | static constexpr auto name = Impl::name; |
266 | |
267 | static FunctionPtr create(const Context &) { return std::make_shared<FunctionBitmapSubset<Impl>>(); } |
268 | |
269 | String getName() const override { return name; } |
270 | |
271 | bool isVariadic() const override { return false; } |
272 | |
273 | size_t getNumberOfArguments() const override { return 3; } |
274 | |
275 | DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override |
276 | { |
277 | const DataTypeAggregateFunction * bitmap_type = typeid_cast<const DataTypeAggregateFunction *>(arguments[0].get()); |
278 | if (!(bitmap_type && bitmap_type->getFunctionName() == AggregateFunctionGroupBitmapData<UInt32>::name())) |
279 | throw Exception( |
280 | "First argument for function " + getName() + " must be a bitmap but it has type " + arguments[0]->getName() + "." , |
281 | ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); |
282 | |
283 | auto arg_type1 = typeid_cast<const DataTypeNumber<UInt32> *>(arguments[1].get()); |
284 | if (!(arg_type1)) |
285 | throw Exception( |
286 | "Second argument for function " + getName() + " must be UInt32 but it has type " + arguments[1]->getName() + "." , |
287 | ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); |
288 | |
289 | auto arg_type2 = typeid_cast<const DataTypeNumber<UInt32> *>(arguments[1].get()); |
290 | if (!(arg_type2)) |
291 | throw Exception( |
292 | "Third argument for function " + getName() + " must be UInt32 but it has type " + arguments[2]->getName() + "." , |
293 | ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); |
294 | |
295 | return arguments[0]; |
296 | } |
297 | |
298 | bool useDefaultImplementationForConstants() const override { return true; } |
299 | |
300 | void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) override |
301 | { |
302 | const IDataType * from_type = block.getByPosition(arguments[0]).type.get(); |
303 | const DataTypeAggregateFunction * aggr_type = typeid_cast<const DataTypeAggregateFunction *>(from_type); |
304 | WhichDataType which(aggr_type->getArgumentsDataTypes()[0]); |
305 | if (which.isUInt8()) |
306 | executeIntType<UInt8>(block, arguments, result, input_rows_count); |
307 | else if (which.isUInt16()) |
308 | executeIntType<UInt16>(block, arguments, result, input_rows_count); |
309 | else if (which.isUInt32()) |
310 | executeIntType<UInt32>(block, arguments, result, input_rows_count); |
311 | else if (which.isUInt64()) |
312 | executeIntType<UInt64>(block, arguments, result, input_rows_count); |
313 | else |
314 | throw Exception( |
315 | "Unexpected type " + from_type->getName() + " of argument of function " + getName(), ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); |
316 | } |
317 | |
318 | private: |
319 | using ToType = UInt64; |
320 | |
321 | template <typename T> |
322 | void executeIntType( |
323 | Block & block, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) |
324 | const |
325 | { |
326 | const IColumn * columns[3]; |
327 | bool is_column_const[3]; |
328 | const ColumnAggregateFunction * col_agg_func; |
329 | const PaddedPODArray<AggregateDataPtr> * container0; |
330 | const PaddedPODArray<UInt32> * container1, * container2; |
331 | |
332 | for (size_t i = 0; i < 3; ++i) |
333 | { |
334 | columns[i] = block.getByPosition(arguments[i]).column.get(); |
335 | is_column_const[i] = isColumnConst(*columns[i]); |
336 | } |
337 | if (is_column_const[0]) |
338 | col_agg_func = typeid_cast<const ColumnAggregateFunction*>(typeid_cast<const ColumnConst*>(columns[0])->getDataColumnPtr().get()); |
339 | else |
340 | col_agg_func = typeid_cast<const ColumnAggregateFunction*>(columns[0]); |
341 | |
342 | container0 = &col_agg_func->getData(); |
343 | if (is_column_const[1]) |
344 | container1 = &typeid_cast<const ColumnUInt32*>(typeid_cast<const ColumnConst*>(columns[1])->getDataColumnPtr().get())->getData(); |
345 | else |
346 | container1 = &typeid_cast<const ColumnUInt32*>(columns[1])->getData(); |
347 | if (is_column_const[2]) |
348 | container2 = &typeid_cast<const ColumnUInt32*>(typeid_cast<const ColumnConst*>(columns[2])->getDataColumnPtr().get())->getData(); |
349 | else |
350 | container2 = &typeid_cast<const ColumnUInt32*>(columns[2])->getData(); |
351 | |
352 | auto col_to = ColumnAggregateFunction::create(col_agg_func->getAggregateFunction()); |
353 | col_to->reserve(input_rows_count); |
354 | |
355 | for (size_t i = 0; i < input_rows_count; ++i) |
356 | { |
357 | const AggregateDataPtr data_ptr_0 = is_column_const[0] ? (*container0)[0] : (*container0)[i]; |
358 | const AggregateFunctionGroupBitmapData<T> & bitmap_data_0 |
359 | = *reinterpret_cast<const AggregateFunctionGroupBitmapData<T>*>(data_ptr_0); |
360 | const UInt32 range_start = is_column_const[1] ? (*container1)[0] : (*container1)[i]; |
361 | const UInt32 range_end = is_column_const[2] ? (*container2)[0] : (*container2)[i]; |
362 | |
363 | col_to->insertDefault(); |
364 | AggregateFunctionGroupBitmapData<T> & bitmap_data_2 |
365 | = *reinterpret_cast<AggregateFunctionGroupBitmapData<T> *>(col_to->getData()[i]); |
366 | Impl::apply(bitmap_data_0, range_start, range_end, bitmap_data_2); |
367 | } |
368 | block.getByPosition(result).column = std::move(col_to); |
369 | } |
370 | }; |
371 | |
372 | struct BitmapSubsetInRangeImpl |
373 | { |
374 | public: |
375 | static constexpr auto name = "bitmapSubsetInRange" ; |
376 | template <typename T> |
377 | static void apply(const AggregateFunctionGroupBitmapData<T> & bitmap_data_0, UInt32 range_start, UInt32 range_end, AggregateFunctionGroupBitmapData<T> & bitmap_data_2) |
378 | { |
379 | bitmap_data_0.rbs.rb_range(range_start, range_end, bitmap_data_2.rbs); |
380 | } |
381 | }; |
382 | |
383 | struct BitmapSubsetLimitImpl |
384 | { |
385 | public: |
386 | static constexpr auto name = "bitmapSubsetLimit" ; |
387 | template <typename T> |
388 | static void apply(const AggregateFunctionGroupBitmapData<T> & bitmap_data_0, UInt32 range_start, UInt32 range_end, AggregateFunctionGroupBitmapData<T> & bitmap_data_2) |
389 | { |
390 | bitmap_data_0.rbs.rb_limit(range_start, range_end, bitmap_data_2.rbs); |
391 | } |
392 | }; |
393 | |
394 | using FunctionBitmapSubsetInRange = FunctionBitmapSubset<BitmapSubsetInRangeImpl>; |
395 | using FunctionBitmapSubsetLimit = FunctionBitmapSubset<BitmapSubsetLimitImpl>; |
396 | |
397 | |
398 | class FunctionBitmapTransform : public IFunction |
399 | { |
400 | public: |
401 | static constexpr auto name = "bitmapTransform" ; |
402 | |
403 | static FunctionPtr create(const Context &) { return std::make_shared<FunctionBitmapTransform>(); } |
404 | |
405 | String getName() const override { return name; } |
406 | |
407 | bool isVariadic() const override { return false; } |
408 | |
409 | size_t getNumberOfArguments() const override { return 3; } |
410 | |
411 | DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override |
412 | { |
413 | const DataTypeAggregateFunction * bitmap_type = typeid_cast<const DataTypeAggregateFunction *>(arguments[0].get()); |
414 | if (!(bitmap_type && bitmap_type->getFunctionName() == AggregateFunctionGroupBitmapData<UInt32>::name())) |
415 | throw Exception( |
416 | "First argument for function " + getName() + " must be a bitmap but it has type " + arguments[0]->getName() + "." , |
417 | ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); |
418 | for (size_t i = 0; i < 2; ++i) |
419 | { |
420 | auto array_type = typeid_cast<const DataTypeArray *>(arguments[i + 1].get()); |
421 | String msg(i == 0 ? "Second" : "Third" ); |
422 | msg += " argument for function " + getName() + " must be an UInt32 array but it has type " + arguments[i + 1]->getName() + "." ; |
423 | if (!array_type) |
424 | throw Exception(msg, ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); |
425 | |
426 | auto nested_type = array_type->getNestedType(); |
427 | WhichDataType which(nested_type); |
428 | if (!which.isUInt32()) |
429 | throw Exception(msg, ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); |
430 | } |
431 | return arguments[0]; |
432 | } |
433 | |
434 | bool useDefaultImplementationForConstants() const override { return true; } |
435 | |
436 | void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) override |
437 | { |
438 | const IDataType * from_type = block.getByPosition(arguments[0]).type.get(); |
439 | const DataTypeAggregateFunction * aggr_type = typeid_cast<const DataTypeAggregateFunction *>(from_type); |
440 | WhichDataType which(aggr_type->getArgumentsDataTypes()[0]); |
441 | if (which.isUInt8()) |
442 | executeIntType<UInt8>(block, arguments, result, input_rows_count); |
443 | else if (which.isUInt16()) |
444 | executeIntType<UInt16>(block, arguments, result, input_rows_count); |
445 | else if (which.isUInt32()) |
446 | executeIntType<UInt32>(block, arguments, result, input_rows_count); |
447 | else if (which.isUInt64()) |
448 | executeIntType<UInt64>(block, arguments, result, input_rows_count); |
449 | else |
450 | throw Exception( |
451 | "Unexpected type " + from_type->getName() + " of argument of function " + getName(), ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); |
452 | } |
453 | |
454 | private: |
455 | using ToType = UInt64; |
456 | |
457 | template <typename T> |
458 | void executeIntType( |
459 | Block & block, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) const |
460 | { |
461 | const IColumn * columns[3]; |
462 | bool is_column_const[3]; |
463 | const ColumnAggregateFunction * col_agg_func; |
464 | const PaddedPODArray<AggregateDataPtr> * container0; |
465 | const ColumnArray * array; |
466 | |
467 | for (size_t i = 0; i < 3; ++i) |
468 | { |
469 | columns[i] = block.getByPosition(arguments[i]).column.get(); |
470 | is_column_const[i] = isColumnConst(*columns[i]); |
471 | } |
472 | if (is_column_const[0]) |
473 | { |
474 | col_agg_func = typeid_cast<const ColumnAggregateFunction*>(typeid_cast<const ColumnConst*>(columns[0])->getDataColumnPtr().get()); |
475 | } |
476 | else |
477 | { |
478 | col_agg_func = typeid_cast<const ColumnAggregateFunction*>(columns[0]); |
479 | } |
480 | container0 = &col_agg_func->getData(); |
481 | |
482 | if (is_column_const[1]) |
483 | array = typeid_cast<const ColumnArray*>(typeid_cast<const ColumnConst*>(columns[1])->getDataColumnPtr().get()); |
484 | else |
485 | { |
486 | array = typeid_cast<const ColumnArray *>(block.getByPosition(arguments[1]).column.get()); |
487 | } |
488 | const ColumnArray::Offsets & from_offsets = array->getOffsets(); |
489 | const ColumnVector<UInt32>::Container & from_container = typeid_cast<const ColumnVector<UInt32> *>(&array->getData())->getData(); |
490 | |
491 | if (is_column_const[2]) |
492 | array = typeid_cast<const ColumnArray*>(typeid_cast<const ColumnConst*>(columns[2])->getDataColumnPtr().get()); |
493 | else |
494 | array = typeid_cast<const ColumnArray *>(block.getByPosition(arguments[2]).column.get()); |
495 | |
496 | const ColumnArray::Offsets & to_offsets = array->getOffsets(); |
497 | const ColumnVector<UInt32>::Container & to_container = typeid_cast<const ColumnVector<UInt32> *>(&array->getData())->getData(); |
498 | auto col_to = ColumnAggregateFunction::create(col_agg_func->getAggregateFunction()); |
499 | col_to->reserve(input_rows_count); |
500 | |
501 | size_t from_start; |
502 | size_t from_end; |
503 | size_t to_start; |
504 | size_t to_end; |
505 | for (size_t i = 0; i < input_rows_count; ++i) |
506 | { |
507 | const AggregateDataPtr data_ptr_0 = is_column_const[0] ? (*container0)[0] : (*container0)[i]; |
508 | const AggregateFunctionGroupBitmapData<T> & bitmap_data_0 |
509 | = *reinterpret_cast<const AggregateFunctionGroupBitmapData<T> *>(data_ptr_0); |
510 | if (is_column_const[1]) |
511 | { |
512 | from_start = 0; |
513 | from_end = from_container.size(); |
514 | } |
515 | else |
516 | { |
517 | from_start = i == 0 ? 0 : from_offsets[i - 1]; |
518 | from_end = from_offsets[i]; |
519 | } |
520 | if (is_column_const[2]) |
521 | { |
522 | to_start = 0; |
523 | to_end = to_container.size(); |
524 | } |
525 | else |
526 | { |
527 | to_start = i == 0 ? 0 : to_offsets[i - 1]; |
528 | to_end = to_offsets[i]; |
529 | } |
530 | if (from_end - from_start != to_end - to_start) |
531 | throw Exception("From array size and to array size mismatch" , ErrorCodes::LOGICAL_ERROR); |
532 | |
533 | col_to->insertDefault(); |
534 | AggregateFunctionGroupBitmapData<T> & bitmap_data_2 |
535 | = *reinterpret_cast<AggregateFunctionGroupBitmapData<T> *>(col_to->getData()[i]); |
536 | bitmap_data_2.rbs.merge(bitmap_data_0.rbs); |
537 | bitmap_data_2.rbs.rb_replace(&from_container[from_start], &to_container[to_start], from_end - from_start); |
538 | } |
539 | block.getByPosition(result).column = std::move(col_to); |
540 | } |
541 | }; |
542 | |
543 | template <typename Impl> |
544 | class FunctionBitmapSelfCardinalityImpl : public IFunction |
545 | { |
546 | public: |
547 | static constexpr auto name = Impl::name; |
548 | |
549 | static FunctionPtr create(const Context &) { return std::make_shared<FunctionBitmapSelfCardinalityImpl<Impl>>(); } |
550 | |
551 | String getName() const override { return name; } |
552 | |
553 | bool isVariadic() const override { return false; } |
554 | |
555 | size_t getNumberOfArguments() const override { return 1; } |
556 | |
557 | DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override |
558 | { |
559 | auto bitmap_type = typeid_cast<const DataTypeAggregateFunction *>(arguments[0].get()); |
560 | if (!(bitmap_type && bitmap_type->getFunctionName() == AggregateFunctionGroupBitmapData<UInt32>::name())) |
561 | throw Exception( |
562 | "First argument for function " + getName() + " must be a bitmap but it has type " + arguments[0]->getName() + "." , |
563 | ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); |
564 | return std::make_shared<DataTypeNumber<ToType>>(); |
565 | } |
566 | |
567 | bool useDefaultImplementationForConstants() const override { return true; } |
568 | |
569 | void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) override |
570 | { |
571 | auto col_to = ColumnVector<ToType>::create(input_rows_count); |
572 | typename ColumnVector<ToType>::Container & vec_to = col_to->getData(); |
573 | const IDataType * from_type = block.getByPosition(arguments[0]).type.get(); |
574 | |
575 | const DataTypeAggregateFunction * aggr_type = typeid_cast<const DataTypeAggregateFunction *>(from_type); |
576 | WhichDataType which(aggr_type->getArgumentsDataTypes()[0]); |
577 | if (which.isUInt8()) |
578 | executeIntType<UInt8>(block, arguments, input_rows_count, vec_to); |
579 | else if (which.isUInt16()) |
580 | executeIntType<UInt16>(block, arguments, input_rows_count, vec_to); |
581 | else if (which.isUInt32()) |
582 | executeIntType<UInt32>(block, arguments, input_rows_count, vec_to); |
583 | else if (which.isUInt64()) |
584 | executeIntType<UInt64>(block, arguments, input_rows_count, vec_to); |
585 | else |
586 | throw Exception( |
587 | "Unexpected type " + from_type->getName() + " of argument of function " + getName(), ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); |
588 | |
589 | block.getByPosition(result).column = std::move(col_to); |
590 | } |
591 | |
592 | private: |
593 | using ToType = UInt64; |
594 | |
595 | template <typename T> |
596 | void executeIntType( |
597 | Block & block, const ColumnNumbers & arguments, size_t input_rows_count, typename ColumnVector<ToType>::Container & vec_to) |
598 | { |
599 | const ColumnAggregateFunction * column |
600 | = typeid_cast<const ColumnAggregateFunction *>(block.getByPosition(arguments[0]).column.get()); |
601 | for (size_t i = 0; i < input_rows_count; ++i) |
602 | { |
603 | const AggregateFunctionGroupBitmapData<T> & bitmap_data |
604 | = *reinterpret_cast<const AggregateFunctionGroupBitmapData<T> *>(column->getData()[i]); |
605 | vec_to[i] = Impl::apply(bitmap_data); |
606 | } |
607 | } |
608 | }; |
609 | |
610 | struct BitmapCardinalityImpl |
611 | { |
612 | public: |
613 | static constexpr auto name = "bitmapCardinality" ; |
614 | template <typename T> |
615 | static UInt64 apply(const AggregateFunctionGroupBitmapData<T> & bitmap_data) |
616 | { |
617 | return bitmap_data.rbs.size(); |
618 | } |
619 | }; |
620 | |
621 | struct BitmapMinImpl |
622 | { |
623 | public: |
624 | static constexpr auto name = "bitmapMin" ; |
625 | template <typename T> |
626 | static UInt64 apply(const AggregateFunctionGroupBitmapData<T> & bitmap_data) |
627 | { |
628 | return bitmap_data.rbs.rb_min(); |
629 | } |
630 | }; |
631 | |
632 | struct BitmapMaxImpl |
633 | { |
634 | public: |
635 | static constexpr auto name = "bitmapMax" ; |
636 | template <typename T> |
637 | static UInt64 apply(const AggregateFunctionGroupBitmapData<T> & bitmap_data) |
638 | { |
639 | return bitmap_data.rbs.rb_max(); |
640 | } |
641 | }; |
642 | |
643 | template <typename T> |
644 | struct BitmapAndCardinalityImpl |
645 | { |
646 | using ReturnType = UInt64; |
647 | static UInt64 apply(const AggregateFunctionGroupBitmapData<T> & bitmap_data_1, const AggregateFunctionGroupBitmapData<T> & bitmap_data_2) |
648 | { |
649 | // roaring_bitmap_and_cardinality( rb1, rb2 ); |
650 | return bitmap_data_1.rbs.rb_and_cardinality(bitmap_data_2.rbs); |
651 | } |
652 | }; |
653 | |
654 | |
655 | template <typename T> |
656 | struct BitmapOrCardinalityImpl |
657 | { |
658 | using ReturnType = UInt64; |
659 | static UInt64 apply(const AggregateFunctionGroupBitmapData<T> & bitmap_data_1, const AggregateFunctionGroupBitmapData<T> & bitmap_data_2) |
660 | { |
661 | // return roaring_bitmap_or_cardinality( rb1, rb2 ); |
662 | return bitmap_data_1.rbs.rb_or_cardinality(bitmap_data_2.rbs); |
663 | } |
664 | }; |
665 | |
666 | template <typename T> |
667 | struct BitmapXorCardinalityImpl |
668 | { |
669 | using ReturnType = UInt64; |
670 | static UInt64 apply(const AggregateFunctionGroupBitmapData<T> & bitmap_data_1, const AggregateFunctionGroupBitmapData<T> & bitmap_data_2) |
671 | { |
672 | // return roaring_bitmap_xor_cardinality( rb1, rb2 ); |
673 | return bitmap_data_1.rbs.rb_xor_cardinality(bitmap_data_2.rbs); |
674 | } |
675 | }; |
676 | |
677 | template <typename T> |
678 | struct BitmapAndnotCardinalityImpl |
679 | { |
680 | using ReturnType = UInt64; |
681 | static UInt64 apply(const AggregateFunctionGroupBitmapData<T> & bitmap_data_1, const AggregateFunctionGroupBitmapData<T> & bitmap_data_2) |
682 | { |
683 | // roaring_bitmap_andnot_cardinality( rb1, rb2 ); |
684 | return bitmap_data_1.rbs.rb_andnot_cardinality(bitmap_data_2.rbs); |
685 | } |
686 | }; |
687 | |
688 | template <typename T> |
689 | struct BitmapHasAllImpl |
690 | { |
691 | using ReturnType = UInt8; |
692 | static UInt8 apply(const AggregateFunctionGroupBitmapData<T> & bitmap_data_1, const AggregateFunctionGroupBitmapData<T> & bitmap_data_2) |
693 | { |
694 | return bitmap_data_1.rbs.rb_is_subset(bitmap_data_2.rbs); |
695 | } |
696 | }; |
697 | |
698 | template <typename T> |
699 | struct BitmapHasAnyImpl |
700 | { |
701 | using ReturnType = UInt8; |
702 | static UInt8 apply(const AggregateFunctionGroupBitmapData<T> & bitmap_data_1, const AggregateFunctionGroupBitmapData<T> & bitmap_data_2) |
703 | { |
704 | return bitmap_data_1.rbs.rb_intersect(bitmap_data_2.rbs); |
705 | } |
706 | }; |
707 | |
708 | class FunctionBitmapContains : public IFunction |
709 | { |
710 | public: |
711 | static constexpr auto name = "bitmapContains" ; |
712 | |
713 | static FunctionPtr create(const Context &) { return std::make_shared<FunctionBitmapContains>(); } |
714 | |
715 | String getName() const override { return name; } |
716 | |
717 | bool isVariadic() const override { return false; } |
718 | |
719 | size_t getNumberOfArguments() const override { return 2; } |
720 | |
721 | DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override |
722 | { |
723 | auto bitmap_type0 = typeid_cast<const DataTypeAggregateFunction *>(arguments[0].get()); |
724 | if (!(bitmap_type0 && bitmap_type0->getFunctionName() == AggregateFunctionGroupBitmapData<UInt32>::name())) |
725 | throw Exception( |
726 | "First argument for function " + getName() + " must be a bitmap but it has type " + arguments[0]->getName() + "." , |
727 | ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); |
728 | auto arg_type1 = typeid_cast<const DataTypeNumber<UInt32> *>(arguments[1].get()); |
729 | if (!(arg_type1)) |
730 | throw Exception( |
731 | "Second argument for function " + getName() + " must be UInt32 but it has type " + arguments[1]->getName() + "." , |
732 | ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); |
733 | |
734 | return std::make_shared<DataTypeNumber<UInt8>>(); |
735 | } |
736 | |
737 | bool useDefaultImplementationForConstants() const override { return true; } |
738 | |
739 | void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) override |
740 | { |
741 | auto col_to = ColumnVector<UInt8>::create(input_rows_count); |
742 | typename ColumnVector<UInt8>::Container & vec_to = col_to->getData(); |
743 | const IDataType * from_type = block.getByPosition(arguments[0]).type.get(); |
744 | |
745 | const DataTypeAggregateFunction * aggr_type = typeid_cast<const DataTypeAggregateFunction *>(from_type); |
746 | WhichDataType which(aggr_type->getArgumentsDataTypes()[0]); |
747 | if (which.isUInt8()) |
748 | executeIntType<UInt8>(block, arguments, input_rows_count, vec_to); |
749 | else if (which.isUInt16()) |
750 | executeIntType<UInt16>(block, arguments, input_rows_count, vec_to); |
751 | else if (which.isUInt32()) |
752 | executeIntType<UInt32>(block, arguments, input_rows_count, vec_to); |
753 | else if (which.isUInt64()) |
754 | executeIntType<UInt64>(block, arguments, input_rows_count, vec_to); |
755 | else |
756 | throw Exception( |
757 | "Unexpected type " + from_type->getName() + " of argument of function " + getName(), ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); |
758 | |
759 | block.getByPosition(result).column = std::move(col_to); |
760 | } |
761 | |
762 | private: |
763 | template <typename T> |
764 | void executeIntType( |
765 | Block & block, const ColumnNumbers & arguments, size_t input_rows_count, typename ColumnVector<UInt8>::Container & vec_to) |
766 | { |
767 | const IColumn * columns[2]; |
768 | bool is_column_const[2]; |
769 | const PaddedPODArray<AggregateDataPtr> * container0; |
770 | const PaddedPODArray<UInt32> * container1; |
771 | |
772 | for (size_t i = 0; i < 2; ++i) |
773 | { |
774 | columns[i] = block.getByPosition(arguments[i]).column.get(); |
775 | is_column_const[i] = isColumnConst(*columns[i]); |
776 | } |
777 | if (is_column_const[0]) |
778 | container0 = &typeid_cast<const ColumnAggregateFunction*>(typeid_cast<const ColumnConst*>(columns[0])->getDataColumnPtr().get())->getData(); |
779 | else |
780 | container0 = &typeid_cast<const ColumnAggregateFunction*>(columns[0])->getData(); |
781 | if (is_column_const[1]) |
782 | container1 = &typeid_cast<const ColumnUInt32*>(typeid_cast<const ColumnConst*>(columns[1])->getDataColumnPtr().get())->getData(); |
783 | else |
784 | container1 = &typeid_cast<const ColumnUInt32*>(columns[1])->getData(); |
785 | |
786 | for (size_t i = 0; i < input_rows_count; ++i) |
787 | { |
788 | const AggregateDataPtr data_ptr_0 = is_column_const[0] ? (*container0)[0] : (*container0)[i]; |
789 | const UInt32 data1 = is_column_const[1] ? (*container1)[0] : (*container1)[i]; |
790 | const AggregateFunctionGroupBitmapData<T> & bitmap_data_0 |
791 | = *reinterpret_cast<const AggregateFunctionGroupBitmapData<T> *>(data_ptr_0); |
792 | vec_to[i] = bitmap_data_0.rbs.rb_contains(data1); |
793 | } |
794 | } |
795 | }; |
796 | |
797 | template <template <typename> class Impl, typename Name, typename ToType> |
798 | class FunctionBitmapCardinality : public IFunction |
799 | { |
800 | public: |
801 | static constexpr auto name = Name::name; |
802 | |
803 | static FunctionPtr create(const Context &) { return std::make_shared<FunctionBitmapCardinality>(); } |
804 | |
805 | String getName() const override { return name; } |
806 | |
807 | bool isVariadic() const override { return false; } |
808 | |
809 | size_t getNumberOfArguments() const override { return 2; } |
810 | |
811 | DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override |
812 | { |
813 | auto bitmap_type0 = typeid_cast<const DataTypeAggregateFunction *>(arguments[0].get()); |
814 | if (!(bitmap_type0 && bitmap_type0->getFunctionName() == AggregateFunctionGroupBitmapData<UInt32>::name())) |
815 | throw Exception( |
816 | "First argument for function " + getName() + " must be a bitmap but it has type " + arguments[0]->getName() + "." , |
817 | ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); |
818 | |
819 | auto bitmap_type1 = typeid_cast<const DataTypeAggregateFunction *>(arguments[1].get()); |
820 | if (!(bitmap_type1 && bitmap_type1->getFunctionName() == AggregateFunctionGroupBitmapData<UInt32>::name())) |
821 | throw Exception( |
822 | "Second argument for function " + getName() + " must be a bitmap but it has type " + arguments[1]->getName() + "." , |
823 | ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); |
824 | |
825 | if (bitmap_type0->getArgumentsDataTypes()[0]->getTypeId() != bitmap_type1->getArgumentsDataTypes()[0]->getTypeId()) |
826 | throw Exception( |
827 | "The nested type in bitmaps must be the same, but one is " + bitmap_type0->getArgumentsDataTypes()[0]->getName() |
828 | + ", and the other is " + bitmap_type1->getArgumentsDataTypes()[0]->getName(), |
829 | ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); |
830 | |
831 | return std::make_shared<DataTypeNumber<ToType>>(); |
832 | } |
833 | |
834 | bool useDefaultImplementationForConstants() const override { return true; } |
835 | |
836 | void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) override |
837 | { |
838 | auto col_to = ColumnVector<ToType>::create(input_rows_count); |
839 | typename ColumnVector<ToType>::Container & vec_to = col_to->getData(); |
840 | const IDataType * from_type = block.getByPosition(arguments[0]).type.get(); |
841 | |
842 | const DataTypeAggregateFunction * aggr_type = typeid_cast<const DataTypeAggregateFunction *>(from_type); |
843 | WhichDataType which(aggr_type->getArgumentsDataTypes()[0]); |
844 | if (which.isUInt8()) |
845 | executeIntType<UInt8>(block, arguments, input_rows_count, vec_to); |
846 | else if (which.isUInt16()) |
847 | executeIntType<UInt16>(block, arguments, input_rows_count, vec_to); |
848 | else if (which.isUInt32()) |
849 | executeIntType<UInt32>(block, arguments, input_rows_count, vec_to); |
850 | else if (which.isUInt64()) |
851 | executeIntType<UInt64>(block, arguments, input_rows_count, vec_to); |
852 | else |
853 | throw Exception( |
854 | "Unexpected type " + from_type->getName() + " of argument of function " + getName(), ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); |
855 | |
856 | block.getByPosition(result).column = std::move(col_to); |
857 | } |
858 | |
859 | private: |
860 | template <typename T> |
861 | void executeIntType( |
862 | Block & block, const ColumnNumbers & arguments, size_t input_rows_count, typename ColumnVector<ToType>::Container & vec_to) |
863 | { |
864 | const ColumnAggregateFunction * columns[2]; |
865 | bool is_column_const[2]; |
866 | for (size_t i = 0; i < 2; ++i) |
867 | { |
868 | if (auto argument_column_const = checkAndGetColumn<ColumnConst>(block.getByPosition(arguments[i]).column.get())) |
869 | { |
870 | columns[i] = typeid_cast<const ColumnAggregateFunction*>(argument_column_const->getDataColumnPtr().get()); |
871 | is_column_const[i] = true; |
872 | } |
873 | else |
874 | { |
875 | columns[i] = typeid_cast<const ColumnAggregateFunction*>(block.getByPosition(arguments[i]).column.get()); |
876 | is_column_const[i] = false; |
877 | } |
878 | } |
879 | |
880 | const PaddedPODArray<AggregateDataPtr> & container0 = columns[0]->getData(); |
881 | const PaddedPODArray<AggregateDataPtr> & container1 = columns[1]->getData(); |
882 | |
883 | for (size_t i = 0; i < input_rows_count; ++i) |
884 | { |
885 | const AggregateDataPtr data_ptr_0 = is_column_const[0] ? container0[0] : container0[i]; |
886 | const AggregateDataPtr data_ptr_1 = is_column_const[1] ? container1[0] : container1[i]; |
887 | const AggregateFunctionGroupBitmapData<T> & bitmap_data_1 |
888 | = *reinterpret_cast<const AggregateFunctionGroupBitmapData<T> *>(data_ptr_0); |
889 | const AggregateFunctionGroupBitmapData<T> & bitmap_data_2 |
890 | = *reinterpret_cast<const AggregateFunctionGroupBitmapData<T> *>(data_ptr_1); |
891 | vec_to[i] = Impl<T>::apply(bitmap_data_1, bitmap_data_2); |
892 | } |
893 | } |
894 | }; |
895 | |
896 | template <typename T> |
897 | struct BitmapAndImpl |
898 | { |
899 | static void apply(AggregateFunctionGroupBitmapData<T> & bitmap_data_1, const AggregateFunctionGroupBitmapData<T> & bitmap_data_2) |
900 | { |
901 | bitmap_data_1.rbs.rb_and(bitmap_data_2.rbs); |
902 | } |
903 | }; |
904 | |
905 | template <typename T> |
906 | struct BitmapOrImpl |
907 | { |
908 | static void apply(AggregateFunctionGroupBitmapData<T> & bitmap_data_1, const AggregateFunctionGroupBitmapData<T> & bitmap_data_2) |
909 | { |
910 | bitmap_data_1.rbs.rb_or(bitmap_data_2.rbs); |
911 | } |
912 | }; |
913 | |
914 | template <typename T> |
915 | struct BitmapXorImpl |
916 | { |
917 | static void apply(AggregateFunctionGroupBitmapData<T> & bitmap_data_1, const AggregateFunctionGroupBitmapData<T> & bitmap_data_2) |
918 | { |
919 | bitmap_data_1.rbs.rb_xor(bitmap_data_2.rbs); |
920 | } |
921 | }; |
922 | |
923 | template <typename T> |
924 | struct BitmapAndnotImpl |
925 | { |
926 | static void apply(AggregateFunctionGroupBitmapData<T> & bitmap_data_1, const AggregateFunctionGroupBitmapData<T> & bitmap_data_2) |
927 | { |
928 | bitmap_data_1.rbs.rb_andnot(bitmap_data_2.rbs); |
929 | } |
930 | }; |
931 | |
932 | template <template <typename> class Impl, typename Name> |
933 | class FunctionBitmap : public IFunction |
934 | { |
935 | public: |
936 | static constexpr auto name = Name::name; |
937 | |
938 | static FunctionPtr create(const Context &) { return std::make_shared<FunctionBitmap>(); } |
939 | |
940 | String getName() const override { return name; } |
941 | |
942 | bool isVariadic() const override { return false; } |
943 | |
944 | size_t getNumberOfArguments() const override { return 2; } |
945 | |
946 | DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override |
947 | { |
948 | auto bitmap_type0 = typeid_cast<const DataTypeAggregateFunction *>(arguments[0].get()); |
949 | if (!(bitmap_type0 && bitmap_type0->getFunctionName() == AggregateFunctionGroupBitmapData<UInt32>::name())) |
950 | throw Exception( |
951 | "First argument for function " + getName() + " must be a bitmap but it has type " + arguments[0]->getName() + "." , |
952 | ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); |
953 | |
954 | auto bitmap_type1 = typeid_cast<const DataTypeAggregateFunction *>(arguments[1].get()); |
955 | if (!(bitmap_type1 && bitmap_type1->getFunctionName() == AggregateFunctionGroupBitmapData<UInt32>::name())) |
956 | throw Exception( |
957 | "Second argument for function " + getName() + " must be a bitmap but it has type " + arguments[1]->getName() + "." , |
958 | ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); |
959 | |
960 | if (bitmap_type0->getArgumentsDataTypes()[0]->getTypeId() != bitmap_type1->getArgumentsDataTypes()[0]->getTypeId()) |
961 | throw Exception( |
962 | "The nested type in bitmaps must be the same, but one is " + bitmap_type0->getArgumentsDataTypes()[0]->getName() |
963 | + ", and the other is " + bitmap_type1->getArgumentsDataTypes()[0]->getName(), |
964 | ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); |
965 | |
966 | return arguments[0]; |
967 | } |
968 | |
969 | bool useDefaultImplementationForConstants() const override { return true; } |
970 | |
971 | void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) override |
972 | { |
973 | const IDataType * from_type = block.getByPosition(arguments[0]).type.get(); |
974 | const DataTypeAggregateFunction * aggr_type = typeid_cast<const DataTypeAggregateFunction *>(from_type); |
975 | WhichDataType which(aggr_type->getArgumentsDataTypes()[0]); |
976 | if (which.isUInt8()) |
977 | executeBitmapData<UInt8>(block, arguments, result, input_rows_count); |
978 | else if (which.isUInt16()) |
979 | executeBitmapData<UInt16>(block, arguments, result, input_rows_count); |
980 | else if (which.isUInt32()) |
981 | executeBitmapData<UInt32>(block, arguments, result, input_rows_count); |
982 | else if (which.isUInt64()) |
983 | executeBitmapData<UInt64>(block, arguments, result, input_rows_count); |
984 | else |
985 | throw Exception( |
986 | "Unexpected type " + from_type->getName() + " of argument of function " + getName(), ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); |
987 | } |
988 | |
989 | private: |
990 | template <typename T> |
991 | void executeBitmapData(Block & block, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) |
992 | { |
993 | const ColumnAggregateFunction * columns[2]; |
994 | bool is_column_const[2]; |
995 | for (size_t i = 0; i < 2; ++i) |
996 | { |
997 | if (auto argument_column_const = typeid_cast<const ColumnConst *>(block.getByPosition(arguments[i]).column.get())) |
998 | { |
999 | columns[i] = typeid_cast<const ColumnAggregateFunction *>(argument_column_const->getDataColumnPtr().get()); |
1000 | is_column_const[i] = true; |
1001 | } |
1002 | else |
1003 | { |
1004 | columns[i] = typeid_cast<const ColumnAggregateFunction *>(block.getByPosition(arguments[i]).column.get()); |
1005 | is_column_const[i] = false; |
1006 | } |
1007 | } |
1008 | |
1009 | auto col_to = ColumnAggregateFunction::create(columns[0]->getAggregateFunction()); |
1010 | |
1011 | col_to->reserve(input_rows_count); |
1012 | |
1013 | const PaddedPODArray<AggregateDataPtr> & container0 = columns[0]->getData(); |
1014 | const PaddedPODArray<AggregateDataPtr> & container1 = columns[1]->getData(); |
1015 | |
1016 | for (size_t i = 0; i < input_rows_count; ++i) |
1017 | { |
1018 | const AggregateDataPtr data_ptr_0 = is_column_const[0] ? container0[0] : container0[i]; |
1019 | const AggregateDataPtr data_ptr_1 = is_column_const[1] ? container1[0] : container1[i]; |
1020 | |
1021 | col_to->insertFrom(data_ptr_0); |
1022 | AggregateFunctionGroupBitmapData<T> & bitmap_data_1 = *reinterpret_cast<AggregateFunctionGroupBitmapData<T> *>(col_to->getData()[i]); |
1023 | const AggregateFunctionGroupBitmapData<T> & bitmap_data_2 |
1024 | = *reinterpret_cast<const AggregateFunctionGroupBitmapData<T> *>(data_ptr_1); |
1025 | Impl<T>::apply(bitmap_data_1, bitmap_data_2); |
1026 | } |
1027 | block.getByPosition(result).column = std::move(col_to); |
1028 | } |
1029 | }; |
1030 | |
1031 | struct NameBitmapBuild |
1032 | { |
1033 | static constexpr auto name = "bitmapBuild" ; |
1034 | }; |
1035 | using FunctionBitmapBuild = FunctionBitmapBuildImpl<NameBitmapBuild>; |
1036 | |
1037 | struct NameBitmapToArray |
1038 | { |
1039 | static constexpr auto name = "bitmapToArray" ; |
1040 | }; |
1041 | using FunctionBitmapToArray = FunctionBitmapToArrayImpl<NameBitmapToArray>; |
1042 | |
1043 | struct NameBitmapCardinality |
1044 | { |
1045 | static constexpr auto name = "bitmapCardinality" ; |
1046 | }; |
1047 | struct NameBitmapAndCardinality |
1048 | { |
1049 | static constexpr auto name = "bitmapAndCardinality" ; |
1050 | }; |
1051 | struct NameBitmapOrCardinality |
1052 | { |
1053 | static constexpr auto name = "bitmapOrCardinality" ; |
1054 | }; |
1055 | struct NameBitmapXorCardinality |
1056 | { |
1057 | static constexpr auto name = "bitmapXorCardinality" ; |
1058 | }; |
1059 | struct NameBitmapAndnotCardinality |
1060 | { |
1061 | static constexpr auto name = "bitmapAndnotCardinality" ; |
1062 | }; |
1063 | struct NameBitmapHasAll |
1064 | { |
1065 | static constexpr auto name = "bitmapHasAll" ; |
1066 | }; |
1067 | struct NameBitmapHasAny |
1068 | { |
1069 | static constexpr auto name = "bitmapHasAny" ; |
1070 | }; |
1071 | |
1072 | using FunctionBitmapSelfCardinality = FunctionBitmapSelfCardinalityImpl<BitmapCardinalityImpl>; |
1073 | using FunctionBitmapMin = FunctionBitmapSelfCardinalityImpl<BitmapMinImpl>; |
1074 | using FunctionBitmapMax = FunctionBitmapSelfCardinalityImpl<BitmapMaxImpl>; |
1075 | using FunctionBitmapAndCardinality = FunctionBitmapCardinality<BitmapAndCardinalityImpl, NameBitmapAndCardinality, UInt64>; |
1076 | using FunctionBitmapOrCardinality = FunctionBitmapCardinality<BitmapOrCardinalityImpl, NameBitmapOrCardinality, UInt64>; |
1077 | using FunctionBitmapXorCardinality = FunctionBitmapCardinality<BitmapXorCardinalityImpl, NameBitmapXorCardinality, UInt64>; |
1078 | using FunctionBitmapAndnotCardinality = FunctionBitmapCardinality<BitmapAndnotCardinalityImpl, NameBitmapAndnotCardinality, UInt64>; |
1079 | using FunctionBitmapHasAll = FunctionBitmapCardinality<BitmapHasAllImpl, NameBitmapHasAll, UInt8>; |
1080 | using FunctionBitmapHasAny = FunctionBitmapCardinality<BitmapHasAnyImpl, NameBitmapHasAny, UInt8>; |
1081 | |
1082 | struct NameBitmapAnd |
1083 | { |
1084 | static constexpr auto name = "bitmapAnd" ; |
1085 | }; |
1086 | struct NameBitmapOr |
1087 | { |
1088 | static constexpr auto name = "bitmapOr" ; |
1089 | }; |
1090 | struct NameBitmapXor |
1091 | { |
1092 | static constexpr auto name = "bitmapXor" ; |
1093 | }; |
1094 | struct NameBitmapAndnot |
1095 | { |
1096 | static constexpr auto name = "bitmapAndnot" ; |
1097 | }; |
1098 | using FunctionBitmapAnd = FunctionBitmap<BitmapAndImpl, NameBitmapAnd>; |
1099 | using FunctionBitmapOr = FunctionBitmap<BitmapOrImpl, NameBitmapOr>; |
1100 | using FunctionBitmapXor = FunctionBitmap<BitmapXorImpl, NameBitmapXor>; |
1101 | using FunctionBitmapAndnot = FunctionBitmap<BitmapAndnotImpl, NameBitmapAndnot>; |
1102 | |
1103 | |
1104 | } |
1105 | |