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 |