/root/doris/be/src/vec/functions/function.h
Line | Count | Source (jump to first uncovered line) |
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 | | // This file is copied from |
18 | | // https://github.com/ClickHouse/ClickHouse/blob/master/src/Functions/IFunction.h |
19 | | // and modified by Doris |
20 | | |
21 | | #pragma once |
22 | | |
23 | | #include <fmt/format.h> |
24 | | #include <glog/logging.h> |
25 | | #include <stddef.h> |
26 | | |
27 | | #include <memory> |
28 | | #include <ostream> |
29 | | #include <string> |
30 | | #include <utility> |
31 | | |
32 | | #include "common/exception.h" |
33 | | #include "common/status.h" |
34 | | #include "udf/udf.h" |
35 | | #include "vec/core/block.h" |
36 | | #include "vec/core/column_numbers.h" |
37 | | #include "vec/core/column_with_type_and_name.h" |
38 | | #include "vec/core/columns_with_type_and_name.h" |
39 | | #include "vec/core/types.h" |
40 | | #include "vec/data_types/data_type.h" |
41 | | #include "vec/data_types/data_type_nullable.h" |
42 | | |
43 | | namespace doris::vectorized { |
44 | | |
45 | | #define RETURN_REAL_TYPE_FOR_DATEV2_FUNCTION(TYPE) \ |
46 | 105 | bool is_nullable = false; \ |
47 | 105 | bool is_datev2 = false; \ |
48 | 155 | for (auto it : arguments) { \ |
49 | 155 | is_nullable = is_nullable || it.type->is_nullable(); \ |
50 | 155 | is_datev2 = is_datev2 || WhichDataType(remove_nullable(it.type)).is_date_v2() || \ |
51 | 155 | WhichDataType(remove_nullable(it.type)).is_date_time_v2(); \ |
52 | 155 | } \ |
53 | 105 | return is_nullable || !is_datev2 ? make_nullable(std::make_shared<TYPE>()) \ |
54 | 105 | : std::make_shared<TYPE>(); |
55 | | |
56 | | class Field; |
57 | | |
58 | | // Only use dispose the variadic argument |
59 | | template <typename T> |
60 | | auto has_variadic_argument_types(T&& arg) -> decltype(T::get_variadic_argument_types()) {}; |
61 | | void has_variadic_argument_types(...); |
62 | | |
63 | | struct NullPresence { |
64 | | bool has_nullable = false; |
65 | | bool has_null_constant = false; |
66 | | }; |
67 | | |
68 | | template <typename T> |
69 | | concept HasGetVariadicArgumentTypesImpl = requires(T t) { |
70 | | { t.get_variadic_argument_types_impl() } -> std::same_as<DataTypes>; |
71 | | }; |
72 | | |
73 | | NullPresence get_null_presence(const Block& block, const ColumnNumbers& args); |
74 | | [[maybe_unused]] NullPresence get_null_presence(const ColumnsWithTypeAndName& args); |
75 | | |
76 | | /// The simplest executable object. |
77 | | /// Motivation: |
78 | | /// * Prepare something heavy once before main execution loop instead of doing it for each block. |
79 | | /// * Provide const interface for IFunctionBase (later). |
80 | | class IPreparedFunction { |
81 | | public: |
82 | 2.26k | virtual ~IPreparedFunction() = default; |
83 | | |
84 | | /// Get the main function name. |
85 | | virtual String get_name() const = 0; |
86 | | |
87 | | virtual Status execute(FunctionContext* context, Block& block, const ColumnNumbers& arguments, |
88 | | size_t result, size_t input_rows_count, bool dry_run) = 0; |
89 | | }; |
90 | | |
91 | | using PreparedFunctionPtr = std::shared_ptr<IPreparedFunction>; |
92 | | |
93 | | class PreparedFunctionImpl : public IPreparedFunction { |
94 | | public: |
95 | | Status execute(FunctionContext* context, Block& block, const ColumnNumbers& arguments, |
96 | | size_t result, size_t input_rows_count, bool dry_run = false) final; |
97 | | |
98 | | /** If the function have non-zero number of arguments, |
99 | | * and if all arguments are constant, that we could automatically provide default implementation: |
100 | | * arguments are converted to ordinary columns with single value which is not const, then function is executed as usual, |
101 | | * and then the result is converted to constant column. |
102 | | */ |
103 | 984 | virtual bool use_default_implementation_for_constants() const { return true; } |
104 | | |
105 | | /** If use_default_implementation_for_nulls() is true, after execute the function, |
106 | | * whether need to replace the nested data of null data to the default value. |
107 | | * E.g. for binary arithmetic exprs, need return true to avoid false overflow. |
108 | | */ |
109 | 0 | virtual bool need_replace_null_data_to_default() const { return false; } |
110 | | |
111 | | protected: |
112 | | virtual Status execute_impl_dry_run(FunctionContext* context, Block& block, |
113 | | const ColumnNumbers& arguments, size_t result, |
114 | 0 | size_t input_rows_count) { |
115 | 0 | return execute_impl(context, block, arguments, result, input_rows_count); |
116 | 0 | } |
117 | | |
118 | | virtual Status execute_impl(FunctionContext* context, Block& block, |
119 | | const ColumnNumbers& arguments, size_t result, |
120 | | size_t input_rows_count) = 0; |
121 | | |
122 | | /** Default implementation in presence of Nullable arguments or NULL constants as arguments is the following: |
123 | | * if some of arguments are NULL constants then return NULL constant, |
124 | | * if some of arguments are Nullable, then execute function as usual for block, |
125 | | * where Nullable columns are substituted with nested columns (they have arbitrary values in rows corresponding to NULL value) |
126 | | * and wrap result in Nullable column where NULLs are in all rows where any of arguments are NULL. |
127 | | */ |
128 | 0 | virtual bool use_default_implementation_for_nulls() const { return true; } |
129 | | |
130 | | /** If function arguments has single low cardinality column and all other arguments are constants, call function on nested column. |
131 | | * Otherwise, convert all low cardinality columns to ordinary columns. |
132 | | * Returns ColumnLowCardinality if at least one argument is ColumnLowCardinality. |
133 | | */ |
134 | 0 | virtual bool use_default_implementation_for_low_cardinality_columns() const { return true; } |
135 | | |
136 | | /** Some arguments could remain constant during this implementation. |
137 | | * Every argument required const must write here and no checks elsewhere. |
138 | | */ |
139 | 0 | virtual ColumnNumbers get_arguments_that_are_always_constant() const { return {}; } |
140 | | |
141 | | private: |
142 | | Status default_implementation_for_nulls(FunctionContext* context, Block& block, |
143 | | const ColumnNumbers& args, size_t result, |
144 | | size_t input_rows_count, bool dry_run, bool* executed); |
145 | | Status default_implementation_for_constant_arguments(FunctionContext* context, Block& block, |
146 | | const ColumnNumbers& args, size_t result, |
147 | | size_t input_rows_count, bool dry_run, |
148 | | bool* executed); |
149 | | Status execute_without_low_cardinality_columns(FunctionContext* context, Block& block, |
150 | | const ColumnNumbers& arguments, size_t result, |
151 | | size_t input_rows_count, bool dry_run); |
152 | | Status _execute_skipped_constant_deal(FunctionContext* context, Block& block, |
153 | | const ColumnNumbers& args, size_t result, |
154 | | size_t input_rows_count, bool dry_run); |
155 | | }; |
156 | | |
157 | | /// Function with known arguments and return type. |
158 | | class IFunctionBase { |
159 | | public: |
160 | 2.26k | virtual ~IFunctionBase() = default; |
161 | | |
162 | | /// Get the main function name. |
163 | | virtual String get_name() const = 0; |
164 | | |
165 | | virtual const DataTypes& get_argument_types() const = 0; |
166 | | virtual const DataTypePtr& get_return_type() const = 0; |
167 | | |
168 | | /// Do preparations and return executable. |
169 | | /// sample_block should contain data types of arguments and values of constants, if relevant. |
170 | | virtual PreparedFunctionPtr prepare(FunctionContext* context, const Block& sample_block, |
171 | | const ColumnNumbers& arguments, size_t result) const = 0; |
172 | | |
173 | | /// Override this when function need to store state in the `FunctionContext`, or do some |
174 | | /// preparation work according to information from `FunctionContext`. |
175 | 260 | virtual Status open(FunctionContext* context, FunctionContext::FunctionStateScope scope) { |
176 | 260 | return Status::OK(); |
177 | 260 | } |
178 | | |
179 | | /// TODO: make const |
180 | | virtual Status execute(FunctionContext* context, Block& block, const ColumnNumbers& arguments, |
181 | 720 | size_t result, size_t input_rows_count, bool dry_run = false) { |
182 | 720 | return prepare(context, block, arguments, result) |
183 | 720 | ->execute(context, block, arguments, result, input_rows_count, dry_run); |
184 | 720 | } |
185 | | |
186 | | /// Do cleaning work when function is finished, i.e., release state variables in the |
187 | | /// `FunctionContext` which are registered in `prepare` phase. |
188 | 1.15k | virtual Status close(FunctionContext* context, FunctionContext::FunctionStateScope scope) { |
189 | 1.15k | return Status::OK(); |
190 | 1.15k | } |
191 | | |
192 | 0 | virtual bool is_stateful() const { return false; } |
193 | | |
194 | 0 | virtual bool can_fast_execute() const { return false; } |
195 | | |
196 | | /** Should we evaluate this function while constant folding, if arguments are constants? |
197 | | * Usually this is true. Notable counterexample is function 'sleep'. |
198 | | * If we will call it during query analysis, we will sleep extra amount of time. |
199 | | */ |
200 | 0 | virtual bool is_suitable_for_constant_folding() const { return true; } |
201 | | |
202 | | /** Some functions like ignore(...) or toTypeName(...) always return constant result which doesn't depend on arguments. |
203 | | * In this case we can calculate result and assume that it's constant in stream header. |
204 | | * There is no need to implement function if it has zero arguments. |
205 | | * Must return ColumnConst with single row or nullptr. |
206 | | */ |
207 | | virtual ColumnPtr get_result_if_always_returns_constant_and_has_arguments( |
208 | 0 | const Block& /*block*/, const ColumnNumbers& /*arguments*/) const { |
209 | 0 | return nullptr; |
210 | 0 | } |
211 | | |
212 | | /** Function is called "injective" if it returns different result for different values of arguments. |
213 | | * Example: hex, negate, tuple... |
214 | | * |
215 | | * Function could be injective with some arguments fixed to some constant values. |
216 | | * Examples: |
217 | | * plus(const, x); |
218 | | * multiply(const, x) where x is an integer and constant is not divisible by two; |
219 | | * concat(x, 'const'); |
220 | | * concat(x, 'const', y) where const contain at least one non-numeric character; |
221 | | * concat with FixedString |
222 | | * dictGet... functions takes name of dictionary as its argument, |
223 | | * and some dictionaries could be explicitly defined as injective. |
224 | | * |
225 | | * It could be used, for example, to remove useless function applications from GROUP BY. |
226 | | * |
227 | | * Sometimes, function is not really injective, but considered as injective, for purpose of query optimization. |
228 | | * For example, to_string function is not injective for Float64 data type, |
229 | | * as it returns 'nan' for many different representation of NaNs. |
230 | | * But we assume, that it is injective. This could be documented as implementation-specific behaviour. |
231 | | * |
232 | | * sample_block should contain data types of arguments and values of constants, if relevant. |
233 | | */ |
234 | 0 | virtual bool get_is_injective(const Block& /*sample_block*/) { return false; } |
235 | | |
236 | | /** Function is called "deterministic", if it returns same result for same values of arguments. |
237 | | * Most of functions are deterministic. Notable counterexample is rand(). |
238 | | * Sometimes, functions are "deterministic" in scope of single query |
239 | | * (even for distributed query), but not deterministic it general. |
240 | | * Example: now(). Another example: functions that work with periodically updated dictionaries. |
241 | | */ |
242 | | |
243 | | virtual bool is_deterministic() const = 0; |
244 | | |
245 | | virtual bool is_deterministic_in_scope_of_query() const = 0; |
246 | | |
247 | | /** Lets you know if the function is monotonic in a range of values. |
248 | | * This is used to work with the index in a sorted chunk of data. |
249 | | * And allows to use the index not only when it is written, for example `date >= const`, but also, for example, `toMonth(date) >= 11`. |
250 | | * All this is considered only for functions of one argument. |
251 | | */ |
252 | 0 | virtual bool has_information_about_monotonicity() const { return false; } |
253 | | |
254 | | virtual bool is_use_default_implementation_for_constants() const = 0; |
255 | | |
256 | | /// The property of monotonicity for a certain range. |
257 | | struct Monotonicity { |
258 | | bool is_monotonic = false; /// Is the function monotonous (nondecreasing or nonincreasing). |
259 | | bool is_positive = |
260 | | true; /// true if the function is nondecreasing, false, if notincreasing. If is_monotonic = false, then it does not matter. |
261 | | bool is_always_monotonic = |
262 | | false; /// Is true if function is monotonic on the whole input range I |
263 | | |
264 | | Monotonicity(bool is_monotonic_ = false, bool is_positive_ = true, |
265 | | bool is_always_monotonic_ = false) |
266 | | : is_monotonic(is_monotonic_), |
267 | | is_positive(is_positive_), |
268 | 0 | is_always_monotonic(is_always_monotonic_) {} |
269 | | }; |
270 | | |
271 | | /** Get information about monotonicity on a range of values. Call only if hasInformationAboutMonotonicity. |
272 | | * NULL can be passed as one of the arguments. This means that the corresponding range is unlimited on the left or on the right. |
273 | | */ |
274 | | virtual Monotonicity get_monotonicity_for_range(const IDataType& /*type*/, |
275 | | const Field& /*left*/, |
276 | 0 | const Field& /*right*/) const { |
277 | 0 | LOG(FATAL) << fmt::format("Function {} has no information about its monotonicity.", |
278 | 0 | get_name()); |
279 | 0 | return Monotonicity {}; |
280 | 0 | } |
281 | | }; |
282 | | |
283 | | using FunctionBasePtr = std::shared_ptr<IFunctionBase>; |
284 | | |
285 | | /// Creates IFunctionBase from argument types list. |
286 | | class IFunctionBuilder { |
287 | | public: |
288 | 3.22k | virtual ~IFunctionBuilder() = default; |
289 | | |
290 | | /// Get the main function name. |
291 | | virtual String get_name() const = 0; |
292 | | |
293 | | /// See the comment for the same method in IFunctionBase |
294 | | virtual bool is_deterministic() const = 0; |
295 | | |
296 | | virtual bool is_deterministic_in_scope_of_query() const = 0; |
297 | | |
298 | | /// Override and return true if function needs to depend on the state of the data. |
299 | | virtual bool is_stateful() const = 0; |
300 | | |
301 | | /// Override and return true if function could take different number of arguments. |
302 | | virtual bool is_variadic() const = 0; |
303 | | |
304 | | /// For non-variadic functions, return number of arguments; otherwise return zero (that should be ignored). |
305 | | virtual size_t get_number_of_arguments() const = 0; |
306 | | |
307 | | /// Throw if number of arguments is incorrect. Default implementation will check only in non-variadic case. |
308 | | virtual void check_number_of_arguments(size_t number_of_arguments) const = 0; |
309 | | |
310 | | /// Check arguments and return IFunctionBase. |
311 | | virtual FunctionBasePtr build(const ColumnsWithTypeAndName& arguments, |
312 | | const DataTypePtr& return_type) const = 0; |
313 | | |
314 | | /// For higher-order functions (functions, that have lambda expression as at least one argument). |
315 | | /// You pass data types with empty DataTypeFunction for lambda arguments. |
316 | | /// This function will replace it with DataTypeFunction containing actual types. |
317 | | virtual DataTypes get_variadic_argument_types() const = 0; |
318 | | |
319 | | /// Returns indexes of arguments, that must be ColumnConst |
320 | | virtual ColumnNumbers get_arguments_that_are_always_constant() const = 0; |
321 | | /// Returns indexes if arguments, that can be Nullable without making result of function Nullable |
322 | | /// (for functions like is_null(x)) |
323 | | virtual ColumnNumbers get_arguments_that_dont_imply_nullable_return_type( |
324 | | size_t number_of_arguments) const = 0; |
325 | | }; |
326 | | |
327 | | using FunctionBuilderPtr = std::shared_ptr<IFunctionBuilder>; |
328 | | |
329 | 0 | inline std::string get_types_string(const ColumnsWithTypeAndName& arguments) { |
330 | 0 | std::string types; |
331 | 0 | for (const auto& argument : arguments) { |
332 | 0 | if (!types.empty()) { |
333 | 0 | types += ", "; |
334 | 0 | } |
335 | 0 | types += argument.type->get_name(); |
336 | 0 | } |
337 | 0 | return types; |
338 | 0 | } |
339 | | |
340 | | /// used in function_factory. when we register a function, save a builder. to get a function, to get a builder. |
341 | | /// will use DefaultFunctionBuilder as the default builder in function's registration if we didn't explicitly specify. |
342 | | class FunctionBuilderImpl : public IFunctionBuilder { |
343 | | public: |
344 | | FunctionBasePtr build(const ColumnsWithTypeAndName& arguments, |
345 | 718 | const DataTypePtr& return_type) const final { |
346 | 718 | const DataTypePtr& func_return_type = get_return_type(arguments); |
347 | | // check return types equal. |
348 | 718 | if (!(return_type->equals(*func_return_type) || |
349 | | // For null constant argument, `get_return_type` would return |
350 | | // Nullable<DataTypeNothing> when `use_default_implementation_for_nulls` is true. |
351 | 718 | (return_type->is_nullable() && func_return_type->is_nullable() && |
352 | 2 | is_nothing(((DataTypeNullable*)func_return_type.get())->get_nested_type())) || |
353 | 718 | is_date_or_datetime_or_decimal(return_type, func_return_type) || |
354 | 718 | is_array_nested_type_date_or_datetime_or_decimal(return_type, func_return_type))) { |
355 | 0 | LOG_WARNING( |
356 | 0 | "function return type check failed, function_name={}, " |
357 | 0 | "expect_return_type={}, real_return_type={}, input_arguments={}", |
358 | 0 | get_name(), return_type->get_name(), func_return_type->get_name(), |
359 | 0 | get_types_string(arguments)); |
360 | 0 | return nullptr; |
361 | 0 | } |
362 | 718 | return build_impl(arguments, return_type); |
363 | 718 | } |
364 | | |
365 | 0 | bool is_deterministic() const override { return true; } |
366 | 0 | bool is_deterministic_in_scope_of_query() const override { return true; } |
367 | 0 | bool is_stateful() const override { return false; } |
368 | 372 | bool is_variadic() const override { return false; } |
369 | | |
370 | | // Default implementation. Will check only in non-variadic case. |
371 | | void check_number_of_arguments(size_t number_of_arguments) const override; |
372 | | // the return type should be same with what FE plans. |
373 | | // it returns: `get_return_type_impl` if `use_default_implementation_for_nulls` = false |
374 | | // `get_return_type_impl` warpped in NULL if `use_default_implementation_for_nulls` = true and input has NULL |
375 | | DataTypePtr get_return_type(const ColumnsWithTypeAndName& arguments) const; |
376 | | |
377 | 960 | DataTypes get_variadic_argument_types() const override { |
378 | 960 | return get_variadic_argument_types_impl(); |
379 | 960 | } |
380 | | |
381 | 0 | ColumnNumbers get_arguments_that_are_always_constant() const override { return {}; } |
382 | | ColumnNumbers get_arguments_that_dont_imply_nullable_return_type( |
383 | 0 | size_t /*number_of_arguments*/) const override { |
384 | 0 | return {}; |
385 | 0 | } |
386 | | |
387 | | protected: |
388 | | // Get the result type by argument type. If the function does not apply to these arguments, throw an exception. |
389 | | // the get_return_type_impl and its overrides should only return the nested type if `use_default_implementation_for_nulls` is true. |
390 | | // whether to wrap in nullable type will be automatically decided. |
391 | 453 | virtual DataTypePtr get_return_type_impl(const ColumnsWithTypeAndName& arguments) const { |
392 | 453 | DataTypes data_types(arguments.size()); |
393 | 1.24k | for (size_t i = 0; i < arguments.size(); ++i) data_types[i] = arguments[i].type; |
394 | | |
395 | 453 | return get_return_type_impl(data_types); |
396 | 453 | } |
397 | | |
398 | 0 | virtual DataTypePtr get_return_type_impl(const DataTypes& /*arguments*/) const { |
399 | 0 | LOG(FATAL) << fmt::format("get_return_type is not implemented for {}", get_name()); |
400 | 0 | return nullptr; |
401 | 0 | } |
402 | | |
403 | | /** If use_default_implementation_for_nulls() is true, than change arguments for get_return_type() and build_impl(): |
404 | | * if some of arguments are Nullable(Nothing) then don't call get_return_type(), call build_impl() with return_type = Nullable(Nothing), |
405 | | * if some of arguments are Nullable, then: |
406 | | * - Nullable types are substituted with nested types for get_return_type() function |
407 | | * - WRAP get_return_type() RESULT IN NULLABLE type and pass to build_impl |
408 | | * |
409 | | * Otherwise build returns build_impl(arguments, get_return_type(arguments)); |
410 | | */ |
411 | 0 | virtual bool use_default_implementation_for_nulls() const { return true; } |
412 | | |
413 | 0 | virtual bool need_replace_null_data_to_default() const { return false; } |
414 | | |
415 | | /** If use_default_implementation_for_nulls() is true, than change arguments for get_return_type() and build_impl(). |
416 | | * If function arguments has low cardinality types, convert them to ordinary types. |
417 | | * get_return_type returns ColumnLowCardinality if at least one argument type is ColumnLowCardinality. |
418 | | */ |
419 | 0 | virtual bool use_default_implementation_for_low_cardinality_columns() const { return true; } |
420 | | |
421 | | /// If it isn't, will convert all ColumnLowCardinality arguments to full columns. |
422 | 0 | virtual bool can_be_executed_on_low_cardinality_dictionary() const { return true; } |
423 | | |
424 | | /// return a real function object to execute. called in build(...). |
425 | | virtual FunctionBasePtr build_impl(const ColumnsWithTypeAndName& arguments, |
426 | | const DataTypePtr& return_type) const = 0; |
427 | | |
428 | 253 | virtual DataTypes get_variadic_argument_types_impl() const { return DataTypes(); } |
429 | | |
430 | | private: |
431 | | DataTypePtr get_return_type_without_low_cardinality( |
432 | | const ColumnsWithTypeAndName& arguments) const; |
433 | | |
434 | | bool is_date_or_datetime_or_decimal(const DataTypePtr& return_type, |
435 | | const DataTypePtr& func_return_type) const; |
436 | | bool is_array_nested_type_date_or_datetime_or_decimal( |
437 | | const DataTypePtr& return_type, const DataTypePtr& func_return_type) const; |
438 | | }; |
439 | | |
440 | | /// Previous function interface. |
441 | | class IFunction : public std::enable_shared_from_this<IFunction>, |
442 | | public FunctionBuilderImpl, |
443 | | public IFunctionBase, |
444 | | public PreparedFunctionImpl { |
445 | | public: |
446 | | String get_name() const override = 0; |
447 | | |
448 | 0 | bool is_stateful() const override { return false; } |
449 | | |
450 | | /// Notice: We should not change the column in the block, because the column may be shared by multiple expressions or exec nodes. |
451 | | virtual Status execute_impl(FunctionContext* context, Block& block, |
452 | | const ColumnNumbers& arguments, size_t result, |
453 | | size_t input_rows_count) override = 0; |
454 | | |
455 | | /// Override this functions to change default implementation behavior. See details in IMyFunction. |
456 | 752 | bool use_default_implementation_for_nulls() const override { return true; } |
457 | | |
458 | 0 | bool need_replace_null_data_to_default() const override { return false; } |
459 | | |
460 | 588 | bool use_default_implementation_for_low_cardinality_columns() const override { return true; } |
461 | | |
462 | | /// all constancy check should use this function to do automatically |
463 | 780 | ColumnNumbers get_arguments_that_are_always_constant() const override { return {}; } |
464 | 0 | bool can_be_executed_on_low_cardinality_dictionary() const override { |
465 | 0 | return is_deterministic_in_scope_of_query(); |
466 | 0 | } |
467 | 0 | bool is_deterministic() const override { return true; } |
468 | 0 | bool is_deterministic_in_scope_of_query() const override { return true; } |
469 | | |
470 | 0 | bool is_use_default_implementation_for_constants() const override { |
471 | 0 | return use_default_implementation_for_constants(); |
472 | 0 | } |
473 | | |
474 | | using PreparedFunctionImpl::execute; |
475 | | using PreparedFunctionImpl::execute_impl_dry_run; |
476 | | using FunctionBuilderImpl::get_return_type_impl; |
477 | | using FunctionBuilderImpl::get_variadic_argument_types_impl; |
478 | | using FunctionBuilderImpl::get_return_type; |
479 | | |
480 | | [[noreturn]] PreparedFunctionPtr prepare(FunctionContext* context, |
481 | | const Block& /*sample_block*/, |
482 | | const ColumnNumbers& /*arguments*/, |
483 | 0 | size_t /*result*/) const final { |
484 | 0 | LOG(FATAL) << "prepare is not implemented for IFunction"; |
485 | 0 | __builtin_unreachable(); |
486 | 0 | } |
487 | | |
488 | 870 | Status open(FunctionContext* context, FunctionContext::FunctionStateScope scope) override { |
489 | 870 | return Status::OK(); |
490 | 870 | } |
491 | | |
492 | 0 | [[noreturn]] const DataTypes& get_argument_types() const final { |
493 | 0 | LOG(FATAL) << "get_argument_types is not implemented for IFunction"; |
494 | 0 | __builtin_unreachable(); |
495 | 0 | } |
496 | | |
497 | 0 | [[noreturn]] const DataTypePtr& get_return_type() const final { |
498 | 0 | LOG(FATAL) << "get_return_type is not implemented for IFunction"; |
499 | 0 | __builtin_unreachable(); |
500 | 0 | } |
501 | | |
502 | | protected: |
503 | | FunctionBasePtr build_impl(const ColumnsWithTypeAndName& /*arguments*/, |
504 | 0 | const DataTypePtr& /*return_type*/) const final { |
505 | 0 | LOG(FATAL) << "build_impl is not implemented for IFunction"; |
506 | 0 | return {}; |
507 | 0 | } |
508 | | }; |
509 | | |
510 | | /// Wrappers over IFunction. If we (default)use DefaultFunction as wrapper, all function execution will go through this. |
511 | | |
512 | | class DefaultExecutable final : public PreparedFunctionImpl { |
513 | | public: |
514 | | explicit DefaultExecutable(std::shared_ptr<IFunction> function_) |
515 | 590 | : function(std::move(function_)) {} |
516 | | |
517 | 0 | String get_name() const override { return function->get_name(); } |
518 | | |
519 | | protected: |
520 | | Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments, |
521 | 590 | size_t result, size_t input_rows_count) final { |
522 | 590 | return function->execute_impl(context, block, arguments, result, input_rows_count); |
523 | 590 | } |
524 | | Status execute_impl_dry_run(FunctionContext* context, Block& block, |
525 | | const ColumnNumbers& arguments, size_t result, |
526 | 0 | size_t input_rows_count) final { |
527 | 0 | return function->execute_impl_dry_run(context, block, arguments, result, input_rows_count); |
528 | 0 | } |
529 | 870 | bool use_default_implementation_for_nulls() const final { |
530 | 870 | return function->use_default_implementation_for_nulls(); |
531 | 870 | } |
532 | 0 | bool need_replace_null_data_to_default() const final { |
533 | 0 | return function->need_replace_null_data_to_default(); |
534 | 0 | } |
535 | 870 | bool use_default_implementation_for_constants() const final { |
536 | 870 | return function->use_default_implementation_for_constants(); |
537 | 870 | } |
538 | 0 | bool use_default_implementation_for_low_cardinality_columns() const final { |
539 | 0 | return function->use_default_implementation_for_low_cardinality_columns(); |
540 | 0 | } |
541 | 870 | ColumnNumbers get_arguments_that_are_always_constant() const final { |
542 | 870 | return function->get_arguments_that_are_always_constant(); |
543 | 870 | } |
544 | | |
545 | | private: |
546 | | std::shared_ptr<IFunction> function; |
547 | | }; |
548 | | |
549 | | /* |
550 | | * when we register a function which didn't specify its base(i.e. inherited from IFunction), actually we use this as a wrapper. |
551 | | * it saves real implementation as `function`. |
552 | | */ |
553 | | class DefaultFunction final : public IFunctionBase { |
554 | | public: |
555 | | DefaultFunction(std::shared_ptr<IFunction> function_, DataTypes arguments_, |
556 | | DataTypePtr return_type_) |
557 | | : function(std::move(function_)), |
558 | | arguments(std::move(arguments_)), |
559 | 588 | return_type(std::move(return_type_)) {} |
560 | | |
561 | 0 | String get_name() const override { return function->get_name(); } |
562 | | |
563 | 0 | const DataTypes& get_argument_types() const override { return arguments; } |
564 | 0 | const DataTypePtr& get_return_type() const override { return return_type; } |
565 | | |
566 | | // return a default wrapper for IFunction. |
567 | | PreparedFunctionPtr prepare(FunctionContext* context, const Block& /*sample_block*/, |
568 | | const ColumnNumbers& /*arguments*/, |
569 | 590 | size_t /*result*/) const override { |
570 | 590 | return std::make_shared<DefaultExecutable>(function); |
571 | 590 | } |
572 | | |
573 | 1.08k | Status open(FunctionContext* context, FunctionContext::FunctionStateScope scope) override { |
574 | 1.08k | return function->open(context, scope); |
575 | 1.08k | } |
576 | | |
577 | 1.04k | Status close(FunctionContext* context, FunctionContext::FunctionStateScope scope) override { |
578 | 1.04k | return function->close(context, scope); |
579 | 1.04k | } |
580 | | |
581 | 0 | bool is_suitable_for_constant_folding() const override { |
582 | 0 | return function->is_suitable_for_constant_folding(); |
583 | 0 | } |
584 | | ColumnPtr get_result_if_always_returns_constant_and_has_arguments( |
585 | 0 | const Block& block, const ColumnNumbers& arguments_) const override { |
586 | 0 | return function->get_result_if_always_returns_constant_and_has_arguments(block, arguments_); |
587 | 0 | } |
588 | | |
589 | 0 | bool get_is_injective(const Block& sample_block) override { |
590 | 0 | return function->get_is_injective(sample_block); |
591 | 0 | } |
592 | | |
593 | 0 | bool is_deterministic() const override { return function->is_deterministic(); } |
594 | | |
595 | 2 | bool can_fast_execute() const override { |
596 | 2 | auto function_name = function->get_name(); |
597 | 2 | return function_name == "eq" || function_name == "ne" || function_name == "lt" || |
598 | 2 | function_name == "gt" || function_name == "le" || function_name == "ge" || |
599 | 2 | function_name == "in" || function_name == "not_in"; |
600 | 2 | } |
601 | | |
602 | 0 | bool is_deterministic_in_scope_of_query() const override { |
603 | 0 | return function->is_deterministic_in_scope_of_query(); |
604 | 0 | } |
605 | | |
606 | 0 | bool has_information_about_monotonicity() const override { |
607 | 0 | return function->has_information_about_monotonicity(); |
608 | 0 | } |
609 | | |
610 | | IFunctionBase::Monotonicity get_monotonicity_for_range(const IDataType& type, const Field& left, |
611 | 0 | const Field& right) const override { |
612 | 0 | return function->get_monotonicity_for_range(type, left, right); |
613 | 0 | } |
614 | | |
615 | 0 | bool is_use_default_implementation_for_constants() const override { |
616 | 0 | return function->is_use_default_implementation_for_constants(); |
617 | 0 | } |
618 | | |
619 | | private: |
620 | | std::shared_ptr<IFunction> function; |
621 | | DataTypes arguments; |
622 | | DataTypePtr return_type; |
623 | | }; |
624 | | |
625 | | class DefaultFunctionBuilder : public FunctionBuilderImpl { |
626 | | public: |
627 | | explicit DefaultFunctionBuilder(std::shared_ptr<IFunction> function_) |
628 | 1.54k | : function(std::move(function_)) {} |
629 | | |
630 | 588 | void check_number_of_arguments(size_t number_of_arguments) const override { |
631 | 588 | return function->check_number_of_arguments(number_of_arguments); |
632 | 588 | } |
633 | | |
634 | 0 | bool is_deterministic() const override { return function->is_deterministic(); } |
635 | 0 | bool is_deterministic_in_scope_of_query() const override { |
636 | 0 | return function->is_deterministic_in_scope_of_query(); |
637 | 0 | } |
638 | | |
639 | 0 | String get_name() const override { return function->get_name(); } |
640 | 0 | bool is_stateful() const override { return function->is_stateful(); } |
641 | 0 | bool is_variadic() const override { return function->is_variadic(); } |
642 | 0 | size_t get_number_of_arguments() const override { return function->get_number_of_arguments(); } |
643 | | |
644 | 0 | ColumnNumbers get_arguments_that_are_always_constant() const override { |
645 | 0 | return function->get_arguments_that_are_always_constant(); |
646 | 0 | } |
647 | | ColumnNumbers get_arguments_that_dont_imply_nullable_return_type( |
648 | 0 | size_t number_of_arguments) const override { |
649 | 0 | return function->get_arguments_that_dont_imply_nullable_return_type(number_of_arguments); |
650 | 0 | } |
651 | | |
652 | | protected: |
653 | 0 | DataTypePtr get_return_type_impl(const DataTypes& arguments) const override { |
654 | 0 | return function->get_return_type_impl(arguments); |
655 | 0 | } |
656 | 588 | DataTypePtr get_return_type_impl(const ColumnsWithTypeAndName& arguments) const override { |
657 | 588 | return function->get_return_type_impl(arguments); |
658 | 588 | } |
659 | | |
660 | 588 | bool use_default_implementation_for_nulls() const override { |
661 | 588 | return function->use_default_implementation_for_nulls(); |
662 | 588 | } |
663 | | |
664 | 0 | bool need_replace_null_data_to_default() const override { |
665 | 0 | return function->need_replace_null_data_to_default(); |
666 | 0 | } |
667 | 588 | bool use_default_implementation_for_low_cardinality_columns() const override { |
668 | 588 | return function->use_default_implementation_for_low_cardinality_columns(); |
669 | 588 | } |
670 | 0 | bool can_be_executed_on_low_cardinality_dictionary() const override { |
671 | 0 | return function->can_be_executed_on_low_cardinality_dictionary(); |
672 | 0 | } |
673 | | |
674 | | FunctionBasePtr build_impl(const ColumnsWithTypeAndName& arguments, |
675 | 588 | const DataTypePtr& return_type) const override { |
676 | 588 | DataTypes data_types(arguments.size()); |
677 | 1.59k | for (size_t i = 0; i < arguments.size(); ++i) { |
678 | 1.00k | data_types[i] = arguments[i].type; |
679 | 1.00k | } |
680 | 588 | return std::make_shared<DefaultFunction>(function, data_types, return_type); |
681 | 588 | } |
682 | | |
683 | 957 | DataTypes get_variadic_argument_types_impl() const override { |
684 | 957 | return function->get_variadic_argument_types_impl(); |
685 | 957 | } |
686 | | |
687 | | private: |
688 | | std::shared_ptr<IFunction> function; |
689 | | }; |
690 | | |
691 | | using FunctionPtr = std::shared_ptr<IFunction>; |
692 | | |
693 | | /** Return ColumnNullable of src, with null map as OR-ed null maps of args columns in blocks. |
694 | | * Or ColumnConst(ColumnNullable) if the result is always NULL or if the result is constant and always not NULL. |
695 | | */ |
696 | | ColumnPtr wrap_in_nullable(const ColumnPtr& src, const Block& block, const ColumnNumbers& args, |
697 | | size_t result, size_t input_rows_count); |
698 | | |
699 | | } // namespace doris::vectorized |