1 | #include <AggregateFunctions/AggregateFunctionFactory.h> |
2 | #include <AggregateFunctions/Helpers.h> |
3 | #include <AggregateFunctions/AggregateFunctionUniqUpTo.h> |
4 | #include <DataTypes/DataTypeDate.h> |
5 | #include <DataTypes/DataTypeDateTime.h> |
6 | #include <DataTypes/DataTypeString.h> |
7 | #include <DataTypes/DataTypeFixedString.h> |
8 | #include "registerAggregateFunctions.h" |
9 | |
10 | |
11 | namespace DB |
12 | { |
13 | |
14 | namespace ErrorCodes |
15 | { |
16 | extern const int ILLEGAL_TYPE_OF_ARGUMENT; |
17 | extern const int NUMBER_OF_ARGUMENTS_DOESNT_MATCH; |
18 | extern const int ARGUMENT_OUT_OF_BOUND; |
19 | } |
20 | |
21 | |
22 | namespace |
23 | { |
24 | |
25 | static constexpr UInt8 uniq_upto_max_threshold = 100; |
26 | |
27 | |
28 | AggregateFunctionPtr createAggregateFunctionUniqUpTo(const std::string & name, const DataTypes & argument_types, const Array & params) |
29 | { |
30 | UInt8 threshold = 5; /// default value |
31 | |
32 | if (!params.empty()) |
33 | { |
34 | if (params.size() != 1) |
35 | throw Exception("Aggregate function " + name + " requires one parameter or less." , ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH); |
36 | |
37 | UInt64 threshold_param = applyVisitor(FieldVisitorConvertToNumber<UInt64>(), params[0]); |
38 | |
39 | if (threshold_param > uniq_upto_max_threshold) |
40 | throw Exception("Too large parameter for aggregate function " + name + ". Maximum: " + toString(uniq_upto_max_threshold), |
41 | ErrorCodes::ARGUMENT_OUT_OF_BOUND); |
42 | |
43 | threshold = threshold_param; |
44 | } |
45 | |
46 | if (argument_types.empty()) |
47 | throw Exception("Incorrect number of arguments for aggregate function " + name, |
48 | ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH); |
49 | |
50 | bool use_exact_hash_function = !isAllArgumentsContiguousInMemory(argument_types); |
51 | |
52 | if (argument_types.size() == 1) |
53 | { |
54 | const IDataType & argument_type = *argument_types[0]; |
55 | |
56 | AggregateFunctionPtr res(createWithNumericType<AggregateFunctionUniqUpTo>(*argument_types[0], threshold, argument_types, params)); |
57 | |
58 | WhichDataType which(argument_type); |
59 | if (res) |
60 | return res; |
61 | else if (which.isDate()) |
62 | return std::make_shared<AggregateFunctionUniqUpTo<DataTypeDate::FieldType>>(threshold, argument_types, params); |
63 | else if (which.isDateTime()) |
64 | return std::make_shared<AggregateFunctionUniqUpTo<DataTypeDateTime::FieldType>>(threshold, argument_types, params); |
65 | else if (which.isStringOrFixedString()) |
66 | return std::make_shared<AggregateFunctionUniqUpTo<String>>(threshold, argument_types, params); |
67 | else if (which.isUUID()) |
68 | return std::make_shared<AggregateFunctionUniqUpTo<DataTypeUUID::FieldType>>(threshold, argument_types, params); |
69 | else if (which.isTuple()) |
70 | { |
71 | if (use_exact_hash_function) |
72 | return std::make_shared<AggregateFunctionUniqUpToVariadic<true, true>>(argument_types, params, threshold); |
73 | else |
74 | return std::make_shared<AggregateFunctionUniqUpToVariadic<false, true>>(argument_types, params, threshold); |
75 | } |
76 | } |
77 | |
78 | /// "Variadic" method also works as a fallback generic case for single argument. |
79 | if (use_exact_hash_function) |
80 | return std::make_shared<AggregateFunctionUniqUpToVariadic<true, false>>(argument_types, params, threshold); |
81 | else |
82 | return std::make_shared<AggregateFunctionUniqUpToVariadic<false, false>>(argument_types, params, threshold); |
83 | } |
84 | |
85 | } |
86 | |
87 | void registerAggregateFunctionUniqUpTo(AggregateFunctionFactory & factory) |
88 | { |
89 | factory.registerFunction("uniqUpTo" , createAggregateFunctionUniqUpTo); |
90 | } |
91 | |
92 | } |
93 | |