be/src/exprs/vectorized_agg_fn.cpp
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 | | #include "exprs/vectorized_agg_fn.h" |
19 | | |
20 | | #include <fmt/format.h> |
21 | | #include <fmt/ranges.h> // IWYU pragma: keep |
22 | | #include <gen_cpp/Exprs_types.h> |
23 | | #include <gen_cpp/PlanNodes_types.h> |
24 | | #include <glog/logging.h> |
25 | | |
26 | | #include <memory> |
27 | | #include <ostream> |
28 | | #include <string_view> |
29 | | #include <vector> |
30 | | |
31 | | #include "common/config.h" |
32 | | #include "common/object_pool.h" |
33 | | #include "core/block/block.h" |
34 | | #include "core/block/column_with_type_and_name.h" |
35 | | #include "core/block/materialize_block.h" |
36 | | #include "core/column/column_const.h" |
37 | | #include "core/data_type/data_type_agg_state.h" |
38 | | #include "core/data_type/data_type_factory.hpp" |
39 | | #include "exec/common/util.hpp" |
40 | | #include "exprs/aggregate/aggregate_function_ai_agg.h" |
41 | | #include "exprs/aggregate/aggregate_function_java_udaf.h" |
42 | | #include "exprs/aggregate/aggregate_function_python_udaf.h" |
43 | | #include "exprs/aggregate/aggregate_function_rpc.h" |
44 | | #include "exprs/aggregate/aggregate_function_simple_factory.h" |
45 | | #include "exprs/aggregate/aggregate_function_sort.h" |
46 | | #include "exprs/aggregate/aggregate_function_state_merge.h" |
47 | | #include "exprs/aggregate/aggregate_function_state_union.h" |
48 | | #include "exprs/vexpr.h" |
49 | | #include "exprs/vexpr_context.h" |
50 | | |
51 | | static constexpr int64_t BE_VERSION_THAT_SUPPORT_NULLABLE_CHECK = 8; |
52 | | |
53 | | namespace doris { |
54 | | class RowDescriptor; |
55 | | class Arena; |
56 | | class BufferWritable; |
57 | | class IColumn; |
58 | | } // namespace doris |
59 | | |
60 | | namespace doris { |
61 | | |
62 | | template <class FunctionType> |
63 | | AggregateFunctionPtr get_agg_state_function(const DataTypes& argument_types, |
64 | 0 | DataTypePtr return_type) { |
65 | 0 | return FunctionType::create( |
66 | 0 | assert_cast<const DataTypeAggState*>(argument_types[0].get())->get_nested_function(), |
67 | 0 | argument_types, return_type); |
68 | 0 | } Unexecuted instantiation: _ZN5doris22get_agg_state_functionINS_19AggregateStateUnionEEESt10shared_ptrINS_18IAggregateFunctionEERKSt6vectorIS2_IKNS_9IDataTypeEESaIS8_EES8_ Unexecuted instantiation: _ZN5doris22get_agg_state_functionINS_19AggregateStateMergeEEESt10shared_ptrINS_18IAggregateFunctionEERKSt6vectorIS2_IKNS_9IDataTypeEESaIS8_EES8_ |
69 | | |
70 | | AggFnEvaluator::AggFnEvaluator(const TExprNode& desc, const bool without_key, |
71 | | const bool is_window_function) |
72 | 20 | : _fn(desc.fn), |
73 | 20 | _is_merge(desc.agg_expr.is_merge_agg), |
74 | 20 | _without_key(without_key), |
75 | 20 | _is_window_function(is_window_function), |
76 | 20 | _data_type(DataTypeFactory::instance().create_data_type( |
77 | 20 | desc.fn.ret_type, desc.__isset.is_nullable ? desc.is_nullable : true)), |
78 | 20 | _always_const_argument_idx(desc.num_children, false) { |
79 | 20 | if (desc.agg_expr.__isset.param_types) { |
80 | 20 | const auto& param_types = desc.agg_expr.param_types; |
81 | 20 | for (const auto& param_type : param_types) { |
82 | 20 | _argument_types_with_sort.push_back( |
83 | 20 | DataTypeFactory::instance().create_data_type(param_type)); |
84 | 20 | } |
85 | 20 | } |
86 | 20 | } |
87 | | |
88 | | Status AggFnEvaluator::create(ObjectPool* pool, const TExpr& desc, const TSortInfo& sort_info, |
89 | | const bool without_key, const bool is_window_function, |
90 | 20 | AggFnEvaluator** result) { |
91 | 20 | *result = |
92 | 20 | pool->add(AggFnEvaluator::create_unique(desc.nodes[0], without_key, is_window_function) |
93 | 20 | .release()); |
94 | 20 | auto& agg_fn_evaluator = *result; |
95 | 20 | int node_idx = 0; |
96 | 40 | for (int i = 0; i < desc.nodes[0].num_children; ++i) { |
97 | 20 | ++node_idx; |
98 | 20 | VExprSPtr expr; |
99 | 20 | VExprContextSPtr ctx; |
100 | 20 | RETURN_IF_ERROR(VExpr::create_tree_from_thrift(desc.nodes, &node_idx, expr, ctx)); |
101 | 20 | agg_fn_evaluator->_input_exprs_ctxs.push_back(ctx); |
102 | 20 | } |
103 | | |
104 | 20 | auto sort_size = sort_info.ordering_exprs.size(); |
105 | 20 | auto real_arguments_size = agg_fn_evaluator->_argument_types_with_sort.size() - sort_size; |
106 | | // Child arguments contains [real arguments, order by arguments], we pass the arguments |
107 | | // to the order by functions |
108 | 20 | for (int i = 0; i < sort_size; ++i) { |
109 | 0 | agg_fn_evaluator->_sort_description.emplace_back(real_arguments_size + i, |
110 | 0 | sort_info.is_asc_order[i] ? 1 : -1, |
111 | 0 | sort_info.nulls_first[i] ? -1 : 1); |
112 | 0 | } |
113 | | |
114 | | // Pass the real arguments to get functions |
115 | 40 | for (int i = 0; i < real_arguments_size; ++i) { |
116 | 20 | agg_fn_evaluator->_real_argument_types.emplace_back( |
117 | 20 | agg_fn_evaluator->_argument_types_with_sort[i]); |
118 | 20 | } |
119 | 20 | return Status::OK(); |
120 | 20 | } |
121 | | |
122 | | Status AggFnEvaluator::prepare(RuntimeState* state, const RowDescriptor& desc, |
123 | | const SlotDescriptor* intermediate_slot_desc, |
124 | 20 | const SlotDescriptor* output_slot_desc) { |
125 | 20 | DCHECK(intermediate_slot_desc != nullptr); |
126 | 20 | DCHECK(_intermediate_slot_desc == nullptr); |
127 | 20 | _output_slot_desc = output_slot_desc; |
128 | 20 | _intermediate_slot_desc = intermediate_slot_desc; |
129 | | |
130 | 20 | Status status = VExpr::prepare(_input_exprs_ctxs, state, desc); |
131 | 20 | RETURN_IF_ERROR(status); |
132 | | |
133 | 20 | DataTypes tmp_argument_types; |
134 | 20 | tmp_argument_types.reserve(_input_exprs_ctxs.size()); |
135 | | |
136 | 20 | std::vector<std::string_view> child_expr_name; |
137 | | |
138 | | // prepare for argument |
139 | 20 | for (auto& _input_exprs_ctx : _input_exprs_ctxs) { |
140 | 20 | auto data_type = _input_exprs_ctx->root()->data_type(); |
141 | 20 | tmp_argument_types.emplace_back(data_type); |
142 | 20 | child_expr_name.emplace_back(_input_exprs_ctx->root()->expr_name()); |
143 | 20 | } |
144 | | |
145 | 20 | std::vector<std::string> column_names; |
146 | 20 | for (const auto& expr_ctx : _input_exprs_ctxs) { |
147 | 20 | const auto& root = expr_ctx->root(); |
148 | 20 | if (!root->expr_name().empty() && !root->is_constant()) { |
149 | 20 | column_names.emplace_back(root->expr_name()); |
150 | 20 | } |
151 | 20 | } |
152 | | |
153 | 20 | const DataTypes& argument_types = |
154 | 20 | _real_argument_types.empty() ? tmp_argument_types : _real_argument_types; |
155 | | |
156 | 20 | if (_fn.binary_type == TFunctionBinaryType::JAVA_UDF) { |
157 | 0 | if (config::enable_java_support) { |
158 | 0 | _function = AggregateJavaUdaf::create(_fn, argument_types, _data_type); |
159 | 0 | RETURN_IF_ERROR(static_cast<AggregateJavaUdaf*>(_function.get())->check_udaf(_fn)); |
160 | 0 | } else { |
161 | 0 | return Status::InternalError( |
162 | 0 | "Java UDAF is not enabled, you can change be config enable_java_support to " |
163 | 0 | "true and restart be."); |
164 | 0 | } |
165 | 20 | } else if (_fn.binary_type == TFunctionBinaryType::PYTHON_UDF) { |
166 | 0 | if (config::enable_python_udf_support) { |
167 | 0 | _function = AggregatePythonUDAF::create(_fn, argument_types, _data_type); |
168 | 0 | RETURN_IF_ERROR(static_cast<AggregatePythonUDAF*>(_function.get())->open()); |
169 | 0 | LOG(INFO) << fmt::format( |
170 | 0 | "Created Python UDAF: {}, runtime_version: {}, function_code: {}", |
171 | 0 | _fn.name.function_name, _fn.runtime_version, _fn.function_code); |
172 | 0 | } else { |
173 | 0 | return Status::InternalError( |
174 | 0 | "Python UDAF is not enabled, you can change be config " |
175 | 0 | "enable_python_udf_support to true and restart be."); |
176 | 0 | } |
177 | 20 | } else if (_fn.binary_type == TFunctionBinaryType::RPC) { |
178 | 0 | _function = AggregateRpcUdaf::create(_fn, argument_types, _data_type); |
179 | 20 | } else if (_fn.binary_type == TFunctionBinaryType::AGG_STATE) { |
180 | 0 | if (argument_types.size() != 1) { |
181 | 0 | return Status::InternalError("Agg state Function must input 1 argument but get {}", |
182 | 0 | argument_types.size()); |
183 | 0 | } |
184 | 0 | if (argument_types[0]->is_nullable()) { |
185 | 0 | return Status::InternalError("Agg state function input type must be not nullable"); |
186 | 0 | } |
187 | 0 | if (argument_types[0]->get_primitive_type() != PrimitiveType::TYPE_AGG_STATE) { |
188 | 0 | return Status::InternalError( |
189 | 0 | "Agg state function input type must be agg_state but get {}", |
190 | 0 | argument_types[0]->get_family_name()); |
191 | 0 | } |
192 | | |
193 | 0 | std::string type_function_name = |
194 | 0 | assert_cast<const DataTypeAggState*>(argument_types[0].get())->get_function_name(); |
195 | 0 | if (type_function_name + AGG_UNION_SUFFIX == _fn.name.function_name) { |
196 | 0 | if (_data_type->is_nullable()) { |
197 | 0 | return Status::InternalError( |
198 | 0 | "Union function return type must be not nullable, real={}", |
199 | 0 | _data_type->get_name()); |
200 | 0 | } |
201 | 0 | if (_data_type->get_primitive_type() != PrimitiveType::TYPE_AGG_STATE) { |
202 | 0 | return Status::InternalError( |
203 | 0 | "Union function return type must be AGG_STATE, real={}", |
204 | 0 | _data_type->get_name()); |
205 | 0 | } |
206 | 0 | _function = get_agg_state_function<AggregateStateUnion>(argument_types, _data_type); |
207 | 0 | } else if (type_function_name + AGG_MERGE_SUFFIX == _fn.name.function_name) { |
208 | 0 | auto type = assert_cast<const DataTypeAggState*>(argument_types[0].get()) |
209 | 0 | ->get_nested_function() |
210 | 0 | ->get_return_type(); |
211 | 0 | if (!type->equals(*_data_type)) { |
212 | 0 | return Status::InternalError("{}'s expect return type is {}, but input {}", |
213 | 0 | argument_types[0]->get_name(), type->get_name(), |
214 | 0 | _data_type->get_name()); |
215 | 0 | } |
216 | 0 | _function = get_agg_state_function<AggregateStateMerge>(argument_types, _data_type); |
217 | 0 | } else { |
218 | 0 | return Status::InternalError("{} not match function {}", argument_types[0]->get_name(), |
219 | 0 | _fn.name.function_name); |
220 | 0 | } |
221 | 20 | } else { |
222 | 20 | const bool is_foreach = |
223 | 20 | AggregateFunctionSimpleFactory::is_foreach(_fn.name.function_name) || |
224 | 20 | AggregateFunctionSimpleFactory::is_foreachv2(_fn.name.function_name); |
225 | | // Here, only foreachv1 needs special treatment, and v2 can follow the normal code logic. |
226 | 20 | if (AggregateFunctionSimpleFactory::is_foreach(_fn.name.function_name)) { |
227 | 0 | _function = AggregateFunctionSimpleFactory::instance().get( |
228 | 0 | _fn.name.function_name, argument_types, _data_type, |
229 | 0 | AggregateFunctionSimpleFactory::result_nullable_by_foreach(_data_type), |
230 | 0 | state->be_exec_version(), |
231 | 0 | {.is_window_function = _is_window_function, |
232 | 0 | .is_foreach = is_foreach, |
233 | 0 | .enable_aggregate_function_null_v2 = |
234 | 0 | state->enable_aggregate_function_null_v2(), |
235 | 0 | .new_version_percentile = |
236 | 0 | state->query_options().__isset.new_version_percentile && |
237 | 0 | state->query_options().new_version_percentile, |
238 | 0 | .column_names = std::move(column_names)}); |
239 | 20 | } else { |
240 | 20 | _function = AggregateFunctionSimpleFactory::instance().get( |
241 | 20 | _fn.name.function_name, argument_types, _data_type, _data_type->is_nullable(), |
242 | 20 | state->be_exec_version(), |
243 | 20 | {.is_window_function = _is_window_function, |
244 | 20 | .is_foreach = is_foreach, |
245 | 20 | .enable_aggregate_function_null_v2 = |
246 | 20 | state->enable_aggregate_function_null_v2(), |
247 | 20 | .new_version_percentile = |
248 | 20 | state->query_options().__isset.new_version_percentile && |
249 | 20 | state->query_options().new_version_percentile, |
250 | 20 | .column_names = std::move(column_names)}); |
251 | 20 | } |
252 | 20 | } |
253 | 20 | if (_function == nullptr) { |
254 | 0 | return Status::InternalError("Agg Function {} is not implemented", _fn.signature); |
255 | 0 | } |
256 | | |
257 | 20 | if (!_sort_description.empty()) { |
258 | 0 | _function = transform_to_sort_agg_function(_function, _argument_types_with_sort, |
259 | 0 | _sort_description, state); |
260 | 0 | } |
261 | 20 | if (_fn.name.function_name == "ai_agg") { |
262 | 0 | _function->set_query_context(state->get_query_ctx()); |
263 | 0 | } |
264 | 20 | if (!_is_merge) { |
265 | 20 | for (auto index : _function->get_const_argument_indexes()) { |
266 | 0 | DORIS_CHECK_LT(index, _always_const_argument_idx.size()); |
267 | 0 | _always_const_argument_idx[index] = true; |
268 | 0 | } |
269 | 20 | } |
270 | | |
271 | | // Foreachv2, like foreachv1, does not check the return type, |
272 | | // because its return type is related to the internal agg. |
273 | 20 | if (!AggregateFunctionSimpleFactory::is_foreach(_fn.name.function_name) && |
274 | 20 | !AggregateFunctionSimpleFactory::is_foreachv2(_fn.name.function_name)) { |
275 | 20 | if (state->be_exec_version() >= BE_VERSION_THAT_SUPPORT_NULLABLE_CHECK) { |
276 | 20 | RETURN_IF_ERROR( |
277 | 20 | _function->verify_result_type(_without_key, argument_types, _data_type)); |
278 | 20 | } |
279 | 20 | } |
280 | 20 | _expr_name = fmt::format("{}({})", _fn.name.function_name, child_expr_name); |
281 | 20 | return Status::OK(); |
282 | 20 | } |
283 | | |
284 | 22 | Status AggFnEvaluator::open(RuntimeState* state) { |
285 | 22 | return VExpr::open(_input_exprs_ctxs, state); |
286 | 22 | } |
287 | | |
288 | 1.06M | void AggFnEvaluator::create(AggregateDataPtr place) { |
289 | 1.06M | _function->create(place); |
290 | 1.06M | } |
291 | | |
292 | 1.06M | void AggFnEvaluator::destroy(AggregateDataPtr place) { |
293 | 1.06M | _function->destroy(place); |
294 | 1.06M | } |
295 | | |
296 | 170 | Status AggFnEvaluator::execute_single_add(Block* block, AggregateDataPtr place, Arena& arena) { |
297 | 170 | RETURN_IF_ERROR(_calc_argument_columns(block)); |
298 | 170 | _function->check_input_columns_type(_agg_columns.data()); |
299 | 170 | _function->add_batch_single_place(block->rows(), place, _agg_columns.data(), arena); |
300 | 170 | return Status::OK(); |
301 | 170 | } |
302 | | |
303 | | Status AggFnEvaluator::execute_batch_add(Block* block, size_t offset, AggregateDataPtr* places, |
304 | 54 | Arena& arena, bool agg_many) { |
305 | 54 | RETURN_IF_ERROR(_calc_argument_columns(block)); |
306 | 54 | _function->check_input_columns_type(_agg_columns.data()); |
307 | 54 | _function->add_batch(block->rows(), places, offset, _agg_columns.data(), arena, agg_many); |
308 | 54 | return Status::OK(); |
309 | 54 | } |
310 | | |
311 | | Status AggFnEvaluator::execute_batch_add_selected(Block* block, size_t offset, |
312 | 2 | AggregateDataPtr* places, Arena& arena) { |
313 | 2 | RETURN_IF_ERROR(_calc_argument_columns(block)); |
314 | 2 | _function->check_input_columns_type(_agg_columns.data()); |
315 | 2 | _function->add_batch_selected(block->rows(), places, offset, _agg_columns.data(), arena); |
316 | 2 | return Status::OK(); |
317 | 2 | } |
318 | | |
319 | | Status AggFnEvaluator::streaming_agg_serialize_to_column(Block* block, MutableColumnPtr& dst, |
320 | 27 | const size_t num_rows, Arena& arena) { |
321 | 27 | RETURN_IF_ERROR(_calc_argument_columns(block)); |
322 | 27 | _function->check_input_columns_type(_agg_columns.data()); |
323 | 27 | _function->streaming_agg_serialize_to_column(_agg_columns.data(), dst, num_rows, arena); |
324 | 27 | return Status::OK(); |
325 | 27 | } |
326 | | |
327 | | void AggFnEvaluator::add_range_single_place(int64_t partition_start, int64_t partition_end, |
328 | | int64_t frame_start, int64_t frame_end, |
329 | | AggregateDataPtr place, const IColumn** columns, |
330 | | Arena& arena, UInt8* use_null_result, |
331 | 47 | UInt8* could_use_previous_result) { |
332 | 47 | _function->check_input_columns_type(columns); |
333 | 47 | _function->add_range_single_place(partition_start, partition_end, frame_start, frame_end, place, |
334 | 47 | columns, arena, use_null_result, could_use_previous_result); |
335 | 47 | } |
336 | | |
337 | | void AggFnEvaluator::execute_function_with_incremental( |
338 | | int64_t partition_start, int64_t partition_end, int64_t frame_start, int64_t frame_end, |
339 | | AggregateDataPtr place, const IColumn** columns, Arena& arena, bool previous_is_nul, |
340 | 20 | bool end_is_nul, bool has_null, UInt8* use_null_result, UInt8* could_use_previous_result) { |
341 | 20 | _function->check_input_columns_type(columns); |
342 | 20 | _function->execute_function_with_incremental( |
343 | 20 | partition_start, partition_end, frame_start, frame_end, place, columns, arena, |
344 | 20 | previous_is_nul, end_is_nul, has_null, use_null_result, could_use_previous_result); |
345 | 20 | } |
346 | | |
347 | 175 | void AggFnEvaluator::insert_result_info(AggregateDataPtr place, IColumn* column) { |
348 | 175 | _function->check_result_column_type(*column); |
349 | 175 | _function->insert_result_into(place, *column); |
350 | 175 | } |
351 | | |
352 | | void AggFnEvaluator::insert_result_info_vec(const std::vector<AggregateDataPtr>& places, |
353 | 13 | size_t offset, IColumn* column, const size_t num_rows) { |
354 | 13 | _function->check_result_column_type(*column); |
355 | 13 | _function->insert_result_into_vec(places, offset, *column, num_rows); |
356 | 13 | } |
357 | | |
358 | | void AggFnEvaluator::insert_result_info_range(ConstAggregateDataPtr place, IColumn* column, |
359 | 67 | size_t start, size_t end) { |
360 | 67 | _function->check_result_column_type(*column); |
361 | 67 | _function->insert_result_into_range(place, *column, start, end); |
362 | 67 | } |
363 | | |
364 | 62 | void AggFnEvaluator::reset(AggregateDataPtr place) { |
365 | 62 | _function->reset(place); |
366 | 62 | } |
367 | | |
368 | 0 | std::string AggFnEvaluator::debug_string(const std::vector<AggFnEvaluator*>& exprs) { |
369 | 0 | std::stringstream out; |
370 | 0 | out << "["; |
371 | |
|
372 | 0 | for (int i = 0; i < exprs.size(); ++i) { |
373 | 0 | out << (i == 0 ? "" : " ") << exprs[i]->debug_string(); |
374 | 0 | } |
375 | |
|
376 | 0 | out << "]"; |
377 | 0 | return out.str(); |
378 | 0 | } |
379 | | |
380 | 0 | std::string AggFnEvaluator::debug_string() const { |
381 | 0 | std::stringstream out; |
382 | 0 | out << "AggFnEvaluator("; |
383 | 0 | out << _fn.signature; |
384 | 0 | out << ")"; |
385 | 0 | return out.str(); |
386 | 0 | } |
387 | | |
388 | 253 | Status AggFnEvaluator::_calc_argument_columns(Block* block) { |
389 | 253 | SCOPED_TIMER(_expr_timer); |
390 | 253 | _agg_columns.resize(_input_exprs_ctxs.size()); |
391 | | |
392 | 540 | for (int i = 0; i < _input_exprs_ctxs.size(); ++i) { |
393 | 287 | int column_id = block->columns(); |
394 | 287 | RETURN_IF_ERROR(_input_exprs_ctxs[i]->execute(block, &column_id)); |
395 | | |
396 | 287 | if (_always_const_argument_idx[i]) { |
397 | 2 | const auto& argument = block->get_by_position(column_id); |
398 | 2 | if (!is_column<ColumnConst>(*argument.column)) { |
399 | 2 | auto const_argument = argument; |
400 | 2 | const_argument.column = |
401 | 2 | ColumnConst::create(argument.column->cut(0, 1), block->rows()); |
402 | 2 | block->insert(std::move(const_argument)); |
403 | 2 | column_id = block->columns() - 1; |
404 | 2 | } |
405 | 285 | } else { |
406 | 285 | block->replace_by_position_if_const(column_id); |
407 | 285 | } |
408 | 287 | _agg_columns[i] = block->get_by_position(column_id).column.get(); |
409 | 287 | } |
410 | 253 | return Status::OK(); |
411 | 253 | } |
412 | | |
413 | 64 | AggFnEvaluator* AggFnEvaluator::clone(RuntimeState* state, ObjectPool* pool) { |
414 | 64 | return pool->add(AggFnEvaluator::create_unique(*this, state).release()); |
415 | 64 | } |
416 | | |
417 | | AggFnEvaluator::AggFnEvaluator(AggFnEvaluator& evaluator, RuntimeState* state) |
418 | 64 | : _fn(evaluator._fn), |
419 | 64 | _is_merge(evaluator._is_merge), |
420 | 64 | _without_key(evaluator._without_key), |
421 | 64 | _is_window_function(evaluator._is_window_function), |
422 | 64 | _argument_types_with_sort(evaluator._argument_types_with_sort), |
423 | 64 | _real_argument_types(evaluator._real_argument_types), |
424 | 64 | _intermediate_slot_desc(evaluator._intermediate_slot_desc), |
425 | 64 | _output_slot_desc(evaluator._output_slot_desc), |
426 | 64 | _sort_description(evaluator._sort_description), |
427 | 64 | _data_type(evaluator._data_type), |
428 | 64 | _function(evaluator._function), |
429 | 64 | _expr_name(evaluator._expr_name), |
430 | 64 | _agg_columns(evaluator._agg_columns), |
431 | 64 | _always_const_argument_idx(evaluator._always_const_argument_idx) { |
432 | 64 | if (evaluator._fn.binary_type == TFunctionBinaryType::JAVA_UDF) { |
433 | 0 | DataTypes tmp_argument_types; |
434 | 0 | tmp_argument_types.reserve(evaluator._input_exprs_ctxs.size()); |
435 | | // prepare for argument |
436 | 0 | for (auto& _input_exprs_ctx : evaluator._input_exprs_ctxs) { |
437 | 0 | auto data_type = _input_exprs_ctx->root()->data_type(); |
438 | 0 | tmp_argument_types.emplace_back(data_type); |
439 | 0 | } |
440 | 0 | const DataTypes& argument_types = |
441 | 0 | _real_argument_types.empty() ? tmp_argument_types : _real_argument_types; |
442 | 0 | _function = AggregateJavaUdaf::create(evaluator._fn, argument_types, evaluator._data_type); |
443 | 0 | THROW_IF_ERROR(static_cast<AggregateJavaUdaf*>(_function.get())->check_udaf(evaluator._fn)); |
444 | 0 | } |
445 | 64 | DCHECK(_function != nullptr); |
446 | | |
447 | 64 | _input_exprs_ctxs.resize(evaluator._input_exprs_ctxs.size()); |
448 | 128 | for (size_t i = 0; i < _input_exprs_ctxs.size(); i++) { |
449 | 64 | WARN_IF_ERROR(evaluator._input_exprs_ctxs[i]->clone(state, _input_exprs_ctxs[i]), ""); |
450 | 64 | } |
451 | 64 | } |
452 | | |
453 | | Status AggFnEvaluator::check_agg_fn_output(uint32_t key_size, |
454 | | const std::vector<AggFnEvaluator*>& agg_fn, |
455 | 0 | const RowDescriptor& output_row_desc) { |
456 | 0 | auto name_and_types = VectorizedUtils::create_name_and_data_types(output_row_desc); |
457 | 0 | for (uint32_t i = key_size, j = 0; i < name_and_types.size(); i++, j++) { |
458 | 0 | auto&& [name, column_type] = name_and_types[i]; |
459 | 0 | auto agg_return_type = agg_fn[j]->get_return_type(); |
460 | 0 | if (!column_type->equals(*agg_return_type)) { |
461 | 0 | if (!column_type->is_nullable() || agg_return_type->is_nullable() || |
462 | 0 | !remove_nullable(column_type)->equals(*agg_return_type)) { |
463 | 0 | return Status::InternalError( |
464 | 0 | "column_type not match data_types in agg node, column_type={}, " |
465 | 0 | "data_types={},column name={}", |
466 | 0 | column_type->get_name(), agg_return_type->get_name(), name); |
467 | 0 | } |
468 | 0 | } |
469 | 0 | } |
470 | 0 | return Status::OK(); |
471 | 0 | } |
472 | | |
473 | 0 | bool AggFnEvaluator::is_blockable() const { |
474 | 0 | return _function->is_blockable() || |
475 | 0 | std::any_of(_input_exprs_ctxs.begin(), _input_exprs_ctxs.end(), |
476 | 0 | [](VExprContextSPtr ctx) { return ctx->root()->is_blockable(); }); |
477 | 0 | } |
478 | | |
479 | | } // namespace doris |