be/src/exprs/function/function_string_concat.h
Line | Count | Source |
1 | | // Licensed to the Apache Software Foundation (ASF) under one |
2 | | // or more contributor license agreements. See the NOTICE file |
3 | | // distributed with this work for additional information |
4 | | // regarding copyright ownership. The ASF licenses this file |
5 | | // to you under the Apache License, Version 2.0 (the |
6 | | // "License"); you may not use this file except in compliance |
7 | | // with the License. You may obtain a copy of the License at |
8 | | // |
9 | | // http://www.apache.org/licenses/LICENSE-2.0 |
10 | | // |
11 | | // Unless required by applicable law or agreed to in writing, |
12 | | // software distributed under the License is distributed on an |
13 | | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
14 | | // KIND, either express or implied. See the License for the |
15 | | // specific language governing permissions and limitations |
16 | | // under the License. |
17 | | |
18 | | #pragma once |
19 | | |
20 | | #include <fmt/format.h> |
21 | | |
22 | | #include <cstddef> |
23 | | #include <cstring> |
24 | | #include <string> |
25 | | #include <string_view> |
26 | | #include <vector> |
27 | | |
28 | | #include "common/status.h" |
29 | | #include "core/assert_cast.h" |
30 | | #include "core/block/block.h" |
31 | | #include "core/block/column_numbers.h" |
32 | | #include "core/column/column.h" |
33 | | #include "core/column/column_array.h" |
34 | | #include "core/column/column_const.h" |
35 | | #include "core/column/column_nullable.h" |
36 | | #include "core/column/column_string.h" |
37 | | #include "core/column/column_vector.h" |
38 | | #include "core/data_type/data_type_array.h" |
39 | | #include "core/data_type/data_type_nullable.h" |
40 | | #include "core/data_type/data_type_number.h" |
41 | | #include "core/data_type/data_type_string.h" |
42 | | #include "core/memcpy_small.h" |
43 | | #include "core/string_ref.h" |
44 | | #include "exec/common/stringop_substring.h" |
45 | | #include "exec/common/template_helpers.hpp" |
46 | | #include "exec/common/util.hpp" |
47 | | #include "exprs/function/function.h" |
48 | | #include "exprs/function/function_helpers.h" |
49 | | #include "exprs/function_context.h" |
50 | | #include "util/simd/vstring_function.h" |
51 | | |
52 | | namespace doris { |
53 | | #include "common/compile_check_avoid_begin.h" |
54 | | |
55 | | class FunctionStringConcat : public IFunction { |
56 | | public: |
57 | | struct ConcatState { |
58 | | bool use_state = false; |
59 | | std::string tail; |
60 | | }; |
61 | | |
62 | | static constexpr auto name = "concat"; |
63 | 6.06k | static FunctionPtr create() { return std::make_shared<FunctionStringConcat>(); } |
64 | 0 | String get_name() const override { return name; } |
65 | 0 | size_t get_number_of_arguments() const override { return 0; } |
66 | 6.05k | bool is_variadic() const override { return true; } |
67 | | |
68 | 6.05k | DataTypePtr get_return_type_impl(const DataTypes& arguments) const override { |
69 | 6.05k | return std::make_shared<DataTypeString>(); |
70 | 6.05k | } |
71 | | |
72 | 34.9k | Status open(FunctionContext* context, FunctionContext::FunctionStateScope scope) override { |
73 | 34.9k | if (scope == FunctionContext::FunctionStateScope::THREAD_LOCAL) { |
74 | 28.8k | return Status::OK(); |
75 | 28.8k | } |
76 | 6.03k | std::shared_ptr<ConcatState> state = std::make_shared<ConcatState>(); |
77 | | |
78 | 6.03k | context->set_function_state(scope, state); |
79 | | |
80 | 6.03k | state->use_state = true; |
81 | | |
82 | | // Optimize function calls like this: |
83 | | // concat(col, "123", "abc", "456") -> tail = "123abc456" |
84 | 11.7k | for (size_t i = 1; i < context->get_num_args(); i++) { |
85 | 6.99k | const auto* column_string = context->get_constant_col(i); |
86 | 6.99k | if (column_string == nullptr) { |
87 | 1.25k | state->use_state = false; |
88 | 1.25k | return IFunction::open(context, scope); |
89 | 1.25k | } |
90 | 5.74k | auto string_vale = column_string->column_ptr->get_data_at(0); |
91 | 5.74k | if (string_vale.data == nullptr) { |
92 | | // For concat(col, null), it is handled by default_implementation_for_nulls |
93 | 33 | state->use_state = false; |
94 | 33 | return IFunction::open(context, scope); |
95 | 33 | } |
96 | | |
97 | 5.70k | state->tail.append(string_vale.begin(), string_vale.size); |
98 | 5.70k | } |
99 | | |
100 | | // The reserve is used here to allow the usage of memcpy_small_allow_read_write_overflow15 below. |
101 | 4.75k | state->tail.reserve(state->tail.size() + 16); |
102 | | |
103 | 4.75k | return IFunction::open(context, scope); |
104 | 6.03k | } |
105 | | |
106 | | Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments, |
107 | 7.53k | uint32_t result, size_t input_rows_count) const override { |
108 | 7.53k | DCHECK_GE(arguments.size(), 1); |
109 | | |
110 | 7.53k | if (arguments.size() == 1) { |
111 | 29 | block.get_by_position(result).column = block.get_by_position(arguments[0]).column; |
112 | 29 | return Status::OK(); |
113 | 29 | } |
114 | 7.50k | auto* concat_state = reinterpret_cast<ConcatState*>( |
115 | 7.50k | context->get_function_state(FunctionContext::FunctionStateScope::FRAGMENT_LOCAL)); |
116 | 7.50k | if (!concat_state) { |
117 | 0 | return Status::RuntimeError("funciton context for function '{}' must have ConcatState;", |
118 | 0 | get_name()); |
119 | 0 | } |
120 | 7.50k | if (concat_state->use_state) { |
121 | 5.13k | const auto& [col, is_const] = |
122 | 5.13k | unpack_if_const(block.get_by_position(arguments[0]).column); |
123 | 5.13k | const auto* col_str = assert_cast<const ColumnString*>(col.get()); |
124 | 5.13k | if (is_const) { |
125 | 0 | return execute_const<true>(concat_state, block, col_str, result, input_rows_count); |
126 | 5.13k | } else { |
127 | 5.13k | return execute_const<false>(concat_state, block, col_str, result, input_rows_count); |
128 | 5.13k | } |
129 | | |
130 | 5.13k | } else { |
131 | 2.36k | return execute_vecotr(block, arguments, result, input_rows_count); |
132 | 2.36k | } |
133 | 7.50k | } |
134 | | |
135 | | Status execute_vecotr(Block& block, const ColumnNumbers& arguments, uint32_t result, |
136 | 2.36k | size_t input_rows_count) const { |
137 | 2.36k | int argument_size = arguments.size(); |
138 | 2.36k | std::vector<ColumnPtr> argument_columns(argument_size); |
139 | | |
140 | 2.36k | std::vector<const ColumnString::Offsets*> offsets_list(argument_size); |
141 | 2.36k | std::vector<const ColumnString::Chars*> chars_list(argument_size); |
142 | 2.36k | std::vector<bool> is_const_args(argument_size); |
143 | | |
144 | 9.41k | for (int i = 0; i < argument_size; ++i) { |
145 | 7.04k | const auto& [col, is_const] = |
146 | 7.04k | unpack_if_const(block.get_by_position(arguments[i]).column); |
147 | | |
148 | 7.04k | const auto* col_str = assert_cast<const ColumnString*>(col.get()); |
149 | 7.04k | offsets_list[i] = &col_str->get_offsets(); |
150 | 7.04k | chars_list[i] = &col_str->get_chars(); |
151 | 7.04k | is_const_args[i] = is_const; |
152 | 7.04k | } |
153 | | |
154 | 2.36k | auto res = ColumnString::create(); |
155 | 2.36k | auto& res_data = res->get_chars(); |
156 | 2.36k | auto& res_offset = res->get_offsets(); |
157 | | |
158 | 2.36k | res_offset.resize(input_rows_count); |
159 | 2.36k | size_t res_reserve_size = 0; |
160 | 9.41k | for (size_t i = 0; i < argument_size; ++i) { |
161 | 7.04k | if (is_const_args[i]) { |
162 | 2.76k | res_reserve_size += (*offsets_list[i])[0] * input_rows_count; |
163 | 4.28k | } else { |
164 | 4.28k | res_reserve_size += (*offsets_list[i])[input_rows_count - 1]; |
165 | 4.28k | } |
166 | 7.04k | } |
167 | | |
168 | 2.36k | ColumnString::check_chars_length(res_reserve_size, 0); |
169 | | |
170 | 2.36k | res_data.resize(res_reserve_size); |
171 | | |
172 | 2.36k | auto* data = res_data.data(); |
173 | 2.36k | size_t dst_offset = 0; |
174 | | |
175 | 760k | for (size_t i = 0; i < input_rows_count; ++i) { |
176 | 4.06M | for (size_t j = 0; j < argument_size; ++j) { |
177 | 3.30M | const auto& current_offsets = *offsets_list[j]; |
178 | 3.30M | const auto& current_chars = *chars_list[j]; |
179 | 3.30M | auto idx = index_check_const(i, is_const_args[j]); |
180 | 3.30M | const auto size = current_offsets[idx] - current_offsets[idx - 1]; |
181 | 3.30M | if (size > 0) { |
182 | 3.29M | memcpy_small_allow_read_write_overflow15( |
183 | 3.29M | data + dst_offset, current_chars.data() + current_offsets[idx - 1], |
184 | 3.29M | size); |
185 | 3.29M | dst_offset += size; |
186 | 3.29M | } |
187 | 3.30M | } |
188 | 757k | res_offset[i] = dst_offset; |
189 | 757k | } |
190 | | |
191 | 2.36k | block.get_by_position(result).column = std::move(res); |
192 | 2.36k | return Status::OK(); |
193 | 2.36k | } |
194 | | |
195 | | template <bool is_const> |
196 | | Status execute_const(ConcatState* concat_state, Block& block, const ColumnString* col_str, |
197 | 5.13k | uint32_t result, size_t input_rows_count) const { |
198 | | // using tail optimize |
199 | | |
200 | 5.13k | auto res = ColumnString::create(); |
201 | 5.13k | auto& res_data = res->get_chars(); |
202 | 5.13k | auto& res_offset = res->get_offsets(); |
203 | 5.13k | res_offset.resize(input_rows_count); |
204 | | |
205 | 5.13k | size_t res_reserve_size = 0; |
206 | 5.13k | if constexpr (is_const) { |
207 | 0 | res_reserve_size = col_str->get_offsets()[0] * input_rows_count; |
208 | 5.13k | } else { |
209 | 5.13k | res_reserve_size = col_str->get_offsets()[input_rows_count - 1]; |
210 | 5.13k | } |
211 | 5.13k | res_reserve_size += concat_state->tail.size() * input_rows_count; |
212 | | |
213 | 5.13k | ColumnString::check_chars_length(res_reserve_size, 0); |
214 | 5.13k | res_data.resize(res_reserve_size); |
215 | | |
216 | 5.13k | const auto& tail = concat_state->tail; |
217 | 5.13k | auto* data = res_data.data(); |
218 | 5.13k | size_t dst_offset = 0; |
219 | | |
220 | 240k | for (size_t i = 0; i < input_rows_count; ++i) { |
221 | 235k | const auto idx = index_check_const<is_const>(i); |
222 | 235k | StringRef str_val = col_str->get_data_at(idx); |
223 | | // copy column |
224 | 235k | memcpy_small_allow_read_write_overflow15(data + dst_offset, str_val.data, str_val.size); |
225 | 235k | dst_offset += str_val.size; |
226 | | // copy tail |
227 | 235k | memcpy_small_allow_read_write_overflow15(data + dst_offset, tail.data(), tail.size()); |
228 | 235k | dst_offset += tail.size(); |
229 | 235k | res_offset[i] = dst_offset; |
230 | 235k | } |
231 | 5.13k | block.get_by_position(result).column = std::move(res); |
232 | 5.13k | return Status::OK(); |
233 | 5.13k | } Unexecuted instantiation: _ZNK5doris20FunctionStringConcat13execute_constILb1EEENS_6StatusEPNS0_11ConcatStateERNS_5BlockEPKNS_9ColumnStrIjEEjm _ZNK5doris20FunctionStringConcat13execute_constILb0EEENS_6StatusEPNS0_11ConcatStateERNS_5BlockEPKNS_9ColumnStrIjEEjm Line | Count | Source | 197 | 5.13k | uint32_t result, size_t input_rows_count) const { | 198 | | // using tail optimize | 199 | | | 200 | 5.13k | auto res = ColumnString::create(); | 201 | 5.13k | auto& res_data = res->get_chars(); | 202 | 5.13k | auto& res_offset = res->get_offsets(); | 203 | 5.13k | res_offset.resize(input_rows_count); | 204 | | | 205 | 5.13k | size_t res_reserve_size = 0; | 206 | | if constexpr (is_const) { | 207 | | res_reserve_size = col_str->get_offsets()[0] * input_rows_count; | 208 | 5.13k | } else { | 209 | 5.13k | res_reserve_size = col_str->get_offsets()[input_rows_count - 1]; | 210 | 5.13k | } | 211 | 5.13k | res_reserve_size += concat_state->tail.size() * input_rows_count; | 212 | | | 213 | 5.13k | ColumnString::check_chars_length(res_reserve_size, 0); | 214 | 5.13k | res_data.resize(res_reserve_size); | 215 | | | 216 | 5.13k | const auto& tail = concat_state->tail; | 217 | 5.13k | auto* data = res_data.data(); | 218 | 5.13k | size_t dst_offset = 0; | 219 | | | 220 | 240k | for (size_t i = 0; i < input_rows_count; ++i) { | 221 | 235k | const auto idx = index_check_const<is_const>(i); | 222 | 235k | StringRef str_val = col_str->get_data_at(idx); | 223 | | // copy column | 224 | 235k | memcpy_small_allow_read_write_overflow15(data + dst_offset, str_val.data, str_val.size); | 225 | 235k | dst_offset += str_val.size; | 226 | | // copy tail | 227 | 235k | memcpy_small_allow_read_write_overflow15(data + dst_offset, tail.data(), tail.size()); | 228 | 235k | dst_offset += tail.size(); | 229 | 235k | res_offset[i] = dst_offset; | 230 | 235k | } | 231 | 5.13k | block.get_by_position(result).column = std::move(res); | 232 | 5.13k | return Status::OK(); | 233 | 5.13k | } |
|
234 | | }; |
235 | | |
236 | | class FunctionStringElt : public IFunction { |
237 | | public: |
238 | | static constexpr auto name = "elt"; |
239 | 422 | static FunctionPtr create() { return std::make_shared<FunctionStringElt>(); } |
240 | 0 | String get_name() const override { return name; } |
241 | 0 | size_t get_number_of_arguments() const override { return 0; } |
242 | 414 | bool is_variadic() const override { return true; } |
243 | | |
244 | 413 | DataTypePtr get_return_type_impl(const DataTypes& arguments) const override { |
245 | 413 | return make_nullable(std::make_shared<DataTypeString>()); |
246 | 413 | } |
247 | 837 | bool use_default_implementation_for_nulls() const override { return false; } |
248 | | |
249 | | Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments, |
250 | 424 | uint32_t result, size_t input_rows_count) const override { |
251 | 424 | int arguent_size = arguments.size(); |
252 | 424 | int num_children = arguent_size - 1; |
253 | 424 | auto res = ColumnString::create(); |
254 | | |
255 | 424 | if (auto const_column = check_and_get_column<ColumnConst>( |
256 | 424 | *block.get_by_position(arguments[0]).column)) { |
257 | 153 | auto data = const_column->get_data_at(0); |
258 | | // return NULL, pos is null or pos < 0 or pos > num_children |
259 | 153 | auto is_null = data.data == nullptr; |
260 | 153 | auto pos = is_null ? 0 : *(Int32*)data.data; |
261 | 153 | is_null = pos <= 0 || pos > num_children; |
262 | | |
263 | 153 | auto null_map = ColumnUInt8::create(input_rows_count, is_null); |
264 | 153 | if (is_null) { |
265 | 135 | res->insert_many_defaults(input_rows_count); |
266 | 135 | } else { |
267 | 18 | auto& target_column = block.get_by_position(arguments[pos]).column; |
268 | 18 | if (auto target_const_column = check_and_get_column<ColumnConst>(*target_column)) { |
269 | 6 | auto target_data = target_const_column->get_data_at(0); |
270 | | // return NULL, no target data |
271 | 6 | if (target_data.data == nullptr) { |
272 | 0 | null_map = ColumnUInt8::create(input_rows_count, true); |
273 | 0 | res->insert_many_defaults(input_rows_count); |
274 | 6 | } else { |
275 | 6 | res->insert_data_repeatedly(target_data.data, target_data.size, |
276 | 6 | input_rows_count); |
277 | 6 | } |
278 | 12 | } else if (auto target_nullable_column = |
279 | 12 | check_and_get_column<ColumnNullable>(*target_column)) { |
280 | 12 | auto& target_null_map = target_nullable_column->get_null_map_data(); |
281 | 12 | VectorizedUtils::update_null_map(null_map->get_data(), target_null_map); |
282 | | |
283 | 12 | auto& target_str_column = assert_cast<const ColumnString&>( |
284 | 12 | target_nullable_column->get_nested_column()); |
285 | 12 | res->get_chars().assign(target_str_column.get_chars().begin(), |
286 | 12 | target_str_column.get_chars().end()); |
287 | 12 | res->get_offsets().assign(target_str_column.get_offsets().begin(), |
288 | 12 | target_str_column.get_offsets().end()); |
289 | 12 | } else { |
290 | 0 | auto& target_str_column = assert_cast<const ColumnString&>(*target_column); |
291 | 0 | res->get_chars().assign(target_str_column.get_chars().begin(), |
292 | 0 | target_str_column.get_chars().end()); |
293 | 0 | res->get_offsets().assign(target_str_column.get_offsets().begin(), |
294 | 0 | target_str_column.get_offsets().end()); |
295 | 0 | } |
296 | 18 | } |
297 | 153 | block.get_by_position(result).column = |
298 | 153 | ColumnNullable::create(std::move(res), std::move(null_map)); |
299 | 271 | } else if (auto pos_null_column = check_and_get_column<ColumnNullable>( |
300 | 271 | *block.get_by_position(arguments[0]).column)) { |
301 | 218 | auto& pos_column = |
302 | 218 | assert_cast<const ColumnInt32&>(pos_null_column->get_nested_column()); |
303 | 218 | auto& pos_null_map = pos_null_column->get_null_map_data(); |
304 | 218 | auto null_map = ColumnUInt8::create(input_rows_count, false); |
305 | 218 | auto& res_null_map = null_map->get_data(); |
306 | | |
307 | 514 | for (size_t i = 0; i < input_rows_count; ++i) { |
308 | 296 | auto pos = pos_column.get_element(i); |
309 | 296 | res_null_map[i] = |
310 | 296 | pos_null_map[i] || pos <= 0 || pos > num_children || |
311 | 296 | block.get_by_position(arguments[pos]).column->get_data_at(i).data == |
312 | 35 | nullptr; |
313 | 296 | if (res_null_map[i]) { |
314 | 261 | res->insert_default(); |
315 | 261 | } else { |
316 | 35 | auto insert_data = block.get_by_position(arguments[pos]).column->get_data_at(i); |
317 | 35 | res->insert_data(insert_data.data, insert_data.size); |
318 | 35 | } |
319 | 296 | } |
320 | 218 | block.get_by_position(result).column = |
321 | 218 | ColumnNullable::create(std::move(res), std::move(null_map)); |
322 | 218 | } else { |
323 | 53 | auto& pos_column = |
324 | 53 | assert_cast<const ColumnInt32&>(*block.get_by_position(arguments[0]).column); |
325 | 53 | auto null_map = ColumnUInt8::create(input_rows_count, false); |
326 | 53 | auto& res_null_map = null_map->get_data(); |
327 | | |
328 | 122 | for (size_t i = 0; i < input_rows_count; ++i) { |
329 | 69 | auto pos = pos_column.get_element(i); |
330 | 69 | res_null_map[i] = |
331 | 69 | pos <= 0 || pos > num_children || |
332 | 69 | block.get_by_position(arguments[pos]).column->get_data_at(i).data == |
333 | 23 | nullptr; |
334 | 69 | if (res_null_map[i]) { |
335 | 46 | res->insert_default(); |
336 | 46 | } else { |
337 | 23 | auto insert_data = block.get_by_position(arguments[pos]).column->get_data_at(i); |
338 | 23 | res->insert_data(insert_data.data, insert_data.size); |
339 | 23 | } |
340 | 69 | } |
341 | 53 | block.get_by_position(result).column = |
342 | 53 | ColumnNullable::create(std::move(res), std::move(null_map)); |
343 | 53 | } |
344 | 424 | return Status::OK(); |
345 | 424 | } |
346 | | }; |
347 | | |
348 | | // concat_ws (string,string....) or (string, Array) |
349 | | // TODO: avoid use fmtlib |
350 | | class FunctionStringConcatWs : public IFunction { |
351 | | public: |
352 | | using Chars = ColumnString::Chars; |
353 | | using Offsets = ColumnString::Offsets; |
354 | | |
355 | | static constexpr auto name = "concat_ws"; |
356 | 595 | static FunctionPtr create() { return std::make_shared<FunctionStringConcatWs>(); } |
357 | 0 | String get_name() const override { return name; } |
358 | 0 | size_t get_number_of_arguments() const override { return 0; } |
359 | 587 | bool is_variadic() const override { return true; } |
360 | | |
361 | 586 | DataTypePtr get_return_type_impl(const DataTypes& arguments) const override { |
362 | 586 | const IDataType* first_type = arguments[0].get(); |
363 | 586 | if (first_type->is_nullable()) { |
364 | 458 | return make_nullable(std::make_shared<DataTypeString>()); |
365 | 458 | } else { |
366 | 128 | return std::make_shared<DataTypeString>(); |
367 | 128 | } |
368 | 586 | } |
369 | 1.20k | bool use_default_implementation_for_nulls() const override { return false; } |
370 | | |
371 | | Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments, |
372 | 616 | uint32_t result, size_t input_rows_count) const override { |
373 | 616 | DCHECK_GE(arguments.size(), 2); |
374 | 616 | auto null_map = ColumnUInt8::create(input_rows_count, 0); |
375 | | // we create a zero column to simply implement |
376 | 616 | auto const_null_map = ColumnUInt8::create(input_rows_count, 0); |
377 | 616 | auto res = ColumnString::create(); |
378 | 616 | bool is_null_type = block.get_by_position(arguments[0]).type.get()->is_nullable(); |
379 | 616 | size_t argument_size = arguments.size(); |
380 | 616 | std::vector<const Offsets*> offsets_list(argument_size); |
381 | 616 | std::vector<const Chars*> chars_list(argument_size); |
382 | 616 | std::vector<const ColumnUInt8::Container*> null_list(argument_size); |
383 | | |
384 | 616 | std::vector<ColumnPtr> argument_columns(argument_size); |
385 | 616 | std::vector<ColumnPtr> argument_null_columns(argument_size); |
386 | | |
387 | 2.13k | for (size_t i = 0; i < argument_size; ++i) { |
388 | 1.52k | argument_columns[i] = |
389 | 1.52k | block.get_by_position(arguments[i]).column->convert_to_full_column_if_const(); |
390 | 1.52k | if (const auto* nullable = |
391 | 1.52k | check_and_get_column<const ColumnNullable>(*argument_columns[i])) { |
392 | | // Danger: Here must dispose the null map data first! Because |
393 | | // argument_columns[i]=nullable->get_nested_column_ptr(); will release the mem |
394 | | // of column nullable mem of null map |
395 | 1.20k | null_list[i] = &nullable->get_null_map_data(); |
396 | 1.20k | argument_null_columns[i] = nullable->get_null_map_column_ptr(); |
397 | 1.20k | argument_columns[i] = nullable->get_nested_column_ptr(); |
398 | 1.20k | } else { |
399 | 320 | null_list[i] = &const_null_map->get_data(); |
400 | 320 | } |
401 | | |
402 | 1.52k | if (is_column<ColumnArray>(argument_columns[i].get())) { |
403 | 118 | continue; |
404 | 118 | } |
405 | | |
406 | 1.40k | const auto* col_str = assert_cast<const ColumnString*>(argument_columns[i].get()); |
407 | 1.40k | offsets_list[i] = &col_str->get_offsets(); |
408 | 1.40k | chars_list[i] = &col_str->get_chars(); |
409 | 1.40k | } |
410 | | |
411 | 616 | auto& res_data = res->get_chars(); |
412 | 616 | auto& res_offset = res->get_offsets(); |
413 | 616 | res_offset.resize(input_rows_count); |
414 | | |
415 | 616 | VectorizedUtils::update_null_map(null_map->get_data(), *null_list[0]); |
416 | 616 | fmt::memory_buffer buffer; |
417 | 616 | std::vector<std::string_view> views; |
418 | | |
419 | 616 | if (is_column<ColumnArray>(argument_columns[1].get())) { |
420 | 116 | if (argument_size != 2) { |
421 | 1 | return Status::InvalidArgument( |
422 | 1 | "concat_ws with array argument expects exactly 2 arguments, but got {}", |
423 | 1 | argument_size); |
424 | 1 | } |
425 | | // Determine if the nested type of the array is String |
426 | 115 | const auto& array_column = reinterpret_cast<const ColumnArray&>(*argument_columns[1]); |
427 | 115 | if (!array_column.get_data().is_column_string()) { |
428 | 0 | return Status::NotSupported( |
429 | 0 | fmt::format("unsupported nested array of type {} for function {}", |
430 | 0 | is_column_nullable(array_column.get_data()) |
431 | 0 | ? array_column.get_data().get_name() |
432 | 0 | : array_column.get_data().get_name(), |
433 | 0 | get_name())); |
434 | 0 | } |
435 | | // Concat string in array |
436 | 115 | _execute_array(input_rows_count, array_column, buffer, views, offsets_list, chars_list, |
437 | 115 | null_list, res_data, res_offset); |
438 | | |
439 | 500 | } else { |
440 | | // Concat string |
441 | 500 | _execute_string(input_rows_count, argument_size, buffer, views, offsets_list, |
442 | 500 | chars_list, null_list, res_data, res_offset); |
443 | 500 | } |
444 | 615 | if (is_null_type) { |
445 | 458 | block.get_by_position(result).column = |
446 | 458 | ColumnNullable::create(std::move(res), std::move(null_map)); |
447 | 458 | } else { |
448 | 157 | block.get_by_position(result).column = std::move(res); |
449 | 157 | } |
450 | 615 | return Status::OK(); |
451 | 616 | } |
452 | | |
453 | | private: |
454 | | void _execute_array(const size_t& input_rows_count, const ColumnArray& array_column, |
455 | | fmt::memory_buffer& buffer, std::vector<std::string_view>& views, |
456 | | const std::vector<const Offsets*>& offsets_list, |
457 | | const std::vector<const Chars*>& chars_list, |
458 | | const std::vector<const ColumnUInt8::Container*>& null_list, |
459 | 115 | Chars& res_data, Offsets& res_offset) const { |
460 | | // Get array nested column |
461 | 115 | const UInt8* array_nested_null_map = nullptr; |
462 | 115 | ColumnPtr array_nested_column = nullptr; |
463 | | |
464 | 115 | if (is_column_nullable(array_column.get_data())) { |
465 | 115 | const auto& array_nested_null_column = |
466 | 115 | reinterpret_cast<const ColumnNullable&>(array_column.get_data()); |
467 | | // String's null map in array |
468 | 115 | array_nested_null_map = |
469 | 115 | array_nested_null_column.get_null_map_column().get_data().data(); |
470 | 115 | array_nested_column = array_nested_null_column.get_nested_column_ptr(); |
471 | 115 | } else { |
472 | 0 | array_nested_column = array_column.get_data_ptr(); |
473 | 0 | } |
474 | | |
475 | 115 | const auto& string_column = reinterpret_cast<const ColumnString&>(*array_nested_column); |
476 | 115 | const Chars& string_src_chars = string_column.get_chars(); |
477 | 115 | const auto& src_string_offsets = string_column.get_offsets(); |
478 | 115 | const auto& src_array_offsets = array_column.get_offsets(); |
479 | 115 | size_t current_src_array_offset = 0; |
480 | 115 | auto& array_nullmap = *null_list[1]; |
481 | | |
482 | | // Concat string in array |
483 | 622 | for (size_t i = 0; i < input_rows_count; ++i) { |
484 | 507 | auto& sep_offsets = *offsets_list[0]; |
485 | 507 | auto& sep_chars = *chars_list[0]; |
486 | 507 | auto& sep_nullmap = *null_list[0]; |
487 | | |
488 | 507 | if (sep_nullmap[i]) { |
489 | 11 | res_offset[i] = res_data.size(); |
490 | 11 | current_src_array_offset += src_array_offsets[i] - src_array_offsets[i - 1]; |
491 | 11 | continue; |
492 | 11 | } |
493 | | |
494 | 496 | if (array_nullmap[i]) { |
495 | 10 | StringOP::push_empty_string(i, res_data, res_offset); |
496 | 10 | current_src_array_offset += src_array_offsets[i] - src_array_offsets[i - 1]; |
497 | 10 | continue; |
498 | 10 | } |
499 | | |
500 | 486 | int sep_size = sep_offsets[i] - sep_offsets[i - 1]; |
501 | 486 | const char* sep_data = reinterpret_cast<const char*>(&sep_chars[sep_offsets[i - 1]]); |
502 | | |
503 | 486 | std::string_view sep(sep_data, sep_size); |
504 | 486 | buffer.clear(); |
505 | 486 | views.clear(); |
506 | | |
507 | 486 | for (auto next_src_array_offset = src_array_offsets[i]; |
508 | 1.29k | current_src_array_offset < next_src_array_offset; ++current_src_array_offset) { |
509 | 809 | const auto current_src_string_offset = |
510 | 809 | current_src_array_offset ? src_string_offsets[current_src_array_offset - 1] |
511 | 809 | : 0; |
512 | 809 | size_t bytes_to_copy = |
513 | 809 | src_string_offsets[current_src_array_offset] - current_src_string_offset; |
514 | 809 | const char* ptr = |
515 | 809 | reinterpret_cast<const char*>(&string_src_chars[current_src_string_offset]); |
516 | | |
517 | 809 | if (array_nested_null_map == nullptr || |
518 | 809 | !array_nested_null_map[current_src_array_offset]) { |
519 | 776 | views.emplace_back(ptr, bytes_to_copy); |
520 | 776 | } |
521 | 809 | } |
522 | | |
523 | | // Direct append instead of fmt::format_to + fmt::join |
524 | 486 | if (!views.empty()) { |
525 | 473 | buffer.append(views[0].data(), views[0].data() + views[0].size()); |
526 | 776 | for (size_t j = 1; j < views.size(); ++j) { |
527 | 303 | if (!sep.empty()) { |
528 | 281 | buffer.append(sep.data(), sep.data() + sep.size()); |
529 | 281 | } |
530 | 303 | buffer.append(views[j].data(), views[j].data() + views[j].size()); |
531 | 303 | } |
532 | 473 | } |
533 | | |
534 | 486 | StringOP::push_value_string(std::string_view(buffer.data(), buffer.size()), i, res_data, |
535 | 486 | res_offset); |
536 | 486 | } |
537 | 115 | } |
538 | | |
539 | | void _execute_string(const size_t& input_rows_count, const size_t& argument_size, |
540 | | fmt::memory_buffer& buffer, std::vector<std::string_view>& views, |
541 | | const std::vector<const Offsets*>& offsets_list, |
542 | | const std::vector<const Chars*>& chars_list, |
543 | | const std::vector<const ColumnUInt8::Container*>& null_list, |
544 | 500 | Chars& res_data, Offsets& res_offset) const { |
545 | | // Concat string |
546 | 1.14k | for (size_t i = 0; i < input_rows_count; ++i) { |
547 | 644 | auto& sep_offsets = *offsets_list[0]; |
548 | 644 | auto& sep_chars = *chars_list[0]; |
549 | 644 | auto& sep_nullmap = *null_list[0]; |
550 | 644 | if (sep_nullmap[i]) { |
551 | 78 | res_offset[i] = res_data.size(); |
552 | 78 | continue; |
553 | 78 | } |
554 | | |
555 | 566 | int sep_size = sep_offsets[i] - sep_offsets[i - 1]; |
556 | 566 | const char* sep_data = reinterpret_cast<const char*>(&sep_chars[sep_offsets[i - 1]]); |
557 | | |
558 | 566 | std::string_view sep(sep_data, sep_size); |
559 | 566 | buffer.clear(); |
560 | 566 | views.clear(); |
561 | 1.38k | for (size_t j = 1; j < argument_size; ++j) { |
562 | 814 | auto& current_offsets = *offsets_list[j]; |
563 | 814 | auto& current_chars = *chars_list[j]; |
564 | 814 | auto& current_nullmap = *null_list[j]; |
565 | 814 | int size = current_offsets[i] - current_offsets[i - 1]; |
566 | 814 | const char* ptr = |
567 | 814 | reinterpret_cast<const char*>(¤t_chars[current_offsets[i - 1]]); |
568 | 814 | if (!current_nullmap[i]) { |
569 | 732 | views.emplace_back(ptr, size); |
570 | 732 | } |
571 | 814 | } |
572 | | // Direct append instead of fmt::format_to + fmt::join |
573 | 566 | if (!views.empty()) { |
574 | 524 | buffer.append(views[0].data(), views[0].data() + views[0].size()); |
575 | 732 | for (size_t j = 1; j < views.size(); ++j) { |
576 | 208 | if (!sep.empty()) { |
577 | 158 | buffer.append(sep.data(), sep.data() + sep.size()); |
578 | 158 | } |
579 | 208 | buffer.append(views[j].data(), views[j].data() + views[j].size()); |
580 | 208 | } |
581 | 524 | } |
582 | 566 | StringOP::push_value_string(std::string_view(buffer.data(), buffer.size()), i, res_data, |
583 | 566 | res_offset); |
584 | 566 | } |
585 | 500 | } |
586 | | }; |
587 | | |
588 | | class FunctionStringRepeat : public IFunction { |
589 | | public: |
590 | | static constexpr auto name = "repeat"; |
591 | 268 | static FunctionPtr create() { return std::make_shared<FunctionStringRepeat>(); } |
592 | 1 | String get_name() const override { return name; } |
593 | 259 | size_t get_number_of_arguments() const override { return 2; } |
594 | | // should set NULL value of nested data to default, |
595 | | // as iff it's not inited and invalid, the repeat result of length is so large cause overflow |
596 | 323 | bool need_replace_null_data_to_default() const override { return true; } |
597 | | |
598 | 259 | DataTypePtr get_return_type_impl(const DataTypes& arguments) const override { |
599 | 259 | return make_nullable(std::make_shared<DataTypeString>()); |
600 | 259 | } |
601 | | Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments, |
602 | 359 | uint32_t result, size_t input_rows_count) const override { |
603 | 359 | DCHECK_EQ(arguments.size(), 2); |
604 | 359 | auto res = ColumnString::create(); |
605 | 359 | auto null_map = ColumnUInt8::create(); |
606 | | |
607 | 359 | ColumnPtr argument_ptr[2]; |
608 | 359 | argument_ptr[0] = |
609 | 359 | block.get_by_position(arguments[0]).column->convert_to_full_column_if_const(); |
610 | 359 | argument_ptr[1] = block.get_by_position(arguments[1]).column; |
611 | | |
612 | 359 | if (const auto* col1 = check_and_get_column<ColumnString>(*argument_ptr[0])) { |
613 | 359 | if (const auto* col2 = check_and_get_column<ColumnInt32>(*argument_ptr[1])) { |
614 | 238 | RETURN_IF_ERROR(vector_vector(col1->get_chars(), col1->get_offsets(), |
615 | 238 | col2->get_data(), res->get_chars(), |
616 | 238 | res->get_offsets(), null_map->get_data())); |
617 | 238 | block.replace_by_position( |
618 | 238 | result, ColumnNullable::create(std::move(res), std::move(null_map))); |
619 | 238 | return Status::OK(); |
620 | 238 | } else if (const auto* col2_const = |
621 | 121 | check_and_get_column<ColumnConst>(*argument_ptr[1])) { |
622 | 121 | DCHECK(check_and_get_column<ColumnInt32>(col2_const->get_data_column())); |
623 | 121 | int repeat = col2_const->get_int(0); |
624 | 121 | if (repeat <= 0) { |
625 | 18 | null_map->get_data().resize_fill(input_rows_count, 0); |
626 | 18 | res->insert_many_defaults(input_rows_count); |
627 | 103 | } else { |
628 | 103 | vector_const(col1->get_chars(), col1->get_offsets(), repeat, res->get_chars(), |
629 | 103 | res->get_offsets(), null_map->get_data()); |
630 | 103 | } |
631 | 121 | block.replace_by_position( |
632 | 121 | result, ColumnNullable::create(std::move(res), std::move(null_map))); |
633 | 121 | return Status::OK(); |
634 | 121 | } |
635 | 359 | } |
636 | | |
637 | 0 | return Status::RuntimeError("repeat function get error param: {}, {}", |
638 | 0 | argument_ptr[0]->get_name(), argument_ptr[1]->get_name()); |
639 | 359 | } |
640 | | |
641 | | Status vector_vector(const ColumnString::Chars& data, const ColumnString::Offsets& offsets, |
642 | | const ColumnInt32::Container& repeats, ColumnString::Chars& res_data, |
643 | | ColumnString::Offsets& res_offsets, |
644 | 238 | ColumnUInt8::Container& null_map) const { |
645 | 238 | size_t input_row_size = offsets.size(); |
646 | | |
647 | 238 | res_offsets.resize(input_row_size); |
648 | 238 | null_map.resize_fill(input_row_size, 0); |
649 | | // Reserve the combined size of rows with positive repeat counts. |
650 | 238 | size_t total = 0; |
651 | 540k | for (ssize_t i = 0; i < input_row_size; ++i) { |
652 | 540k | size_t size = offsets[i] - offsets[i - 1]; |
653 | 540k | int repeat = repeats[i]; |
654 | 540k | if (repeat > 0) { |
655 | 526k | ColumnString::check_chars_length(repeat * size + total, 0); |
656 | 526k | total += repeat * size; |
657 | 526k | } |
658 | 540k | } |
659 | 238 | res_data.reserve(total); |
660 | | |
661 | 540k | for (ssize_t i = 0; i < input_row_size; ++i) { |
662 | 540k | const uint8_t* raw_str = &data[offsets[i - 1]]; |
663 | 540k | size_t size = offsets[i] - offsets[i - 1]; |
664 | 540k | int repeat = repeats[i]; |
665 | 540k | if (repeat <= 0) { |
666 | 13.8k | StringOP::push_empty_string(i, res_data, res_offsets); |
667 | 526k | } else { |
668 | 526k | size_t old_size = res_data.size(); |
669 | 526k | res_data.resize(old_size + repeat * size); |
670 | 526k | StringOP::fast_repeat(res_data.data() + old_size, raw_str, size, repeat); |
671 | 526k | res_offsets[i] = (ColumnString::Offset)res_data.size(); |
672 | 526k | } |
673 | 540k | } |
674 | 238 | return Status::OK(); |
675 | 238 | } |
676 | | |
677 | | // TODO: rethink we should use `DEFAULT_MAX_STRING_SIZE` to bigger here |
678 | | void vector_const(const ColumnString::Chars& data, const ColumnString::Offsets& offsets, |
679 | | int repeat, ColumnString::Chars& res_data, ColumnString::Offsets& res_offsets, |
680 | 103 | ColumnUInt8::Container& null_map) const { |
681 | 103 | size_t input_row_size = offsets.size(); |
682 | | |
683 | 103 | res_offsets.resize(input_row_size); |
684 | 103 | null_map.resize_fill(input_row_size, 0); |
685 | | // Pre-size for const repeat |
686 | 103 | size_t total = 0; |
687 | 4.29k | for (ssize_t i = 0; i < input_row_size; ++i) { |
688 | 4.19k | size_t size = offsets[i] - offsets[i - 1]; |
689 | 4.19k | ColumnString::check_chars_length(repeat * size + total, 0); |
690 | 4.19k | total += repeat * size; |
691 | 4.19k | } |
692 | 103 | res_data.reserve(total); |
693 | | |
694 | 4.28k | for (ssize_t i = 0; i < input_row_size; ++i) { |
695 | 4.17k | const uint8_t* raw_str = &data[offsets[i - 1]]; |
696 | 4.17k | size_t size = offsets[i] - offsets[i - 1]; |
697 | 4.17k | size_t old_size = res_data.size(); |
698 | 4.17k | res_data.resize(old_size + repeat * size); |
699 | 4.17k | StringOP::fast_repeat(res_data.data() + old_size, raw_str, size, repeat); |
700 | 4.17k | res_offsets[i] = (ColumnString::Offset)res_data.size(); |
701 | 4.17k | } |
702 | 103 | } |
703 | | }; |
704 | | |
705 | | /// PaddingChars pre-processes the pad string for efficient padding. |
706 | | /// When is_utf8=false, character count equals byte count — no UTF-8 decoding needed. |
707 | | /// When is_utf8=true, we build a byte-offset table for code points. |
708 | | /// In both cases, the pad string is pre-expanded (doubled) until it has >= 16 characters, |
709 | | /// so that each memcpy in append_to copies at least 16 bytes at a time. |
710 | | template <bool is_utf8> |
711 | | struct PaddingChars { |
712 | | std::string pad_string; |
713 | | /// utf8_byte_offsets[i] = byte offset of i-th code point in pad_string. |
714 | | /// utf8_byte_offsets has (num_chars + 1) entries, with [0]=0 and [num_chars]=pad_string.size(). |
715 | | std::vector<size_t> utf8_byte_offsets; |
716 | | |
717 | | explicit PaddingChars(const uint8_t* data, size_t len) |
718 | 1.12k | : pad_string(reinterpret_cast<const char*>(data), len) { |
719 | 1.12k | init(); |
720 | 1.12k | } _ZN5doris12PaddingCharsILb0EEC2EPKhm Line | Count | Source | 718 | 97 | : pad_string(reinterpret_cast<const char*>(data), len) { | 719 | 97 | init(); | 720 | 97 | } |
_ZN5doris12PaddingCharsILb1EEC2EPKhm Line | Count | Source | 718 | 1.02k | : pad_string(reinterpret_cast<const char*>(data), len) { | 719 | 1.02k | init(); | 720 | 1.02k | } |
|
721 | | |
722 | 878k | size_t num_chars() const { |
723 | 878k | if constexpr (is_utf8) { |
724 | 3.87k | return utf8_byte_offsets.size() - 1; |
725 | 874k | } else { |
726 | 874k | return pad_string.size(); |
727 | 874k | } |
728 | 878k | } _ZNK5doris12PaddingCharsILb0EE9num_charsEv Line | Count | Source | 722 | 874k | size_t num_chars() const { | 723 | | if constexpr (is_utf8) { | 724 | | return utf8_byte_offsets.size() - 1; | 725 | 874k | } else { | 726 | 874k | return pad_string.size(); | 727 | 874k | } | 728 | 874k | } |
_ZNK5doris12PaddingCharsILb1EE9num_charsEv Line | Count | Source | 722 | 3.87k | size_t num_chars() const { | 723 | 3.87k | if constexpr (is_utf8) { | 724 | 3.87k | return utf8_byte_offsets.size() - 1; | 725 | | } else { | 726 | | return pad_string.size(); | 727 | | } | 728 | 3.87k | } |
|
729 | | |
730 | 445k | size_t chars_to_bytes(size_t n) const { |
731 | 445k | if constexpr (is_utf8) { |
732 | 368 | return utf8_byte_offsets[n]; |
733 | 445k | } else { |
734 | 445k | return n; |
735 | 445k | } |
736 | 445k | } _ZNK5doris12PaddingCharsILb0EE14chars_to_bytesEm Line | Count | Source | 730 | 445k | size_t chars_to_bytes(size_t n) const { | 731 | | if constexpr (is_utf8) { | 732 | | return utf8_byte_offsets[n]; | 733 | 445k | } else { | 734 | 445k | return n; | 735 | 445k | } | 736 | 445k | } |
_ZNK5doris12PaddingCharsILb1EE14chars_to_bytesEm Line | Count | Source | 730 | 368 | size_t chars_to_bytes(size_t n) const { | 731 | 368 | if constexpr (is_utf8) { | 732 | 368 | return utf8_byte_offsets[n]; | 733 | | } else { | 734 | | return n; | 735 | | } | 736 | 368 | } |
|
737 | | |
738 | | /// Append `num_chars_to_pad` padding characters to dst, return bytes written. |
739 | 218k | size_t append_to(uint8_t* dst, size_t num_chars_to_pad) const { |
740 | 218k | if (num_chars_to_pad == 0) { |
741 | 0 | return 0; |
742 | 0 | } |
743 | 218k | const auto* src = reinterpret_cast<const uint8_t*>(pad_string.data()); |
744 | 218k | const size_t step = num_chars(); |
745 | 218k | uint8_t* dst_start = dst; |
746 | 226k | while (num_chars_to_pad > step) { |
747 | 8.18k | size_t bytes = chars_to_bytes(step); |
748 | 8.18k | memcpy(dst, src, bytes); |
749 | 8.18k | dst += bytes; |
750 | 8.18k | num_chars_to_pad -= step; |
751 | 8.18k | } |
752 | 218k | size_t bytes = chars_to_bytes(num_chars_to_pad); |
753 | 218k | memcpy(dst, src, bytes); |
754 | 218k | dst += bytes; |
755 | 218k | return dst - dst_start; |
756 | 218k | } _ZNK5doris12PaddingCharsILb0EE9append_toEPhm Line | Count | Source | 739 | 218k | size_t append_to(uint8_t* dst, size_t num_chars_to_pad) const { | 740 | 218k | if (num_chars_to_pad == 0) { | 741 | 0 | return 0; | 742 | 0 | } | 743 | 218k | const auto* src = reinterpret_cast<const uint8_t*>(pad_string.data()); | 744 | 218k | const size_t step = num_chars(); | 745 | 218k | uint8_t* dst_start = dst; | 746 | 226k | while (num_chars_to_pad > step) { | 747 | 8.18k | size_t bytes = chars_to_bytes(step); | 748 | 8.18k | memcpy(dst, src, bytes); | 749 | 8.18k | dst += bytes; | 750 | 8.18k | num_chars_to_pad -= step; | 751 | 8.18k | } | 752 | 218k | size_t bytes = chars_to_bytes(num_chars_to_pad); | 753 | 218k | memcpy(dst, src, bytes); | 754 | 218k | dst += bytes; | 755 | 218k | return dst - dst_start; | 756 | 218k | } |
_ZNK5doris12PaddingCharsILb1EE9append_toEPhm Line | Count | Source | 739 | 184 | size_t append_to(uint8_t* dst, size_t num_chars_to_pad) const { | 740 | 184 | if (num_chars_to_pad == 0) { | 741 | 0 | return 0; | 742 | 0 | } | 743 | 184 | const auto* src = reinterpret_cast<const uint8_t*>(pad_string.data()); | 744 | 184 | const size_t step = num_chars(); | 745 | 184 | uint8_t* dst_start = dst; | 746 | 184 | while (num_chars_to_pad > step) { | 747 | 0 | size_t bytes = chars_to_bytes(step); | 748 | 0 | memcpy(dst, src, bytes); | 749 | 0 | dst += bytes; | 750 | 0 | num_chars_to_pad -= step; | 751 | 0 | } | 752 | 184 | size_t bytes = chars_to_bytes(num_chars_to_pad); | 753 | 184 | memcpy(dst, src, bytes); | 754 | 184 | dst += bytes; | 755 | 184 | return dst - dst_start; | 756 | 184 | } |
|
757 | | |
758 | | private: |
759 | 1.12k | void init() { |
760 | 1.12k | if (pad_string.empty()) { |
761 | 0 | return; |
762 | 0 | } |
763 | | |
764 | 1.12k | if constexpr (is_utf8) { |
765 | | // Build byte-offset table for each code point. |
766 | 1.02k | size_t offset = 0; |
767 | 1.02k | utf8_byte_offsets.reserve(pad_string.size() + 1); |
768 | 8.11k | while (offset < pad_string.size()) { |
769 | 7.08k | utf8_byte_offsets.push_back(offset); |
770 | 7.08k | offset += get_utf8_byte_length(static_cast<uint8_t>(pad_string[offset])); |
771 | 7.08k | offset = std::min(offset, pad_string.size()); |
772 | 7.08k | } |
773 | 1.02k | utf8_byte_offsets.push_back(pad_string.size()); |
774 | 1.02k | } |
775 | | |
776 | | // Pre-expand pad_string until it has >= 16 characters. |
777 | | // This ensures append_to() copies at least 16 bytes per iteration. |
778 | 3.44k | while (num_chars() < 16) { |
779 | 2.32k | if constexpr (is_utf8) { |
780 | 2.07k | size_t old_count = utf8_byte_offsets.size(); |
781 | 2.07k | size_t base = utf8_byte_offsets.back(); |
782 | 17.1k | for (size_t i = 1; i < old_count; ++i) { |
783 | 15.0k | utf8_byte_offsets.push_back(utf8_byte_offsets[i] + base); |
784 | 15.0k | } |
785 | 2.07k | } |
786 | 2.32k | pad_string += pad_string; |
787 | 2.32k | } |
788 | 1.12k | } _ZN5doris12PaddingCharsILb0EE4initEv Line | Count | Source | 759 | 97 | void init() { | 760 | 97 | if (pad_string.empty()) { | 761 | 0 | return; | 762 | 0 | } | 763 | | | 764 | | if constexpr (is_utf8) { | 765 | | // Build byte-offset table for each code point. | 766 | | size_t offset = 0; | 767 | | utf8_byte_offsets.reserve(pad_string.size() + 1); | 768 | | while (offset < pad_string.size()) { | 769 | | utf8_byte_offsets.push_back(offset); | 770 | | offset += get_utf8_byte_length(static_cast<uint8_t>(pad_string[offset])); | 771 | | offset = std::min(offset, pad_string.size()); | 772 | | } | 773 | | utf8_byte_offsets.push_back(pad_string.size()); | 774 | | } | 775 | | | 776 | | // Pre-expand pad_string until it has >= 16 characters. | 777 | | // This ensures append_to() copies at least 16 bytes per iteration. | 778 | 338 | while (num_chars() < 16) { | 779 | | if constexpr (is_utf8) { | 780 | | size_t old_count = utf8_byte_offsets.size(); | 781 | | size_t base = utf8_byte_offsets.back(); | 782 | | for (size_t i = 1; i < old_count; ++i) { | 783 | | utf8_byte_offsets.push_back(utf8_byte_offsets[i] + base); | 784 | | } | 785 | | } | 786 | 241 | pad_string += pad_string; | 787 | 241 | } | 788 | 97 | } |
_ZN5doris12PaddingCharsILb1EE4initEv Line | Count | Source | 759 | 1.02k | void init() { | 760 | 1.02k | if (pad_string.empty()) { | 761 | 0 | return; | 762 | 0 | } | 763 | | | 764 | 1.02k | if constexpr (is_utf8) { | 765 | | // Build byte-offset table for each code point. | 766 | 1.02k | size_t offset = 0; | 767 | 1.02k | utf8_byte_offsets.reserve(pad_string.size() + 1); | 768 | 8.11k | while (offset < pad_string.size()) { | 769 | 7.08k | utf8_byte_offsets.push_back(offset); | 770 | 7.08k | offset += get_utf8_byte_length(static_cast<uint8_t>(pad_string[offset])); | 771 | 7.08k | offset = std::min(offset, pad_string.size()); | 772 | 7.08k | } | 773 | 1.02k | utf8_byte_offsets.push_back(pad_string.size()); | 774 | 1.02k | } | 775 | | | 776 | | // Pre-expand pad_string until it has >= 16 characters. | 777 | | // This ensures append_to() copies at least 16 bytes per iteration. | 778 | 3.10k | while (num_chars() < 16) { | 779 | 2.07k | if constexpr (is_utf8) { | 780 | 2.07k | size_t old_count = utf8_byte_offsets.size(); | 781 | 2.07k | size_t base = utf8_byte_offsets.back(); | 782 | 17.1k | for (size_t i = 1; i < old_count; ++i) { | 783 | 15.0k | utf8_byte_offsets.push_back(utf8_byte_offsets[i] + base); | 784 | 15.0k | } | 785 | 2.07k | } | 786 | 2.07k | pad_string += pad_string; | 787 | 2.07k | } | 788 | 1.02k | } |
|
789 | | }; |
790 | | |
791 | | template <typename Impl> |
792 | | class FunctionStringPad : public IFunction { |
793 | | public: |
794 | | static constexpr auto name = Impl::name; |
795 | 1.65k | static FunctionPtr create() { return std::make_shared<FunctionStringPad>(); }_ZN5doris17FunctionStringPadINS_10StringLPadEE6createEv Line | Count | Source | 795 | 888 | static FunctionPtr create() { return std::make_shared<FunctionStringPad>(); } |
_ZN5doris17FunctionStringPadINS_10StringRPadEE6createEv Line | Count | Source | 795 | 771 | static FunctionPtr create() { return std::make_shared<FunctionStringPad>(); } |
|
796 | 2 | String get_name() const override { return name; }_ZNK5doris17FunctionStringPadINS_10StringLPadEE8get_nameB5cxx11Ev Line | Count | Source | 796 | 1 | String get_name() const override { return name; } |
_ZNK5doris17FunctionStringPadINS_10StringRPadEE8get_nameB5cxx11Ev Line | Count | Source | 796 | 1 | String get_name() const override { return name; } |
|
797 | 1.64k | size_t get_number_of_arguments() const override { return 3; }_ZNK5doris17FunctionStringPadINS_10StringLPadEE23get_number_of_argumentsEv Line | Count | Source | 797 | 879 | size_t get_number_of_arguments() const override { return 3; } |
_ZNK5doris17FunctionStringPadINS_10StringRPadEE23get_number_of_argumentsEv Line | Count | Source | 797 | 762 | size_t get_number_of_arguments() const override { return 3; } |
|
798 | | |
799 | 1.64k | DataTypePtr get_return_type_impl(const DataTypes& arguments) const override { |
800 | 1.64k | return make_nullable(std::make_shared<DataTypeString>()); |
801 | 1.64k | } _ZNK5doris17FunctionStringPadINS_10StringLPadEE20get_return_type_implERKSt6vectorISt10shared_ptrIKNS_9IDataTypeEESaIS7_EE Line | Count | Source | 799 | 879 | DataTypePtr get_return_type_impl(const DataTypes& arguments) const override { | 800 | 879 | return make_nullable(std::make_shared<DataTypeString>()); | 801 | 879 | } |
_ZNK5doris17FunctionStringPadINS_10StringRPadEE20get_return_type_implERKSt6vectorISt10shared_ptrIKNS_9IDataTypeEESaIS7_EE Line | Count | Source | 799 | 762 | DataTypePtr get_return_type_impl(const DataTypes& arguments) const override { | 800 | 762 | return make_nullable(std::make_shared<DataTypeString>()); | 801 | 762 | } |
|
802 | | |
803 | | Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments, |
804 | 1.18k | uint32_t result, size_t input_rows_count) const override { |
805 | 1.18k | DCHECK_GE(arguments.size(), 3); |
806 | 1.18k | auto null_map = ColumnUInt8::create(input_rows_count, 0); |
807 | 1.18k | auto res = ColumnString::create(); |
808 | | |
809 | 1.18k | ColumnPtr col[3]; |
810 | 1.18k | bool col_const[3]; |
811 | 4.74k | for (size_t i = 0; i < 3; ++i) { |
812 | 3.56k | std::tie(col[i], col_const[i]) = |
813 | 3.56k | unpack_if_const(block.get_by_position(arguments[i]).column); |
814 | 3.56k | } |
815 | 1.18k | auto& null_map_data = null_map->get_data(); |
816 | 1.18k | auto& res_offsets = res->get_offsets(); |
817 | 1.18k | auto& res_chars = res->get_chars(); |
818 | 1.18k | res_offsets.resize(input_rows_count); |
819 | | |
820 | 1.18k | const auto* strcol = assert_cast<const ColumnString*>(col[0].get()); |
821 | 1.18k | const auto* col_len = assert_cast<const ColumnInt32*>(col[1].get()); |
822 | 1.18k | const auto& col_len_data = col_len->get_data(); |
823 | | |
824 | 1.18k | const auto* padcol = assert_cast<const ColumnString*>(col[2].get()); |
825 | | |
826 | 1.18k | if (col_const[1] && col_const[2]) { |
827 | 174 | auto pad = padcol->get_data_at(0); |
828 | 174 | const bool pad_all_ascii = |
829 | 174 | simd::VStringFunctions::is_ascii({pad.data, static_cast<size_t>(pad.size)}); |
830 | 174 | const bool all_ascii = pad_all_ascii && strcol->is_ascii(); |
831 | 174 | std::visit( |
832 | 174 | [&](auto str_const) { |
833 | 174 | if (all_ascii) { |
834 | 119 | execute_const_len_const_pad<true, str_const>( |
835 | 119 | *strcol, col_len_data, *padcol, res_offsets, res_chars, |
836 | 119 | null_map_data, input_rows_count); |
837 | 119 | } else { |
838 | 55 | execute_const_len_const_pad<false, str_const>( |
839 | 55 | *strcol, col_len_data, *padcol, res_offsets, res_chars, |
840 | 55 | null_map_data, input_rows_count); |
841 | 55 | } |
842 | 174 | }, _ZZNK5doris17FunctionStringPadINS_10StringLPadEE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjmENKUlT_E_clISt17integral_constantIbLb0EEEEDaSC_ Line | Count | Source | 832 | 109 | [&](auto str_const) { | 833 | 109 | if (all_ascii) { | 834 | 82 | execute_const_len_const_pad<true, str_const>( | 835 | 82 | *strcol, col_len_data, *padcol, res_offsets, res_chars, | 836 | 82 | null_map_data, input_rows_count); | 837 | 82 | } else { | 838 | 27 | execute_const_len_const_pad<false, str_const>( | 839 | 27 | *strcol, col_len_data, *padcol, res_offsets, res_chars, | 840 | 27 | null_map_data, input_rows_count); | 841 | 27 | } | 842 | 109 | }, |
Unexecuted instantiation: _ZZNK5doris17FunctionStringPadINS_10StringLPadEE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjmENKUlT_E_clISt17integral_constantIbLb1EEEEDaSC_ _ZZNK5doris17FunctionStringPadINS_10StringRPadEE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjmENKUlT_E_clISt17integral_constantIbLb0EEEEDaSC_ Line | Count | Source | 832 | 65 | [&](auto str_const) { | 833 | 65 | if (all_ascii) { | 834 | 37 | execute_const_len_const_pad<true, str_const>( | 835 | 37 | *strcol, col_len_data, *padcol, res_offsets, res_chars, | 836 | 37 | null_map_data, input_rows_count); | 837 | 37 | } else { | 838 | 28 | execute_const_len_const_pad<false, str_const>( | 839 | 28 | *strcol, col_len_data, *padcol, res_offsets, res_chars, | 840 | 28 | null_map_data, input_rows_count); | 841 | 28 | } | 842 | 65 | }, |
Unexecuted instantiation: _ZZNK5doris17FunctionStringPadINS_10StringRPadEE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjmENKUlT_E_clISt17integral_constantIbLb1EEEEDaSC_ |
843 | 174 | make_bool_variant(col_const[0])); |
844 | 1.01k | } else { |
845 | 1.01k | std::visit( |
846 | 1.01k | [&](auto str_const) { |
847 | 1.01k | execute_general<str_const>(*strcol, col_len_data, col_const[1], *padcol, |
848 | 1.01k | col_const[2], res_offsets, res_chars, |
849 | 1.01k | null_map_data, input_rows_count); |
850 | 1.01k | }, _ZZNK5doris17FunctionStringPadINS_10StringLPadEE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjmENKUlT_E0_clISt17integral_constantIbLb0EEEEDaSC_ Line | Count | Source | 846 | 366 | [&](auto str_const) { | 847 | 366 | execute_general<str_const>(*strcol, col_len_data, col_const[1], *padcol, | 848 | 366 | col_const[2], res_offsets, res_chars, | 849 | 366 | null_map_data, input_rows_count); | 850 | 366 | }, |
_ZZNK5doris17FunctionStringPadINS_10StringLPadEE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjmENKUlT_E0_clISt17integral_constantIbLb1EEEEDaSC_ Line | Count | Source | 846 | 186 | [&](auto str_const) { | 847 | 186 | execute_general<str_const>(*strcol, col_len_data, col_const[1], *padcol, | 848 | 186 | col_const[2], res_offsets, res_chars, | 849 | 186 | null_map_data, input_rows_count); | 850 | 186 | }, |
_ZZNK5doris17FunctionStringPadINS_10StringRPadEE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjmENKUlT_E0_clISt17integral_constantIbLb0EEEEDaSC_ Line | Count | Source | 846 | 275 | [&](auto str_const) { | 847 | 275 | execute_general<str_const>(*strcol, col_len_data, col_const[1], *padcol, | 848 | 275 | col_const[2], res_offsets, res_chars, | 849 | 275 | null_map_data, input_rows_count); | 850 | 275 | }, |
_ZZNK5doris17FunctionStringPadINS_10StringRPadEE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjmENKUlT_E0_clISt17integral_constantIbLb1EEEEDaSC_ Line | Count | Source | 846 | 186 | [&](auto str_const) { | 847 | 186 | execute_general<str_const>(*strcol, col_len_data, col_const[1], *padcol, | 848 | 186 | col_const[2], res_offsets, res_chars, | 849 | 186 | null_map_data, input_rows_count); | 850 | 186 | }, |
|
851 | 1.01k | make_bool_variant(col_const[0])); |
852 | 1.01k | } |
853 | | |
854 | 1.18k | block.get_by_position(result).column = |
855 | 1.18k | ColumnNullable::create(std::move(res), std::move(null_map)); |
856 | 1.18k | return Status::OK(); |
857 | 1.18k | } _ZNK5doris17FunctionStringPadINS_10StringLPadEE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjm Line | Count | Source | 804 | 661 | uint32_t result, size_t input_rows_count) const override { | 805 | 661 | DCHECK_GE(arguments.size(), 3); | 806 | 661 | auto null_map = ColumnUInt8::create(input_rows_count, 0); | 807 | 661 | auto res = ColumnString::create(); | 808 | | | 809 | 661 | ColumnPtr col[3]; | 810 | 661 | bool col_const[3]; | 811 | 2.64k | for (size_t i = 0; i < 3; ++i) { | 812 | 1.98k | std::tie(col[i], col_const[i]) = | 813 | 1.98k | unpack_if_const(block.get_by_position(arguments[i]).column); | 814 | 1.98k | } | 815 | 661 | auto& null_map_data = null_map->get_data(); | 816 | 661 | auto& res_offsets = res->get_offsets(); | 817 | 661 | auto& res_chars = res->get_chars(); | 818 | 661 | res_offsets.resize(input_rows_count); | 819 | | | 820 | 661 | const auto* strcol = assert_cast<const ColumnString*>(col[0].get()); | 821 | 661 | const auto* col_len = assert_cast<const ColumnInt32*>(col[1].get()); | 822 | 661 | const auto& col_len_data = col_len->get_data(); | 823 | | | 824 | 661 | const auto* padcol = assert_cast<const ColumnString*>(col[2].get()); | 825 | | | 826 | 661 | if (col_const[1] && col_const[2]) { | 827 | 109 | auto pad = padcol->get_data_at(0); | 828 | 109 | const bool pad_all_ascii = | 829 | 109 | simd::VStringFunctions::is_ascii({pad.data, static_cast<size_t>(pad.size)}); | 830 | 109 | const bool all_ascii = pad_all_ascii && strcol->is_ascii(); | 831 | 109 | std::visit( | 832 | 109 | [&](auto str_const) { | 833 | 109 | if (all_ascii) { | 834 | 109 | execute_const_len_const_pad<true, str_const>( | 835 | 109 | *strcol, col_len_data, *padcol, res_offsets, res_chars, | 836 | 109 | null_map_data, input_rows_count); | 837 | 109 | } else { | 838 | 109 | execute_const_len_const_pad<false, str_const>( | 839 | 109 | *strcol, col_len_data, *padcol, res_offsets, res_chars, | 840 | 109 | null_map_data, input_rows_count); | 841 | 109 | } | 842 | 109 | }, | 843 | 109 | make_bool_variant(col_const[0])); | 844 | 552 | } else { | 845 | 552 | std::visit( | 846 | 552 | [&](auto str_const) { | 847 | 552 | execute_general<str_const>(*strcol, col_len_data, col_const[1], *padcol, | 848 | 552 | col_const[2], res_offsets, res_chars, | 849 | 552 | null_map_data, input_rows_count); | 850 | 552 | }, | 851 | 552 | make_bool_variant(col_const[0])); | 852 | 552 | } | 853 | | | 854 | 661 | block.get_by_position(result).column = | 855 | 661 | ColumnNullable::create(std::move(res), std::move(null_map)); | 856 | 661 | return Status::OK(); | 857 | 661 | } |
_ZNK5doris17FunctionStringPadINS_10StringRPadEE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjm Line | Count | Source | 804 | 526 | uint32_t result, size_t input_rows_count) const override { | 805 | 526 | DCHECK_GE(arguments.size(), 3); | 806 | 526 | auto null_map = ColumnUInt8::create(input_rows_count, 0); | 807 | 526 | auto res = ColumnString::create(); | 808 | | | 809 | 526 | ColumnPtr col[3]; | 810 | 526 | bool col_const[3]; | 811 | 2.10k | for (size_t i = 0; i < 3; ++i) { | 812 | 1.57k | std::tie(col[i], col_const[i]) = | 813 | 1.57k | unpack_if_const(block.get_by_position(arguments[i]).column); | 814 | 1.57k | } | 815 | 526 | auto& null_map_data = null_map->get_data(); | 816 | 526 | auto& res_offsets = res->get_offsets(); | 817 | 526 | auto& res_chars = res->get_chars(); | 818 | 526 | res_offsets.resize(input_rows_count); | 819 | | | 820 | 526 | const auto* strcol = assert_cast<const ColumnString*>(col[0].get()); | 821 | 526 | const auto* col_len = assert_cast<const ColumnInt32*>(col[1].get()); | 822 | 526 | const auto& col_len_data = col_len->get_data(); | 823 | | | 824 | 526 | const auto* padcol = assert_cast<const ColumnString*>(col[2].get()); | 825 | | | 826 | 526 | if (col_const[1] && col_const[2]) { | 827 | 65 | auto pad = padcol->get_data_at(0); | 828 | 65 | const bool pad_all_ascii = | 829 | 65 | simd::VStringFunctions::is_ascii({pad.data, static_cast<size_t>(pad.size)}); | 830 | 65 | const bool all_ascii = pad_all_ascii && strcol->is_ascii(); | 831 | 65 | std::visit( | 832 | 65 | [&](auto str_const) { | 833 | 65 | if (all_ascii) { | 834 | 65 | execute_const_len_const_pad<true, str_const>( | 835 | 65 | *strcol, col_len_data, *padcol, res_offsets, res_chars, | 836 | 65 | null_map_data, input_rows_count); | 837 | 65 | } else { | 838 | 65 | execute_const_len_const_pad<false, str_const>( | 839 | 65 | *strcol, col_len_data, *padcol, res_offsets, res_chars, | 840 | 65 | null_map_data, input_rows_count); | 841 | 65 | } | 842 | 65 | }, | 843 | 65 | make_bool_variant(col_const[0])); | 844 | 461 | } else { | 845 | 461 | std::visit( | 846 | 461 | [&](auto str_const) { | 847 | 461 | execute_general<str_const>(*strcol, col_len_data, col_const[1], *padcol, | 848 | 461 | col_const[2], res_offsets, res_chars, | 849 | 461 | null_map_data, input_rows_count); | 850 | 461 | }, | 851 | 461 | make_bool_variant(col_const[0])); | 852 | 461 | } | 853 | | | 854 | 526 | block.get_by_position(result).column = | 855 | 526 | ColumnNullable::create(std::move(res), std::move(null_map)); | 856 | 526 | return Status::OK(); | 857 | 526 | } |
|
858 | | |
859 | | private: |
860 | | template <bool is_utf8> |
861 | 219k | static size_t get_char_length(const uint8_t* str_data, size_t str_byte_len) { |
862 | 219k | if constexpr (is_utf8) { |
863 | 797 | return simd::VStringFunctions::get_char_len(reinterpret_cast<const char*>(str_data), |
864 | 797 | str_byte_len); |
865 | 797 | } |
866 | 0 | return str_byte_len; |
867 | 219k | } _ZN5doris17FunctionStringPadINS_10StringLPadEE15get_char_lengthILb0EEEmPKhm Line | Count | Source | 861 | 216k | static size_t get_char_length(const uint8_t* str_data, size_t str_byte_len) { | 862 | | if constexpr (is_utf8) { | 863 | | return simd::VStringFunctions::get_char_len(reinterpret_cast<const char*>(str_data), | 864 | | str_byte_len); | 865 | | } | 866 | 216k | return str_byte_len; | 867 | 216k | } |
_ZN5doris17FunctionStringPadINS_10StringLPadEE15get_char_lengthILb1EEEmPKhm Line | Count | Source | 861 | 441 | static size_t get_char_length(const uint8_t* str_data, size_t str_byte_len) { | 862 | 441 | if constexpr (is_utf8) { | 863 | 441 | return simd::VStringFunctions::get_char_len(reinterpret_cast<const char*>(str_data), | 864 | 441 | str_byte_len); | 865 | 441 | } | 866 | 0 | return str_byte_len; | 867 | 441 | } |
_ZN5doris17FunctionStringPadINS_10StringRPadEE15get_char_lengthILb0EEEmPKhm Line | Count | Source | 861 | 2.06k | static size_t get_char_length(const uint8_t* str_data, size_t str_byte_len) { | 862 | | if constexpr (is_utf8) { | 863 | | return simd::VStringFunctions::get_char_len(reinterpret_cast<const char*>(str_data), | 864 | | str_byte_len); | 865 | | } | 866 | 2.06k | return str_byte_len; | 867 | 2.06k | } |
_ZN5doris17FunctionStringPadINS_10StringRPadEE15get_char_lengthILb1EEEmPKhm Line | Count | Source | 861 | 356 | static size_t get_char_length(const uint8_t* str_data, size_t str_byte_len) { | 862 | 356 | if constexpr (is_utf8) { | 863 | 356 | return simd::VStringFunctions::get_char_len(reinterpret_cast<const char*>(str_data), | 864 | 356 | str_byte_len); | 865 | 356 | } | 866 | 0 | return str_byte_len; | 867 | 356 | } |
|
868 | | |
869 | | template <bool is_utf8> |
870 | | static size_t get_truncated_byte_length(const uint8_t* str_data, size_t str_byte_len, |
871 | 624 | size_t str_char_len, size_t target_len) { |
872 | 624 | if constexpr (!is_utf8) { |
873 | 32 | return target_len; |
874 | 32 | } |
875 | 624 | if (str_char_len == target_len) { |
876 | 109 | return str_byte_len; |
877 | 109 | } |
878 | 515 | auto [byte_len, _] = simd::VStringFunctions::iterate_utf8_with_limit_length( |
879 | 515 | reinterpret_cast<const char*>(str_data), |
880 | 515 | reinterpret_cast<const char*>(str_data) + str_byte_len, target_len); |
881 | 515 | return byte_len; |
882 | 624 | } _ZN5doris17FunctionStringPadINS_10StringLPadEE25get_truncated_byte_lengthILb0EEEmPKhmmm Line | Count | Source | 871 | 16 | size_t str_char_len, size_t target_len) { | 872 | 16 | if constexpr (!is_utf8) { | 873 | 16 | return target_len; | 874 | 16 | } | 875 | 16 | if (str_char_len == target_len) { | 876 | 0 | return str_byte_len; | 877 | 0 | } | 878 | 16 | auto [byte_len, _] = simd::VStringFunctions::iterate_utf8_with_limit_length( | 879 | 16 | reinterpret_cast<const char*>(str_data), | 880 | 16 | reinterpret_cast<const char*>(str_data) + str_byte_len, target_len); | 881 | 16 | return byte_len; | 882 | 16 | } |
_ZN5doris17FunctionStringPadINS_10StringLPadEE25get_truncated_byte_lengthILb1EEEmPKhmmm Line | Count | Source | 871 | 315 | size_t str_char_len, size_t target_len) { | 872 | | if constexpr (!is_utf8) { | 873 | | return target_len; | 874 | | } | 875 | 315 | if (str_char_len == target_len) { | 876 | 64 | return str_byte_len; | 877 | 64 | } | 878 | 251 | auto [byte_len, _] = simd::VStringFunctions::iterate_utf8_with_limit_length( | 879 | 251 | reinterpret_cast<const char*>(str_data), | 880 | 251 | reinterpret_cast<const char*>(str_data) + str_byte_len, target_len); | 881 | 251 | return byte_len; | 882 | 315 | } |
_ZN5doris17FunctionStringPadINS_10StringRPadEE25get_truncated_byte_lengthILb0EEEmPKhmmm Line | Count | Source | 871 | 16 | size_t str_char_len, size_t target_len) { | 872 | 16 | if constexpr (!is_utf8) { | 873 | 16 | return target_len; | 874 | 16 | } | 875 | 16 | if (str_char_len == target_len) { | 876 | 0 | return str_byte_len; | 877 | 0 | } | 878 | 16 | auto [byte_len, _] = simd::VStringFunctions::iterate_utf8_with_limit_length( | 879 | 16 | reinterpret_cast<const char*>(str_data), | 880 | 16 | reinterpret_cast<const char*>(str_data) + str_byte_len, target_len); | 881 | 16 | return byte_len; | 882 | 16 | } |
_ZN5doris17FunctionStringPadINS_10StringRPadEE25get_truncated_byte_lengthILb1EEEmPKhmmm Line | Count | Source | 871 | 277 | size_t str_char_len, size_t target_len) { | 872 | | if constexpr (!is_utf8) { | 873 | | return target_len; | 874 | | } | 875 | 277 | if (str_char_len == target_len) { | 876 | 45 | return str_byte_len; | 877 | 45 | } | 878 | 232 | auto [byte_len, _] = simd::VStringFunctions::iterate_utf8_with_limit_length( | 879 | 232 | reinterpret_cast<const char*>(str_data), | 880 | 232 | reinterpret_cast<const char*>(str_data) + str_byte_len, target_len); | 881 | 232 | return byte_len; | 882 | 277 | } |
|
883 | | |
884 | 219k | static void ensure_capacity(ColumnString::Chars& res_chars, size_t needed, size_t row) { |
885 | 219k | if (needed <= res_chars.size()) { |
886 | 219k | return; |
887 | 219k | } |
888 | 145 | ColumnString::check_chars_length(needed, row); |
889 | 145 | res_chars.resize(std::max(needed, res_chars.size() * 3 / 2)); |
890 | 145 | } _ZN5doris17FunctionStringPadINS_10StringLPadEE15ensure_capacityERNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEEmm Line | Count | Source | 884 | 216k | static void ensure_capacity(ColumnString::Chars& res_chars, size_t needed, size_t row) { | 885 | 216k | if (needed <= res_chars.size()) { | 886 | 216k | return; | 887 | 216k | } | 888 | 96 | ColumnString::check_chars_length(needed, row); | 889 | 96 | res_chars.resize(std::max(needed, res_chars.size() * 3 / 2)); | 890 | 96 | } |
_ZN5doris17FunctionStringPadINS_10StringRPadEE15ensure_capacityERNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEEmm Line | Count | Source | 884 | 2.41k | static void ensure_capacity(ColumnString::Chars& res_chars, size_t needed, size_t row) { | 885 | 2.41k | if (needed <= res_chars.size()) { | 886 | 2.36k | return; | 887 | 2.36k | } | 888 | 49 | ColumnString::check_chars_length(needed, row); | 889 | 49 | res_chars.resize(std::max(needed, res_chars.size() * 3 / 2)); | 890 | 49 | } |
|
891 | | |
892 | | template <bool is_utf8> |
893 | | static size_t estimate_const_output_bytes(const ColumnString::Chars& strcol_chars, |
894 | | int target_len, size_t input_rows_count, |
895 | 174 | const PaddingChars<is_utf8>* padding) { |
896 | 174 | if (target_len <= 0) { |
897 | 96 | return 0; |
898 | 96 | } |
899 | 78 | if constexpr (!is_utf8) { |
900 | 65 | return static_cast<size_t>(target_len) * input_rows_count; |
901 | 65 | } |
902 | 78 | if (padding != nullptr && padding->num_chars() > 0) { |
903 | 11 | size_t pad_bytes_per_char = |
904 | 11 | (padding->pad_string.size() + padding->num_chars() - 1) / padding->num_chars(); |
905 | 11 | return strcol_chars.size() + |
906 | 11 | static_cast<size_t>(target_len) * pad_bytes_per_char * input_rows_count; |
907 | 11 | } |
908 | 67 | return strcol_chars.size(); |
909 | 78 | } _ZN5doris17FunctionStringPadINS_10StringLPadEE27estimate_const_output_bytesILb0EEEmRKNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEEimPKNS_12PaddingCharsIXT_EEE Line | Count | Source | 895 | 82 | const PaddingChars<is_utf8>* padding) { | 896 | 82 | if (target_len <= 0) { | 897 | 27 | return 0; | 898 | 27 | } | 899 | 55 | if constexpr (!is_utf8) { | 900 | 55 | return static_cast<size_t>(target_len) * input_rows_count; | 901 | 55 | } | 902 | 55 | if (padding != nullptr && padding->num_chars() > 0) { | 903 | 0 | size_t pad_bytes_per_char = | 904 | 0 | (padding->pad_string.size() + padding->num_chars() - 1) / padding->num_chars(); | 905 | 0 | return strcol_chars.size() + | 906 | 0 | static_cast<size_t>(target_len) * pad_bytes_per_char * input_rows_count; | 907 | 0 | } | 908 | 55 | return strcol_chars.size(); | 909 | 55 | } |
_ZN5doris17FunctionStringPadINS_10StringLPadEE27estimate_const_output_bytesILb1EEEmRKNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEEimPKNS_12PaddingCharsIXT_EEE Line | Count | Source | 895 | 27 | const PaddingChars<is_utf8>* padding) { | 896 | 27 | if (target_len <= 0) { | 897 | 21 | return 0; | 898 | 21 | } | 899 | | if constexpr (!is_utf8) { | 900 | | return static_cast<size_t>(target_len) * input_rows_count; | 901 | | } | 902 | 6 | if (padding != nullptr && padding->num_chars() > 0) { | 903 | 5 | size_t pad_bytes_per_char = | 904 | 5 | (padding->pad_string.size() + padding->num_chars() - 1) / padding->num_chars(); | 905 | 5 | return strcol_chars.size() + | 906 | 5 | static_cast<size_t>(target_len) * pad_bytes_per_char * input_rows_count; | 907 | 5 | } | 908 | 1 | return strcol_chars.size(); | 909 | 6 | } |
_ZN5doris17FunctionStringPadINS_10StringRPadEE27estimate_const_output_bytesILb0EEEmRKNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEEimPKNS_12PaddingCharsIXT_EEE Line | Count | Source | 895 | 37 | const PaddingChars<is_utf8>* padding) { | 896 | 37 | if (target_len <= 0) { | 897 | 27 | return 0; | 898 | 27 | } | 899 | 10 | if constexpr (!is_utf8) { | 900 | 10 | return static_cast<size_t>(target_len) * input_rows_count; | 901 | 10 | } | 902 | 10 | if (padding != nullptr && padding->num_chars() > 0) { | 903 | 0 | size_t pad_bytes_per_char = | 904 | 0 | (padding->pad_string.size() + padding->num_chars() - 1) / padding->num_chars(); | 905 | 0 | return strcol_chars.size() + | 906 | 0 | static_cast<size_t>(target_len) * pad_bytes_per_char * input_rows_count; | 907 | 0 | } | 908 | 10 | return strcol_chars.size(); | 909 | 10 | } |
_ZN5doris17FunctionStringPadINS_10StringRPadEE27estimate_const_output_bytesILb1EEEmRKNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEEimPKNS_12PaddingCharsIXT_EEE Line | Count | Source | 895 | 28 | const PaddingChars<is_utf8>* padding) { | 896 | 28 | if (target_len <= 0) { | 897 | 21 | return 0; | 898 | 21 | } | 899 | | if constexpr (!is_utf8) { | 900 | | return static_cast<size_t>(target_len) * input_rows_count; | 901 | | } | 902 | 7 | if (padding != nullptr && padding->num_chars() > 0) { | 903 | 6 | size_t pad_bytes_per_char = | 904 | 6 | (padding->pad_string.size() + padding->num_chars() - 1) / padding->num_chars(); | 905 | 6 | return strcol_chars.size() + | 906 | 6 | static_cast<size_t>(target_len) * pad_bytes_per_char * input_rows_count; | 907 | 6 | } | 908 | 1 | return strcol_chars.size(); | 909 | 7 | } |
|
910 | | |
911 | | template <bool is_utf8> |
912 | | static void append_result_row(const uint8_t* str_data, size_t str_byte_len, int target_len, |
913 | | const PaddingChars<is_utf8>* padding, |
914 | | ColumnString::Chars& res_chars, |
915 | | ColumnString::Offsets& res_offsets, |
916 | | ColumnUInt8::Container& null_map_data, size_t row, |
917 | 219k | size_t& dst_offset) { |
918 | 219k | if (target_len < 0) { |
919 | 568 | null_map_data[row] = true; |
920 | 568 | res_offsets[row] = dst_offset; |
921 | 568 | return; |
922 | 568 | } |
923 | | |
924 | 219k | const size_t str_char_len = get_char_length<is_utf8>(str_data, str_byte_len); |
925 | 219k | const size_t target_char_len = static_cast<size_t>(target_len); |
926 | 219k | if (str_char_len >= target_char_len) { |
927 | 624 | const size_t truncated_byte_len = get_truncated_byte_length<is_utf8>( |
928 | 624 | str_data, str_byte_len, str_char_len, target_char_len); |
929 | 624 | const size_t needed = dst_offset + truncated_byte_len; |
930 | 624 | ensure_capacity(res_chars, needed, row); |
931 | 624 | memcpy(res_chars.data() + dst_offset, str_data, truncated_byte_len); |
932 | 624 | dst_offset += truncated_byte_len; |
933 | 624 | res_offsets[row] = dst_offset; |
934 | 624 | return; |
935 | 624 | } |
936 | | |
937 | 218k | if (padding == nullptr || padding->num_chars() == 0) { |
938 | 21 | res_offsets[row] = dst_offset; |
939 | 21 | return; |
940 | 21 | } |
941 | | |
942 | 218k | const size_t pad_char_count = target_char_len - str_char_len; |
943 | 218k | const size_t full_cycles = pad_char_count / padding->num_chars(); |
944 | 218k | const size_t remainder_chars = pad_char_count % padding->num_chars(); |
945 | 218k | const size_t pad_bytes = |
946 | 218k | full_cycles * padding->pad_string.size() + padding->chars_to_bytes(remainder_chars); |
947 | 218k | const size_t needed = dst_offset + str_byte_len + pad_bytes; |
948 | 218k | ensure_capacity(res_chars, needed, row); |
949 | | |
950 | 218k | if constexpr (Impl::is_lpad) { |
951 | 216k | dst_offset += padding->append_to(res_chars.data() + dst_offset, pad_char_count); |
952 | 216k | memcpy(res_chars.data() + dst_offset, str_data, str_byte_len); |
953 | 216k | dst_offset += str_byte_len; |
954 | 216k | } else { |
955 | 2.11k | memcpy(res_chars.data() + dst_offset, str_data, str_byte_len); |
956 | 2.11k | dst_offset += str_byte_len; |
957 | 2.11k | dst_offset += padding->append_to(res_chars.data() + dst_offset, pad_char_count); |
958 | 2.11k | } |
959 | 218k | res_offsets[row] = dst_offset; |
960 | 218k | } _ZN5doris17FunctionStringPadINS_10StringLPadEE17append_result_rowILb0EEEvPKhmiPKNS_12PaddingCharsIXT_EEERNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEERNSA_IjLm4096ESD_Lm16ELm15EEESF_mRm Line | Count | Source | 917 | 216k | size_t& dst_offset) { | 918 | 216k | if (target_len < 0) { | 919 | 18 | null_map_data[row] = true; | 920 | 18 | res_offsets[row] = dst_offset; | 921 | 18 | return; | 922 | 18 | } | 923 | | | 924 | 216k | const size_t str_char_len = get_char_length<is_utf8>(str_data, str_byte_len); | 925 | 216k | const size_t target_char_len = static_cast<size_t>(target_len); | 926 | 216k | if (str_char_len >= target_char_len) { | 927 | 16 | const size_t truncated_byte_len = get_truncated_byte_length<is_utf8>( | 928 | 16 | str_data, str_byte_len, str_char_len, target_char_len); | 929 | 16 | const size_t needed = dst_offset + truncated_byte_len; | 930 | 16 | ensure_capacity(res_chars, needed, row); | 931 | 16 | memcpy(res_chars.data() + dst_offset, str_data, truncated_byte_len); | 932 | 16 | dst_offset += truncated_byte_len; | 933 | 16 | res_offsets[row] = dst_offset; | 934 | 16 | return; | 935 | 16 | } | 936 | | | 937 | 216k | if (padding == nullptr || padding->num_chars() == 0) { | 938 | 0 | res_offsets[row] = dst_offset; | 939 | 0 | return; | 940 | 0 | } | 941 | | | 942 | 216k | const size_t pad_char_count = target_char_len - str_char_len; | 943 | 216k | const size_t full_cycles = pad_char_count / padding->num_chars(); | 944 | 216k | const size_t remainder_chars = pad_char_count % padding->num_chars(); | 945 | 216k | const size_t pad_bytes = | 946 | 216k | full_cycles * padding->pad_string.size() + padding->chars_to_bytes(remainder_chars); | 947 | 216k | const size_t needed = dst_offset + str_byte_len + pad_bytes; | 948 | 216k | ensure_capacity(res_chars, needed, row); | 949 | | | 950 | 216k | if constexpr (Impl::is_lpad) { | 951 | 216k | dst_offset += padding->append_to(res_chars.data() + dst_offset, pad_char_count); | 952 | 216k | memcpy(res_chars.data() + dst_offset, str_data, str_byte_len); | 953 | 216k | dst_offset += str_byte_len; | 954 | | } else { | 955 | | memcpy(res_chars.data() + dst_offset, str_data, str_byte_len); | 956 | | dst_offset += str_byte_len; | 957 | | dst_offset += padding->append_to(res_chars.data() + dst_offset, pad_char_count); | 958 | | } | 959 | 216k | res_offsets[row] = dst_offset; | 960 | 216k | } |
_ZN5doris17FunctionStringPadINS_10StringLPadEE17append_result_rowILb1EEEvPKhmiPKNS_12PaddingCharsIXT_EEERNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEERNSA_IjLm4096ESD_Lm16ELm15EEESF_mRm Line | Count | Source | 917 | 710 | size_t& dst_offset) { | 918 | 710 | if (target_len < 0) { | 919 | 269 | null_map_data[row] = true; | 920 | 269 | res_offsets[row] = dst_offset; | 921 | 269 | return; | 922 | 269 | } | 923 | | | 924 | 441 | const size_t str_char_len = get_char_length<is_utf8>(str_data, str_byte_len); | 925 | 441 | const size_t target_char_len = static_cast<size_t>(target_len); | 926 | 441 | if (str_char_len >= target_char_len) { | 927 | 315 | const size_t truncated_byte_len = get_truncated_byte_length<is_utf8>( | 928 | 315 | str_data, str_byte_len, str_char_len, target_char_len); | 929 | 315 | const size_t needed = dst_offset + truncated_byte_len; | 930 | 315 | ensure_capacity(res_chars, needed, row); | 931 | 315 | memcpy(res_chars.data() + dst_offset, str_data, truncated_byte_len); | 932 | 315 | dst_offset += truncated_byte_len; | 933 | 315 | res_offsets[row] = dst_offset; | 934 | 315 | return; | 935 | 315 | } | 936 | | | 937 | 126 | if (padding == nullptr || padding->num_chars() == 0) { | 938 | 11 | res_offsets[row] = dst_offset; | 939 | 11 | return; | 940 | 11 | } | 941 | | | 942 | 115 | const size_t pad_char_count = target_char_len - str_char_len; | 943 | 115 | const size_t full_cycles = pad_char_count / padding->num_chars(); | 944 | 115 | const size_t remainder_chars = pad_char_count % padding->num_chars(); | 945 | 115 | const size_t pad_bytes = | 946 | 115 | full_cycles * padding->pad_string.size() + padding->chars_to_bytes(remainder_chars); | 947 | 115 | const size_t needed = dst_offset + str_byte_len + pad_bytes; | 948 | 115 | ensure_capacity(res_chars, needed, row); | 949 | | | 950 | 115 | if constexpr (Impl::is_lpad) { | 951 | 115 | dst_offset += padding->append_to(res_chars.data() + dst_offset, pad_char_count); | 952 | 115 | memcpy(res_chars.data() + dst_offset, str_data, str_byte_len); | 953 | 115 | dst_offset += str_byte_len; | 954 | | } else { | 955 | | memcpy(res_chars.data() + dst_offset, str_data, str_byte_len); | 956 | | dst_offset += str_byte_len; | 957 | | dst_offset += padding->append_to(res_chars.data() + dst_offset, pad_char_count); | 958 | | } | 959 | 115 | res_offsets[row] = dst_offset; | 960 | 115 | } |
_ZN5doris17FunctionStringPadINS_10StringRPadEE17append_result_rowILb0EEEvPKhmiPKNS_12PaddingCharsIXT_EEERNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEERNSA_IjLm4096ESD_Lm16ELm15EEESF_mRm Line | Count | Source | 917 | 2.08k | size_t& dst_offset) { | 918 | 2.08k | if (target_len < 0) { | 919 | 18 | null_map_data[row] = true; | 920 | 18 | res_offsets[row] = dst_offset; | 921 | 18 | return; | 922 | 18 | } | 923 | | | 924 | 2.06k | const size_t str_char_len = get_char_length<is_utf8>(str_data, str_byte_len); | 925 | 2.06k | const size_t target_char_len = static_cast<size_t>(target_len); | 926 | 2.06k | if (str_char_len >= target_char_len) { | 927 | 16 | const size_t truncated_byte_len = get_truncated_byte_length<is_utf8>( | 928 | 16 | str_data, str_byte_len, str_char_len, target_char_len); | 929 | 16 | const size_t needed = dst_offset + truncated_byte_len; | 930 | 16 | ensure_capacity(res_chars, needed, row); | 931 | 16 | memcpy(res_chars.data() + dst_offset, str_data, truncated_byte_len); | 932 | 16 | dst_offset += truncated_byte_len; | 933 | 16 | res_offsets[row] = dst_offset; | 934 | 16 | return; | 935 | 16 | } | 936 | | | 937 | 2.04k | if (padding == nullptr || padding->num_chars() == 0) { | 938 | 0 | res_offsets[row] = dst_offset; | 939 | 0 | return; | 940 | 0 | } | 941 | | | 942 | 2.04k | const size_t pad_char_count = target_char_len - str_char_len; | 943 | 2.04k | const size_t full_cycles = pad_char_count / padding->num_chars(); | 944 | 2.04k | const size_t remainder_chars = pad_char_count % padding->num_chars(); | 945 | 2.04k | const size_t pad_bytes = | 946 | 2.04k | full_cycles * padding->pad_string.size() + padding->chars_to_bytes(remainder_chars); | 947 | 2.04k | const size_t needed = dst_offset + str_byte_len + pad_bytes; | 948 | 2.04k | ensure_capacity(res_chars, needed, row); | 949 | | | 950 | | if constexpr (Impl::is_lpad) { | 951 | | dst_offset += padding->append_to(res_chars.data() + dst_offset, pad_char_count); | 952 | | memcpy(res_chars.data() + dst_offset, str_data, str_byte_len); | 953 | | dst_offset += str_byte_len; | 954 | 2.04k | } else { | 955 | 2.04k | memcpy(res_chars.data() + dst_offset, str_data, str_byte_len); | 956 | 2.04k | dst_offset += str_byte_len; | 957 | 2.04k | dst_offset += padding->append_to(res_chars.data() + dst_offset, pad_char_count); | 958 | 2.04k | } | 959 | 2.04k | res_offsets[row] = dst_offset; | 960 | 2.04k | } |
_ZN5doris17FunctionStringPadINS_10StringRPadEE17append_result_rowILb1EEEvPKhmiPKNS_12PaddingCharsIXT_EEERNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEERNSA_IjLm4096ESD_Lm16ELm15EEESF_mRm Line | Count | Source | 917 | 619 | size_t& dst_offset) { | 918 | 619 | if (target_len < 0) { | 919 | 263 | null_map_data[row] = true; | 920 | 263 | res_offsets[row] = dst_offset; | 921 | 263 | return; | 922 | 263 | } | 923 | | | 924 | 356 | const size_t str_char_len = get_char_length<is_utf8>(str_data, str_byte_len); | 925 | 356 | const size_t target_char_len = static_cast<size_t>(target_len); | 926 | 356 | if (str_char_len >= target_char_len) { | 927 | 277 | const size_t truncated_byte_len = get_truncated_byte_length<is_utf8>( | 928 | 277 | str_data, str_byte_len, str_char_len, target_char_len); | 929 | 277 | const size_t needed = dst_offset + truncated_byte_len; | 930 | 277 | ensure_capacity(res_chars, needed, row); | 931 | 277 | memcpy(res_chars.data() + dst_offset, str_data, truncated_byte_len); | 932 | 277 | dst_offset += truncated_byte_len; | 933 | 277 | res_offsets[row] = dst_offset; | 934 | 277 | return; | 935 | 277 | } | 936 | | | 937 | 79 | if (padding == nullptr || padding->num_chars() == 0) { | 938 | 10 | res_offsets[row] = dst_offset; | 939 | 10 | return; | 940 | 10 | } | 941 | | | 942 | 69 | const size_t pad_char_count = target_char_len - str_char_len; | 943 | 69 | const size_t full_cycles = pad_char_count / padding->num_chars(); | 944 | 69 | const size_t remainder_chars = pad_char_count % padding->num_chars(); | 945 | 69 | const size_t pad_bytes = | 946 | 69 | full_cycles * padding->pad_string.size() + padding->chars_to_bytes(remainder_chars); | 947 | 69 | const size_t needed = dst_offset + str_byte_len + pad_bytes; | 948 | 69 | ensure_capacity(res_chars, needed, row); | 949 | | | 950 | | if constexpr (Impl::is_lpad) { | 951 | | dst_offset += padding->append_to(res_chars.data() + dst_offset, pad_char_count); | 952 | | memcpy(res_chars.data() + dst_offset, str_data, str_byte_len); | 953 | | dst_offset += str_byte_len; | 954 | 69 | } else { | 955 | 69 | memcpy(res_chars.data() + dst_offset, str_data, str_byte_len); | 956 | 69 | dst_offset += str_byte_len; | 957 | 69 | dst_offset += padding->append_to(res_chars.data() + dst_offset, pad_char_count); | 958 | 69 | } | 959 | 69 | res_offsets[row] = dst_offset; | 960 | 69 | } |
|
961 | | |
962 | | template <bool all_ascii, bool str_const> |
963 | | static void execute_const_len_const_pad(const ColumnString& strcol, |
964 | | const ColumnInt32::Container& col_len_data, |
965 | | const ColumnString& padcol, |
966 | | ColumnString::Offsets& res_offsets, |
967 | | ColumnString::Chars& res_chars, |
968 | | ColumnUInt8::Container& null_map_data, |
969 | 174 | size_t input_rows_count) { |
970 | 174 | constexpr bool is_utf8 = !all_ascii; |
971 | 174 | using PadChars = PaddingChars<is_utf8>; |
972 | | |
973 | 174 | const int target_len = col_len_data[0]; |
974 | 174 | std::optional<PadChars> padding; |
975 | 174 | const auto pad = padcol.get_data_at(0); |
976 | 174 | if (!pad.empty()) { |
977 | 144 | padding.emplace(reinterpret_cast<const uint8_t*>(pad.data), pad.size); |
978 | 144 | } |
979 | | |
980 | 174 | const PadChars* padding_ptr = padding ? &*padding : nullptr; |
981 | 174 | const size_t estimated_total = estimate_const_output_bytes<is_utf8>( |
982 | 174 | strcol.get_chars(), target_len, input_rows_count, padding_ptr); |
983 | 174 | if (estimated_total > 0) { |
984 | 78 | ColumnString::check_chars_length(estimated_total, 0, input_rows_count); |
985 | 78 | } |
986 | 174 | res_chars.resize(estimated_total); |
987 | | |
988 | 174 | size_t dst_offset = 0; |
989 | 218k | for (size_t i = 0; i < input_rows_count; ++i) { |
990 | 218k | auto str = strcol.get_data_at(index_check_const<str_const>(i)); |
991 | 218k | append_result_row<is_utf8>(reinterpret_cast<const uint8_t*>(str.data), str.size, |
992 | 218k | target_len, padding_ptr, res_chars, res_offsets, |
993 | 218k | null_map_data, i, dst_offset); |
994 | 218k | } |
995 | 174 | res_chars.resize(dst_offset); |
996 | 174 | } _ZN5doris17FunctionStringPadINS_10StringLPadEE27execute_const_len_const_padILb1ELb0EEEvRKNS_9ColumnStrIjEERKNS_8PODArrayIiLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEES7_RNS8_IjLm4096ESB_Lm16ELm15EEERNS8_IhLm4096ESB_Lm16ELm15EEESI_m Line | Count | Source | 969 | 82 | size_t input_rows_count) { | 970 | 82 | constexpr bool is_utf8 = !all_ascii; | 971 | 82 | using PadChars = PaddingChars<is_utf8>; | 972 | | | 973 | 82 | const int target_len = col_len_data[0]; | 974 | 82 | std::optional<PadChars> padding; | 975 | 82 | const auto pad = padcol.get_data_at(0); | 976 | 82 | if (!pad.empty()) { | 977 | 71 | padding.emplace(reinterpret_cast<const uint8_t*>(pad.data), pad.size); | 978 | 71 | } | 979 | | | 980 | 82 | const PadChars* padding_ptr = padding ? &*padding : nullptr; | 981 | 82 | const size_t estimated_total = estimate_const_output_bytes<is_utf8>( | 982 | 82 | strcol.get_chars(), target_len, input_rows_count, padding_ptr); | 983 | 82 | if (estimated_total > 0) { | 984 | 55 | ColumnString::check_chars_length(estimated_total, 0, input_rows_count); | 985 | 55 | } | 986 | 82 | res_chars.resize(estimated_total); | 987 | | | 988 | 82 | size_t dst_offset = 0; | 989 | 216k | for (size_t i = 0; i < input_rows_count; ++i) { | 990 | 216k | auto str = strcol.get_data_at(index_check_const<str_const>(i)); | 991 | 216k | append_result_row<is_utf8>(reinterpret_cast<const uint8_t*>(str.data), str.size, | 992 | 216k | target_len, padding_ptr, res_chars, res_offsets, | 993 | 216k | null_map_data, i, dst_offset); | 994 | 216k | } | 995 | 82 | res_chars.resize(dst_offset); | 996 | 82 | } |
_ZN5doris17FunctionStringPadINS_10StringLPadEE27execute_const_len_const_padILb0ELb0EEEvRKNS_9ColumnStrIjEERKNS_8PODArrayIiLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEES7_RNS8_IjLm4096ESB_Lm16ELm15EEERNS8_IhLm4096ESB_Lm16ELm15EEESI_m Line | Count | Source | 969 | 27 | size_t input_rows_count) { | 970 | 27 | constexpr bool is_utf8 = !all_ascii; | 971 | 27 | using PadChars = PaddingChars<is_utf8>; | 972 | | | 973 | 27 | const int target_len = col_len_data[0]; | 974 | 27 | std::optional<PadChars> padding; | 975 | 27 | const auto pad = padcol.get_data_at(0); | 976 | 27 | if (!pad.empty()) { | 977 | 23 | padding.emplace(reinterpret_cast<const uint8_t*>(pad.data), pad.size); | 978 | 23 | } | 979 | | | 980 | 27 | const PadChars* padding_ptr = padding ? &*padding : nullptr; | 981 | 27 | const size_t estimated_total = estimate_const_output_bytes<is_utf8>( | 982 | 27 | strcol.get_chars(), target_len, input_rows_count, padding_ptr); | 983 | 27 | if (estimated_total > 0) { | 984 | 6 | ColumnString::check_chars_length(estimated_total, 0, input_rows_count); | 985 | 6 | } | 986 | 27 | res_chars.resize(estimated_total); | 987 | | | 988 | 27 | size_t dst_offset = 0; | 989 | 54 | for (size_t i = 0; i < input_rows_count; ++i) { | 990 | 27 | auto str = strcol.get_data_at(index_check_const<str_const>(i)); | 991 | 27 | append_result_row<is_utf8>(reinterpret_cast<const uint8_t*>(str.data), str.size, | 992 | 27 | target_len, padding_ptr, res_chars, res_offsets, | 993 | 27 | null_map_data, i, dst_offset); | 994 | 27 | } | 995 | 27 | res_chars.resize(dst_offset); | 996 | 27 | } |
Unexecuted instantiation: _ZN5doris17FunctionStringPadINS_10StringLPadEE27execute_const_len_const_padILb1ELb1EEEvRKNS_9ColumnStrIjEERKNS_8PODArrayIiLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEES7_RNS8_IjLm4096ESB_Lm16ELm15EEERNS8_IhLm4096ESB_Lm16ELm15EEESI_m Unexecuted instantiation: _ZN5doris17FunctionStringPadINS_10StringLPadEE27execute_const_len_const_padILb0ELb1EEEvRKNS_9ColumnStrIjEERKNS_8PODArrayIiLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEES7_RNS8_IjLm4096ESB_Lm16ELm15EEERNS8_IhLm4096ESB_Lm16ELm15EEESI_m _ZN5doris17FunctionStringPadINS_10StringRPadEE27execute_const_len_const_padILb1ELb0EEEvRKNS_9ColumnStrIjEERKNS_8PODArrayIiLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEES7_RNS8_IjLm4096ESB_Lm16ELm15EEERNS8_IhLm4096ESB_Lm16ELm15EEESI_m Line | Count | Source | 969 | 37 | size_t input_rows_count) { | 970 | 37 | constexpr bool is_utf8 = !all_ascii; | 971 | 37 | using PadChars = PaddingChars<is_utf8>; | 972 | | | 973 | 37 | const int target_len = col_len_data[0]; | 974 | 37 | std::optional<PadChars> padding; | 975 | 37 | const auto pad = padcol.get_data_at(0); | 976 | 37 | if (!pad.empty()) { | 977 | 26 | padding.emplace(reinterpret_cast<const uint8_t*>(pad.data), pad.size); | 978 | 26 | } | 979 | | | 980 | 37 | const PadChars* padding_ptr = padding ? &*padding : nullptr; | 981 | 37 | const size_t estimated_total = estimate_const_output_bytes<is_utf8>( | 982 | 37 | strcol.get_chars(), target_len, input_rows_count, padding_ptr); | 983 | 37 | if (estimated_total > 0) { | 984 | 10 | ColumnString::check_chars_length(estimated_total, 0, input_rows_count); | 985 | 10 | } | 986 | 37 | res_chars.resize(estimated_total); | 987 | | | 988 | 37 | size_t dst_offset = 0; | 989 | 2.12k | for (size_t i = 0; i < input_rows_count; ++i) { | 990 | 2.08k | auto str = strcol.get_data_at(index_check_const<str_const>(i)); | 991 | 2.08k | append_result_row<is_utf8>(reinterpret_cast<const uint8_t*>(str.data), str.size, | 992 | 2.08k | target_len, padding_ptr, res_chars, res_offsets, | 993 | 2.08k | null_map_data, i, dst_offset); | 994 | 2.08k | } | 995 | 37 | res_chars.resize(dst_offset); | 996 | 37 | } |
_ZN5doris17FunctionStringPadINS_10StringRPadEE27execute_const_len_const_padILb0ELb0EEEvRKNS_9ColumnStrIjEERKNS_8PODArrayIiLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEES7_RNS8_IjLm4096ESB_Lm16ELm15EEERNS8_IhLm4096ESB_Lm16ELm15EEESI_m Line | Count | Source | 969 | 28 | size_t input_rows_count) { | 970 | 28 | constexpr bool is_utf8 = !all_ascii; | 971 | 28 | using PadChars = PaddingChars<is_utf8>; | 972 | | | 973 | 28 | const int target_len = col_len_data[0]; | 974 | 28 | std::optional<PadChars> padding; | 975 | 28 | const auto pad = padcol.get_data_at(0); | 976 | 28 | if (!pad.empty()) { | 977 | 24 | padding.emplace(reinterpret_cast<const uint8_t*>(pad.data), pad.size); | 978 | 24 | } | 979 | | | 980 | 28 | const PadChars* padding_ptr = padding ? &*padding : nullptr; | 981 | 28 | const size_t estimated_total = estimate_const_output_bytes<is_utf8>( | 982 | 28 | strcol.get_chars(), target_len, input_rows_count, padding_ptr); | 983 | 28 | if (estimated_total > 0) { | 984 | 7 | ColumnString::check_chars_length(estimated_total, 0, input_rows_count); | 985 | 7 | } | 986 | 28 | res_chars.resize(estimated_total); | 987 | | | 988 | 28 | size_t dst_offset = 0; | 989 | 56 | for (size_t i = 0; i < input_rows_count; ++i) { | 990 | 28 | auto str = strcol.get_data_at(index_check_const<str_const>(i)); | 991 | 28 | append_result_row<is_utf8>(reinterpret_cast<const uint8_t*>(str.data), str.size, | 992 | 28 | target_len, padding_ptr, res_chars, res_offsets, | 993 | 28 | null_map_data, i, dst_offset); | 994 | 28 | } | 995 | 28 | res_chars.resize(dst_offset); | 996 | 28 | } |
Unexecuted instantiation: _ZN5doris17FunctionStringPadINS_10StringRPadEE27execute_const_len_const_padILb1ELb1EEEvRKNS_9ColumnStrIjEERKNS_8PODArrayIiLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEES7_RNS8_IjLm4096ESB_Lm16ELm15EEERNS8_IhLm4096ESB_Lm16ELm15EEESI_m Unexecuted instantiation: _ZN5doris17FunctionStringPadINS_10StringRPadEE27execute_const_len_const_padILb0ELb1EEEvRKNS_9ColumnStrIjEERKNS_8PODArrayIiLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEES7_RNS8_IjLm4096ESB_Lm16ELm15EEERNS8_IhLm4096ESB_Lm16ELm15EEESI_m |
997 | | |
998 | | template <bool str_const> |
999 | | static void execute_general(const ColumnString& strcol, |
1000 | | const ColumnInt32::Container& col_len_data, bool len_const, |
1001 | | const ColumnString& padcol, bool pad_const, |
1002 | | ColumnString::Offsets& res_offsets, ColumnString::Chars& res_chars, |
1003 | 1.01k | ColumnUInt8::Container& null_map_data, size_t input_rows_count) { |
1004 | 1.01k | using PadChars = PaddingChars<true>; |
1005 | 1.01k | std::optional<PadChars> const_padding; |
1006 | 1.01k | const PadChars* const_padding_ptr = nullptr; |
1007 | 1.01k | if (pad_const) { |
1008 | 248 | auto pad = padcol.get_data_at(0); |
1009 | 248 | if (!pad.empty()) { |
1010 | 188 | const_padding.emplace(reinterpret_cast<const uint8_t*>(pad.data), pad.size); |
1011 | 188 | const_padding_ptr = &*const_padding; |
1012 | 188 | } |
1013 | 248 | } |
1014 | | |
1015 | 1.01k | res_chars.resize(strcol.get_chars().size()); |
1016 | 1.01k | size_t dst_offset = 0; |
1017 | 2.28k | for (size_t i = 0; i < input_rows_count; ++i) { |
1018 | 1.27k | auto str = strcol.get_data_at(index_check_const<str_const>(i)); |
1019 | 1.27k | const int target_len = col_len_data[len_const ? 0 : i]; |
1020 | | |
1021 | 1.27k | const PadChars* padding_ptr = const_padding_ptr; |
1022 | 1.27k | std::optional<PadChars> row_padding; |
1023 | 1.27k | if (!pad_const) { |
1024 | 1.02k | auto pad = padcol.get_data_at(i); |
1025 | 1.02k | if (!pad.empty()) { |
1026 | 789 | row_padding.emplace(reinterpret_cast<const uint8_t*>(pad.data), pad.size); |
1027 | 789 | padding_ptr = &*row_padding; |
1028 | 789 | } else { |
1029 | 237 | padding_ptr = nullptr; |
1030 | 237 | } |
1031 | 1.02k | } |
1032 | | |
1033 | 1.27k | append_result_row<true>(reinterpret_cast<const uint8_t*>(str.data), str.size, |
1034 | 1.27k | target_len, padding_ptr, res_chars, res_offsets, null_map_data, |
1035 | 1.27k | i, dst_offset); |
1036 | 1.27k | } |
1037 | 1.01k | res_chars.resize(dst_offset); |
1038 | 1.01k | } _ZN5doris17FunctionStringPadINS_10StringLPadEE15execute_generalILb0EEEvRKNS_9ColumnStrIjEERKNS_8PODArrayIiLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEEbS7_bRNS8_IjLm4096ESB_Lm16ELm15EEERNS8_IhLm4096ESB_Lm16ELm15EEESI_m Line | Count | Source | 1003 | 366 | ColumnUInt8::Container& null_map_data, size_t input_rows_count) { | 1004 | 366 | using PadChars = PaddingChars<true>; | 1005 | 366 | std::optional<PadChars> const_padding; | 1006 | 366 | const PadChars* const_padding_ptr = nullptr; | 1007 | 366 | if (pad_const) { | 1008 | 62 | auto pad = padcol.get_data_at(0); | 1009 | 62 | if (!pad.empty()) { | 1010 | 47 | const_padding.emplace(reinterpret_cast<const uint8_t*>(pad.data), pad.size); | 1011 | 47 | const_padding_ptr = &*const_padding; | 1012 | 47 | } | 1013 | 62 | } | 1014 | | | 1015 | 366 | res_chars.resize(strcol.get_chars().size()); | 1016 | 366 | size_t dst_offset = 0; | 1017 | 863 | for (size_t i = 0; i < input_rows_count; ++i) { | 1018 | 497 | auto str = strcol.get_data_at(index_check_const<str_const>(i)); | 1019 | 497 | const int target_len = col_len_data[len_const ? 0 : i]; | 1020 | | | 1021 | 497 | const PadChars* padding_ptr = const_padding_ptr; | 1022 | 497 | std::optional<PadChars> row_padding; | 1023 | 497 | if (!pad_const) { | 1024 | 435 | auto pad = padcol.get_data_at(i); | 1025 | 435 | if (!pad.empty()) { | 1026 | 343 | row_padding.emplace(reinterpret_cast<const uint8_t*>(pad.data), pad.size); | 1027 | 343 | padding_ptr = &*row_padding; | 1028 | 343 | } else { | 1029 | 92 | padding_ptr = nullptr; | 1030 | 92 | } | 1031 | 435 | } | 1032 | | | 1033 | 497 | append_result_row<true>(reinterpret_cast<const uint8_t*>(str.data), str.size, | 1034 | 497 | target_len, padding_ptr, res_chars, res_offsets, null_map_data, | 1035 | 497 | i, dst_offset); | 1036 | 497 | } | 1037 | 366 | res_chars.resize(dst_offset); | 1038 | 366 | } |
_ZN5doris17FunctionStringPadINS_10StringLPadEE15execute_generalILb1EEEvRKNS_9ColumnStrIjEERKNS_8PODArrayIiLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEEbS7_bRNS8_IjLm4096ESB_Lm16ELm15EEERNS8_IhLm4096ESB_Lm16ELm15EEESI_m Line | Count | Source | 1003 | 186 | ColumnUInt8::Container& null_map_data, size_t input_rows_count) { | 1004 | 186 | using PadChars = PaddingChars<true>; | 1005 | 186 | std::optional<PadChars> const_padding; | 1006 | 186 | const PadChars* const_padding_ptr = nullptr; | 1007 | 186 | if (pad_const) { | 1008 | 62 | auto pad = padcol.get_data_at(0); | 1009 | 62 | if (!pad.empty()) { | 1010 | 47 | const_padding.emplace(reinterpret_cast<const uint8_t*>(pad.data), pad.size); | 1011 | 47 | const_padding_ptr = &*const_padding; | 1012 | 47 | } | 1013 | 62 | } | 1014 | | | 1015 | 186 | res_chars.resize(strcol.get_chars().size()); | 1016 | 186 | size_t dst_offset = 0; | 1017 | 372 | for (size_t i = 0; i < input_rows_count; ++i) { | 1018 | 186 | auto str = strcol.get_data_at(index_check_const<str_const>(i)); | 1019 | 186 | const int target_len = col_len_data[len_const ? 0 : i]; | 1020 | | | 1021 | 186 | const PadChars* padding_ptr = const_padding_ptr; | 1022 | 186 | std::optional<PadChars> row_padding; | 1023 | 186 | if (!pad_const) { | 1024 | 124 | auto pad = padcol.get_data_at(i); | 1025 | 124 | if (!pad.empty()) { | 1026 | 94 | row_padding.emplace(reinterpret_cast<const uint8_t*>(pad.data), pad.size); | 1027 | 94 | padding_ptr = &*row_padding; | 1028 | 94 | } else { | 1029 | 30 | padding_ptr = nullptr; | 1030 | 30 | } | 1031 | 124 | } | 1032 | | | 1033 | 186 | append_result_row<true>(reinterpret_cast<const uint8_t*>(str.data), str.size, | 1034 | 186 | target_len, padding_ptr, res_chars, res_offsets, null_map_data, | 1035 | 186 | i, dst_offset); | 1036 | 186 | } | 1037 | 186 | res_chars.resize(dst_offset); | 1038 | 186 | } |
_ZN5doris17FunctionStringPadINS_10StringRPadEE15execute_generalILb0EEEvRKNS_9ColumnStrIjEERKNS_8PODArrayIiLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEEbS7_bRNS8_IjLm4096ESB_Lm16ELm15EEERNS8_IhLm4096ESB_Lm16ELm15EEESI_m Line | Count | Source | 1003 | 275 | ColumnUInt8::Container& null_map_data, size_t input_rows_count) { | 1004 | 275 | using PadChars = PaddingChars<true>; | 1005 | 275 | std::optional<PadChars> const_padding; | 1006 | 275 | const PadChars* const_padding_ptr = nullptr; | 1007 | 275 | if (pad_const) { | 1008 | 62 | auto pad = padcol.get_data_at(0); | 1009 | 62 | if (!pad.empty()) { | 1010 | 47 | const_padding.emplace(reinterpret_cast<const uint8_t*>(pad.data), pad.size); | 1011 | 47 | const_padding_ptr = &*const_padding; | 1012 | 47 | } | 1013 | 62 | } | 1014 | | | 1015 | 275 | res_chars.resize(strcol.get_chars().size()); | 1016 | 275 | size_t dst_offset = 0; | 1017 | 680 | for (size_t i = 0; i < input_rows_count; ++i) { | 1018 | 405 | auto str = strcol.get_data_at(index_check_const<str_const>(i)); | 1019 | 405 | const int target_len = col_len_data[len_const ? 0 : i]; | 1020 | | | 1021 | 405 | const PadChars* padding_ptr = const_padding_ptr; | 1022 | 405 | std::optional<PadChars> row_padding; | 1023 | 405 | if (!pad_const) { | 1024 | 343 | auto pad = padcol.get_data_at(i); | 1025 | 343 | if (!pad.empty()) { | 1026 | 258 | row_padding.emplace(reinterpret_cast<const uint8_t*>(pad.data), pad.size); | 1027 | 258 | padding_ptr = &*row_padding; | 1028 | 258 | } else { | 1029 | 85 | padding_ptr = nullptr; | 1030 | 85 | } | 1031 | 343 | } | 1032 | | | 1033 | 405 | append_result_row<true>(reinterpret_cast<const uint8_t*>(str.data), str.size, | 1034 | 405 | target_len, padding_ptr, res_chars, res_offsets, null_map_data, | 1035 | 405 | i, dst_offset); | 1036 | 405 | } | 1037 | 275 | res_chars.resize(dst_offset); | 1038 | 275 | } |
_ZN5doris17FunctionStringPadINS_10StringRPadEE15execute_generalILb1EEEvRKNS_9ColumnStrIjEERKNS_8PODArrayIiLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEEbS7_bRNS8_IjLm4096ESB_Lm16ELm15EEERNS8_IhLm4096ESB_Lm16ELm15EEESI_m Line | Count | Source | 1003 | 186 | ColumnUInt8::Container& null_map_data, size_t input_rows_count) { | 1004 | 186 | using PadChars = PaddingChars<true>; | 1005 | 186 | std::optional<PadChars> const_padding; | 1006 | 186 | const PadChars* const_padding_ptr = nullptr; | 1007 | 186 | if (pad_const) { | 1008 | 62 | auto pad = padcol.get_data_at(0); | 1009 | 62 | if (!pad.empty()) { | 1010 | 47 | const_padding.emplace(reinterpret_cast<const uint8_t*>(pad.data), pad.size); | 1011 | 47 | const_padding_ptr = &*const_padding; | 1012 | 47 | } | 1013 | 62 | } | 1014 | | | 1015 | 186 | res_chars.resize(strcol.get_chars().size()); | 1016 | 186 | size_t dst_offset = 0; | 1017 | 372 | for (size_t i = 0; i < input_rows_count; ++i) { | 1018 | 186 | auto str = strcol.get_data_at(index_check_const<str_const>(i)); | 1019 | 186 | const int target_len = col_len_data[len_const ? 0 : i]; | 1020 | | | 1021 | 186 | const PadChars* padding_ptr = const_padding_ptr; | 1022 | 186 | std::optional<PadChars> row_padding; | 1023 | 186 | if (!pad_const) { | 1024 | 124 | auto pad = padcol.get_data_at(i); | 1025 | 124 | if (!pad.empty()) { | 1026 | 94 | row_padding.emplace(reinterpret_cast<const uint8_t*>(pad.data), pad.size); | 1027 | 94 | padding_ptr = &*row_padding; | 1028 | 94 | } else { | 1029 | 30 | padding_ptr = nullptr; | 1030 | 30 | } | 1031 | 124 | } | 1032 | | | 1033 | 186 | append_result_row<true>(reinterpret_cast<const uint8_t*>(str.data), str.size, | 1034 | 186 | target_len, padding_ptr, res_chars, res_offsets, null_map_data, | 1035 | 186 | i, dst_offset); | 1036 | 186 | } | 1037 | 186 | res_chars.resize(dst_offset); | 1038 | 186 | } |
|
1039 | | }; |
1040 | | |
1041 | | #include "common/compile_check_avoid_end.h" |
1042 | | } // namespace doris |