1 | #pragma once |
2 | |
3 | #include <common/StringRef.h> |
4 | #include <DataTypes/IDataType.h> |
5 | #include <AggregateFunctions/IAggregateFunction.h> |
6 | #include <AggregateFunctions/AggregateFunctionMinMaxAny.h> // SingleValueDataString used in embedded compiler |
7 | |
8 | |
9 | namespace DB |
10 | { |
11 | |
12 | namespace ErrorCodes |
13 | { |
14 | extern const int ILLEGAL_TYPE_OF_ARGUMENT; |
15 | } |
16 | |
17 | |
18 | /// For possible values for template parameters, see AggregateFunctionMinMaxAny.h |
19 | template <typename ResultData, typename ValueData> |
20 | struct AggregateFunctionArgMinMaxData |
21 | { |
22 | using ResultData_t = ResultData; |
23 | using ValueData_t = ValueData; |
24 | |
25 | ResultData result; // the argument at which the minimum/maximum value is reached. |
26 | ValueData value; // value for which the minimum/maximum is calculated. |
27 | |
28 | static bool allocatesMemoryInArena() |
29 | { |
30 | return ResultData::allocatesMemoryInArena() || ValueData::allocatesMemoryInArena(); |
31 | } |
32 | }; |
33 | |
34 | /// Returns the first arg value found for the minimum/maximum value. Example: argMax(arg, value). |
35 | template <typename Data> |
36 | class AggregateFunctionArgMinMax final : public IAggregateFunctionDataHelper<Data, AggregateFunctionArgMinMax<Data>> |
37 | { |
38 | private: |
39 | const DataTypePtr & type_res; |
40 | const DataTypePtr & type_val; |
41 | |
42 | public: |
43 | AggregateFunctionArgMinMax(const DataTypePtr & type_res_, const DataTypePtr & type_val_) |
44 | : IAggregateFunctionDataHelper<Data, AggregateFunctionArgMinMax<Data>>({type_res_, type_val_}, {}), |
45 | type_res(this->argument_types[0]), type_val(this->argument_types[1]) |
46 | { |
47 | if (!type_val->isComparable()) |
48 | throw Exception("Illegal type " + type_val->getName() + " of second argument of aggregate function " + getName() |
49 | + " because the values of that data type are not comparable" , ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); |
50 | } |
51 | |
52 | String getName() const override { return StringRef(Data::ValueData_t::name()) == StringRef("min" ) ? "argMin" : "argMax" ; } |
53 | |
54 | DataTypePtr getReturnType() const override |
55 | { |
56 | return type_res; |
57 | } |
58 | |
59 | void add(AggregateDataPtr place, const IColumn ** columns, size_t row_num, Arena * arena) const override |
60 | { |
61 | if (this->data(place).value.changeIfBetter(*columns[1], row_num, arena)) |
62 | this->data(place).result.change(*columns[0], row_num, arena); |
63 | } |
64 | |
65 | void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena * arena) const override |
66 | { |
67 | if (this->data(place).value.changeIfBetter(this->data(rhs).value, arena)) |
68 | this->data(place).result.change(this->data(rhs).result, arena); |
69 | } |
70 | |
71 | void serialize(ConstAggregateDataPtr place, WriteBuffer & buf) const override |
72 | { |
73 | this->data(place).result.write(buf, *type_res); |
74 | this->data(place).value.write(buf, *type_val); |
75 | } |
76 | |
77 | void deserialize(AggregateDataPtr place, ReadBuffer & buf, Arena * arena) const override |
78 | { |
79 | this->data(place).result.read(buf, *type_res, arena); |
80 | this->data(place).value.read(buf, *type_val, arena); |
81 | } |
82 | |
83 | bool allocatesMemoryInArena() const override |
84 | { |
85 | return Data::allocatesMemoryInArena(); |
86 | } |
87 | |
88 | void insertResultInto(ConstAggregateDataPtr place, IColumn & to) const override |
89 | { |
90 | this->data(place).result.insertResultInto(to); |
91 | } |
92 | }; |
93 | |
94 | } |
95 | |