Coverage Report

Created: 2026-10-19 18:18

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/root/doris/be/src/exprs/function_context.h
Line
Count
Source
1
// Licensed to the Apache Software Foundation (ASF) under one
2
// or more contributor license agreements.  See the NOTICE file
3
// distributed with this work for additional information
4
// regarding copyright ownership.  The ASF licenses this file
5
// to you under the Apache License, Version 2.0 (the
6
// "License"); you may not use this file except in compliance
7
// with the License.  You may obtain a copy of the License at
8
//
9
//   http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing,
12
// software distributed under the License is distributed on an
13
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
// KIND, either express or implied.  See the License for the
15
// specific language governing permissions and limitations
16
// under the License.
17
18
#pragma once
19
20
#include <gen_cpp/Types_types.h>
21
22
#include <cstdint>
23
#include <memory>
24
#include <optional>
25
#include <string>
26
#include <vector>
27
28
#include "core/arena.h"
29
#include "runtime/runtime_profile.h"
30
31
namespace cctz {
32
class time_zone;
33
}
34
35
namespace doris {
36
37
struct ColumnPtrWrapper;
38
struct StringRef;
39
class RuntimeState;
40
41
class IDataType;
42
using DataTypePtr = std::shared_ptr<const IDataType>;
43
44
// The FunctionContext is passed to every UDF/UDA and is the interface for UDF to
45
// rest of system. It contains APIs to examine system state, report errors
46
// and manage memory.
47
class FunctionContext {
48
public:
49
    enum FunctionStateScope {
50
        /// Indicates that function state for this FunctionContext's UDF is shared across
51
        /// plan fragment (a query is divided into multiple plan fragments, each of which
52
        /// is responsible for a part of query execution). Within plan fragment, there
53
        /// may be multiple instances of UDF executing concurrently with multiple
54
        /// FunctionContexts sharing this state, meaning that the state must be
55
        /// thread-safe. The Prepare() function for UDF may be called with this scope
56
        /// concurrently on a single host if UDF will be evaluated in multiple plan
57
        /// fragments on that host. In general, read-only state that doesn't need to be
58
        /// recomputed for every UDF call should be fragment-local.
59
        /// TODO: not yet implemented
60
        FRAGMENT_LOCAL,
61
62
        /// Indicates that function state is local to execution thread. This state
63
        /// does not need to be thread-safe. However, this state will be initialized (via the
64
        /// Prepare() function) once for every execution thread, so fragment-local state
65
        /// should be used when possible for better performance. In general, inexpensive
66
        /// shared state that is written to by the UDF (e.g. scratch space) should be
67
        /// thread-local.
68
        THREAD_LOCAL,
69
    };
70
71
    static std::unique_ptr<doris::FunctionContext> create_context(
72
            RuntimeState* state, const DataTypePtr& return_type,
73
            const std::vector<DataTypePtr>& arg_types);
74
75
    /// Returns a new FunctionContext with the same constant args, fragment-local state, and
76
    /// debug flag as this FunctionContext. The caller is responsible for calling delete on
77
    /// it.
78
    std::unique_ptr<doris::FunctionContext> clone();
79
80
    void set_constant_cols(const std::vector<std::shared_ptr<doris::ColumnPtrWrapper>>& cols);
81
82
50.0k
    RuntimeState* state() { return _state; }
83
84
    const cctz::time_zone* time_zone() const;
85
    const std::string& time_zone_name() const;
86
87
2
    void set_dict_function(const TDictFunction& dict_function) { _dict_function = dict_function; }
88
89
4
    std::optional<TDictFunction>& dict_function() { return _dict_function; };
90
14.1k
    bool check_overflow_for_decimal() const { return _check_overflow_for_decimal; }
91
92
35.5k
    bool enable_strict_mode() const { return _enable_strict_mode; }
93
94
8
    bool is_auto_partition_boundary_context() const { return _is_auto_partition_boundary_context; }
95
96
458
    bool set_check_overflow_for_decimal(bool check_overflow_for_decimal) {
97
458
        return _check_overflow_for_decimal = check_overflow_for_decimal;
98
458
    }
99
100
50.8k
    bool set_enable_strict_mode(bool enable_strict_mode) {
101
50.8k
        return _enable_strict_mode = enable_strict_mode;
102
50.8k
    }
103
104
0
    void set_auto_partition_boundary_context() { _is_auto_partition_boundary_context = true; }
105
106
48.2k
    void set_string_as_jsonb_string(bool string_as_jsonb_string) {
107
48.2k
        _string_as_jsonb_string = string_as_jsonb_string;
108
48.2k
    }
109
110
48.2k
    void set_jsonb_string_as_string(bool jsonb_string_as_string) {
111
48.2k
        _jsonb_string_as_string = jsonb_string_as_string;
112
48.2k
    }
113
114
0
    void set_udf_execute_timer(RuntimeProfile::Counter* udf_execute_timer) {
115
0
        _udf_execute_timer = udf_execute_timer;
116
0
    }
117
118
0
    RuntimeProfile::Counter* get_udf_execute_timer() { return _udf_execute_timer; }
119
120
    // Cast flag, when enable string_as_jsonb_string, string casting to jsonb will not parse string
121
    // instead just insert a string literal
122
47.7k
    bool string_as_jsonb_string() const { return _string_as_jsonb_string; }
123
124
    // Cast flag, when enable jsonb_string_as_string, jsonb string casting to string will not parse string
125
    // instead just insert a string literal
126
138
    bool jsonb_string_as_string() const { return _jsonb_string_as_string; }
127
128
    // Sets an error for this UDF. If this is called, this will trigger a
129
    // query to fail.
130
    // Note: when you set an error for UDFs used in Data Load, you should
131
    // ensure that the function return value is null.
132
    void set_error(const char* error_msg);
133
134
    // Adds a warning that is returned to the user. This can include things like
135
    // overflow or other recoverable error conditions.
136
    // Warnings are capped at a maximum number. Returns true if the warning was
137
    // added and false if it was ignored due to the cap.
138
    bool add_warning(const char* warning_msg);
139
140
    /// Methods for maintaining state across UDF/UDA function calls. SetFunctionState() can
141
    /// be used to store a pointer that can then be retrieved via GetFunctionState(). If
142
    /// GetFunctionState() is called when no pointer is set, it will return
143
    /// nullptr. SetFunctionState() does not take ownership of 'ptr'; it is up to the UDF/UDA
144
    /// to clean up any function state if necessary.
145
    void set_function_state(FunctionStateScope scope, std::shared_ptr<void> ptr);
146
147
    void* get_function_state(FunctionStateScope scope) const;
148
149
    // Returns the return type information of this function. For UDAs, this is the final
150
    // return type of the UDA (e.g., the type returned by the finalize function).
151
    const DataTypePtr get_return_type() const;
152
153
    // Returns the number of arguments to this function (not including the FunctionContext*
154
    // argument).
155
    int get_num_args() const;
156
157
    // Returns type information for the arg_idx-th argument (0-indexed, not including
158
    // the FunctionContext* argument). Returns nullptr if arg_idx is invalid.
159
    const DataTypePtr get_arg_type(int arg_idx) const;
160
161
    // Returns true if the arg_idx-th input argument (0 indexed, not including
162
    // the FunctionContext* argument) is a constant (e.g. 5, "string", 1 + 1).
163
    bool is_col_constant(int arg_idx) const;
164
165
    // Returns a pointer to the value of the arg_idx-th input argument (0 indexed, not
166
    // including the FunctionContext* argument). Returns nullptr if the argument is not
167
    // constant. This function can be used to obtain user-specified constants in a UDF's
168
    // Init() or Close() functions.
169
    doris::ColumnPtrWrapper* get_constant_col(int arg_idx) const;
170
171
    // Creates a StringRef, which memory is available when this function context is used next time
172
    StringRef create_temp_string_val(int64_t len);
173
174
100k
    ~FunctionContext() = default;
175
176
0
    Arena& get_arena() { return arena; }
177
178
private:
179
100k
    FunctionContext() = default;
180
181
    // Disable copy ctor and assignment operator
182
    FunctionContext(const FunctionContext& other);
183
184
    FunctionContext& operator=(const FunctionContext& other);
185
186
    // We use the query's runtime state to report errors and warnings. nullptr for test
187
    // contexts.
188
    RuntimeState* _state = nullptr;
189
190
    // Empty if there's no error
191
    std::string _error_msg;
192
193
    // The number of warnings reported.
194
    int64_t _num_warnings;
195
196
    /// The function state accessed via FunctionContext::Get/SetFunctionState()
197
    std::shared_ptr<void> _thread_local_fn_state;
198
    std::shared_ptr<void> _fragment_local_fn_state;
199
200
    // Type descriptor for the return type of the function.
201
    DataTypePtr _return_type;
202
203
    // Type descriptors for each argument of the function.
204
    std::vector<DataTypePtr> _arg_types;
205
206
    std::vector<std::shared_ptr<doris::ColumnPtrWrapper>> _constant_cols;
207
208
    // UDF execute timer
209
    RuntimeProfile::Counter* _udf_execute_timer = nullptr;
210
    bool _check_overflow_for_decimal = false;
211
    bool _enable_strict_mode = false;
212
    bool _is_auto_partition_boundary_context = false;
213
214
    bool _string_as_jsonb_string = false;
215
    bool _jsonb_string_as_string = false;
216
217
    std::string _string_result;
218
219
    Arena arena;
220
221
    std::optional<TDictFunction> _dict_function;
222
};
223
224
using doris::FunctionContext;
225
226
} // namespace doris