be/src/exprs/aggregate/aggregate_function_state_union.h
Line | Count | Source |
1 | | // Licensed to the Apache Software Foundation (ASF) under one |
2 | | // or more contributor license agreements. See the NOTICE file |
3 | | // distributed with this work for additional information |
4 | | // regarding copyright ownership. The ASF licenses this file |
5 | | // to you under the Apache License, Version 2.0 (the |
6 | | // "License"); you may not use this file except in compliance |
7 | | // with the License. You may obtain a copy of the License at |
8 | | // |
9 | | // http://www.apache.org/licenses/LICENSE-2.0 |
10 | | // |
11 | | // Unless required by applicable law or agreed to in writing, |
12 | | // software distributed under the License is distributed on an |
13 | | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
14 | | // KIND, either express or implied. See the License for the |
15 | | // specific language governing permissions and limitations |
16 | | // under the License. |
17 | | |
18 | | #pragma once |
19 | | |
20 | | #include <utility> |
21 | | |
22 | | #include "core/data_type/data_type_agg_state.h" |
23 | | #include "exprs/aggregate/aggregate_function.h" |
24 | | |
25 | | namespace doris { |
26 | | const static std::string AGG_UNION_SUFFIX = "_union"; |
27 | | |
28 | | class AggregateStateUnion : public AggregateFunctionNonFinalBase, |
29 | | public IAggregateFunctionHelper<AggregateStateUnion> { |
30 | | public: |
31 | | AggregateStateUnion(AggregateFunctionPtr function, const DataTypes& argument_types_, |
32 | | DataTypePtr return_type) |
33 | 203 | : IAggregateFunctionHelper(argument_types_), |
34 | 203 | _function(std::move(function)), |
35 | 203 | _return_type(std::move(return_type)) {} |
36 | 203 | ~AggregateStateUnion() override = default; |
37 | | |
38 | | static AggregateFunctionPtr create(AggregateFunctionPtr function, |
39 | | const DataTypes& argument_types_, |
40 | 67 | const DataTypePtr& return_type) { |
41 | 67 | CHECK(argument_types_.size() == 1); |
42 | 67 | if (function == nullptr) { |
43 | 0 | return nullptr; |
44 | 0 | } |
45 | 67 | return std::make_shared<AggregateStateUnion>(function, argument_types_, return_type); |
46 | 67 | } |
47 | | |
48 | 0 | void set_version(const int version_) override { |
49 | 0 | IAggregateFunctionHelper::set_version(version_); |
50 | 0 | _function->set_version(version_); |
51 | 0 | } |
52 | | |
53 | 3.09k | void create(AggregateDataPtr __restrict place) const override { _function->create(place); } |
54 | | |
55 | 0 | String get_name() const override { return _function->get_name() + AGG_UNION_SUFFIX; } |
56 | | |
57 | 0 | DataTypePtr get_return_type() const override { return _return_type; } |
58 | | |
59 | | void add(AggregateDataPtr __restrict place, const IColumn** columns, ssize_t row_num, |
60 | 15 | Arena& arena) const override { |
61 | | //the range is [begin, end] |
62 | 15 | _function->deserialize_and_merge_from_column_range(place, *columns[0], row_num, row_num, |
63 | 15 | arena); |
64 | 15 | } |
65 | | |
66 | | void add_batch_single_place(size_t batch_size, AggregateDataPtr place, const IColumn** columns, |
67 | 4 | Arena& arena) const override { |
68 | 4 | _function->deserialize_and_merge_from_column_range(place, *columns[0], 0, batch_size - 1, |
69 | 4 | arena); |
70 | 4 | } |
71 | | |
72 | | void add_batch(size_t batch_size, AggregateDataPtr* places, size_t place_offset, |
73 | 644 | const IColumn** columns, Arena& arena, bool agg_many) const override { |
74 | 644 | add_batch_impl<false>(batch_size, places, place_offset, columns, arena); |
75 | 644 | } |
76 | | |
77 | | void add_batch_selected(size_t batch_size, AggregateDataPtr* places, size_t place_offset, |
78 | 896 | const IColumn** columns, Arena& arena) const override { |
79 | 896 | add_batch_impl<true>(batch_size, places, place_offset, columns, arena); |
80 | 896 | } |
81 | 14 | void reset(AggregateDataPtr place) const override { _function->reset(place); } |
82 | | |
83 | | void merge(AggregateDataPtr __restrict place, ConstAggregateDataPtr rhs, |
84 | 0 | Arena& arena) const override { |
85 | 0 | _function->merge(place, rhs, arena); |
86 | 0 | } |
87 | | |
88 | 0 | void serialize(ConstAggregateDataPtr __restrict place, BufferWritable& buf) const override { |
89 | 0 | _function->serialize(place, buf); |
90 | 0 | } |
91 | | |
92 | | void deserialize(AggregateDataPtr __restrict place, BufferReadable& buf, |
93 | 0 | Arena& arena) const override { |
94 | 0 | _function->deserialize(place, buf, arena); |
95 | 0 | } |
96 | | |
97 | 15 | void insert_result_into(ConstAggregateDataPtr __restrict place, IColumn& to) const override { |
98 | 15 | _function->serialize_without_key_to_column(place, to); |
99 | 15 | } |
100 | | |
101 | 3.09k | void destroy(AggregateDataPtr __restrict place) const noexcept override { |
102 | 3.09k | _function->destroy(place); |
103 | 3.09k | } |
104 | | |
105 | 0 | bool is_trivial() const override { return false; } |
106 | | |
107 | 3.60k | size_t size_of_data() const override { return _function->size_of_data(); } |
108 | | |
109 | 5.12k | size_t align_of_data() const override { return _function->align_of_data(); } |
110 | | |
111 | | private: |
112 | | template <bool selected> |
113 | | void add_batch_impl(size_t batch_size, AggregateDataPtr* places, size_t place_offset, |
114 | 1.54k | const IColumn** columns, Arena& arena) const { |
115 | | // Some batch implementations read the first serialized row before entering their loop. |
116 | 1.54k | if (batch_size == 0) { |
117 | 512 | return; |
118 | 512 | } |
119 | | // Delegate the whole batch so native state columns (e.g. SUM) can merge directly, |
120 | | // instead of dispatching through the range interface for every input row. |
121 | | // Generic implementations need aligned scratch states and manage their construction, |
122 | | // destruction and exception cleanup. Release only this storage after the batch; |
123 | | // keep passing the caller's arena for allocations that merged states may retain. |
124 | | // The function can be shared by evaluators, so scratch must not be a mutable member. |
125 | 1.02k | Arena scratch_arena; |
126 | 1.02k | AggregateDataPtr scratch = nullptr; |
127 | 1.02k | if (_function->needs_deserialize_and_merge_scratch()) { |
128 | 513 | scratch = scratch_arena.aligned_alloc(batch_size * _function->size_of_data(), |
129 | 513 | _function->align_of_data()); |
130 | 513 | } |
131 | 1.02k | if constexpr (selected) { |
132 | 640 | _function->deserialize_and_merge_vec_selected(places, place_offset, scratch, columns[0], |
133 | 640 | arena, batch_size); |
134 | 640 | } else { |
135 | 388 | _function->deserialize_and_merge_vec(places, place_offset, scratch, columns[0], arena, |
136 | 388 | batch_size); |
137 | 388 | } |
138 | 1.02k | } _ZNK5doris19AggregateStateUnion14add_batch_implILb0EEEvmPPcmPPKNS_7IColumnERNS_5ArenaE Line | Count | Source | 114 | 644 | const IColumn** columns, Arena& arena) const { | 115 | | // Some batch implementations read the first serialized row before entering their loop. | 116 | 644 | if (batch_size == 0) { | 117 | 256 | return; | 118 | 256 | } | 119 | | // Delegate the whole batch so native state columns (e.g. SUM) can merge directly, | 120 | | // instead of dispatching through the range interface for every input row. | 121 | | // Generic implementations need aligned scratch states and manage their construction, | 122 | | // destruction and exception cleanup. Release only this storage after the batch; | 123 | | // keep passing the caller's arena for allocations that merged states may retain. | 124 | | // The function can be shared by evaluators, so scratch must not be a mutable member. | 125 | 388 | Arena scratch_arena; | 126 | 388 | AggregateDataPtr scratch = nullptr; | 127 | 388 | if (_function->needs_deserialize_and_merge_scratch()) { | 128 | 193 | scratch = scratch_arena.aligned_alloc(batch_size * _function->size_of_data(), | 129 | 193 | _function->align_of_data()); | 130 | 193 | } | 131 | | if constexpr (selected) { | 132 | | _function->deserialize_and_merge_vec_selected(places, place_offset, scratch, columns[0], | 133 | | arena, batch_size); | 134 | 388 | } else { | 135 | 388 | _function->deserialize_and_merge_vec(places, place_offset, scratch, columns[0], arena, | 136 | 388 | batch_size); | 137 | 388 | } | 138 | 388 | } |
_ZNK5doris19AggregateStateUnion14add_batch_implILb1EEEvmPPcmPPKNS_7IColumnERNS_5ArenaE Line | Count | Source | 114 | 896 | const IColumn** columns, Arena& arena) const { | 115 | | // Some batch implementations read the first serialized row before entering their loop. | 116 | 896 | if (batch_size == 0) { | 117 | 256 | return; | 118 | 256 | } | 119 | | // Delegate the whole batch so native state columns (e.g. SUM) can merge directly, | 120 | | // instead of dispatching through the range interface for every input row. | 121 | | // Generic implementations need aligned scratch states and manage their construction, | 122 | | // destruction and exception cleanup. Release only this storage after the batch; | 123 | | // keep passing the caller's arena for allocations that merged states may retain. | 124 | | // The function can be shared by evaluators, so scratch must not be a mutable member. | 125 | 640 | Arena scratch_arena; | 126 | 640 | AggregateDataPtr scratch = nullptr; | 127 | 640 | if (_function->needs_deserialize_and_merge_scratch()) { | 128 | 320 | scratch = scratch_arena.aligned_alloc(batch_size * _function->size_of_data(), | 129 | 320 | _function->align_of_data()); | 130 | 320 | } | 131 | 640 | if constexpr (selected) { | 132 | 640 | _function->deserialize_and_merge_vec_selected(places, place_offset, scratch, columns[0], | 133 | 640 | arena, batch_size); | 134 | | } else { | 135 | | _function->deserialize_and_merge_vec(places, place_offset, scratch, columns[0], arena, | 136 | | batch_size); | 137 | | } | 138 | 640 | } |
|
139 | | |
140 | | protected: |
141 | | AggregateFunctionPtr _function; |
142 | | DataTypePtr _return_type; |
143 | | }; |
144 | | |
145 | | } // namespace doris |