Coverage Report

Created: 2026-07-12 10:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
be/src/exprs/function/function_regexp.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 <glog/logging.h>
19
#include <re2/re2.h>
20
#include <re2/stringpiece.h>
21
#include <stddef.h>
22
23
#include <boost/regex.hpp>
24
#include <memory>
25
#include <string>
26
#include <string_view>
27
#include <type_traits>
28
#include <utility>
29
#include <vector>
30
31
#include "common/status.h"
32
#include "core/block/block.h"
33
#include "core/block/column_numbers.h"
34
#include "core/block/column_with_type_and_name.h"
35
#include "core/column/column.h"
36
#include "core/column/column_array.h"
37
#include "core/column/column_const.h"
38
#include "core/column/column_execute_util.h"
39
#include "core/column/column_nullable.h"
40
#include "core/column/column_string.h"
41
#include "core/column/column_vector.h"
42
#include "core/data_type/data_type.h"
43
#include "core/data_type/data_type_array.h"
44
#include "core/data_type/data_type_nullable.h"
45
#include "core/data_type/data_type_number.h"
46
#include "core/data_type/data_type_string.h"
47
#include "core/string_ref.h"
48
#include "core/types.h"
49
#include "exec/common/stringop_substring.h"
50
#include "exprs/aggregate/aggregate_function.h"
51
#include "exprs/function/function.h"
52
#include "exprs/function/simple_function_factory.h"
53
#include "exprs/function_context.h"
54
#include "exprs/string_functions.h"
55
56
namespace doris {
57
58
// Helper structure to hold either RE2 or Boost.Regex
59
struct RegexpExtractEngine {
60
    std::unique_ptr<re2::RE2> re2_regex;
61
    std::unique_ptr<boost::regex> boost_regex;
62
63
0
    bool is_boost() const { return boost_regex != nullptr; }
64
60
    bool is_re2() const { return re2_regex != nullptr; }
65
66
    // Try to compile with RE2 first, fallback to Boost.Regex if RE2 fails
67
    static bool compile(const StringRef& pattern, std::string* error_str,
68
35
                        RegexpExtractEngine& engine, bool enable_extended_regex) {
69
35
        re2::RE2::Options options;
70
35
        options.set_log_errors(false); // avoid RE2 printing to stderr; we handle errors ourselves
71
35
        options.set_dot_nl(true); // make '.' match '\n' by default, consistent with REGEXP/LIKE
72
35
        engine.re2_regex =
73
35
                std::make_unique<re2::RE2>(re2::StringPiece(pattern.data, pattern.size), options);
74
75
35
        if (engine.re2_regex->ok()) {
76
34
            return true;
77
34
        } else if (!enable_extended_regex) {
78
1
            *error_str = fmt::format(
79
1
                    "Invalid regex pattern: {}. Error: {}. If you need advanced regex features, "
80
1
                    "try setting enable_extended_regex=true",
81
1
                    std::string(pattern.data, pattern.size), engine.re2_regex->error());
82
1
            return false;
83
1
        }
84
85
        // RE2 failed, try Boost.Regex for advanced features like zero-width assertions
86
0
        engine.re2_regex.reset();
87
0
        try {
88
0
            boost::regex::flag_type flags = boost::regex::normal;
89
0
            engine.boost_regex = std::make_unique<boost::regex>(pattern.data,
90
0
                                                                pattern.data + pattern.size, flags);
91
0
            return true;
92
0
        } catch (const boost::regex_error& e) {
93
0
            if (error_str) {
94
0
                *error_str = fmt::format("Invalid regex pattern: {}. Error: {}",
95
0
                                         std::string(pattern.data, pattern.size), e.what());
96
0
            }
97
0
            return false;
98
0
        }
99
0
    }
100
101
    // Get number of capturing groups
102
30
    int number_of_capturing_groups() const {
103
30
        if (is_re2()) {
104
30
            return re2_regex->NumberOfCapturingGroups();
105
30
        } else if (is_boost()) {
106
0
            return static_cast<int>(boost_regex->mark_count());
107
0
        }
108
0
        return 0;
109
30
    }
110
111
    // Match function for extraction
112
16
    bool match_and_extract(const char* data, size_t size, int index, std::string& result) const {
113
16
        if (is_re2()) {
114
16
            int max_matches = 1 + re2_regex->NumberOfCapturingGroups();
115
16
            if (index >= max_matches) {
116
0
                return false;
117
0
            }
118
16
            std::vector<re2::StringPiece> matches(max_matches);
119
16
            bool success = re2_regex->Match(re2::StringPiece(data, size), 0, size,
120
16
                                            re2::RE2::UNANCHORED, matches.data(), max_matches);
121
16
            if (success && index < matches.size()) {
122
16
                const re2::StringPiece& match = matches[index];
123
16
                result.assign(match.data(), match.size());
124
16
                return true;
125
16
            }
126
0
            return false;
127
16
        } else if (is_boost()) {
128
0
            boost::cmatch matches;
129
0
            bool success = boost::regex_search(data, data + size, matches, *boost_regex);
130
0
            if (success && index < matches.size()) {
131
0
                result = matches[index].str();
132
0
                return true;
133
0
            }
134
0
            return false;
135
0
        }
136
0
        return false;
137
16
    }
138
139
    // Match all occurrences and extract the first capturing group
140
    void match_all_and_extract(const char* data, size_t size,
141
14
                               std::vector<std::string>& results) const {
142
14
        if (is_re2()) {
143
14
            int max_matches = 1 + re2_regex->NumberOfCapturingGroups();
144
14
            if (max_matches < 2) {
145
0
                return; // No capturing groups
146
0
            }
147
148
14
            size_t pos = 0;
149
34
            while (pos < size) {
150
31
                const char* str_pos = data + pos;
151
31
                size_t str_size = size - pos;
152
31
                std::vector<re2::StringPiece> matches(max_matches);
153
31
                bool success = re2_regex->Match(re2::StringPiece(str_pos, str_size), 0, str_size,
154
31
                                                re2::RE2::UNANCHORED, matches.data(), max_matches);
155
31
                if (!success) {
156
11
                    break;
157
11
                }
158
20
                if (matches[0].empty()) {
159
0
                    pos += 1;
160
0
                    continue;
161
0
                }
162
                // Extract first capturing group
163
20
                if (matches.size() > 1 && !matches[1].empty()) {
164
20
                    results.emplace_back(matches[1].data(), matches[1].size());
165
20
                }
166
                // Move position forward
167
20
                auto offset = std::string(str_pos, str_size)
168
20
                                      .find(std::string(matches[0].data(), matches[0].size()));
169
20
                pos += offset + matches[0].size();
170
20
            }
171
14
        } else if (is_boost()) {
172
0
            const char* search_start = data;
173
0
            const char* search_end = data + size;
174
0
            boost::match_results<const char*> matches;
175
176
0
            while (boost::regex_search(search_start, search_end, matches, *boost_regex)) {
177
0
                if (matches.size() > 1 && matches[1].matched) {
178
0
                    results.emplace_back(matches[1].str());
179
0
                }
180
0
                if (matches[0].length() == 0) {
181
0
                    if (search_start == search_end) {
182
0
                        break;
183
0
                    }
184
0
                    search_start += 1;
185
0
                } else {
186
0
                    search_start = matches[0].second;
187
0
                }
188
0
            }
189
0
        }
190
14
    }
191
};
192
193
struct RegexpCountImpl {
194
    using StringColumnView = ColumnView<TYPE_STRING>;
195
196
    static void execute_impl(FunctionContext* context, ColumnPtr argument_columns[],
197
13
                             size_t input_rows_count, ColumnInt32::Container& result_data) {
198
13
        auto str_col = StringColumnView::create(argument_columns[0]);
199
13
        auto pattern_col = StringColumnView::create(argument_columns[1]);
200
31
        for (size_t i = 0; i < input_rows_count; ++i) {
201
18
            DCHECK(!str_col.is_null_at(i));
202
18
            DCHECK(!pattern_col.is_null_at(i));
203
18
            result_data[i] = _execute_inner_loop(context, str_col, pattern_col, i);
204
18
        }
205
13
    }
206
    static int _execute_inner_loop(FunctionContext* context, const StringColumnView& str_col,
207
18
                                   const StringColumnView& pattern_col, const size_t index_now) {
208
18
        re2::RE2* re = reinterpret_cast<re2::RE2*>(
209
18
                context->get_function_state(FunctionContext::THREAD_LOCAL));
210
18
        std::unique_ptr<re2::RE2> scoped_re;
211
18
        if (re == nullptr) {
212
12
            std::string error_str;
213
12
            const auto pattern = pattern_col.value_at(index_now);
214
12
            bool st = StringFunctions::compile_regex(pattern, &error_str, StringRef(), StringRef(),
215
12
                                                     scoped_re);
216
12
            if (!st) {
217
0
                context->add_warning(error_str.c_str());
218
0
                throw Exception(Status::InvalidArgument(error_str));
219
0
                return 0;
220
0
            }
221
12
            re = scoped_re.get();
222
12
        }
223
224
18
        const auto str = str_col.value_at(index_now);
225
18
        int count = 0;
226
18
        size_t pos = 0;
227
70
        while (pos < str.size) {
228
64
            auto str_pos = str.data + pos;
229
64
            auto str_size = str.size - pos;
230
64
            re2::StringPiece str_sp_current = re2::StringPiece(str_pos, str_size);
231
64
            re2::StringPiece match;
232
233
64
            bool success = re->Match(str_sp_current, 0, str_size, re2::RE2::UNANCHORED, &match, 1);
234
64
            if (!success) {
235
12
                break;
236
12
            }
237
52
            if (match.empty()) {
238
20
                pos += 1;
239
20
                continue;
240
20
            }
241
32
            count++;
242
32
            size_t match_start = match.data() - str_sp_current.data();
243
32
            pos += match_start + match.size();
244
32
        }
245
246
18
        return count;
247
18
    }
248
};
249
250
class FunctionRegexpCount : public IFunction {
251
public:
252
    static constexpr auto name = "regexp_count";
253
254
21
    static FunctionPtr create() { return std::make_shared<FunctionRegexpCount>(); }
255
256
1
    String get_name() const override { return name; }
257
258
19
    size_t get_number_of_arguments() const override { return 2; }
259
260
19
    DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
261
19
        return std::make_shared<DataTypeInt32>();
262
19
    }
263
264
38
    Status open(FunctionContext* context, FunctionContext::FunctionStateScope scope) override {
265
38
        if (scope == FunctionContext::THREAD_LOCAL) {
266
19
            if (context->is_col_constant(1)) {
267
12
                DCHECK(!context->get_function_state(scope));
268
12
                const auto pattern_col = context->get_constant_col(1)->column_ptr;
269
12
                const auto& pattern = pattern_col->get_data_at(0);
270
12
                if (pattern.size == 0) {
271
4
                    return Status::OK();
272
4
                }
273
274
8
                std::string error_str;
275
8
                std::unique_ptr<re2::RE2> scoped_re;
276
8
                bool st = StringFunctions::compile_regex(pattern, &error_str, StringRef(),
277
8
                                                         StringRef(), scoped_re);
278
8
                if (!st) {
279
0
                    context->set_error(error_str.c_str());
280
0
                    return Status::InvalidArgument(error_str);
281
0
                }
282
8
                std::shared_ptr<re2::RE2> re(scoped_re.release());
283
8
                context->set_function_state(scope, re);
284
8
            }
285
19
        }
286
34
        return Status::OK();
287
38
    }
288
289
    Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
290
13
                        uint32_t result, size_t input_rows_count) const override {
291
13
        auto result_data_column = ColumnInt32::create(input_rows_count);
292
13
        auto& result_data = result_data_column->get_data();
293
294
13
        ColumnPtr argument_columns[2];
295
296
13
        argument_columns[0] = block.get_by_position(arguments[0]).column;
297
13
        argument_columns[1] = block.get_by_position(arguments[1]).column;
298
13
        RegexpCountImpl::execute_impl(context, argument_columns, input_rows_count, result_data);
299
300
13
        block.get_by_position(result).column = std::move(result_data_column);
301
13
        return Status::OK();
302
13
    }
303
};
304
305
struct ThreeParamTypes {
306
2
    static DataTypes get_variadic_argument_types() {
307
2
        return {std::make_shared<DataTypeString>(), std::make_shared<DataTypeString>(),
308
2
                std::make_shared<DataTypeString>()};
309
2
    }
310
};
311
312
struct FourParamTypes {
313
2
    static DataTypes get_variadic_argument_types() {
314
2
        return {std::make_shared<DataTypeString>(), std::make_shared<DataTypeString>(),
315
2
                std::make_shared<DataTypeString>(), std::make_shared<DataTypeString>()};
316
2
    }
317
};
318
319
// template FunctionRegexpFunctionality is used for regexp_replace/regexp_replace_one
320
template <typename Impl, typename ParamTypes>
321
class FunctionRegexpReplace : public IFunction {
322
public:
323
    static constexpr auto name = Impl::name;
324
325
24
    static FunctionPtr create() { return std::make_shared<FunctionRegexpReplace>(); }
_ZN5doris21FunctionRegexpReplaceINS_17RegexpReplaceImplILb0EEENS_15ThreeParamTypesEE6createEv
Line
Count
Source
325
10
    static FunctionPtr create() { return std::make_shared<FunctionRegexpReplace>(); }
_ZN5doris21FunctionRegexpReplaceINS_17RegexpReplaceImplILb0EEENS_14FourParamTypesEE6createEv
Line
Count
Source
325
2
    static FunctionPtr create() { return std::make_shared<FunctionRegexpReplace>(); }
_ZN5doris21FunctionRegexpReplaceINS_17RegexpReplaceImplILb1EEENS_15ThreeParamTypesEE6createEv
Line
Count
Source
325
10
    static FunctionPtr create() { return std::make_shared<FunctionRegexpReplace>(); }
_ZN5doris21FunctionRegexpReplaceINS_17RegexpReplaceImplILb1EEENS_14FourParamTypesEE6createEv
Line
Count
Source
325
2
    static FunctionPtr create() { return std::make_shared<FunctionRegexpReplace>(); }
326
327
0
    String get_name() const override { return name; }
Unexecuted instantiation: _ZNK5doris21FunctionRegexpReplaceINS_17RegexpReplaceImplILb0EEENS_15ThreeParamTypesEE8get_nameB5cxx11Ev
Unexecuted instantiation: _ZNK5doris21FunctionRegexpReplaceINS_17RegexpReplaceImplILb0EEENS_14FourParamTypesEE8get_nameB5cxx11Ev
Unexecuted instantiation: _ZNK5doris21FunctionRegexpReplaceINS_17RegexpReplaceImplILb1EEENS_15ThreeParamTypesEE8get_nameB5cxx11Ev
Unexecuted instantiation: _ZNK5doris21FunctionRegexpReplaceINS_17RegexpReplaceImplILb1EEENS_14FourParamTypesEE8get_nameB5cxx11Ev
328
329
0
    size_t get_number_of_arguments() const override {
330
0
        return get_variadic_argument_types_impl().size();
331
0
    }
Unexecuted instantiation: _ZNK5doris21FunctionRegexpReplaceINS_17RegexpReplaceImplILb0EEENS_15ThreeParamTypesEE23get_number_of_argumentsEv
Unexecuted instantiation: _ZNK5doris21FunctionRegexpReplaceINS_17RegexpReplaceImplILb0EEENS_14FourParamTypesEE23get_number_of_argumentsEv
Unexecuted instantiation: _ZNK5doris21FunctionRegexpReplaceINS_17RegexpReplaceImplILb1EEENS_15ThreeParamTypesEE23get_number_of_argumentsEv
Unexecuted instantiation: _ZNK5doris21FunctionRegexpReplaceINS_17RegexpReplaceImplILb1EEENS_14FourParamTypesEE23get_number_of_argumentsEv
332
333
20
    bool is_variadic() const override { return true; }
_ZNK5doris21FunctionRegexpReplaceINS_17RegexpReplaceImplILb0EEENS_15ThreeParamTypesEE11is_variadicEv
Line
Count
Source
333
9
    bool is_variadic() const override { return true; }
_ZNK5doris21FunctionRegexpReplaceINS_17RegexpReplaceImplILb0EEENS_14FourParamTypesEE11is_variadicEv
Line
Count
Source
333
1
    bool is_variadic() const override { return true; }
_ZNK5doris21FunctionRegexpReplaceINS_17RegexpReplaceImplILb1EEENS_15ThreeParamTypesEE11is_variadicEv
Line
Count
Source
333
9
    bool is_variadic() const override { return true; }
_ZNK5doris21FunctionRegexpReplaceINS_17RegexpReplaceImplILb1EEENS_14FourParamTypesEE11is_variadicEv
Line
Count
Source
333
1
    bool is_variadic() const override { return true; }
334
335
16
    DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
336
16
        return make_nullable(std::make_shared<DataTypeString>());
337
16
    }
_ZNK5doris21FunctionRegexpReplaceINS_17RegexpReplaceImplILb0EEENS_15ThreeParamTypesEE20get_return_type_implERKSt6vectorISt10shared_ptrIKNS_9IDataTypeEESaIS9_EE
Line
Count
Source
335
8
    DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
336
8
        return make_nullable(std::make_shared<DataTypeString>());
337
8
    }
Unexecuted instantiation: _ZNK5doris21FunctionRegexpReplaceINS_17RegexpReplaceImplILb0EEENS_14FourParamTypesEE20get_return_type_implERKSt6vectorISt10shared_ptrIKNS_9IDataTypeEESaIS9_EE
_ZNK5doris21FunctionRegexpReplaceINS_17RegexpReplaceImplILb1EEENS_15ThreeParamTypesEE20get_return_type_implERKSt6vectorISt10shared_ptrIKNS_9IDataTypeEESaIS9_EE
Line
Count
Source
335
8
    DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
336
8
        return make_nullable(std::make_shared<DataTypeString>());
337
8
    }
Unexecuted instantiation: _ZNK5doris21FunctionRegexpReplaceINS_17RegexpReplaceImplILb1EEENS_14FourParamTypesEE20get_return_type_implERKSt6vectorISt10shared_ptrIKNS_9IDataTypeEESaIS9_EE
338
339
4
    DataTypes get_variadic_argument_types_impl() const override {
340
4
        return ParamTypes::get_variadic_argument_types();
341
4
    }
_ZNK5doris21FunctionRegexpReplaceINS_17RegexpReplaceImplILb0EEENS_15ThreeParamTypesEE32get_variadic_argument_types_implEv
Line
Count
Source
339
1
    DataTypes get_variadic_argument_types_impl() const override {
340
1
        return ParamTypes::get_variadic_argument_types();
341
1
    }
_ZNK5doris21FunctionRegexpReplaceINS_17RegexpReplaceImplILb0EEENS_14FourParamTypesEE32get_variadic_argument_types_implEv
Line
Count
Source
339
1
    DataTypes get_variadic_argument_types_impl() const override {
340
1
        return ParamTypes::get_variadic_argument_types();
341
1
    }
_ZNK5doris21FunctionRegexpReplaceINS_17RegexpReplaceImplILb1EEENS_15ThreeParamTypesEE32get_variadic_argument_types_implEv
Line
Count
Source
339
1
    DataTypes get_variadic_argument_types_impl() const override {
340
1
        return ParamTypes::get_variadic_argument_types();
341
1
    }
_ZNK5doris21FunctionRegexpReplaceINS_17RegexpReplaceImplILb1EEENS_14FourParamTypesEE32get_variadic_argument_types_implEv
Line
Count
Source
339
1
    DataTypes get_variadic_argument_types_impl() const override {
340
1
        return ParamTypes::get_variadic_argument_types();
341
1
    }
342
343
32
    Status open(FunctionContext* context, FunctionContext::FunctionStateScope scope) override {
344
32
        if (scope == FunctionContext::THREAD_LOCAL) {
345
16
            if (context->is_col_constant(1)) {
346
16
                DCHECK(!context->get_function_state(scope));
347
16
                const auto pattern_col = context->get_constant_col(1)->column_ptr;
348
16
                const auto& pattern = pattern_col->get_data_at(0);
349
16
                if (pattern.size == 0) {
350
4
                    return Status::OK();
351
4
                }
352
353
12
                std::string error_str;
354
12
                std::unique_ptr<re2::RE2> scoped_re;
355
12
                StringRef options_value;
356
12
                if constexpr (std::is_same_v<FourParamTypes, ParamTypes>) {
357
0
                    DCHECK_EQ(context->get_num_args(), 4);
358
0
                    DCHECK(context->is_col_constant(3));
359
0
                    const auto options_col = context->get_constant_col(3)->column_ptr;
360
0
                    options_value = options_col->get_data_at(0);
361
0
                }
362
363
12
                bool st = StringFunctions::compile_regex(pattern, &error_str, StringRef(),
364
12
                                                         options_value, scoped_re);
365
12
                if (!st) {
366
0
                    context->set_error(error_str.c_str());
367
0
                    return Status::InvalidArgument(error_str);
368
0
                }
369
12
                std::shared_ptr<re2::RE2> re(scoped_re.release());
370
12
                context->set_function_state(scope, re);
371
12
            }
372
16
        }
373
28
        return Status::OK();
374
32
    }
_ZN5doris21FunctionRegexpReplaceINS_17RegexpReplaceImplILb0EEENS_15ThreeParamTypesEE4openEPNS_15FunctionContextENS5_18FunctionStateScopeE
Line
Count
Source
343
16
    Status open(FunctionContext* context, FunctionContext::FunctionStateScope scope) override {
344
16
        if (scope == FunctionContext::THREAD_LOCAL) {
345
8
            if (context->is_col_constant(1)) {
346
8
                DCHECK(!context->get_function_state(scope));
347
8
                const auto pattern_col = context->get_constant_col(1)->column_ptr;
348
8
                const auto& pattern = pattern_col->get_data_at(0);
349
8
                if (pattern.size == 0) {
350
2
                    return Status::OK();
351
2
                }
352
353
6
                std::string error_str;
354
6
                std::unique_ptr<re2::RE2> scoped_re;
355
6
                StringRef options_value;
356
                if constexpr (std::is_same_v<FourParamTypes, ParamTypes>) {
357
                    DCHECK_EQ(context->get_num_args(), 4);
358
                    DCHECK(context->is_col_constant(3));
359
                    const auto options_col = context->get_constant_col(3)->column_ptr;
360
                    options_value = options_col->get_data_at(0);
361
                }
362
363
6
                bool st = StringFunctions::compile_regex(pattern, &error_str, StringRef(),
364
6
                                                         options_value, scoped_re);
365
6
                if (!st) {
366
0
                    context->set_error(error_str.c_str());
367
0
                    return Status::InvalidArgument(error_str);
368
0
                }
369
6
                std::shared_ptr<re2::RE2> re(scoped_re.release());
370
6
                context->set_function_state(scope, re);
371
6
            }
372
8
        }
373
14
        return Status::OK();
374
16
    }
Unexecuted instantiation: _ZN5doris21FunctionRegexpReplaceINS_17RegexpReplaceImplILb0EEENS_14FourParamTypesEE4openEPNS_15FunctionContextENS5_18FunctionStateScopeE
_ZN5doris21FunctionRegexpReplaceINS_17RegexpReplaceImplILb1EEENS_15ThreeParamTypesEE4openEPNS_15FunctionContextENS5_18FunctionStateScopeE
Line
Count
Source
343
16
    Status open(FunctionContext* context, FunctionContext::FunctionStateScope scope) override {
344
16
        if (scope == FunctionContext::THREAD_LOCAL) {
345
8
            if (context->is_col_constant(1)) {
346
8
                DCHECK(!context->get_function_state(scope));
347
8
                const auto pattern_col = context->get_constant_col(1)->column_ptr;
348
8
                const auto& pattern = pattern_col->get_data_at(0);
349
8
                if (pattern.size == 0) {
350
2
                    return Status::OK();
351
2
                }
352
353
6
                std::string error_str;
354
6
                std::unique_ptr<re2::RE2> scoped_re;
355
6
                StringRef options_value;
356
                if constexpr (std::is_same_v<FourParamTypes, ParamTypes>) {
357
                    DCHECK_EQ(context->get_num_args(), 4);
358
                    DCHECK(context->is_col_constant(3));
359
                    const auto options_col = context->get_constant_col(3)->column_ptr;
360
                    options_value = options_col->get_data_at(0);
361
                }
362
363
6
                bool st = StringFunctions::compile_regex(pattern, &error_str, StringRef(),
364
6
                                                         options_value, scoped_re);
365
6
                if (!st) {
366
0
                    context->set_error(error_str.c_str());
367
0
                    return Status::InvalidArgument(error_str);
368
0
                }
369
6
                std::shared_ptr<re2::RE2> re(scoped_re.release());
370
6
                context->set_function_state(scope, re);
371
6
            }
372
8
        }
373
14
        return Status::OK();
374
16
    }
Unexecuted instantiation: _ZN5doris21FunctionRegexpReplaceINS_17RegexpReplaceImplILb1EEENS_14FourParamTypesEE4openEPNS_15FunctionContextENS5_18FunctionStateScopeE
375
376
    Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
377
12
                        uint32_t result, size_t input_rows_count) const override {
378
12
        size_t argument_size = arguments.size();
379
380
12
        auto result_null_map = ColumnUInt8::create(input_rows_count, 0);
381
12
        auto result_data_column = ColumnString::create();
382
12
        auto& result_data = result_data_column->get_chars();
383
12
        auto& result_offset = result_data_column->get_offsets();
384
12
        result_offset.resize(input_rows_count);
385
386
12
        bool col_const[3];
387
12
        ColumnPtr argument_columns[3];
388
48
        for (int i = 0; i < 3; ++i) {
389
36
            col_const[i] = is_column_const(*block.get_by_position(arguments[i]).column);
390
36
        }
391
12
        argument_columns[0] = col_const[0] ? static_cast<const ColumnConst&>(
392
0
                                                     *block.get_by_position(arguments[0]).column)
393
0
                                                     .convert_to_full_column()
394
12
                                           : block.get_by_position(arguments[0]).column;
395
396
12
        default_preprocess_parameter_columns(argument_columns, col_const, {1, 2}, block, arguments);
397
398
12
        StringRef options_value;
399
12
        if (col_const[1] && col_const[2]) {
400
0
            Impl::execute_impl_const_args(context, argument_columns, options_value,
401
0
                                          input_rows_count, result_data, result_offset,
402
0
                                          result_null_map->get_data());
403
12
        } else {
404
            // the options have check in FE, so is always const, and get idx of 0
405
12
            if (argument_size == 4) {
406
0
                options_value = block.get_by_position(arguments[3]).column->get_data_at(0);
407
0
            }
408
12
            Impl::execute_impl(context, argument_columns, options_value, input_rows_count,
409
12
                               result_data, result_offset, result_null_map->get_data());
410
12
        }
411
412
12
        block.get_by_position(result).column =
413
12
                ColumnNullable::create(std::move(result_data_column), std::move(result_null_map));
414
12
        return Status::OK();
415
12
    }
_ZNK5doris21FunctionRegexpReplaceINS_17RegexpReplaceImplILb0EEENS_15ThreeParamTypesEE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjm
Line
Count
Source
377
6
                        uint32_t result, size_t input_rows_count) const override {
378
6
        size_t argument_size = arguments.size();
379
380
6
        auto result_null_map = ColumnUInt8::create(input_rows_count, 0);
381
6
        auto result_data_column = ColumnString::create();
382
6
        auto& result_data = result_data_column->get_chars();
383
6
        auto& result_offset = result_data_column->get_offsets();
384
6
        result_offset.resize(input_rows_count);
385
386
6
        bool col_const[3];
387
6
        ColumnPtr argument_columns[3];
388
24
        for (int i = 0; i < 3; ++i) {
389
18
            col_const[i] = is_column_const(*block.get_by_position(arguments[i]).column);
390
18
        }
391
6
        argument_columns[0] = col_const[0] ? static_cast<const ColumnConst&>(
392
0
                                                     *block.get_by_position(arguments[0]).column)
393
0
                                                     .convert_to_full_column()
394
6
                                           : block.get_by_position(arguments[0]).column;
395
396
6
        default_preprocess_parameter_columns(argument_columns, col_const, {1, 2}, block, arguments);
397
398
6
        StringRef options_value;
399
6
        if (col_const[1] && col_const[2]) {
400
0
            Impl::execute_impl_const_args(context, argument_columns, options_value,
401
0
                                          input_rows_count, result_data, result_offset,
402
0
                                          result_null_map->get_data());
403
6
        } else {
404
            // the options have check in FE, so is always const, and get idx of 0
405
6
            if (argument_size == 4) {
406
0
                options_value = block.get_by_position(arguments[3]).column->get_data_at(0);
407
0
            }
408
6
            Impl::execute_impl(context, argument_columns, options_value, input_rows_count,
409
6
                               result_data, result_offset, result_null_map->get_data());
410
6
        }
411
412
6
        block.get_by_position(result).column =
413
6
                ColumnNullable::create(std::move(result_data_column), std::move(result_null_map));
414
6
        return Status::OK();
415
6
    }
Unexecuted instantiation: _ZNK5doris21FunctionRegexpReplaceINS_17RegexpReplaceImplILb0EEENS_14FourParamTypesEE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjm
_ZNK5doris21FunctionRegexpReplaceINS_17RegexpReplaceImplILb1EEENS_15ThreeParamTypesEE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjm
Line
Count
Source
377
6
                        uint32_t result, size_t input_rows_count) const override {
378
6
        size_t argument_size = arguments.size();
379
380
6
        auto result_null_map = ColumnUInt8::create(input_rows_count, 0);
381
6
        auto result_data_column = ColumnString::create();
382
6
        auto& result_data = result_data_column->get_chars();
383
6
        auto& result_offset = result_data_column->get_offsets();
384
6
        result_offset.resize(input_rows_count);
385
386
6
        bool col_const[3];
387
6
        ColumnPtr argument_columns[3];
388
24
        for (int i = 0; i < 3; ++i) {
389
18
            col_const[i] = is_column_const(*block.get_by_position(arguments[i]).column);
390
18
        }
391
6
        argument_columns[0] = col_const[0] ? static_cast<const ColumnConst&>(
392
0
                                                     *block.get_by_position(arguments[0]).column)
393
0
                                                     .convert_to_full_column()
394
6
                                           : block.get_by_position(arguments[0]).column;
395
396
6
        default_preprocess_parameter_columns(argument_columns, col_const, {1, 2}, block, arguments);
397
398
6
        StringRef options_value;
399
6
        if (col_const[1] && col_const[2]) {
400
0
            Impl::execute_impl_const_args(context, argument_columns, options_value,
401
0
                                          input_rows_count, result_data, result_offset,
402
0
                                          result_null_map->get_data());
403
6
        } else {
404
            // the options have check in FE, so is always const, and get idx of 0
405
6
            if (argument_size == 4) {
406
0
                options_value = block.get_by_position(arguments[3]).column->get_data_at(0);
407
0
            }
408
6
            Impl::execute_impl(context, argument_columns, options_value, input_rows_count,
409
6
                               result_data, result_offset, result_null_map->get_data());
410
6
        }
411
412
6
        block.get_by_position(result).column =
413
6
                ColumnNullable::create(std::move(result_data_column), std::move(result_null_map));
414
6
        return Status::OK();
415
6
    }
Unexecuted instantiation: _ZNK5doris21FunctionRegexpReplaceINS_17RegexpReplaceImplILb1EEENS_14FourParamTypesEE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjm
416
};
417
418
template <bool ReplaceOne>
419
struct RegexpReplaceImpl {
420
    static constexpr auto name = ReplaceOne ? "regexp_replace_one" : "regexp_replace";
421
422
    static void execute_impl(FunctionContext* context, ColumnPtr argument_columns[],
423
                             const StringRef& options_value, size_t input_rows_count,
424
                             ColumnString::Chars& result_data, ColumnString::Offsets& result_offset,
425
12
                             NullMap& null_map) {
426
12
        const auto* str_col = check_and_get_column<ColumnString>(argument_columns[0].get());
427
12
        const auto* pattern_col = check_and_get_column<ColumnString>(argument_columns[1].get());
428
12
        const auto* replace_col = check_and_get_column<ColumnString>(argument_columns[2].get());
429
430
24
        for (size_t i = 0; i < input_rows_count; ++i) {
431
12
            _execute_inner_loop<false>(context, str_col, pattern_col, replace_col, options_value,
432
12
                                       result_data, result_offset, null_map, i);
433
12
        }
434
12
    }
_ZN5doris17RegexpReplaceImplILb0EE12execute_implEPNS_15FunctionContextEPNS_3COWINS_7IColumnEE13immutable_ptrIS5_EERKNS_9StringRefEmRNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEERNSD_IjLm4096ESG_Lm16ELm15EEESI_
Line
Count
Source
425
6
                             NullMap& null_map) {
426
6
        const auto* str_col = check_and_get_column<ColumnString>(argument_columns[0].get());
427
6
        const auto* pattern_col = check_and_get_column<ColumnString>(argument_columns[1].get());
428
6
        const auto* replace_col = check_and_get_column<ColumnString>(argument_columns[2].get());
429
430
12
        for (size_t i = 0; i < input_rows_count; ++i) {
431
6
            _execute_inner_loop<false>(context, str_col, pattern_col, replace_col, options_value,
432
6
                                       result_data, result_offset, null_map, i);
433
6
        }
434
6
    }
_ZN5doris17RegexpReplaceImplILb1EE12execute_implEPNS_15FunctionContextEPNS_3COWINS_7IColumnEE13immutable_ptrIS5_EERKNS_9StringRefEmRNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEERNSD_IjLm4096ESG_Lm16ELm15EEESI_
Line
Count
Source
425
6
                             NullMap& null_map) {
426
6
        const auto* str_col = check_and_get_column<ColumnString>(argument_columns[0].get());
427
6
        const auto* pattern_col = check_and_get_column<ColumnString>(argument_columns[1].get());
428
6
        const auto* replace_col = check_and_get_column<ColumnString>(argument_columns[2].get());
429
430
12
        for (size_t i = 0; i < input_rows_count; ++i) {
431
6
            _execute_inner_loop<false>(context, str_col, pattern_col, replace_col, options_value,
432
6
                                       result_data, result_offset, null_map, i);
433
6
        }
434
6
    }
435
436
    static void execute_impl_const_args(FunctionContext* context, ColumnPtr argument_columns[],
437
                                        const StringRef& options_value, size_t input_rows_count,
438
                                        ColumnString::Chars& result_data,
439
0
                                        ColumnString::Offsets& result_offset, NullMap& null_map) {
440
0
        const auto* str_col = check_and_get_column<ColumnString>(argument_columns[0].get());
441
0
        const auto* pattern_col = check_and_get_column<ColumnString>(argument_columns[1].get());
442
0
        const auto* replace_col = check_and_get_column<ColumnString>(argument_columns[2].get());
443
444
0
        for (size_t i = 0; i < input_rows_count; ++i) {
445
0
            _execute_inner_loop<true>(context, str_col, pattern_col, replace_col, options_value,
446
0
                                      result_data, result_offset, null_map, i);
447
0
        }
448
0
    }
Unexecuted instantiation: _ZN5doris17RegexpReplaceImplILb0EE23execute_impl_const_argsEPNS_15FunctionContextEPNS_3COWINS_7IColumnEE13immutable_ptrIS5_EERKNS_9StringRefEmRNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEERNSD_IjLm4096ESG_Lm16ELm15EEESI_
Unexecuted instantiation: _ZN5doris17RegexpReplaceImplILb1EE23execute_impl_const_argsEPNS_15FunctionContextEPNS_3COWINS_7IColumnEE13immutable_ptrIS5_EERKNS_9StringRefEmRNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEERNSD_IjLm4096ESG_Lm16ELm15EEESI_
449
450
    template <bool Const>
451
    static void _execute_inner_loop(FunctionContext* context, const ColumnString* str_col,
452
                                    const ColumnString* pattern_col,
453
                                    const ColumnString* replace_col, const StringRef& options_value,
454
                                    ColumnString::Chars& result_data,
455
                                    ColumnString::Offsets& result_offset, NullMap& null_map,
456
12
                                    const size_t index_now) {
457
12
        re2::RE2* re = reinterpret_cast<re2::RE2*>(
458
12
                context->get_function_state(FunctionContext::THREAD_LOCAL));
459
12
        std::unique_ptr<re2::RE2> scoped_re; // destroys re if state->re is nullptr
460
12
        if (re == nullptr) {
461
4
            std::string error_str;
462
4
            const auto& pattern = pattern_col->get_data_at(index_check_const(index_now, Const));
463
4
            bool st = StringFunctions::compile_regex(pattern, &error_str, StringRef(),
464
4
                                                     options_value, scoped_re);
465
4
            if (!st) {
466
0
                context->add_warning(error_str.c_str());
467
0
                StringOP::push_null_string(index_now, result_data, result_offset, null_map);
468
0
                return;
469
0
            }
470
4
            re = scoped_re.get();
471
4
        }
472
473
12
        re2::StringPiece replace_str = re2::StringPiece(
474
12
                replace_col->get_data_at(index_check_const(index_now, Const)).to_string_view());
475
476
12
        std::string result_str(str_col->get_data_at(index_now).to_string());
477
12
        if constexpr (ReplaceOne) {
478
6
            re2::RE2::Replace(&result_str, *re, replace_str);
479
6
        } else {
480
6
            re2::RE2::GlobalReplace(&result_str, *re, replace_str);
481
6
        }
482
12
        StringOP::push_value_string(result_str, index_now, result_data, result_offset);
483
12
    }
Unexecuted instantiation: _ZN5doris17RegexpReplaceImplILb0EE19_execute_inner_loopILb1EEEvPNS_15FunctionContextEPKNS_9ColumnStrIjEES8_S8_RKNS_9StringRefERNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEERNSC_IjLm4096ESF_Lm16ELm15EEESH_m
_ZN5doris17RegexpReplaceImplILb0EE19_execute_inner_loopILb0EEEvPNS_15FunctionContextEPKNS_9ColumnStrIjEES8_S8_RKNS_9StringRefERNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEERNSC_IjLm4096ESF_Lm16ELm15EEESH_m
Line
Count
Source
456
6
                                    const size_t index_now) {
457
6
        re2::RE2* re = reinterpret_cast<re2::RE2*>(
458
6
                context->get_function_state(FunctionContext::THREAD_LOCAL));
459
6
        std::unique_ptr<re2::RE2> scoped_re; // destroys re if state->re is nullptr
460
6
        if (re == nullptr) {
461
2
            std::string error_str;
462
2
            const auto& pattern = pattern_col->get_data_at(index_check_const(index_now, Const));
463
2
            bool st = StringFunctions::compile_regex(pattern, &error_str, StringRef(),
464
2
                                                     options_value, scoped_re);
465
2
            if (!st) {
466
0
                context->add_warning(error_str.c_str());
467
0
                StringOP::push_null_string(index_now, result_data, result_offset, null_map);
468
0
                return;
469
0
            }
470
2
            re = scoped_re.get();
471
2
        }
472
473
6
        re2::StringPiece replace_str = re2::StringPiece(
474
6
                replace_col->get_data_at(index_check_const(index_now, Const)).to_string_view());
475
476
6
        std::string result_str(str_col->get_data_at(index_now).to_string());
477
        if constexpr (ReplaceOne) {
478
            re2::RE2::Replace(&result_str, *re, replace_str);
479
6
        } else {
480
6
            re2::RE2::GlobalReplace(&result_str, *re, replace_str);
481
6
        }
482
6
        StringOP::push_value_string(result_str, index_now, result_data, result_offset);
483
6
    }
Unexecuted instantiation: _ZN5doris17RegexpReplaceImplILb1EE19_execute_inner_loopILb1EEEvPNS_15FunctionContextEPKNS_9ColumnStrIjEES8_S8_RKNS_9StringRefERNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEERNSC_IjLm4096ESF_Lm16ELm15EEESH_m
_ZN5doris17RegexpReplaceImplILb1EE19_execute_inner_loopILb0EEEvPNS_15FunctionContextEPKNS_9ColumnStrIjEES8_S8_RKNS_9StringRefERNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEERNSC_IjLm4096ESF_Lm16ELm15EEESH_m
Line
Count
Source
456
6
                                    const size_t index_now) {
457
6
        re2::RE2* re = reinterpret_cast<re2::RE2*>(
458
6
                context->get_function_state(FunctionContext::THREAD_LOCAL));
459
6
        std::unique_ptr<re2::RE2> scoped_re; // destroys re if state->re is nullptr
460
6
        if (re == nullptr) {
461
2
            std::string error_str;
462
2
            const auto& pattern = pattern_col->get_data_at(index_check_const(index_now, Const));
463
2
            bool st = StringFunctions::compile_regex(pattern, &error_str, StringRef(),
464
2
                                                     options_value, scoped_re);
465
2
            if (!st) {
466
0
                context->add_warning(error_str.c_str());
467
0
                StringOP::push_null_string(index_now, result_data, result_offset, null_map);
468
0
                return;
469
0
            }
470
2
            re = scoped_re.get();
471
2
        }
472
473
6
        re2::StringPiece replace_str = re2::StringPiece(
474
6
                replace_col->get_data_at(index_check_const(index_now, Const)).to_string_view());
475
476
6
        std::string result_str(str_col->get_data_at(index_now).to_string());
477
6
        if constexpr (ReplaceOne) {
478
6
            re2::RE2::Replace(&result_str, *re, replace_str);
479
        } else {
480
            re2::RE2::GlobalReplace(&result_str, *re, replace_str);
481
        }
482
6
        StringOP::push_value_string(result_str, index_now, result_data, result_offset);
483
6
    }
484
};
485
486
template <bool ReturnNull>
487
struct RegexpExtractImpl {
488
    static constexpr auto name = ReturnNull ? "regexp_extract_or_null" : "regexp_extract";
489
    static constexpr size_t num_args = 3;
490
    static constexpr size_t PATTERN_ARG_IDX = 1;
491
492
20
    static DataTypePtr return_type() { return make_nullable(std::make_shared<DataTypeString>()); }
_ZN5doris17RegexpExtractImplILb1EE11return_typeEv
Line
Count
Source
492
10
    static DataTypePtr return_type() { return make_nullable(std::make_shared<DataTypeString>()); }
_ZN5doris17RegexpExtractImplILb0EE11return_typeEv
Line
Count
Source
492
10
    static DataTypePtr return_type() { return make_nullable(std::make_shared<DataTypeString>()); }
493
494
    static Status execute(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
495
16
                          uint32_t result, size_t input_rows_count) {
496
16
        bool col_const[3];
497
16
        ColumnPtr argument_columns[3];
498
64
        for (int i = 0; i < 3; ++i) {
499
48
            col_const[i] = is_column_const(*block.get_by_position(arguments[i]).column);
500
48
        }
501
16
        argument_columns[0] = col_const[0] ? static_cast<const ColumnConst&>(
502
0
                                                     *block.get_by_position(arguments[0]).column)
503
0
                                                     .convert_to_full_column()
504
16
                                           : block.get_by_position(arguments[0]).column;
505
506
16
        auto result_null_map = ColumnUInt8::create(input_rows_count, 0);
507
16
        auto result_data_column = ColumnString::create();
508
16
        auto& result_data = result_data_column->get_chars();
509
16
        auto& result_offset = result_data_column->get_offsets();
510
16
        result_offset.resize(input_rows_count);
511
16
        auto& null_map = result_null_map->get_data();
512
513
16
        default_preprocess_parameter_columns(argument_columns, col_const, {1, 2}, block, arguments);
514
515
16
        if (col_const[1] && col_const[2]) {
516
0
            _execute_loop<true>(context, argument_columns, input_rows_count, result_data,
517
0
                                result_offset, null_map);
518
16
        } else {
519
16
            _execute_loop<false>(context, argument_columns, input_rows_count, result_data,
520
16
                                 result_offset, null_map);
521
16
        }
522
523
16
        block.get_by_position(result).column =
524
16
                ColumnNullable::create(std::move(result_data_column), std::move(result_null_map));
525
16
        return Status::OK();
526
16
    }
_ZN5doris17RegexpExtractImplILb1EE7executeEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjm
Line
Count
Source
495
8
                          uint32_t result, size_t input_rows_count) {
496
8
        bool col_const[3];
497
8
        ColumnPtr argument_columns[3];
498
32
        for (int i = 0; i < 3; ++i) {
499
24
            col_const[i] = is_column_const(*block.get_by_position(arguments[i]).column);
500
24
        }
501
8
        argument_columns[0] = col_const[0] ? static_cast<const ColumnConst&>(
502
0
                                                     *block.get_by_position(arguments[0]).column)
503
0
                                                     .convert_to_full_column()
504
8
                                           : block.get_by_position(arguments[0]).column;
505
506
8
        auto result_null_map = ColumnUInt8::create(input_rows_count, 0);
507
8
        auto result_data_column = ColumnString::create();
508
8
        auto& result_data = result_data_column->get_chars();
509
8
        auto& result_offset = result_data_column->get_offsets();
510
8
        result_offset.resize(input_rows_count);
511
8
        auto& null_map = result_null_map->get_data();
512
513
8
        default_preprocess_parameter_columns(argument_columns, col_const, {1, 2}, block, arguments);
514
515
8
        if (col_const[1] && col_const[2]) {
516
0
            _execute_loop<true>(context, argument_columns, input_rows_count, result_data,
517
0
                                result_offset, null_map);
518
8
        } else {
519
8
            _execute_loop<false>(context, argument_columns, input_rows_count, result_data,
520
8
                                 result_offset, null_map);
521
8
        }
522
523
8
        block.get_by_position(result).column =
524
8
                ColumnNullable::create(std::move(result_data_column), std::move(result_null_map));
525
8
        return Status::OK();
526
8
    }
_ZN5doris17RegexpExtractImplILb0EE7executeEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjm
Line
Count
Source
495
8
                          uint32_t result, size_t input_rows_count) {
496
8
        bool col_const[3];
497
8
        ColumnPtr argument_columns[3];
498
32
        for (int i = 0; i < 3; ++i) {
499
24
            col_const[i] = is_column_const(*block.get_by_position(arguments[i]).column);
500
24
        }
501
8
        argument_columns[0] = col_const[0] ? static_cast<const ColumnConst&>(
502
0
                                                     *block.get_by_position(arguments[0]).column)
503
0
                                                     .convert_to_full_column()
504
8
                                           : block.get_by_position(arguments[0]).column;
505
506
8
        auto result_null_map = ColumnUInt8::create(input_rows_count, 0);
507
8
        auto result_data_column = ColumnString::create();
508
8
        auto& result_data = result_data_column->get_chars();
509
8
        auto& result_offset = result_data_column->get_offsets();
510
8
        result_offset.resize(input_rows_count);
511
8
        auto& null_map = result_null_map->get_data();
512
513
8
        default_preprocess_parameter_columns(argument_columns, col_const, {1, 2}, block, arguments);
514
515
8
        if (col_const[1] && col_const[2]) {
516
0
            _execute_loop<true>(context, argument_columns, input_rows_count, result_data,
517
0
                                result_offset, null_map);
518
8
        } else {
519
8
            _execute_loop<false>(context, argument_columns, input_rows_count, result_data,
520
8
                                 result_offset, null_map);
521
8
        }
522
523
8
        block.get_by_position(result).column =
524
8
                ColumnNullable::create(std::move(result_data_column), std::move(result_null_map));
525
8
        return Status::OK();
526
8
    }
527
528
private:
529
    template <bool Const>
530
    static void _execute_loop(FunctionContext* context, ColumnPtr argument_columns[],
531
                              size_t input_rows_count, ColumnString::Chars& result_data,
532
16
                              ColumnString::Offsets& result_offset, NullMap& null_map) {
533
16
        const auto* str_col = check_and_get_column<ColumnString>(argument_columns[0].get());
534
16
        const auto* pattern_col = check_and_get_column<ColumnString>(argument_columns[1].get());
535
16
        const auto* index_col = check_and_get_column<ColumnInt64>(argument_columns[2].get());
536
537
16
        if constexpr (Const) {
538
0
            const auto& index_data = index_col->get_int(0);
539
0
            if (index_data < 0) {
540
0
                for (size_t i = 0; i < input_rows_count; ++i) {
541
0
                    ReturnNull ? StringOP::push_null_string(i, result_data, result_offset, null_map)
542
0
                               : StringOP::push_empty_string(i, result_data, result_offset);
543
0
                }
544
0
                return;
545
0
            }
546
0
            for (size_t i = 0; i < input_rows_count; ++i) {
547
0
                _execute_inner_loop<true>(context, str_col, pattern_col, index_data, result_data,
548
0
                                          result_offset, null_map, i);
549
0
            }
550
16
        } else {
551
32
            for (size_t i = 0; i < input_rows_count; ++i) {
552
16
                const auto& index_data = index_col->get_int(i);
553
16
                if (index_data < 0) {
554
0
                    ReturnNull ? StringOP::push_null_string(i, result_data, result_offset, null_map)
555
0
                               : StringOP::push_empty_string(i, result_data, result_offset);
556
0
                    continue;
557
0
                }
558
16
                _execute_inner_loop<false>(context, str_col, pattern_col, index_data, result_data,
559
16
                                           result_offset, null_map, i);
560
16
            }
561
16
        }
562
16
    }
Unexecuted instantiation: _ZN5doris17RegexpExtractImplILb1EE13_execute_loopILb1EEEvPNS_15FunctionContextEPNS_3COWINS_7IColumnEE13immutable_ptrIS6_EEmRNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEERNSB_IjLm4096ESE_Lm16ELm15EEESG_
_ZN5doris17RegexpExtractImplILb1EE13_execute_loopILb0EEEvPNS_15FunctionContextEPNS_3COWINS_7IColumnEE13immutable_ptrIS6_EEmRNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEERNSB_IjLm4096ESE_Lm16ELm15EEESG_
Line
Count
Source
532
8
                              ColumnString::Offsets& result_offset, NullMap& null_map) {
533
8
        const auto* str_col = check_and_get_column<ColumnString>(argument_columns[0].get());
534
8
        const auto* pattern_col = check_and_get_column<ColumnString>(argument_columns[1].get());
535
8
        const auto* index_col = check_and_get_column<ColumnInt64>(argument_columns[2].get());
536
537
        if constexpr (Const) {
538
            const auto& index_data = index_col->get_int(0);
539
            if (index_data < 0) {
540
                for (size_t i = 0; i < input_rows_count; ++i) {
541
                    ReturnNull ? StringOP::push_null_string(i, result_data, result_offset, null_map)
542
                               : StringOP::push_empty_string(i, result_data, result_offset);
543
                }
544
                return;
545
            }
546
            for (size_t i = 0; i < input_rows_count; ++i) {
547
                _execute_inner_loop<true>(context, str_col, pattern_col, index_data, result_data,
548
                                          result_offset, null_map, i);
549
            }
550
8
        } else {
551
16
            for (size_t i = 0; i < input_rows_count; ++i) {
552
8
                const auto& index_data = index_col->get_int(i);
553
8
                if (index_data < 0) {
554
0
                    ReturnNull ? StringOP::push_null_string(i, result_data, result_offset, null_map)
555
0
                               : StringOP::push_empty_string(i, result_data, result_offset);
556
0
                    continue;
557
0
                }
558
8
                _execute_inner_loop<false>(context, str_col, pattern_col, index_data, result_data,
559
8
                                           result_offset, null_map, i);
560
8
            }
561
8
        }
562
8
    }
Unexecuted instantiation: _ZN5doris17RegexpExtractImplILb0EE13_execute_loopILb1EEEvPNS_15FunctionContextEPNS_3COWINS_7IColumnEE13immutable_ptrIS6_EEmRNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEERNSB_IjLm4096ESE_Lm16ELm15EEESG_
_ZN5doris17RegexpExtractImplILb0EE13_execute_loopILb0EEEvPNS_15FunctionContextEPNS_3COWINS_7IColumnEE13immutable_ptrIS6_EEmRNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEERNSB_IjLm4096ESE_Lm16ELm15EEESG_
Line
Count
Source
532
8
                              ColumnString::Offsets& result_offset, NullMap& null_map) {
533
8
        const auto* str_col = check_and_get_column<ColumnString>(argument_columns[0].get());
534
8
        const auto* pattern_col = check_and_get_column<ColumnString>(argument_columns[1].get());
535
8
        const auto* index_col = check_and_get_column<ColumnInt64>(argument_columns[2].get());
536
537
        if constexpr (Const) {
538
            const auto& index_data = index_col->get_int(0);
539
            if (index_data < 0) {
540
                for (size_t i = 0; i < input_rows_count; ++i) {
541
                    ReturnNull ? StringOP::push_null_string(i, result_data, result_offset, null_map)
542
                               : StringOP::push_empty_string(i, result_data, result_offset);
543
                }
544
                return;
545
            }
546
            for (size_t i = 0; i < input_rows_count; ++i) {
547
                _execute_inner_loop<true>(context, str_col, pattern_col, index_data, result_data,
548
                                          result_offset, null_map, i);
549
            }
550
8
        } else {
551
16
            for (size_t i = 0; i < input_rows_count; ++i) {
552
8
                const auto& index_data = index_col->get_int(i);
553
8
                if (index_data < 0) {
554
0
                    ReturnNull ? StringOP::push_null_string(i, result_data, result_offset, null_map)
555
0
                               : StringOP::push_empty_string(i, result_data, result_offset);
556
0
                    continue;
557
0
                }
558
8
                _execute_inner_loop<false>(context, str_col, pattern_col, index_data, result_data,
559
8
                                           result_offset, null_map, i);
560
8
            }
561
8
        }
562
8
    }
563
564
    template <bool Const>
565
    static void _execute_inner_loop(FunctionContext* context, const ColumnString* str_col,
566
                                    const ColumnString* pattern_col, const Int64 index_data,
567
                                    ColumnString::Chars& result_data,
568
                                    ColumnString::Offsets& result_offset, NullMap& null_map,
569
16
                                    const size_t index_now) {
570
16
        auto* engine = reinterpret_cast<RegexpExtractEngine*>(
571
16
                context->get_function_state(FunctionContext::THREAD_LOCAL));
572
16
        std::unique_ptr<RegexpExtractEngine> scoped_engine;
573
574
16
        if (engine == nullptr) {
575
0
            std::string error_str;
576
0
            const auto& pattern = pattern_col->get_data_at(index_check_const(index_now, Const));
577
0
            scoped_engine = std::make_unique<RegexpExtractEngine>();
578
0
            bool st = RegexpExtractEngine::compile(pattern, &error_str, *scoped_engine,
579
0
                                                   context->state()->enable_extended_regex());
580
0
            if (!st) {
581
0
                context->add_warning(error_str.c_str());
582
0
                StringOP::push_null_string(index_now, result_data, result_offset, null_map);
583
0
                return;
584
0
            }
585
0
            engine = scoped_engine.get();
586
0
        }
587
588
16
        const auto& str = str_col->get_data_at(index_now);
589
590
16
        int max_matches = 1 + engine->number_of_capturing_groups();
591
16
        if (index_data >= max_matches) {
592
0
            ReturnNull ? StringOP::push_null_string(index_now, result_data, result_offset, null_map)
593
0
                       : StringOP::push_empty_string(index_now, result_data, result_offset);
594
0
            return;
595
0
        }
596
597
16
        std::string match_result;
598
16
        bool success = engine->match_and_extract(str.data, str.size, static_cast<int>(index_data),
599
16
                                                 match_result);
600
601
16
        if (!success) {
602
0
            ReturnNull ? StringOP::push_null_string(index_now, result_data, result_offset, null_map)
603
0
                       : StringOP::push_empty_string(index_now, result_data, result_offset);
604
0
            return;
605
0
        }
606
607
16
        StringOP::push_value_string(std::string_view(match_result.data(), match_result.size()),
608
16
                                    index_now, result_data, result_offset);
609
16
    }
Unexecuted instantiation: _ZN5doris17RegexpExtractImplILb1EE19_execute_inner_loopILb1EEEvPNS_15FunctionContextEPKNS_9ColumnStrIjEES8_lRNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEERNS9_IjLm4096ESC_Lm16ELm15EEESE_m
_ZN5doris17RegexpExtractImplILb1EE19_execute_inner_loopILb0EEEvPNS_15FunctionContextEPKNS_9ColumnStrIjEES8_lRNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEERNS9_IjLm4096ESC_Lm16ELm15EEESE_m
Line
Count
Source
569
8
                                    const size_t index_now) {
570
8
        auto* engine = reinterpret_cast<RegexpExtractEngine*>(
571
8
                context->get_function_state(FunctionContext::THREAD_LOCAL));
572
8
        std::unique_ptr<RegexpExtractEngine> scoped_engine;
573
574
8
        if (engine == nullptr) {
575
0
            std::string error_str;
576
0
            const auto& pattern = pattern_col->get_data_at(index_check_const(index_now, Const));
577
0
            scoped_engine = std::make_unique<RegexpExtractEngine>();
578
0
            bool st = RegexpExtractEngine::compile(pattern, &error_str, *scoped_engine,
579
0
                                                   context->state()->enable_extended_regex());
580
0
            if (!st) {
581
0
                context->add_warning(error_str.c_str());
582
0
                StringOP::push_null_string(index_now, result_data, result_offset, null_map);
583
0
                return;
584
0
            }
585
0
            engine = scoped_engine.get();
586
0
        }
587
588
8
        const auto& str = str_col->get_data_at(index_now);
589
590
8
        int max_matches = 1 + engine->number_of_capturing_groups();
591
8
        if (index_data >= max_matches) {
592
0
            ReturnNull ? StringOP::push_null_string(index_now, result_data, result_offset, null_map)
593
0
                       : StringOP::push_empty_string(index_now, result_data, result_offset);
594
0
            return;
595
0
        }
596
597
8
        std::string match_result;
598
8
        bool success = engine->match_and_extract(str.data, str.size, static_cast<int>(index_data),
599
8
                                                 match_result);
600
601
8
        if (!success) {
602
0
            ReturnNull ? StringOP::push_null_string(index_now, result_data, result_offset, null_map)
603
0
                       : StringOP::push_empty_string(index_now, result_data, result_offset);
604
0
            return;
605
0
        }
606
607
8
        StringOP::push_value_string(std::string_view(match_result.data(), match_result.size()),
608
8
                                    index_now, result_data, result_offset);
609
8
    }
Unexecuted instantiation: _ZN5doris17RegexpExtractImplILb0EE19_execute_inner_loopILb1EEEvPNS_15FunctionContextEPKNS_9ColumnStrIjEES8_lRNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEERNS9_IjLm4096ESC_Lm16ELm15EEESE_m
_ZN5doris17RegexpExtractImplILb0EE19_execute_inner_loopILb0EEEvPNS_15FunctionContextEPKNS_9ColumnStrIjEES8_lRNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEERNS9_IjLm4096ESC_Lm16ELm15EEESE_m
Line
Count
Source
569
8
                                    const size_t index_now) {
570
8
        auto* engine = reinterpret_cast<RegexpExtractEngine*>(
571
8
                context->get_function_state(FunctionContext::THREAD_LOCAL));
572
8
        std::unique_ptr<RegexpExtractEngine> scoped_engine;
573
574
8
        if (engine == nullptr) {
575
0
            std::string error_str;
576
0
            const auto& pattern = pattern_col->get_data_at(index_check_const(index_now, Const));
577
0
            scoped_engine = std::make_unique<RegexpExtractEngine>();
578
0
            bool st = RegexpExtractEngine::compile(pattern, &error_str, *scoped_engine,
579
0
                                                   context->state()->enable_extended_regex());
580
0
            if (!st) {
581
0
                context->add_warning(error_str.c_str());
582
0
                StringOP::push_null_string(index_now, result_data, result_offset, null_map);
583
0
                return;
584
0
            }
585
0
            engine = scoped_engine.get();
586
0
        }
587
588
8
        const auto& str = str_col->get_data_at(index_now);
589
590
8
        int max_matches = 1 + engine->number_of_capturing_groups();
591
8
        if (index_data >= max_matches) {
592
0
            ReturnNull ? StringOP::push_null_string(index_now, result_data, result_offset, null_map)
593
0
                       : StringOP::push_empty_string(index_now, result_data, result_offset);
594
0
            return;
595
0
        }
596
597
8
        std::string match_result;
598
8
        bool success = engine->match_and_extract(str.data, str.size, static_cast<int>(index_data),
599
8
                                                 match_result);
600
601
8
        if (!success) {
602
0
            ReturnNull ? StringOP::push_null_string(index_now, result_data, result_offset, null_map)
603
0
                       : StringOP::push_empty_string(index_now, result_data, result_offset);
604
0
            return;
605
0
        }
606
607
8
        StringOP::push_value_string(std::string_view(match_result.data(), match_result.size()),
608
8
                                    index_now, result_data, result_offset);
609
8
    }
610
};
611
612
// Output handler for existing string-formatted result: "['a','b']"
613
struct RegexpExtractAllStringOutput {
614
    static constexpr const char* func_name = "regexp_extract_all";
615
9
    static DataTypePtr return_type() { return make_nullable(std::make_shared<DataTypeString>()); }
616
617
    ColumnString::Chars& result_data;
618
    ColumnString::Offsets& result_offset;
619
620
0
    void push_empty(size_t index) {
621
0
        StringOP::push_empty_string(index, result_data, result_offset);
622
0
    }
623
0
    void push_null(size_t index, NullMap& null_map) {
624
0
        StringOP::push_null_string(index, result_data, result_offset, null_map);
625
0
    }
626
7
    void push_matches(size_t index, const std::vector<std::string>& matches) {
627
7
        size_t total_size = 2; // '[' and ']'
628
12
        for (const auto& m : matches) {
629
12
            total_size += m.size() + 3; // "'xxx',"
630
12
        }
631
632
7
        size_t old_size = result_data.size();
633
7
        result_data.resize(old_size + total_size);
634
7
        char* pos = reinterpret_cast<char*>(&result_data[old_size]);
635
636
7
        *pos++ = '[';
637
19
        for (size_t j = 0; j < matches.size(); ++j) {
638
12
            if (j > 0) {
639
5
                *pos++ = ',';
640
5
            }
641
12
            *pos++ = '\'';
642
12
            memcpy(pos, matches[j].data(), matches[j].size());
643
12
            pos += matches[j].size();
644
12
            *pos++ = '\'';
645
12
        }
646
7
        *pos++ = ']';
647
648
7
        result_data.resize(old_size + static_cast<size_t>(pos - reinterpret_cast<char*>(
649
7
                                                                        &result_data[old_size])));
650
7
        result_offset[index] = static_cast<ColumnString::Offset>(result_data.size());
651
7
    }
652
653
    struct State {
654
        ColumnString::MutablePtr data_column;
655
7
        explicit State(size_t rows) : data_column(ColumnString::create()) {
656
7
            data_column->get_offsets().resize(rows);
657
7
        }
658
7
        RegexpExtractAllStringOutput create_handler() {
659
7
            return {.result_data = data_column->get_chars(),
660
7
                    .result_offset = data_column->get_offsets()};
661
7
        }
662
7
        ColumnPtr finalize(ColumnUInt8::MutablePtr null_map) {
663
7
            return ColumnNullable::create(std::move(data_column), std::move(null_map));
664
7
        }
665
    };
666
};
667
668
// Output handler for proper Array<Nullable<String>> result
669
struct RegexpExtractAllArrayOutput {
670
    static constexpr const char* func_name = "regexp_extract_all_array";
671
10
    static DataTypePtr return_type() {
672
10
        return make_nullable(
673
10
                std::make_shared<DataTypeArray>(make_nullable(std::make_shared<DataTypeString>())));
674
10
    }
675
676
    ColumnString& nested_col;
677
    ColumnArray::Offsets64& array_offsets;
678
    NullMap& nested_null_map;
679
    UInt64 current_offset = 0;
680
681
1
    void push_empty(size_t index) { array_offsets.push_back(current_offset); }
682
0
    void push_null(size_t index, NullMap& null_map) {
683
0
        null_map[index] = 1;
684
0
        array_offsets.push_back(current_offset);
685
0
    }
686
6
    void push_matches(size_t index, const std::vector<std::string>& matches) {
687
8
        for (const auto& m : matches) {
688
8
            nested_col.insert_data(m.data(), m.size());
689
8
            nested_null_map.push_back(0);
690
8
            current_offset++;
691
8
        }
692
6
        array_offsets.push_back(current_offset);
693
6
    }
694
695
    struct State {
696
        ColumnArray::MutablePtr array_column;
697
        ColumnNullable* nested_nullable;
698
7
        explicit State(size_t /*rows*/) {
699
7
            auto nullable_str = make_nullable(std::make_shared<DataTypeString>());
700
7
            array_column = ColumnArray::create(nullable_str->create_column(),
701
7
                                               ColumnArray::ColumnOffsets::create());
702
7
            nested_nullable = assert_cast<ColumnNullable*>(&array_column->get_data());
703
7
        }
704
7
        RegexpExtractAllArrayOutput create_handler() {
705
7
            return {.nested_col = assert_cast<ColumnString&>(nested_nullable->get_nested_column()),
706
7
                    .array_offsets = array_column->get_offsets(),
707
7
                    .nested_null_map = nested_nullable->get_null_map_data()};
708
7
        }
709
7
        ColumnPtr finalize(ColumnUInt8::MutablePtr null_map) {
710
7
            return ColumnNullable::create(std::move(array_column), std::move(null_map));
711
7
        }
712
    };
713
};
714
715
// Handler controls return type & column layout
716
template <typename Handler>
717
struct RegexpExtractAllImpl {
718
    static constexpr auto name = Handler::func_name;
719
    static constexpr size_t num_args = 2;
720
    static constexpr size_t PATTERN_ARG_IDX = 1;
721
722
19
    static DataTypePtr return_type() { return Handler::return_type(); }
_ZN5doris20RegexpExtractAllImplINS_28RegexpExtractAllStringOutputEE11return_typeEv
Line
Count
Source
722
9
    static DataTypePtr return_type() { return Handler::return_type(); }
_ZN5doris20RegexpExtractAllImplINS_27RegexpExtractAllArrayOutputEE11return_typeEv
Line
Count
Source
722
10
    static DataTypePtr return_type() { return Handler::return_type(); }
723
724
    static Status execute(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
725
14
                          uint32_t result, size_t input_rows_count) {
726
14
        bool col_const[2];
727
14
        ColumnPtr argument_columns[2];
728
42
        for (int i = 0; i < 2; ++i) {
729
28
            col_const[i] = is_column_const(*block.get_by_position(arguments[i]).column);
730
28
        }
731
14
        argument_columns[0] = col_const[0] ? static_cast<const ColumnConst&>(
732
0
                                                     *block.get_by_position(arguments[0]).column)
733
0
                                                     .convert_to_full_column()
734
14
                                           : block.get_by_position(arguments[0]).column;
735
736
14
        default_preprocess_parameter_columns(argument_columns, col_const, {1}, block, arguments);
737
738
14
        const auto* str_col = check_and_get_column<ColumnString>(argument_columns[0].get());
739
14
        const auto* pattern_col = check_and_get_column<ColumnString>(argument_columns[1].get());
740
741
14
        auto outer_null_map = ColumnUInt8::create(input_rows_count, 0);
742
14
        auto& null_map_data = outer_null_map->get_data();
743
744
14
        typename Handler::State state(input_rows_count);
745
14
        auto handler = state.create_handler();
746
747
14
        std::visit(
748
14
                [&](auto is_const) {
749
28
                    for (size_t i = 0; i < input_rows_count; ++i) {
750
14
                        if (null_map_data[i]) {
751
0
                            handler.push_null(i, null_map_data);
752
0
                            continue;
753
0
                        }
754
14
                        regexp_extract_all_inner_loop<is_const>(context, str_col, pattern_col,
755
14
                                                                handler, null_map_data, i);
756
14
                    }
757
14
                },
Unexecuted instantiation: _ZZN5doris20RegexpExtractAllImplINS_28RegexpExtractAllStringOutputEE7executeEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjmENKUlT_E_clISt17integral_constantIbLb0EEEEDaSC_
_ZZN5doris20RegexpExtractAllImplINS_28RegexpExtractAllStringOutputEE7executeEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjmENKUlT_E_clISt17integral_constantIbLb1EEEEDaSC_
Line
Count
Source
748
7
                [&](auto is_const) {
749
14
                    for (size_t i = 0; i < input_rows_count; ++i) {
750
7
                        if (null_map_data[i]) {
751
0
                            handler.push_null(i, null_map_data);
752
0
                            continue;
753
0
                        }
754
7
                        regexp_extract_all_inner_loop<is_const>(context, str_col, pattern_col,
755
7
                                                                handler, null_map_data, i);
756
7
                    }
757
7
                },
Unexecuted instantiation: _ZZN5doris20RegexpExtractAllImplINS_27RegexpExtractAllArrayOutputEE7executeEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjmENKUlT_E_clISt17integral_constantIbLb0EEEEDaSC_
_ZZN5doris20RegexpExtractAllImplINS_27RegexpExtractAllArrayOutputEE7executeEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjmENKUlT_E_clISt17integral_constantIbLb1EEEEDaSC_
Line
Count
Source
748
7
                [&](auto is_const) {
749
14
                    for (size_t i = 0; i < input_rows_count; ++i) {
750
7
                        if (null_map_data[i]) {
751
0
                            handler.push_null(i, null_map_data);
752
0
                            continue;
753
0
                        }
754
7
                        regexp_extract_all_inner_loop<is_const>(context, str_col, pattern_col,
755
7
                                                                handler, null_map_data, i);
756
7
                    }
757
7
                },
758
14
                make_bool_variant(col_const[1]));
759
760
14
        block.get_by_position(result).column = state.finalize(std::move(outer_null_map));
761
14
        return Status::OK();
762
14
    }
_ZN5doris20RegexpExtractAllImplINS_28RegexpExtractAllStringOutputEE7executeEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjm
Line
Count
Source
725
7
                          uint32_t result, size_t input_rows_count) {
726
7
        bool col_const[2];
727
7
        ColumnPtr argument_columns[2];
728
21
        for (int i = 0; i < 2; ++i) {
729
14
            col_const[i] = is_column_const(*block.get_by_position(arguments[i]).column);
730
14
        }
731
7
        argument_columns[0] = col_const[0] ? static_cast<const ColumnConst&>(
732
0
                                                     *block.get_by_position(arguments[0]).column)
733
0
                                                     .convert_to_full_column()
734
7
                                           : block.get_by_position(arguments[0]).column;
735
736
7
        default_preprocess_parameter_columns(argument_columns, col_const, {1}, block, arguments);
737
738
7
        const auto* str_col = check_and_get_column<ColumnString>(argument_columns[0].get());
739
7
        const auto* pattern_col = check_and_get_column<ColumnString>(argument_columns[1].get());
740
741
7
        auto outer_null_map = ColumnUInt8::create(input_rows_count, 0);
742
7
        auto& null_map_data = outer_null_map->get_data();
743
744
7
        typename Handler::State state(input_rows_count);
745
7
        auto handler = state.create_handler();
746
747
7
        std::visit(
748
7
                [&](auto is_const) {
749
7
                    for (size_t i = 0; i < input_rows_count; ++i) {
750
7
                        if (null_map_data[i]) {
751
7
                            handler.push_null(i, null_map_data);
752
7
                            continue;
753
7
                        }
754
7
                        regexp_extract_all_inner_loop<is_const>(context, str_col, pattern_col,
755
7
                                                                handler, null_map_data, i);
756
7
                    }
757
7
                },
758
7
                make_bool_variant(col_const[1]));
759
760
7
        block.get_by_position(result).column = state.finalize(std::move(outer_null_map));
761
7
        return Status::OK();
762
7
    }
_ZN5doris20RegexpExtractAllImplINS_27RegexpExtractAllArrayOutputEE7executeEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjm
Line
Count
Source
725
7
                          uint32_t result, size_t input_rows_count) {
726
7
        bool col_const[2];
727
7
        ColumnPtr argument_columns[2];
728
21
        for (int i = 0; i < 2; ++i) {
729
14
            col_const[i] = is_column_const(*block.get_by_position(arguments[i]).column);
730
14
        }
731
7
        argument_columns[0] = col_const[0] ? static_cast<const ColumnConst&>(
732
0
                                                     *block.get_by_position(arguments[0]).column)
733
0
                                                     .convert_to_full_column()
734
7
                                           : block.get_by_position(arguments[0]).column;
735
736
7
        default_preprocess_parameter_columns(argument_columns, col_const, {1}, block, arguments);
737
738
7
        const auto* str_col = check_and_get_column<ColumnString>(argument_columns[0].get());
739
7
        const auto* pattern_col = check_and_get_column<ColumnString>(argument_columns[1].get());
740
741
7
        auto outer_null_map = ColumnUInt8::create(input_rows_count, 0);
742
7
        auto& null_map_data = outer_null_map->get_data();
743
744
7
        typename Handler::State state(input_rows_count);
745
7
        auto handler = state.create_handler();
746
747
7
        std::visit(
748
7
                [&](auto is_const) {
749
7
                    for (size_t i = 0; i < input_rows_count; ++i) {
750
7
                        if (null_map_data[i]) {
751
7
                            handler.push_null(i, null_map_data);
752
7
                            continue;
753
7
                        }
754
7
                        regexp_extract_all_inner_loop<is_const>(context, str_col, pattern_col,
755
7
                                                                handler, null_map_data, i);
756
7
                    }
757
7
                },
758
7
                make_bool_variant(col_const[1]));
759
760
7
        block.get_by_position(result).column = state.finalize(std::move(outer_null_map));
761
7
        return Status::OK();
762
7
    }
763
764
private:
765
    template <bool is_const>
766
    static void regexp_extract_all_inner_loop(FunctionContext* context, const ColumnString* str_col,
767
                                              const ColumnString* pattern_col, Handler& handler,
768
14
                                              NullMap& null_map, const size_t index_now) {
769
14
        auto* engine = reinterpret_cast<RegexpExtractEngine*>(
770
14
                context->get_function_state(FunctionContext::THREAD_LOCAL));
771
14
        std::unique_ptr<RegexpExtractEngine> scoped_engine;
772
773
14
        if (engine == nullptr) {
774
0
            std::string error_str;
775
0
            const auto& pattern = pattern_col->get_data_at(index_check_const(index_now, is_const));
776
0
            scoped_engine = std::make_unique<RegexpExtractEngine>();
777
0
            bool st = RegexpExtractEngine::compile(pattern, &error_str, *scoped_engine,
778
0
                                                   context->state()->enable_extended_regex());
779
0
            if (!st) {
780
0
                context->add_warning(error_str.c_str());
781
0
                handler.push_null(index_now, null_map);
782
0
                return;
783
0
            }
784
0
            engine = scoped_engine.get();
785
0
        }
786
787
14
        if (engine->number_of_capturing_groups() == 0) {
788
0
            handler.push_empty(index_now);
789
0
            return;
790
0
        }
791
14
        const auto& str = str_col->get_data_at(index_now);
792
14
        std::vector<std::string> res_matches;
793
14
        engine->match_all_and_extract(str.data, str.size, res_matches);
794
795
14
        if (res_matches.empty()) {
796
1
            handler.push_empty(index_now);
797
1
            return;
798
1
        }
799
13
        handler.push_matches(index_now, res_matches);
800
13
    }
Unexecuted instantiation: _ZN5doris20RegexpExtractAllImplINS_28RegexpExtractAllStringOutputEE29regexp_extract_all_inner_loopILb0EEEvPNS_15FunctionContextEPKNS_9ColumnStrIjEES9_RS1_RNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEEm
_ZN5doris20RegexpExtractAllImplINS_28RegexpExtractAllStringOutputEE29regexp_extract_all_inner_loopILb1EEEvPNS_15FunctionContextEPKNS_9ColumnStrIjEES9_RS1_RNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEEm
Line
Count
Source
768
7
                                              NullMap& null_map, const size_t index_now) {
769
7
        auto* engine = reinterpret_cast<RegexpExtractEngine*>(
770
7
                context->get_function_state(FunctionContext::THREAD_LOCAL));
771
7
        std::unique_ptr<RegexpExtractEngine> scoped_engine;
772
773
7
        if (engine == nullptr) {
774
0
            std::string error_str;
775
0
            const auto& pattern = pattern_col->get_data_at(index_check_const(index_now, is_const));
776
0
            scoped_engine = std::make_unique<RegexpExtractEngine>();
777
0
            bool st = RegexpExtractEngine::compile(pattern, &error_str, *scoped_engine,
778
0
                                                   context->state()->enable_extended_regex());
779
0
            if (!st) {
780
0
                context->add_warning(error_str.c_str());
781
0
                handler.push_null(index_now, null_map);
782
0
                return;
783
0
            }
784
0
            engine = scoped_engine.get();
785
0
        }
786
787
7
        if (engine->number_of_capturing_groups() == 0) {
788
0
            handler.push_empty(index_now);
789
0
            return;
790
0
        }
791
7
        const auto& str = str_col->get_data_at(index_now);
792
7
        std::vector<std::string> res_matches;
793
7
        engine->match_all_and_extract(str.data, str.size, res_matches);
794
795
7
        if (res_matches.empty()) {
796
0
            handler.push_empty(index_now);
797
0
            return;
798
0
        }
799
7
        handler.push_matches(index_now, res_matches);
800
7
    }
Unexecuted instantiation: _ZN5doris20RegexpExtractAllImplINS_27RegexpExtractAllArrayOutputEE29regexp_extract_all_inner_loopILb0EEEvPNS_15FunctionContextEPKNS_9ColumnStrIjEES9_RS1_RNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEEm
_ZN5doris20RegexpExtractAllImplINS_27RegexpExtractAllArrayOutputEE29regexp_extract_all_inner_loopILb1EEEvPNS_15FunctionContextEPKNS_9ColumnStrIjEES9_RS1_RNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEEm
Line
Count
Source
768
7
                                              NullMap& null_map, const size_t index_now) {
769
7
        auto* engine = reinterpret_cast<RegexpExtractEngine*>(
770
7
                context->get_function_state(FunctionContext::THREAD_LOCAL));
771
7
        std::unique_ptr<RegexpExtractEngine> scoped_engine;
772
773
7
        if (engine == nullptr) {
774
0
            std::string error_str;
775
0
            const auto& pattern = pattern_col->get_data_at(index_check_const(index_now, is_const));
776
0
            scoped_engine = std::make_unique<RegexpExtractEngine>();
777
0
            bool st = RegexpExtractEngine::compile(pattern, &error_str, *scoped_engine,
778
0
                                                   context->state()->enable_extended_regex());
779
0
            if (!st) {
780
0
                context->add_warning(error_str.c_str());
781
0
                handler.push_null(index_now, null_map);
782
0
                return;
783
0
            }
784
0
            engine = scoped_engine.get();
785
0
        }
786
787
7
        if (engine->number_of_capturing_groups() == 0) {
788
0
            handler.push_empty(index_now);
789
0
            return;
790
0
        }
791
7
        const auto& str = str_col->get_data_at(index_now);
792
7
        std::vector<std::string> res_matches;
793
7
        engine->match_all_and_extract(str.data, str.size, res_matches);
794
795
7
        if (res_matches.empty()) {
796
1
            handler.push_empty(index_now);
797
1
            return;
798
1
        }
799
6
        handler.push_matches(index_now, res_matches);
800
6
    }
801
};
802
803
// template FunctionRegexpFunctionality is used for regexp_xxxx series functions, not for regexp match.
804
template <typename Impl>
805
class FunctionRegexpFunctionality : public IFunction {
806
public:
807
    static constexpr auto name = Impl::name;
808
809
47
    static FunctionPtr create() { return std::make_shared<FunctionRegexpFunctionality>(); }
_ZN5doris27FunctionRegexpFunctionalityINS_17RegexpExtractImplILb1EEEE6createEv
Line
Count
Source
809
12
    static FunctionPtr create() { return std::make_shared<FunctionRegexpFunctionality>(); }
_ZN5doris27FunctionRegexpFunctionalityINS_17RegexpExtractImplILb0EEEE6createEv
Line
Count
Source
809
12
    static FunctionPtr create() { return std::make_shared<FunctionRegexpFunctionality>(); }
_ZN5doris27FunctionRegexpFunctionalityINS_20RegexpExtractAllImplINS_28RegexpExtractAllStringOutputEEEE6createEv
Line
Count
Source
809
11
    static FunctionPtr create() { return std::make_shared<FunctionRegexpFunctionality>(); }
_ZN5doris27FunctionRegexpFunctionalityINS_20RegexpExtractAllImplINS_27RegexpExtractAllArrayOutputEEEE6createEv
Line
Count
Source
809
12
    static FunctionPtr create() { return std::make_shared<FunctionRegexpFunctionality>(); }
810
811
4
    String get_name() const override { return name; }
_ZNK5doris27FunctionRegexpFunctionalityINS_17RegexpExtractImplILb1EEEE8get_nameB5cxx11Ev
Line
Count
Source
811
1
    String get_name() const override { return name; }
_ZNK5doris27FunctionRegexpFunctionalityINS_17RegexpExtractImplILb0EEEE8get_nameB5cxx11Ev
Line
Count
Source
811
1
    String get_name() const override { return name; }
_ZNK5doris27FunctionRegexpFunctionalityINS_20RegexpExtractAllImplINS_28RegexpExtractAllStringOutputEEEE8get_nameB5cxx11Ev
Line
Count
Source
811
1
    String get_name() const override { return name; }
_ZNK5doris27FunctionRegexpFunctionalityINS_20RegexpExtractAllImplINS_27RegexpExtractAllArrayOutputEEEE8get_nameB5cxx11Ev
Line
Count
Source
811
1
    String get_name() const override { return name; }
812
813
39
    size_t get_number_of_arguments() const override { return Impl::num_args; }
_ZNK5doris27FunctionRegexpFunctionalityINS_17RegexpExtractImplILb1EEEE23get_number_of_argumentsEv
Line
Count
Source
813
10
    size_t get_number_of_arguments() const override { return Impl::num_args; }
_ZNK5doris27FunctionRegexpFunctionalityINS_17RegexpExtractImplILb0EEEE23get_number_of_argumentsEv
Line
Count
Source
813
10
    size_t get_number_of_arguments() const override { return Impl::num_args; }
_ZNK5doris27FunctionRegexpFunctionalityINS_20RegexpExtractAllImplINS_28RegexpExtractAllStringOutputEEEE23get_number_of_argumentsEv
Line
Count
Source
813
9
    size_t get_number_of_arguments() const override { return Impl::num_args; }
_ZNK5doris27FunctionRegexpFunctionalityINS_20RegexpExtractAllImplINS_27RegexpExtractAllArrayOutputEEEE23get_number_of_argumentsEv
Line
Count
Source
813
10
    size_t get_number_of_arguments() const override { return Impl::num_args; }
814
815
39
    DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
816
39
        return Impl::return_type();
817
39
    }
_ZNK5doris27FunctionRegexpFunctionalityINS_17RegexpExtractImplILb1EEEE20get_return_type_implERKSt6vectorISt10shared_ptrIKNS_9IDataTypeEESaIS8_EE
Line
Count
Source
815
10
    DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
816
10
        return Impl::return_type();
817
10
    }
_ZNK5doris27FunctionRegexpFunctionalityINS_17RegexpExtractImplILb0EEEE20get_return_type_implERKSt6vectorISt10shared_ptrIKNS_9IDataTypeEESaIS8_EE
Line
Count
Source
815
10
    DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
816
10
        return Impl::return_type();
817
10
    }
_ZNK5doris27FunctionRegexpFunctionalityINS_20RegexpExtractAllImplINS_28RegexpExtractAllStringOutputEEEE20get_return_type_implERKSt6vectorISt10shared_ptrIKNS_9IDataTypeEESaIS9_EE
Line
Count
Source
815
9
    DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
816
9
        return Impl::return_type();
817
9
    }
_ZNK5doris27FunctionRegexpFunctionalityINS_20RegexpExtractAllImplINS_27RegexpExtractAllArrayOutputEEEE20get_return_type_implERKSt6vectorISt10shared_ptrIKNS_9IDataTypeEESaIS9_EE
Line
Count
Source
815
10
    DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
816
10
        return Impl::return_type();
817
10
    }
818
819
78
    Status open(FunctionContext* context, FunctionContext::FunctionStateScope scope) override {
820
78
        if (scope == FunctionContext::THREAD_LOCAL) {
821
39
            if (context->is_col_constant(Impl::PATTERN_ARG_IDX)) {
822
39
                DCHECK(!context->get_function_state(scope));
823
39
                const auto pattern_col =
824
39
                        context->get_constant_col(Impl::PATTERN_ARG_IDX)->column_ptr;
825
39
                const auto& pattern = pattern_col->get_data_at(0);
826
39
                if (pattern.size == 0) {
827
4
                    return Status::OK();
828
4
                }
829
830
35
                std::string error_str;
831
35
                auto engine = std::make_shared<RegexpExtractEngine>();
832
35
                bool st = RegexpExtractEngine::compile(pattern, &error_str, *engine,
833
35
                                                       context->state()->enable_extended_regex());
834
835
35
                if (!st) {
836
1
                    context->set_error(error_str.c_str());
837
1
                    return Status::InvalidArgument(error_str);
838
1
                }
839
34
                context->set_function_state(scope, engine);
840
34
            }
841
39
        }
842
73
        return Status::OK();
843
78
    }
_ZN5doris27FunctionRegexpFunctionalityINS_17RegexpExtractImplILb1EEEE4openEPNS_15FunctionContextENS4_18FunctionStateScopeE
Line
Count
Source
819
20
    Status open(FunctionContext* context, FunctionContext::FunctionStateScope scope) override {
820
20
        if (scope == FunctionContext::THREAD_LOCAL) {
821
10
            if (context->is_col_constant(Impl::PATTERN_ARG_IDX)) {
822
10
                DCHECK(!context->get_function_state(scope));
823
10
                const auto pattern_col =
824
10
                        context->get_constant_col(Impl::PATTERN_ARG_IDX)->column_ptr;
825
10
                const auto& pattern = pattern_col->get_data_at(0);
826
10
                if (pattern.size == 0) {
827
1
                    return Status::OK();
828
1
                }
829
830
9
                std::string error_str;
831
9
                auto engine = std::make_shared<RegexpExtractEngine>();
832
9
                bool st = RegexpExtractEngine::compile(pattern, &error_str, *engine,
833
9
                                                       context->state()->enable_extended_regex());
834
835
9
                if (!st) {
836
0
                    context->set_error(error_str.c_str());
837
0
                    return Status::InvalidArgument(error_str);
838
0
                }
839
9
                context->set_function_state(scope, engine);
840
9
            }
841
10
        }
842
19
        return Status::OK();
843
20
    }
_ZN5doris27FunctionRegexpFunctionalityINS_17RegexpExtractImplILb0EEEE4openEPNS_15FunctionContextENS4_18FunctionStateScopeE
Line
Count
Source
819
20
    Status open(FunctionContext* context, FunctionContext::FunctionStateScope scope) override {
820
20
        if (scope == FunctionContext::THREAD_LOCAL) {
821
10
            if (context->is_col_constant(Impl::PATTERN_ARG_IDX)) {
822
10
                DCHECK(!context->get_function_state(scope));
823
10
                const auto pattern_col =
824
10
                        context->get_constant_col(Impl::PATTERN_ARG_IDX)->column_ptr;
825
10
                const auto& pattern = pattern_col->get_data_at(0);
826
10
                if (pattern.size == 0) {
827
1
                    return Status::OK();
828
1
                }
829
830
9
                std::string error_str;
831
9
                auto engine = std::make_shared<RegexpExtractEngine>();
832
9
                bool st = RegexpExtractEngine::compile(pattern, &error_str, *engine,
833
9
                                                       context->state()->enable_extended_regex());
834
835
9
                if (!st) {
836
0
                    context->set_error(error_str.c_str());
837
0
                    return Status::InvalidArgument(error_str);
838
0
                }
839
9
                context->set_function_state(scope, engine);
840
9
            }
841
10
        }
842
19
        return Status::OK();
843
20
    }
_ZN5doris27FunctionRegexpFunctionalityINS_20RegexpExtractAllImplINS_28RegexpExtractAllStringOutputEEEE4openEPNS_15FunctionContextENS5_18FunctionStateScopeE
Line
Count
Source
819
18
    Status open(FunctionContext* context, FunctionContext::FunctionStateScope scope) override {
820
18
        if (scope == FunctionContext::THREAD_LOCAL) {
821
9
            if (context->is_col_constant(Impl::PATTERN_ARG_IDX)) {
822
9
                DCHECK(!context->get_function_state(scope));
823
9
                const auto pattern_col =
824
9
                        context->get_constant_col(Impl::PATTERN_ARG_IDX)->column_ptr;
825
9
                const auto& pattern = pattern_col->get_data_at(0);
826
9
                if (pattern.size == 0) {
827
1
                    return Status::OK();
828
1
                }
829
830
8
                std::string error_str;
831
8
                auto engine = std::make_shared<RegexpExtractEngine>();
832
8
                bool st = RegexpExtractEngine::compile(pattern, &error_str, *engine,
833
8
                                                       context->state()->enable_extended_regex());
834
835
8
                if (!st) {
836
0
                    context->set_error(error_str.c_str());
837
0
                    return Status::InvalidArgument(error_str);
838
0
                }
839
8
                context->set_function_state(scope, engine);
840
8
            }
841
9
        }
842
17
        return Status::OK();
843
18
    }
_ZN5doris27FunctionRegexpFunctionalityINS_20RegexpExtractAllImplINS_27RegexpExtractAllArrayOutputEEEE4openEPNS_15FunctionContextENS5_18FunctionStateScopeE
Line
Count
Source
819
20
    Status open(FunctionContext* context, FunctionContext::FunctionStateScope scope) override {
820
20
        if (scope == FunctionContext::THREAD_LOCAL) {
821
10
            if (context->is_col_constant(Impl::PATTERN_ARG_IDX)) {
822
10
                DCHECK(!context->get_function_state(scope));
823
10
                const auto pattern_col =
824
10
                        context->get_constant_col(Impl::PATTERN_ARG_IDX)->column_ptr;
825
10
                const auto& pattern = pattern_col->get_data_at(0);
826
10
                if (pattern.size == 0) {
827
1
                    return Status::OK();
828
1
                }
829
830
9
                std::string error_str;
831
9
                auto engine = std::make_shared<RegexpExtractEngine>();
832
9
                bool st = RegexpExtractEngine::compile(pattern, &error_str, *engine,
833
9
                                                       context->state()->enable_extended_regex());
834
835
9
                if (!st) {
836
1
                    context->set_error(error_str.c_str());
837
1
                    return Status::InvalidArgument(error_str);
838
1
                }
839
8
                context->set_function_state(scope, engine);
840
8
            }
841
10
        }
842
18
        return Status::OK();
843
20
    }
844
845
    Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
846
30
                        uint32_t result, size_t input_rows_count) const override {
847
30
        return Impl::execute(context, block, arguments, result, input_rows_count);
848
30
    }
_ZNK5doris27FunctionRegexpFunctionalityINS_17RegexpExtractImplILb1EEEE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjm
Line
Count
Source
846
8
                        uint32_t result, size_t input_rows_count) const override {
847
8
        return Impl::execute(context, block, arguments, result, input_rows_count);
848
8
    }
_ZNK5doris27FunctionRegexpFunctionalityINS_17RegexpExtractImplILb0EEEE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjm
Line
Count
Source
846
8
                        uint32_t result, size_t input_rows_count) const override {
847
8
        return Impl::execute(context, block, arguments, result, input_rows_count);
848
8
    }
_ZNK5doris27FunctionRegexpFunctionalityINS_20RegexpExtractAllImplINS_28RegexpExtractAllStringOutputEEEE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjm
Line
Count
Source
846
7
                        uint32_t result, size_t input_rows_count) const override {
847
7
        return Impl::execute(context, block, arguments, result, input_rows_count);
848
7
    }
_ZNK5doris27FunctionRegexpFunctionalityINS_20RegexpExtractAllImplINS_27RegexpExtractAllArrayOutputEEEE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjm
Line
Count
Source
846
7
                        uint32_t result, size_t input_rows_count) const override {
847
7
        return Impl::execute(context, block, arguments, result, input_rows_count);
848
7
    }
849
};
850
851
1
void register_function_regexp_extract(SimpleFunctionFactory& factory) {
852
1
    factory.register_function<FunctionRegexpReplace<RegexpReplaceImpl<false>, ThreeParamTypes>>();
853
1
    factory.register_function<FunctionRegexpReplace<RegexpReplaceImpl<false>, FourParamTypes>>();
854
1
    factory.register_function<FunctionRegexpReplace<RegexpReplaceImpl<true>, ThreeParamTypes>>();
855
1
    factory.register_function<FunctionRegexpReplace<RegexpReplaceImpl<true>, FourParamTypes>>();
856
1
    factory.register_function<FunctionRegexpFunctionality<RegexpExtractImpl<true>>>();
857
1
    factory.register_function<FunctionRegexpFunctionality<RegexpExtractImpl<false>>>();
858
1
    factory.register_function<
859
1
            FunctionRegexpFunctionality<RegexpExtractAllImpl<RegexpExtractAllStringOutput>>>();
860
1
    factory.register_function<
861
1
            FunctionRegexpFunctionality<RegexpExtractAllImpl<RegexpExtractAllArrayOutput>>>();
862
1
    factory.register_function<FunctionRegexpCount>();
863
1
}
864
865
} // namespace doris