be/src/exprs/aggregate/aggregate_function_window_funnel.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 | | // This file is copied from |
19 | | // https://github.com/ClickHouse/ClickHouse/blob/master/AggregateFunctionWindowFunnel.h |
20 | | // and modified by Doris |
21 | | |
22 | | #pragma once |
23 | | |
24 | | #include <gen_cpp/data.pb.h> |
25 | | |
26 | | #include <algorithm> |
27 | | #include <boost/iterator/iterator_facade.hpp> |
28 | | #include <iterator> |
29 | | #include <memory> |
30 | | #include <type_traits> |
31 | | #include <utility> |
32 | | |
33 | | #include "common/cast_set.h" |
34 | | #include "common/exception.h" |
35 | | #include "common/status.h" |
36 | | #include "core/assert_cast.h" |
37 | | #include "core/binary_cast.hpp" |
38 | | #include "core/column/column_string.h" |
39 | | #include "core/column/column_vector.h" |
40 | | #include "core/data_type/data_type_number.h" |
41 | | #include "core/types.h" |
42 | | #include "core/value/vdatetime_value.h" |
43 | | #include "exec/sort/sort_block.h" |
44 | | #include "exprs/aggregate/aggregate_function.h" |
45 | | #include "util/simd/bits.h" |
46 | | #include "util/var_int.h" |
47 | | |
48 | | namespace doris { |
49 | | class Arena; |
50 | | class BufferReadable; |
51 | | class BufferWritable; |
52 | | class IColumn; |
53 | | } // namespace doris |
54 | | |
55 | | namespace doris { |
56 | | |
57 | | enum class WindowFunnelMode : Int64 { INVALID, DEFAULT, DEDUPLICATION, FIXED, INCREASE }; |
58 | | |
59 | 252 | inline WindowFunnelMode string_to_window_funnel_mode(const String& string) { |
60 | 252 | if (string == "default") { |
61 | 95 | return WindowFunnelMode::DEFAULT; |
62 | 157 | } else if (string == "deduplication") { |
63 | 36 | return WindowFunnelMode::DEDUPLICATION; |
64 | 121 | } else if (string == "fixed") { |
65 | 19 | return WindowFunnelMode::FIXED; |
66 | 102 | } else if (string == "increase") { |
67 | 18 | return WindowFunnelMode::INCREASE; |
68 | 84 | } else { |
69 | 84 | return WindowFunnelMode::INVALID; |
70 | 84 | } |
71 | 252 | } |
72 | | |
73 | | template <PrimitiveType T> |
74 | | struct DataValue { |
75 | | using TimestampEvent = std::vector<ColumnUInt8::Container>; |
76 | | using DateValueType = typename PrimitiveTypeTraits<T>::CppType; |
77 | | std::vector<DateValueType> dt; |
78 | | TimestampEvent event_columns_data; |
79 | | bool operator<(const DataValue& other) const { return dt < other.dt; } |
80 | 2 | void clear() { |
81 | 2 | dt.clear(); |
82 | 8 | for (auto& data : event_columns_data) { |
83 | 8 | data.clear(); |
84 | 8 | } |
85 | 2 | } _ZN5doris9DataValueILNS_13PrimitiveTypeE26EE5clearEv Line | Count | Source | 80 | 2 | void clear() { | 81 | 2 | dt.clear(); | 82 | 8 | for (auto& data : event_columns_data) { | 83 | 8 | data.clear(); | 84 | 8 | } | 85 | 2 | } |
Unexecuted instantiation: _ZN5doris9DataValueILNS_13PrimitiveTypeE42EE5clearEv |
86 | 72 | auto size() const { return dt.size(); }_ZNK5doris9DataValueILNS_13PrimitiveTypeE26EE4sizeEv Line | Count | Source | 86 | 72 | auto size() const { return dt.size(); } |
Unexecuted instantiation: _ZNK5doris9DataValueILNS_13PrimitiveTypeE42EE4sizeEv |
87 | 11 | bool empty() const { return dt.empty(); }_ZNK5doris9DataValueILNS_13PrimitiveTypeE26EE5emptyEv Line | Count | Source | 87 | 11 | bool empty() const { return dt.empty(); } |
Unexecuted instantiation: _ZNK5doris9DataValueILNS_13PrimitiveTypeE42EE5emptyEv |
88 | | std::string debug_string() const { |
89 | | std::string result = "\n" + std::to_string(dt.size()) + " " + |
90 | | std::to_string(event_columns_data[0].size()) + "\n"; |
91 | | for (size_t i = 0; i < dt.size(); ++i) { |
92 | | result += dt[i].debug_string() + " ,"; |
93 | | for (const auto& event : event_columns_data) { |
94 | | result += std::to_string(event[i]) + ","; |
95 | | } |
96 | | result += "\n"; |
97 | | } |
98 | | return result; |
99 | | } |
100 | | }; |
101 | | |
102 | | template <PrimitiveType T> |
103 | | struct WindowFunnelState { |
104 | | static constexpr PrimitiveType PType = T; |
105 | | using NativeType = typename PrimitiveTypeTraits<T>::StorageFieldType; |
106 | | using DateValueType = typename PrimitiveTypeTraits<T>::CppType; |
107 | | int event_count = 0; |
108 | | int64_t window; |
109 | | bool enable_mode; |
110 | | WindowFunnelMode window_funnel_mode; |
111 | | DataValue<T> events_list; |
112 | | |
113 | 34 | WindowFunnelState() { |
114 | 34 | event_count = 0; |
115 | 34 | window = 0; |
116 | 34 | window_funnel_mode = WindowFunnelMode::INVALID; |
117 | 34 | } _ZN5doris17WindowFunnelStateILNS_13PrimitiveTypeE26EEC2Ev Line | Count | Source | 113 | 34 | WindowFunnelState() { | 114 | 34 | event_count = 0; | 115 | 34 | window = 0; | 116 | 34 | window_funnel_mode = WindowFunnelMode::INVALID; | 117 | 34 | } |
Unexecuted instantiation: _ZN5doris17WindowFunnelStateILNS_13PrimitiveTypeE42EEC2Ev |
118 | 34 | WindowFunnelState(int arg_event_count) : WindowFunnelState() { |
119 | 34 | event_count = arg_event_count; |
120 | 34 | events_list.event_columns_data.resize(event_count); |
121 | 34 | } _ZN5doris17WindowFunnelStateILNS_13PrimitiveTypeE26EEC2Ei Line | Count | Source | 118 | 34 | WindowFunnelState(int arg_event_count) : WindowFunnelState() { | 119 | 34 | event_count = arg_event_count; | 120 | 34 | events_list.event_columns_data.resize(event_count); | 121 | 34 | } |
Unexecuted instantiation: _ZN5doris17WindowFunnelStateILNS_13PrimitiveTypeE42EEC2Ei |
122 | | |
123 | 0 | void reset() { events_list.clear(); }Unexecuted instantiation: _ZN5doris17WindowFunnelStateILNS_13PrimitiveTypeE26EE5resetEv Unexecuted instantiation: _ZN5doris17WindowFunnelStateILNS_13PrimitiveTypeE42EE5resetEv |
124 | | |
125 | 84 | void add(const IColumn** arg_columns, ssize_t row_num, int64_t win, WindowFunnelMode mode) { |
126 | 84 | window = win; |
127 | 84 | window_funnel_mode = enable_mode ? mode : WindowFunnelMode::DEFAULT; |
128 | 84 | events_list.dt.emplace_back( |
129 | 84 | assert_cast<const typename PrimitiveTypeTraits<PType>::ColumnType&, |
130 | 84 | TypeCheckOnRelease::DISABLE>(*arg_columns[2]) |
131 | 84 | .get_data()[row_num]); |
132 | 420 | for (int i = 0; i < event_count; i++) { |
133 | 336 | events_list.event_columns_data[i].emplace_back( |
134 | 336 | assert_cast<const ColumnUInt8&, TypeCheckOnRelease::DISABLE>( |
135 | 336 | *arg_columns[3 + i]) |
136 | 336 | .get_data()[row_num]); |
137 | 336 | } |
138 | 84 | } _ZN5doris17WindowFunnelStateILNS_13PrimitiveTypeE26EE3addEPPKNS_7IColumnEllNS_16WindowFunnelModeE Line | Count | Source | 125 | 84 | void add(const IColumn** arg_columns, ssize_t row_num, int64_t win, WindowFunnelMode mode) { | 126 | 84 | window = win; | 127 | 84 | window_funnel_mode = enable_mode ? mode : WindowFunnelMode::DEFAULT; | 128 | 84 | events_list.dt.emplace_back( | 129 | 84 | assert_cast<const typename PrimitiveTypeTraits<PType>::ColumnType&, | 130 | 84 | TypeCheckOnRelease::DISABLE>(*arg_columns[2]) | 131 | 84 | .get_data()[row_num]); | 132 | 420 | for (int i = 0; i < event_count; i++) { | 133 | 336 | events_list.event_columns_data[i].emplace_back( | 134 | 336 | assert_cast<const ColumnUInt8&, TypeCheckOnRelease::DISABLE>( | 135 | 336 | *arg_columns[3 + i]) | 136 | 336 | .get_data()[row_num]); | 137 | 336 | } | 138 | 84 | } |
Unexecuted instantiation: _ZN5doris17WindowFunnelStateILNS_13PrimitiveTypeE42EE3addEPPKNS_7IColumnEllNS_16WindowFunnelModeE |
139 | | |
140 | | // todo: rethink thid sort method. |
141 | 24 | void sort() { |
142 | 24 | auto num = events_list.size(); |
143 | 24 | std::vector<size_t> indices(num); |
144 | 24 | std::iota(indices.begin(), indices.end(), 0); |
145 | 24 | std::sort(indices.begin(), indices.end(), |
146 | 102 | [this](size_t i1, size_t i2) { return events_list.dt[i1] < events_list.dt[i2]; });_ZZN5doris17WindowFunnelStateILNS_13PrimitiveTypeE26EE4sortEvENKUlmmE_clEmm Line | Count | Source | 146 | 102 | [this](size_t i1, size_t i2) { return events_list.dt[i1] < events_list.dt[i2]; }); |
Unexecuted instantiation: _ZZN5doris17WindowFunnelStateILNS_13PrimitiveTypeE42EE4sortEvENKUlmmE_clEmm |
147 | | |
148 | 120 | auto reorder = [&indices, &num](auto& vec) { |
149 | 120 | std::decay_t<decltype(vec)> temp; |
150 | 120 | temp.resize(num); |
151 | 560 | for (auto i = 0; i < num; i++) { |
152 | 440 | temp[i] = vec[indices[i]]; |
153 | 440 | } |
154 | 120 | std::swap(vec, temp); |
155 | 120 | }; _ZZN5doris17WindowFunnelStateILNS_13PrimitiveTypeE26EE4sortEvENKUlRT_E_clISt6vectorINS_11DateV2ValueINS_19DateTimeV2ValueTypeEEESaISA_EEEEDaS4_ Line | Count | Source | 148 | 24 | auto reorder = [&indices, &num](auto& vec) { | 149 | 24 | std::decay_t<decltype(vec)> temp; | 150 | 24 | temp.resize(num); | 151 | 112 | for (auto i = 0; i < num; i++) { | 152 | 88 | temp[i] = vec[indices[i]]; | 153 | 88 | } | 154 | 24 | std::swap(vec, temp); | 155 | 24 | }; |
_ZZN5doris17WindowFunnelStateILNS_13PrimitiveTypeE26EE4sortEvENKUlRT_E_clINS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEEEEDaS4_ Line | Count | Source | 148 | 96 | auto reorder = [&indices, &num](auto& vec) { | 149 | 96 | std::decay_t<decltype(vec)> temp; | 150 | 96 | temp.resize(num); | 151 | 448 | for (auto i = 0; i < num; i++) { | 152 | 352 | temp[i] = vec[indices[i]]; | 153 | 352 | } | 154 | 96 | std::swap(vec, temp); | 155 | 96 | }; |
Unexecuted instantiation: _ZZN5doris17WindowFunnelStateILNS_13PrimitiveTypeE42EE4sortEvENKUlRT_E_clISt6vectorINS_16TimestampTzValueESaIS8_EEEEDaS4_ Unexecuted instantiation: _ZZN5doris17WindowFunnelStateILNS_13PrimitiveTypeE42EE4sortEvENKUlRT_E_clINS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEEEEDaS4_ |
156 | | |
157 | 24 | reorder(events_list.dt); |
158 | 96 | for (auto& inner_vec : events_list.event_columns_data) { |
159 | 96 | reorder(inner_vec); |
160 | 96 | } |
161 | 24 | } _ZN5doris17WindowFunnelStateILNS_13PrimitiveTypeE26EE4sortEv Line | Count | Source | 141 | 24 | void sort() { | 142 | 24 | auto num = events_list.size(); | 143 | 24 | std::vector<size_t> indices(num); | 144 | 24 | std::iota(indices.begin(), indices.end(), 0); | 145 | 24 | std::sort(indices.begin(), indices.end(), | 146 | 24 | [this](size_t i1, size_t i2) { return events_list.dt[i1] < events_list.dt[i2]; }); | 147 | | | 148 | 24 | auto reorder = [&indices, &num](auto& vec) { | 149 | 24 | std::decay_t<decltype(vec)> temp; | 150 | 24 | temp.resize(num); | 151 | 24 | for (auto i = 0; i < num; i++) { | 152 | 24 | temp[i] = vec[indices[i]]; | 153 | 24 | } | 154 | 24 | std::swap(vec, temp); | 155 | 24 | }; | 156 | | | 157 | 24 | reorder(events_list.dt); | 158 | 96 | for (auto& inner_vec : events_list.event_columns_data) { | 159 | 96 | reorder(inner_vec); | 160 | 96 | } | 161 | 24 | } |
Unexecuted instantiation: _ZN5doris17WindowFunnelStateILNS_13PrimitiveTypeE42EE4sortEv |
162 | | |
163 | | template <WindowFunnelMode WINDOW_FUNNEL_MODE> |
164 | 36 | int _match_event_list(size_t& start_row, size_t row_count) const { |
165 | 36 | int matched_count = 0; |
166 | 36 | DateValueType end_timestamp; |
167 | | |
168 | 36 | if (window < 0) { |
169 | 0 | throw Exception(ErrorCode::INVALID_ARGUMENT, |
170 | 0 | "the sliding time window must be a positive integer, but got: {}", |
171 | 0 | window); |
172 | 0 | } |
173 | 36 | TimeInterval interval(SECOND, window, false); |
174 | 36 | int column_idx = 0; |
175 | 36 | const auto& timestamp_data = events_list.dt; |
176 | 36 | const auto& first_event_data = events_list.event_columns_data[column_idx].data(); |
177 | 36 | auto match_row = simd::find_one(first_event_data, start_row, row_count); |
178 | 36 | start_row = match_row + 1; |
179 | 36 | if (match_row < row_count) { |
180 | 22 | auto prev_timestamp = timestamp_data[match_row]; |
181 | 22 | end_timestamp = prev_timestamp; |
182 | 22 | end_timestamp.template date_add_interval<SECOND>(interval); |
183 | | |
184 | 22 | matched_count++; |
185 | 22 | column_idx++; |
186 | 22 | auto last_match_row = match_row; |
187 | 22 | ++match_row; |
188 | 62 | for (; column_idx < event_count && match_row < row_count; column_idx++, match_row++) { |
189 | 54 | const auto& event_data = events_list.event_columns_data[column_idx]; |
190 | 54 | if constexpr (WINDOW_FUNNEL_MODE == WindowFunnelMode::FIXED) { |
191 | 0 | if (event_data[match_row] == 1) { |
192 | 0 | auto current_timestamp = timestamp_data[match_row]; |
193 | 0 | if (current_timestamp <= end_timestamp) { |
194 | 0 | matched_count++; |
195 | 0 | continue; |
196 | 0 | } |
197 | 0 | } |
198 | 0 | break; |
199 | 0 | } |
200 | 0 | match_row = simd::find_one(event_data.data(), match_row, row_count); |
201 | 54 | if (match_row < row_count) { |
202 | 54 | auto current_timestamp = timestamp_data[match_row]; |
203 | 54 | bool is_matched = current_timestamp <= end_timestamp; |
204 | 54 | if (is_matched) { |
205 | 40 | if constexpr (WINDOW_FUNNEL_MODE == WindowFunnelMode::INCREASE) { |
206 | 0 | is_matched = current_timestamp > prev_timestamp; |
207 | 0 | } |
208 | 40 | } |
209 | 54 | if (!is_matched) { |
210 | 14 | break; |
211 | 14 | } |
212 | 40 | if constexpr (WINDOW_FUNNEL_MODE == WindowFunnelMode::INCREASE) { |
213 | 0 | prev_timestamp = timestamp_data[match_row]; |
214 | 0 | } |
215 | 40 | if constexpr (WINDOW_FUNNEL_MODE == WindowFunnelMode::DEDUPLICATION) { |
216 | 0 | bool is_dup = false; |
217 | 0 | if (match_row != last_match_row + 1) { |
218 | 0 | for (int tmp_column_idx = 0; tmp_column_idx < column_idx; |
219 | 0 | tmp_column_idx++) { |
220 | 0 | const auto& tmp_event_data = |
221 | 0 | events_list.event_columns_data[tmp_column_idx].data(); |
222 | 0 | auto dup_match_row = simd::find_one(tmp_event_data, |
223 | 0 | last_match_row + 1, match_row); |
224 | 0 | if (dup_match_row < match_row) { |
225 | 0 | is_dup = true; |
226 | 0 | break; |
227 | 0 | } |
228 | 0 | } |
229 | 0 | } |
230 | 0 | if (is_dup) { |
231 | 0 | break; |
232 | 0 | } |
233 | 0 | last_match_row = match_row; |
234 | 0 | } |
235 | 0 | matched_count++; |
236 | 40 | } else { |
237 | 0 | break; |
238 | 0 | } |
239 | 54 | } |
240 | 22 | } |
241 | 0 | return matched_count; |
242 | 0 | } _ZNK5doris17WindowFunnelStateILNS_13PrimitiveTypeE26EE17_match_event_listILNS_16WindowFunnelModeE1EEEiRmm Line | Count | Source | 164 | 36 | int _match_event_list(size_t& start_row, size_t row_count) const { | 165 | 36 | int matched_count = 0; | 166 | 36 | DateValueType end_timestamp; | 167 | | | 168 | 36 | if (window < 0) { | 169 | 0 | throw Exception(ErrorCode::INVALID_ARGUMENT, | 170 | 0 | "the sliding time window must be a positive integer, but got: {}", | 171 | 0 | window); | 172 | 0 | } | 173 | 36 | TimeInterval interval(SECOND, window, false); | 174 | 36 | int column_idx = 0; | 175 | 36 | const auto& timestamp_data = events_list.dt; | 176 | 36 | const auto& first_event_data = events_list.event_columns_data[column_idx].data(); | 177 | 36 | auto match_row = simd::find_one(first_event_data, start_row, row_count); | 178 | 36 | start_row = match_row + 1; | 179 | 36 | if (match_row < row_count) { | 180 | 22 | auto prev_timestamp = timestamp_data[match_row]; | 181 | 22 | end_timestamp = prev_timestamp; | 182 | 22 | end_timestamp.template date_add_interval<SECOND>(interval); | 183 | | | 184 | 22 | matched_count++; | 185 | 22 | column_idx++; | 186 | 22 | auto last_match_row = match_row; | 187 | 22 | ++match_row; | 188 | 62 | for (; column_idx < event_count && match_row < row_count; column_idx++, match_row++) { | 189 | 54 | const auto& event_data = events_list.event_columns_data[column_idx]; | 190 | | if constexpr (WINDOW_FUNNEL_MODE == WindowFunnelMode::FIXED) { | 191 | | if (event_data[match_row] == 1) { | 192 | | auto current_timestamp = timestamp_data[match_row]; | 193 | | if (current_timestamp <= end_timestamp) { | 194 | | matched_count++; | 195 | | continue; | 196 | | } | 197 | | } | 198 | | break; | 199 | | } | 200 | 54 | match_row = simd::find_one(event_data.data(), match_row, row_count); | 201 | 54 | if (match_row < row_count) { | 202 | 54 | auto current_timestamp = timestamp_data[match_row]; | 203 | 54 | bool is_matched = current_timestamp <= end_timestamp; | 204 | 54 | if (is_matched) { | 205 | | if constexpr (WINDOW_FUNNEL_MODE == WindowFunnelMode::INCREASE) { | 206 | | is_matched = current_timestamp > prev_timestamp; | 207 | | } | 208 | 40 | } | 209 | 54 | if (!is_matched) { | 210 | 14 | break; | 211 | 14 | } | 212 | | if constexpr (WINDOW_FUNNEL_MODE == WindowFunnelMode::INCREASE) { | 213 | | prev_timestamp = timestamp_data[match_row]; | 214 | | } | 215 | | if constexpr (WINDOW_FUNNEL_MODE == WindowFunnelMode::DEDUPLICATION) { | 216 | | bool is_dup = false; | 217 | | if (match_row != last_match_row + 1) { | 218 | | for (int tmp_column_idx = 0; tmp_column_idx < column_idx; | 219 | | tmp_column_idx++) { | 220 | | const auto& tmp_event_data = | 221 | | events_list.event_columns_data[tmp_column_idx].data(); | 222 | | auto dup_match_row = simd::find_one(tmp_event_data, | 223 | | last_match_row + 1, match_row); | 224 | | if (dup_match_row < match_row) { | 225 | | is_dup = true; | 226 | | break; | 227 | | } | 228 | | } | 229 | | } | 230 | | if (is_dup) { | 231 | | break; | 232 | | } | 233 | | last_match_row = match_row; | 234 | | } | 235 | 40 | matched_count++; | 236 | 40 | } else { | 237 | 0 | break; | 238 | 0 | } | 239 | 54 | } | 240 | 22 | } | 241 | 36 | return matched_count; | 242 | 36 | } |
Unexecuted instantiation: _ZNK5doris17WindowFunnelStateILNS_13PrimitiveTypeE26EE17_match_event_listILNS_16WindowFunnelModeE2EEEiRmm Unexecuted instantiation: _ZNK5doris17WindowFunnelStateILNS_13PrimitiveTypeE26EE17_match_event_listILNS_16WindowFunnelModeE3EEEiRmm Unexecuted instantiation: _ZNK5doris17WindowFunnelStateILNS_13PrimitiveTypeE26EE17_match_event_listILNS_16WindowFunnelModeE4EEEiRmm Unexecuted instantiation: _ZNK5doris17WindowFunnelStateILNS_13PrimitiveTypeE42EE17_match_event_listILNS_16WindowFunnelModeE1EEEiRmm Unexecuted instantiation: _ZNK5doris17WindowFunnelStateILNS_13PrimitiveTypeE42EE17_match_event_listILNS_16WindowFunnelModeE2EEEiRmm Unexecuted instantiation: _ZNK5doris17WindowFunnelStateILNS_13PrimitiveTypeE42EE17_match_event_listILNS_16WindowFunnelModeE3EEEiRmm Unexecuted instantiation: _ZNK5doris17WindowFunnelStateILNS_13PrimitiveTypeE42EE17_match_event_listILNS_16WindowFunnelModeE4EEEiRmm |
243 | | |
244 | | template <WindowFunnelMode WINDOW_FUNNEL_MODE> |
245 | 22 | int _get_internal() const { |
246 | 22 | size_t start_row = 0; |
247 | 22 | int max_found_event_count = 0; |
248 | 22 | auto row_count = events_list.size(); |
249 | 50 | while (start_row < row_count) { |
250 | 36 | auto found_event_count = _match_event_list<WINDOW_FUNNEL_MODE>(start_row, row_count); |
251 | 36 | if (found_event_count == event_count) { |
252 | 8 | return found_event_count; |
253 | 8 | } |
254 | 28 | max_found_event_count = std::max(max_found_event_count, found_event_count); |
255 | 28 | } |
256 | 14 | return max_found_event_count; |
257 | 22 | } _ZNK5doris17WindowFunnelStateILNS_13PrimitiveTypeE26EE13_get_internalILNS_16WindowFunnelModeE1EEEiv Line | Count | Source | 245 | 22 | int _get_internal() const { | 246 | 22 | size_t start_row = 0; | 247 | 22 | int max_found_event_count = 0; | 248 | 22 | auto row_count = events_list.size(); | 249 | 50 | while (start_row < row_count) { | 250 | 36 | auto found_event_count = _match_event_list<WINDOW_FUNNEL_MODE>(start_row, row_count); | 251 | 36 | if (found_event_count == event_count) { | 252 | 8 | return found_event_count; | 253 | 8 | } | 254 | 28 | max_found_event_count = std::max(max_found_event_count, found_event_count); | 255 | 28 | } | 256 | 14 | return max_found_event_count; | 257 | 22 | } |
Unexecuted instantiation: _ZNK5doris17WindowFunnelStateILNS_13PrimitiveTypeE26EE13_get_internalILNS_16WindowFunnelModeE2EEEiv Unexecuted instantiation: _ZNK5doris17WindowFunnelStateILNS_13PrimitiveTypeE26EE13_get_internalILNS_16WindowFunnelModeE3EEEiv Unexecuted instantiation: _ZNK5doris17WindowFunnelStateILNS_13PrimitiveTypeE26EE13_get_internalILNS_16WindowFunnelModeE4EEEiv Unexecuted instantiation: _ZNK5doris17WindowFunnelStateILNS_13PrimitiveTypeE42EE13_get_internalILNS_16WindowFunnelModeE1EEEiv Unexecuted instantiation: _ZNK5doris17WindowFunnelStateILNS_13PrimitiveTypeE42EE13_get_internalILNS_16WindowFunnelModeE2EEEiv Unexecuted instantiation: _ZNK5doris17WindowFunnelStateILNS_13PrimitiveTypeE42EE13_get_internalILNS_16WindowFunnelModeE3EEEiv Unexecuted instantiation: _ZNK5doris17WindowFunnelStateILNS_13PrimitiveTypeE42EE13_get_internalILNS_16WindowFunnelModeE4EEEiv |
258 | 24 | int get() const { |
259 | 24 | auto row_count = events_list.size(); |
260 | 24 | if (event_count == 0 || row_count == 0) { |
261 | 2 | return 0; |
262 | 2 | } |
263 | 22 | switch (window_funnel_mode) { |
264 | 22 | case WindowFunnelMode::DEFAULT: |
265 | 22 | return _get_internal<WindowFunnelMode::DEFAULT>(); |
266 | 0 | case WindowFunnelMode::DEDUPLICATION: |
267 | 0 | return _get_internal<WindowFunnelMode::DEDUPLICATION>(); |
268 | 0 | case WindowFunnelMode::FIXED: |
269 | 0 | return _get_internal<WindowFunnelMode::FIXED>(); |
270 | 0 | case WindowFunnelMode::INCREASE: |
271 | 0 | return _get_internal<WindowFunnelMode::INCREASE>(); |
272 | 0 | default: |
273 | 0 | throw doris::Exception(ErrorCode::INTERNAL_ERROR, "Invalid window_funnel mode"); |
274 | 0 | return 0; |
275 | 22 | } |
276 | 22 | } _ZNK5doris17WindowFunnelStateILNS_13PrimitiveTypeE26EE3getEv Line | Count | Source | 258 | 24 | int get() const { | 259 | 24 | auto row_count = events_list.size(); | 260 | 24 | if (event_count == 0 || row_count == 0) { | 261 | 2 | return 0; | 262 | 2 | } | 263 | 22 | switch (window_funnel_mode) { | 264 | 22 | case WindowFunnelMode::DEFAULT: | 265 | 22 | return _get_internal<WindowFunnelMode::DEFAULT>(); | 266 | 0 | case WindowFunnelMode::DEDUPLICATION: | 267 | 0 | return _get_internal<WindowFunnelMode::DEDUPLICATION>(); | 268 | 0 | case WindowFunnelMode::FIXED: | 269 | 0 | return _get_internal<WindowFunnelMode::FIXED>(); | 270 | 0 | case WindowFunnelMode::INCREASE: | 271 | 0 | return _get_internal<WindowFunnelMode::INCREASE>(); | 272 | 0 | default: | 273 | 0 | throw doris::Exception(ErrorCode::INTERNAL_ERROR, "Invalid window_funnel mode"); | 274 | 0 | return 0; | 275 | 22 | } | 276 | 22 | } |
Unexecuted instantiation: _ZNK5doris17WindowFunnelStateILNS_13PrimitiveTypeE42EE3getEv |
277 | | |
278 | 11 | void merge(const WindowFunnelState<T>& other) { |
279 | 11 | if (other.events_list.empty()) { |
280 | 1 | return; |
281 | 1 | } |
282 | 10 | events_list.dt.insert(std::end(events_list.dt), std::begin(other.events_list.dt), |
283 | 10 | std::end(other.events_list.dt)); |
284 | 50 | for (size_t i = 0; i < event_count; i++) { |
285 | 40 | events_list.event_columns_data[i].insert( |
286 | 40 | std::end(events_list.event_columns_data[i]), |
287 | 40 | std::begin(other.events_list.event_columns_data[i]), |
288 | 40 | std::end(other.events_list.event_columns_data[i])); |
289 | 40 | } |
290 | 10 | event_count = event_count > 0 ? event_count : other.event_count; |
291 | 10 | window = window > 0 ? window : other.window; |
292 | 10 | if (enable_mode) { |
293 | 0 | window_funnel_mode = window_funnel_mode == WindowFunnelMode::INVALID |
294 | 0 | ? other.window_funnel_mode |
295 | 0 | : window_funnel_mode; |
296 | 10 | } else { |
297 | 10 | window_funnel_mode = WindowFunnelMode::DEFAULT; |
298 | 10 | } |
299 | 10 | } _ZN5doris17WindowFunnelStateILNS_13PrimitiveTypeE26EE5mergeERKS2_ Line | Count | Source | 278 | 11 | void merge(const WindowFunnelState<T>& other) { | 279 | 11 | if (other.events_list.empty()) { | 280 | 1 | return; | 281 | 1 | } | 282 | 10 | events_list.dt.insert(std::end(events_list.dt), std::begin(other.events_list.dt), | 283 | 10 | std::end(other.events_list.dt)); | 284 | 50 | for (size_t i = 0; i < event_count; i++) { | 285 | 40 | events_list.event_columns_data[i].insert( | 286 | 40 | std::end(events_list.event_columns_data[i]), | 287 | 40 | std::begin(other.events_list.event_columns_data[i]), | 288 | 40 | std::end(other.events_list.event_columns_data[i])); | 289 | 40 | } | 290 | 10 | event_count = event_count > 0 ? event_count : other.event_count; | 291 | 10 | window = window > 0 ? window : other.window; | 292 | 10 | if (enable_mode) { | 293 | 0 | window_funnel_mode = window_funnel_mode == WindowFunnelMode::INVALID | 294 | 0 | ? other.window_funnel_mode | 295 | 0 | : window_funnel_mode; | 296 | 10 | } else { | 297 | 10 | window_funnel_mode = WindowFunnelMode::DEFAULT; | 298 | 10 | } | 299 | 10 | } |
Unexecuted instantiation: _ZN5doris17WindowFunnelStateILNS_13PrimitiveTypeE42EE5mergeERKS2_ |
300 | | |
301 | 2 | void write(BufferWritable& out) const { |
302 | 2 | write_var_int(event_count, out); |
303 | 2 | write_var_int(window, out); |
304 | 2 | if (enable_mode) { |
305 | 0 | write_var_int(static_cast<std::underlying_type_t<WindowFunnelMode>>(window_funnel_mode), |
306 | 0 | out); |
307 | 0 | } |
308 | 2 | auto size = events_list.size(); |
309 | 2 | write_var_int(size, out); |
310 | 4 | for (const auto& timestamp : events_list.dt) { |
311 | 4 | write_var_int(timestamp.to_date_int_val(), out); |
312 | 4 | } |
313 | 10 | for (int64_t i = 0; i < event_count; i++) { |
314 | 8 | const auto& event_columns_data = events_list.event_columns_data[i]; |
315 | 16 | for (auto event : event_columns_data) { |
316 | 16 | write_var_int(event, out); |
317 | 16 | } |
318 | 8 | } |
319 | 2 | } _ZNK5doris17WindowFunnelStateILNS_13PrimitiveTypeE26EE5writeERNS_14BufferWritableE Line | Count | Source | 301 | 2 | void write(BufferWritable& out) const { | 302 | 2 | write_var_int(event_count, out); | 303 | 2 | write_var_int(window, out); | 304 | 2 | if (enable_mode) { | 305 | 0 | write_var_int(static_cast<std::underlying_type_t<WindowFunnelMode>>(window_funnel_mode), | 306 | 0 | out); | 307 | 0 | } | 308 | 2 | auto size = events_list.size(); | 309 | 2 | write_var_int(size, out); | 310 | 4 | for (const auto& timestamp : events_list.dt) { | 311 | 4 | write_var_int(timestamp.to_date_int_val(), out); | 312 | 4 | } | 313 | 10 | for (int64_t i = 0; i < event_count; i++) { | 314 | 8 | const auto& event_columns_data = events_list.event_columns_data[i]; | 315 | 16 | for (auto event : event_columns_data) { | 316 | 16 | write_var_int(event, out); | 317 | 16 | } | 318 | 8 | } | 319 | 2 | } |
Unexecuted instantiation: _ZNK5doris17WindowFunnelStateILNS_13PrimitiveTypeE42EE5writeERNS_14BufferWritableE |
320 | | |
321 | 2 | void read(BufferReadable& in) { |
322 | 2 | int64_t event_level; |
323 | 2 | read_var_int(event_level, in); |
324 | 2 | event_count = (int)event_level; |
325 | 2 | read_var_int(window, in); |
326 | 2 | window_funnel_mode = WindowFunnelMode::DEFAULT; |
327 | 2 | if (enable_mode) { |
328 | 0 | int64_t mode; |
329 | 0 | read_var_int(mode, in); |
330 | 0 | window_funnel_mode = static_cast<WindowFunnelMode>(mode); |
331 | 0 | } |
332 | 2 | int64_t size = 0; |
333 | 2 | read_var_int(size, in); |
334 | 2 | events_list.clear(); |
335 | 2 | events_list.dt.resize(size); |
336 | 6 | for (auto i = 0; i < size; i++) { |
337 | 4 | Int64 timestamp = 0; |
338 | 4 | read_var_int(timestamp, in); |
339 | 4 | events_list.dt[i] = DateValueType(static_cast<UInt64>(timestamp)); |
340 | 4 | } |
341 | 2 | events_list.event_columns_data.resize(event_count); |
342 | 10 | for (int64_t i = 0; i < event_count; i++) { |
343 | 8 | auto& event_columns_data = events_list.event_columns_data[i]; |
344 | 8 | event_columns_data.resize(size); |
345 | 24 | for (auto j = 0; j < size; j++) { |
346 | 16 | Int64 temp_value; |
347 | 16 | read_var_int(temp_value, in); |
348 | 16 | event_columns_data[j] = static_cast<UInt8>(temp_value); |
349 | 16 | } |
350 | 8 | } |
351 | 2 | } _ZN5doris17WindowFunnelStateILNS_13PrimitiveTypeE26EE4readERNS_14BufferReadableE Line | Count | Source | 321 | 2 | void read(BufferReadable& in) { | 322 | 2 | int64_t event_level; | 323 | 2 | read_var_int(event_level, in); | 324 | 2 | event_count = (int)event_level; | 325 | 2 | read_var_int(window, in); | 326 | 2 | window_funnel_mode = WindowFunnelMode::DEFAULT; | 327 | 2 | if (enable_mode) { | 328 | 0 | int64_t mode; | 329 | 0 | read_var_int(mode, in); | 330 | 0 | window_funnel_mode = static_cast<WindowFunnelMode>(mode); | 331 | 0 | } | 332 | 2 | int64_t size = 0; | 333 | 2 | read_var_int(size, in); | 334 | 2 | events_list.clear(); | 335 | 2 | events_list.dt.resize(size); | 336 | 6 | for (auto i = 0; i < size; i++) { | 337 | 4 | Int64 timestamp = 0; | 338 | 4 | read_var_int(timestamp, in); | 339 | 4 | events_list.dt[i] = DateValueType(static_cast<UInt64>(timestamp)); | 340 | 4 | } | 341 | 2 | events_list.event_columns_data.resize(event_count); | 342 | 10 | for (int64_t i = 0; i < event_count; i++) { | 343 | 8 | auto& event_columns_data = events_list.event_columns_data[i]; | 344 | 8 | event_columns_data.resize(size); | 345 | 24 | for (auto j = 0; j < size; j++) { | 346 | 16 | Int64 temp_value; | 347 | 16 | read_var_int(temp_value, in); | 348 | 16 | event_columns_data[j] = static_cast<UInt8>(temp_value); | 349 | 16 | } | 350 | 8 | } | 351 | 2 | } |
Unexecuted instantiation: _ZN5doris17WindowFunnelStateILNS_13PrimitiveTypeE42EE4readERNS_14BufferReadableE |
352 | | }; |
353 | | |
354 | | template <PrimitiveType T> |
355 | | class AggregateFunctionWindowFunnel final |
356 | | : public IAggregateFunctionDataHelper<WindowFunnelState<T>, |
357 | | AggregateFunctionWindowFunnel<T>>, |
358 | | MultiExpression, |
359 | | NullableAggregateFunction { |
360 | | public: |
361 | | AggregateFunctionWindowFunnel(const DataTypes& argument_types_) |
362 | 6 | : IAggregateFunctionDataHelper<WindowFunnelState<T>, AggregateFunctionWindowFunnel<T>>( |
363 | 6 | argument_types_) {}_ZN5doris29AggregateFunctionWindowFunnelILNS_13PrimitiveTypeE26EEC2ERKSt6vectorISt10shared_ptrIKNS_9IDataTypeEESaIS7_EE Line | Count | Source | 362 | 6 | : IAggregateFunctionDataHelper<WindowFunnelState<T>, AggregateFunctionWindowFunnel<T>>( | 363 | 6 | argument_types_) {} |
Unexecuted instantiation: _ZN5doris29AggregateFunctionWindowFunnelILNS_13PrimitiveTypeE42EEC2ERKSt6vectorISt10shared_ptrIKNS_9IDataTypeEESaIS7_EE |
364 | | |
365 | 34 | void create(AggregateDataPtr __restrict place) const override { |
366 | 34 | auto data = new (place) WindowFunnelState<T>( |
367 | 34 | cast_set<int>(IAggregateFunction::get_argument_types().size() - 3)); |
368 | | /// support window funnel mode from 2.0. See `BeExecVersionManager::max_be_exec_version` |
369 | 34 | data->enable_mode = IAggregateFunction::version >= 3; |
370 | 34 | } _ZNK5doris29AggregateFunctionWindowFunnelILNS_13PrimitiveTypeE26EE6createEPc Line | Count | Source | 365 | 34 | void create(AggregateDataPtr __restrict place) const override { | 366 | 34 | auto data = new (place) WindowFunnelState<T>( | 367 | 34 | cast_set<int>(IAggregateFunction::get_argument_types().size() - 3)); | 368 | | /// support window funnel mode from 2.0. See `BeExecVersionManager::max_be_exec_version` | 369 | 34 | data->enable_mode = IAggregateFunction::version >= 3; | 370 | 34 | } |
Unexecuted instantiation: _ZNK5doris29AggregateFunctionWindowFunnelILNS_13PrimitiveTypeE42EE6createEPc |
371 | | |
372 | 0 | String get_name() const override { return "window_funnel"; }Unexecuted instantiation: _ZNK5doris29AggregateFunctionWindowFunnelILNS_13PrimitiveTypeE26EE8get_nameB5cxx11Ev Unexecuted instantiation: _ZNK5doris29AggregateFunctionWindowFunnelILNS_13PrimitiveTypeE42EE8get_nameB5cxx11Ev |
373 | | |
374 | 0 | DataTypePtr get_return_type() const override { return std::make_shared<DataTypeInt32>(); }Unexecuted instantiation: _ZNK5doris29AggregateFunctionWindowFunnelILNS_13PrimitiveTypeE26EE15get_return_typeEv Unexecuted instantiation: _ZNK5doris29AggregateFunctionWindowFunnelILNS_13PrimitiveTypeE42EE15get_return_typeEv |
375 | | |
376 | 0 | void reset(AggregateDataPtr __restrict place) const override { this->data(place).reset(); }Unexecuted instantiation: _ZNK5doris29AggregateFunctionWindowFunnelILNS_13PrimitiveTypeE26EE5resetEPc Unexecuted instantiation: _ZNK5doris29AggregateFunctionWindowFunnelILNS_13PrimitiveTypeE42EE5resetEPc |
377 | | |
378 | | void add(AggregateDataPtr __restrict place, const IColumn** columns, ssize_t row_num, |
379 | 84 | Arena&) const override { |
380 | 84 | const auto& window = |
381 | 84 | assert_cast<const ColumnInt64&, TypeCheckOnRelease::DISABLE>(*columns[0]) |
382 | 84 | .get_data()[row_num]; |
383 | 84 | StringRef mode = columns[1]->get_data_at(row_num); |
384 | 84 | this->data(place).add(columns, row_num, window, |
385 | 84 | string_to_window_funnel_mode(mode.to_string())); |
386 | 84 | } _ZNK5doris29AggregateFunctionWindowFunnelILNS_13PrimitiveTypeE26EE3addEPcPPKNS_7IColumnElRNS_5ArenaE Line | Count | Source | 379 | 84 | Arena&) const override { | 380 | 84 | const auto& window = | 381 | 84 | assert_cast<const ColumnInt64&, TypeCheckOnRelease::DISABLE>(*columns[0]) | 382 | 84 | .get_data()[row_num]; | 383 | 84 | StringRef mode = columns[1]->get_data_at(row_num); | 384 | 84 | this->data(place).add(columns, row_num, window, | 385 | 84 | string_to_window_funnel_mode(mode.to_string())); | 386 | 84 | } |
Unexecuted instantiation: _ZNK5doris29AggregateFunctionWindowFunnelILNS_13PrimitiveTypeE42EE3addEPcPPKNS_7IColumnElRNS_5ArenaE |
387 | | |
388 | 0 | void check_input_columns_type(const IColumn** columns) const override { |
389 | 0 | this->template check_argument_column_type<ColumnInt64>(columns[0]); |
390 | 0 | this->template check_argument_column_type<ColumnString>(columns[1]); |
391 | 0 | this->template check_argument_column_type<typename PrimitiveTypeTraits<T>::ColumnType>( |
392 | 0 | columns[2]); |
393 | 0 | for (size_t i = 3; i < this->argument_types.size(); ++i) { |
394 | 0 | this->template check_argument_column_type<ColumnUInt8>(columns[i]); |
395 | 0 | } |
396 | 0 | } Unexecuted instantiation: _ZNK5doris29AggregateFunctionWindowFunnelILNS_13PrimitiveTypeE26EE24check_input_columns_typeEPPKNS_7IColumnE Unexecuted instantiation: _ZNK5doris29AggregateFunctionWindowFunnelILNS_13PrimitiveTypeE42EE24check_input_columns_typeEPPKNS_7IColumnE |
397 | | |
398 | | void merge(AggregateDataPtr __restrict place, ConstAggregateDataPtr rhs, |
399 | 11 | Arena&) const override { |
400 | 11 | this->data(place).merge(this->data(rhs)); |
401 | 11 | } _ZNK5doris29AggregateFunctionWindowFunnelILNS_13PrimitiveTypeE26EE5mergeEPcPKcRNS_5ArenaE Line | Count | Source | 399 | 11 | Arena&) const override { | 400 | 11 | this->data(place).merge(this->data(rhs)); | 401 | 11 | } |
Unexecuted instantiation: _ZNK5doris29AggregateFunctionWindowFunnelILNS_13PrimitiveTypeE42EE5mergeEPcPKcRNS_5ArenaE |
402 | | |
403 | 2 | void serialize(ConstAggregateDataPtr __restrict place, BufferWritable& buf) const override { |
404 | 2 | this->data(place).write(buf); |
405 | 2 | } _ZNK5doris29AggregateFunctionWindowFunnelILNS_13PrimitiveTypeE26EE9serializeEPKcRNS_14BufferWritableE Line | Count | Source | 403 | 2 | void serialize(ConstAggregateDataPtr __restrict place, BufferWritable& buf) const override { | 404 | 2 | this->data(place).write(buf); | 405 | 2 | } |
Unexecuted instantiation: _ZNK5doris29AggregateFunctionWindowFunnelILNS_13PrimitiveTypeE42EE9serializeEPKcRNS_14BufferWritableE |
406 | | |
407 | | void deserialize(AggregateDataPtr __restrict place, BufferReadable& buf, |
408 | 2 | Arena&) const override { |
409 | 2 | this->data(place).read(buf); |
410 | 2 | } _ZNK5doris29AggregateFunctionWindowFunnelILNS_13PrimitiveTypeE26EE11deserializeEPcRNS_14BufferReadableERNS_5ArenaE Line | Count | Source | 408 | 2 | Arena&) const override { | 409 | 2 | this->data(place).read(buf); | 410 | 2 | } |
Unexecuted instantiation: _ZNK5doris29AggregateFunctionWindowFunnelILNS_13PrimitiveTypeE42EE11deserializeEPcRNS_14BufferReadableERNS_5ArenaE |
411 | | |
412 | 24 | void insert_result_into(ConstAggregateDataPtr __restrict place, IColumn& to) const override { |
413 | | // place is essentially an AggregateDataPtr, passed as a ConstAggregateDataPtr. |
414 | 24 | this->data(const_cast<AggregateDataPtr>(place)).sort(); |
415 | 24 | assert_cast<ColumnInt32&, TypeCheckOnRelease::DISABLE>(to).get_data().push_back( |
416 | 24 | IAggregateFunctionDataHelper<WindowFunnelState<T>, |
417 | 24 | AggregateFunctionWindowFunnel<T>>::data(place) |
418 | 24 | .get()); |
419 | 24 | } _ZNK5doris29AggregateFunctionWindowFunnelILNS_13PrimitiveTypeE26EE18insert_result_intoEPKcRNS_7IColumnE Line | Count | Source | 412 | 24 | void insert_result_into(ConstAggregateDataPtr __restrict place, IColumn& to) const override { | 413 | | // place is essentially an AggregateDataPtr, passed as a ConstAggregateDataPtr. | 414 | 24 | this->data(const_cast<AggregateDataPtr>(place)).sort(); | 415 | 24 | assert_cast<ColumnInt32&, TypeCheckOnRelease::DISABLE>(to).get_data().push_back( | 416 | 24 | IAggregateFunctionDataHelper<WindowFunnelState<T>, | 417 | 24 | AggregateFunctionWindowFunnel<T>>::data(place) | 418 | 24 | .get()); | 419 | 24 | } |
Unexecuted instantiation: _ZNK5doris29AggregateFunctionWindowFunnelILNS_13PrimitiveTypeE42EE18insert_result_intoEPKcRNS_7IColumnE |
420 | | |
421 | | protected: |
422 | | using IAggregateFunction::version; |
423 | | }; |
424 | | } // namespace doris |