Coverage Report

Created: 2026-06-24 11:44

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
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
1.10k
    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
1.09k
    bool is_variadic() const override { return true; }
67
68
1.09k
    DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
69
1.09k
        return std::make_shared<DataTypeString>();
70
1.09k
    }
71
72
4.84k
    Status open(FunctionContext* context, FunctionContext::FunctionStateScope scope) override {
73
4.84k
        if (scope == FunctionContext::THREAD_LOCAL) {
74
3.75k
            return Status::OK();
75
3.75k
        }
76
1.09k
        std::shared_ptr<ConcatState> state = std::make_shared<ConcatState>();
77
78
1.09k
        context->set_function_state(scope, state);
79
80
1.09k
        state->use_state = true;
81
82
        // Optimize function calls like this:
83
        // concat(col, "123", "abc", "456") -> tail = "123abc456"
84
1.83k
        for (size_t i = 1; i < context->get_num_args(); i++) {
85
1.54k
            const auto* column_string = context->get_constant_col(i);
86
1.54k
            if (column_string == nullptr) {
87
773
                state->use_state = false;
88
773
                return IFunction::open(context, scope);
89
773
            }
90
771
            auto string_vale = column_string->column_ptr->get_data_at(0);
91
771
            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
738
            state->tail.append(string_vale.begin(), string_vale.size);
98
738
        }
99
100
        // The reserve is used here to allow the usage of memcpy_small_allow_read_write_overflow15 below.
101
289
        state->tail.reserve(state->tail.size() + 16);
102
103
289
        return IFunction::open(context, scope);
104
1.09k
    }
105
106
    Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
107
1.19k
                        uint32_t result, size_t input_rows_count) const override {
108
1.19k
        DCHECK_GE(arguments.size(), 1);
109
110
1.19k
        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
1.16k
        auto* concat_state = reinterpret_cast<ConcatState*>(
115
1.16k
                context->get_function_state(FunctionContext::FRAGMENT_LOCAL));
116
1.16k
        if (!concat_state) {
117
0
            return Status::RuntimeError("funciton context for function '{}' must have ConcatState;",
118
0
                                        get_name());
119
0
        }
120
1.16k
        if (concat_state->use_state) {
121
276
            const auto& [col, is_const] =
122
276
                    unpack_if_const(block.get_by_position(arguments[0]).column);
123
276
            const auto* col_str = assert_cast<const ColumnString*>(col.get());
124
276
            if (is_const) {
125
0
                return execute_const<true>(concat_state, block, col_str, result, input_rows_count);
126
276
            } else {
127
276
                return execute_const<false>(concat_state, block, col_str, result, input_rows_count);
128
276
            }
129
130
888
        } else {
131
888
            return execute_vecotr(block, arguments, result, input_rows_count);
132
888
        }
133
1.16k
    }
134
135
    Status execute_vecotr(Block& block, const ColumnNumbers& arguments, uint32_t result,
136
888
                          size_t input_rows_count) const {
137
888
        int argument_size = arguments.size();
138
888
        std::vector<ColumnPtr> argument_columns(argument_size);
139
140
888
        std::vector<const ColumnString::Offsets*> offsets_list(argument_size);
141
888
        std::vector<const ColumnString::Chars*> chars_list(argument_size);
142
888
        std::vector<bool> is_const_args(argument_size);
143
144
3.34k
        for (int i = 0; i < argument_size; ++i) {
145
2.45k
            const auto& [col, is_const] =
146
2.45k
                    unpack_if_const(block.get_by_position(arguments[i]).column);
147
148
2.45k
            const auto* col_str = assert_cast<const ColumnString*>(col.get());
149
2.45k
            offsets_list[i] = &col_str->get_offsets();
150
2.45k
            chars_list[i] = &col_str->get_chars();
151
2.45k
            is_const_args[i] = is_const;
152
2.45k
        }
153
154
888
        auto res = ColumnString::create();
155
888
        auto& res_data = res->get_chars();
156
888
        auto& res_offset = res->get_offsets();
157
158
888
        res_offset.resize(input_rows_count);
159
888
        size_t res_reserve_size = 0;
160
3.34k
        for (size_t i = 0; i < argument_size; ++i) {
161
2.46k
            if (is_const_args[i]) {
162
824
                res_reserve_size += (*offsets_list[i])[0] * input_rows_count;
163
1.63k
            } else {
164
1.63k
                res_reserve_size += (*offsets_list[i])[input_rows_count - 1];
165
1.63k
            }
166
2.46k
        }
167
168
888
        ColumnString::check_chars_length(res_reserve_size, 0);
169
170
888
        res_data.resize(res_reserve_size);
171
172
888
        auto* data = res_data.data();
173
888
        size_t dst_offset = 0;
174
175
71.9k
        for (size_t i = 0; i < input_rows_count; ++i) {
176
247k
            for (size_t j = 0; j < argument_size; ++j) {
177
176k
                const auto& current_offsets = *offsets_list[j];
178
176k
                const auto& current_chars = *chars_list[j];
179
176k
                auto idx = index_check_const(i, is_const_args[j]);
180
176k
                const auto size = current_offsets[idx] - current_offsets[idx - 1];
181
176k
                if (size > 0) {
182
176k
                    memcpy_small_allow_read_write_overflow15(
183
176k
                            data + dst_offset, current_chars.data() + current_offsets[idx - 1],
184
176k
                            size);
185
176k
                    dst_offset += size;
186
176k
                }
187
176k
            }
188
71.0k
            res_offset[i] = dst_offset;
189
71.0k
        }
190
191
888
        block.get_by_position(result).column = std::move(res);
192
888
        return Status::OK();
193
888
    }
194
195
    template <bool is_const>
196
    Status execute_const(ConcatState* concat_state, Block& block, const ColumnString* col_str,
197
276
                         uint32_t result, size_t input_rows_count) const {
198
        // using tail optimize
199
200
276
        auto res = ColumnString::create();
201
276
        auto& res_data = res->get_chars();
202
276
        auto& res_offset = res->get_offsets();
203
276
        res_offset.resize(input_rows_count);
204
205
276
        size_t res_reserve_size = 0;
206
276
        if constexpr (is_const) {
207
0
            res_reserve_size = col_str->get_offsets()[0] * input_rows_count;
208
276
        } else {
209
276
            res_reserve_size = col_str->get_offsets()[input_rows_count - 1];
210
276
        }
211
276
        res_reserve_size += concat_state->tail.size() * input_rows_count;
212
213
276
        ColumnString::check_chars_length(res_reserve_size, 0);
214
276
        res_data.resize(res_reserve_size);
215
216
276
        const auto& tail = concat_state->tail;
217
276
        auto* data = res_data.data();
218
276
        size_t dst_offset = 0;
219
220
883
        for (size_t i = 0; i < input_rows_count; ++i) {
221
607
            const auto idx = index_check_const<is_const>(i);
222
607
            StringRef str_val = col_str->get_data_at(idx);
223
            // copy column
224
607
            memcpy_small_allow_read_write_overflow15(data + dst_offset, str_val.data, str_val.size);
225
607
            dst_offset += str_val.size;
226
            // copy tail
227
607
            memcpy_small_allow_read_write_overflow15(data + dst_offset, tail.data(), tail.size());
228
607
            dst_offset += tail.size();
229
607
            res_offset[i] = dst_offset;
230
607
        }
231
276
        block.get_by_position(result).column = std::move(res);
232
276
        return Status::OK();
233
276
    }
Unexecuted instantiation: _ZNK5doris20FunctionStringConcat13execute_constILb1EEENS_6StatusEPNS0_11ConcatStateERNS_5BlockEPKNS_9ColumnStrIjEEjm
_ZNK5doris20FunctionStringConcat13execute_constILb0EEENS_6StatusEPNS0_11ConcatStateERNS_5BlockEPKNS_9ColumnStrIjEEjm
Line
Count
Source
197
276
                         uint32_t result, size_t input_rows_count) const {
198
        // using tail optimize
199
200
276
        auto res = ColumnString::create();
201
276
        auto& res_data = res->get_chars();
202
276
        auto& res_offset = res->get_offsets();
203
276
        res_offset.resize(input_rows_count);
204
205
276
        size_t res_reserve_size = 0;
206
        if constexpr (is_const) {
207
            res_reserve_size = col_str->get_offsets()[0] * input_rows_count;
208
276
        } else {
209
276
            res_reserve_size = col_str->get_offsets()[input_rows_count - 1];
210
276
        }
211
276
        res_reserve_size += concat_state->tail.size() * input_rows_count;
212
213
276
        ColumnString::check_chars_length(res_reserve_size, 0);
214
276
        res_data.resize(res_reserve_size);
215
216
276
        const auto& tail = concat_state->tail;
217
276
        auto* data = res_data.data();
218
276
        size_t dst_offset = 0;
219
220
883
        for (size_t i = 0; i < input_rows_count; ++i) {
221
607
            const auto idx = index_check_const<is_const>(i);
222
607
            StringRef str_val = col_str->get_data_at(idx);
223
            // copy column
224
607
            memcpy_small_allow_read_write_overflow15(data + dst_offset, str_val.data, str_val.size);
225
607
            dst_offset += str_val.size;
226
            // copy tail
227
607
            memcpy_small_allow_read_write_overflow15(data + dst_offset, tail.data(), tail.size());
228
607
            dst_offset += tail.size();
229
607
            res_offset[i] = dst_offset;
230
607
        }
231
276
        block.get_by_position(result).column = std::move(res);
232
276
        return Status::OK();
233
276
    }
234
};
235
236
class FunctionStringElt : public IFunction {
237
public:
238
    static constexpr auto name = "elt";
239
423
    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
415
    bool is_variadic() const override { return true; }
243
244
414
    DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
245
414
        return make_nullable(std::make_shared<DataTypeString>());
246
414
    }
247
840
    bool use_default_implementation_for_nulls() const override { return false; }
248
249
    Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
250
426
                        uint32_t result, size_t input_rows_count) const override {
251
426
        int arguent_size = arguments.size();
252
426
        int num_children = arguent_size - 1;
253
426
        auto res = ColumnString::create();
254
255
426
        if (auto const_column = check_and_get_column<ColumnConst>(
256
426
                    *block.get_by_position(arguments[0]).column)) {
257
154
            auto data = const_column->get_data_at(0);
258
            // return NULL, pos is null or pos < 0 or pos > num_children
259
154
            auto is_null = data.data == nullptr;
260
154
            auto pos = is_null ? 0 : *(Int32*)data.data;
261
154
            is_null = pos <= 0 || pos > num_children;
262
263
154
            auto null_map = ColumnUInt8::create(input_rows_count, is_null);
264
154
            if (is_null) {
265
135
                res->insert_many_defaults(input_rows_count);
266
135
            } else {
267
19
                auto& target_column = block.get_by_position(arguments[pos]).column;
268
19
                if (auto target_const_column = check_and_get_column<ColumnConst>(*target_column)) {
269
7
                    auto target_data = target_const_column->get_data_at(0);
270
                    // return NULL, no target data
271
7
                    if (target_data.data == nullptr) {
272
1
                        null_map = ColumnUInt8::create(input_rows_count, true);
273
1
                        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
19
            }
297
154
            block.get_by_position(result).column =
298
154
                    ColumnNullable::create(std::move(res), std::move(null_map));
299
272
        } else if (auto pos_null_column = check_and_get_column<ColumnNullable>(
300
272
                           *block.get_by_position(arguments[0]).column)) {
301
219
            auto& pos_column =
302
219
                    assert_cast<const ColumnInt32&>(pos_null_column->get_nested_column());
303
219
            auto& pos_null_map = pos_null_column->get_null_map_data();
304
219
            auto null_map = ColumnUInt8::create(input_rows_count, false);
305
219
            auto& res_null_map = null_map->get_data();
306
307
515
            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
219
            block.get_by_position(result).column =
321
219
                    ColumnNullable::create(std::move(res), std::move(null_map));
322
219
        } 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
426
        return Status::OK();
345
426
    }
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
554
    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
546
    bool is_variadic() const override { return true; }
360
361
545
    DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
362
545
        const IDataType* first_type = arguments[0].get();
363
545
        if (first_type->is_nullable()) {
364
458
            return make_nullable(std::make_shared<DataTypeString>());
365
458
        } else {
366
87
            return std::make_shared<DataTypeString>();
367
87
        }
368
545
    }
369
1.10k
    bool use_default_implementation_for_nulls() const override { return false; }
370
371
    Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
372
563
                        uint32_t result, size_t input_rows_count) const override {
373
563
        DCHECK_GE(arguments.size(), 2);
374
563
        auto null_map = ColumnUInt8::create(input_rows_count, 0);
375
        // we create a zero column to simply implement
376
563
        auto const_null_map = ColumnUInt8::create(input_rows_count, 0);
377
563
        auto res = ColumnString::create();
378
563
        bool is_null_type = block.get_by_position(arguments[0]).type.get()->is_nullable();
379
563
        size_t argument_size = arguments.size();
380
563
        std::vector<const Offsets*> offsets_list(argument_size);
381
563
        std::vector<const Chars*> chars_list(argument_size);
382
563
        std::vector<const ColumnUInt8::Container*> null_list(argument_size);
383
384
563
        std::vector<ColumnPtr> argument_columns(argument_size);
385
563
        std::vector<ColumnPtr> argument_null_columns(argument_size);
386
387
1.93k
        for (size_t i = 0; i < argument_size; ++i) {
388
1.37k
            argument_columns[i] =
389
1.37k
                    block.get_by_position(arguments[i]).column->convert_to_full_column_if_const();
390
1.37k
            if (const auto* nullable =
391
1.37k
                        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.14k
                null_list[i] = &nullable->get_null_map_data();
396
1.14k
                argument_null_columns[i] = nullable->get_null_map_column_ptr();
397
1.14k
                argument_columns[i] = nullable->get_nested_column_ptr();
398
1.14k
            } else {
399
233
                null_list[i] = &const_null_map->get_data();
400
233
            }
401
402
1.37k
            if (is_column<ColumnArray>(argument_columns[i].get())) {
403
102
                continue;
404
102
            }
405
406
1.27k
            const auto* col_str = assert_cast<const ColumnString*>(argument_columns[i].get());
407
1.27k
            offsets_list[i] = &col_str->get_offsets();
408
1.27k
            chars_list[i] = &col_str->get_chars();
409
1.27k
        }
410
411
563
        auto& res_data = res->get_chars();
412
563
        auto& res_offset = res->get_offsets();
413
563
        res_offset.resize(input_rows_count);
414
415
563
        VectorizedUtils::update_null_map(null_map->get_data(), *null_list[0]);
416
563
        fmt::memory_buffer buffer;
417
563
        std::vector<std::string_view> views;
418
419
563
        if (is_column<ColumnArray>(argument_columns[1].get())) {
420
100
            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
99
            const auto& array_column = reinterpret_cast<const ColumnArray&>(*argument_columns[1]);
427
99
            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
99
            _execute_array(input_rows_count, array_column, buffer, views, offsets_list, chars_list,
437
99
                           null_list, res_data, res_offset);
438
439
463
        } else {
440
            // Concat string
441
463
            _execute_string(input_rows_count, argument_size, buffer, views, offsets_list,
442
463
                            chars_list, null_list, res_data, res_offset);
443
463
        }
444
562
        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
104
            block.get_by_position(result).column = std::move(res);
449
104
        }
450
562
        return Status::OK();
451
563
    }
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
99
                        Chars& res_data, Offsets& res_offset) const {
460
        // Get array nested column
461
99
        const UInt8* array_nested_null_map = nullptr;
462
99
        ColumnPtr array_nested_column = nullptr;
463
464
99
        if (is_column_nullable(array_column.get_data())) {
465
99
            const auto& array_nested_null_column =
466
99
                    reinterpret_cast<const ColumnNullable&>(array_column.get_data());
467
            // String's null map in array
468
99
            array_nested_null_map =
469
99
                    array_nested_null_column.get_null_map_column().get_data().data();
470
99
            array_nested_column = array_nested_null_column.get_nested_column_ptr();
471
99
        } else {
472
0
            array_nested_column = array_column.get_data_ptr();
473
0
        }
474
475
99
        const auto& string_column = reinterpret_cast<const ColumnString&>(*array_nested_column);
476
99
        const Chars& string_src_chars = string_column.get_chars();
477
99
        const auto& src_string_offsets = string_column.get_offsets();
478
99
        const auto& src_array_offsets = array_column.get_offsets();
479
99
        size_t current_src_array_offset = 0;
480
99
        auto& array_nullmap = *null_list[1];
481
482
        // Concat string in array
483
602
        for (size_t i = 0; i < input_rows_count; ++i) {
484
503
            auto& sep_offsets = *offsets_list[0];
485
503
            auto& sep_chars = *chars_list[0];
486
503
            auto& sep_nullmap = *null_list[0];
487
488
503
            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
492
            if (array_nullmap[i]) {
495
8
                StringOP::push_empty_string(i, res_data, res_offset);
496
8
                current_src_array_offset += src_array_offsets[i] - src_array_offsets[i - 1];
497
8
                continue;
498
8
            }
499
500
484
            int sep_size = sep_offsets[i] - sep_offsets[i - 1];
501
484
            const char* sep_data = reinterpret_cast<const char*>(&sep_chars[sep_offsets[i - 1]]);
502
503
484
            std::string_view sep(sep_data, sep_size);
504
484
            buffer.clear();
505
484
            views.clear();
506
507
484
            for (auto next_src_array_offset = src_array_offsets[i];
508
1.28k
                 current_src_array_offset < next_src_array_offset; ++current_src_array_offset) {
509
803
                const auto current_src_string_offset =
510
803
                        current_src_array_offset ? src_string_offsets[current_src_array_offset - 1]
511
803
                                                 : 0;
512
803
                size_t bytes_to_copy =
513
803
                        src_string_offsets[current_src_array_offset] - current_src_string_offset;
514
803
                const char* ptr =
515
803
                        reinterpret_cast<const char*>(&string_src_chars[current_src_string_offset]);
516
517
803
                if (array_nested_null_map == nullptr ||
518
803
                    !array_nested_null_map[current_src_array_offset]) {
519
774
                    views.emplace_back(ptr, bytes_to_copy);
520
774
                }
521
803
            }
522
523
484
            fmt::format_to(buffer, "{}", fmt::join(views, sep));
524
525
484
            StringOP::push_value_string(std::string_view(buffer.data(), buffer.size()), i, res_data,
526
484
                                        res_offset);
527
484
        }
528
99
    }
529
530
    void _execute_string(const size_t& input_rows_count, const size_t& argument_size,
531
                         fmt::memory_buffer& buffer, std::vector<std::string_view>& views,
532
                         const std::vector<const Offsets*>& offsets_list,
533
                         const std::vector<const Chars*>& chars_list,
534
                         const std::vector<const ColumnUInt8::Container*>& null_list,
535
463
                         Chars& res_data, Offsets& res_offset) const {
536
        // Concat string
537
1.06k
        for (size_t i = 0; i < input_rows_count; ++i) {
538
604
            auto& sep_offsets = *offsets_list[0];
539
604
            auto& sep_chars = *chars_list[0];
540
604
            auto& sep_nullmap = *null_list[0];
541
604
            if (sep_nullmap[i]) {
542
78
                res_offset[i] = res_data.size();
543
78
                continue;
544
78
            }
545
546
526
            int sep_size = sep_offsets[i] - sep_offsets[i - 1];
547
526
            const char* sep_data = reinterpret_cast<const char*>(&sep_chars[sep_offsets[i - 1]]);
548
549
526
            std::string_view sep(sep_data, sep_size);
550
526
            buffer.clear();
551
526
            views.clear();
552
1.25k
            for (size_t j = 1; j < argument_size; ++j) {
553
732
                auto& current_offsets = *offsets_list[j];
554
732
                auto& current_chars = *chars_list[j];
555
732
                auto& current_nullmap = *null_list[j];
556
732
                int size = current_offsets[i] - current_offsets[i - 1];
557
732
                const char* ptr =
558
732
                        reinterpret_cast<const char*>(&current_chars[current_offsets[i - 1]]);
559
732
                if (!current_nullmap[i]) {
560
656
                    views.emplace_back(ptr, size);
561
656
                }
562
732
            }
563
526
            fmt::format_to(buffer, "{}", fmt::join(views, sep));
564
526
            StringOP::push_value_string(std::string_view(buffer.data(), buffer.size()), i, res_data,
565
526
                                        res_offset);
566
526
        }
567
463
    }
568
};
569
570
class FunctionStringRepeat : public IFunction {
571
public:
572
    static constexpr auto name = "repeat";
573
248
    static FunctionPtr create() { return std::make_shared<FunctionStringRepeat>(); }
574
1
    String get_name() const override { return name; }
575
239
    size_t get_number_of_arguments() const override { return 2; }
576
    // should set NULL value of nested data to default,
577
    // as iff it's not inited and invalid, the repeat result of length is so large cause overflow
578
235
    bool need_replace_null_data_to_default() const override { return true; }
579
580
239
    DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
581
239
        return make_nullable(std::make_shared<DataTypeString>());
582
239
    }
583
    Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
584
270
                        uint32_t result, size_t input_rows_count) const override {
585
270
        DCHECK_EQ(arguments.size(), 2);
586
270
        auto res = ColumnString::create();
587
270
        auto null_map = ColumnUInt8::create();
588
589
270
        ColumnPtr argument_ptr[2];
590
270
        argument_ptr[0] =
591
270
                block.get_by_position(arguments[0]).column->convert_to_full_column_if_const();
592
270
        argument_ptr[1] = block.get_by_position(arguments[1]).column;
593
594
270
        if (const auto* col1 = check_and_get_column<ColumnString>(*argument_ptr[0])) {
595
270
            if (const auto* col2 = check_and_get_column<ColumnInt32>(*argument_ptr[1])) {
596
152
                RETURN_IF_ERROR(vector_vector(col1->get_chars(), col1->get_offsets(),
597
152
                                              col2->get_data(), res->get_chars(),
598
152
                                              res->get_offsets(), null_map->get_data()));
599
152
                block.replace_by_position(
600
152
                        result, ColumnNullable::create(std::move(res), std::move(null_map)));
601
152
                return Status::OK();
602
152
            } else if (const auto* col2_const =
603
118
                               check_and_get_column<ColumnConst>(*argument_ptr[1])) {
604
118
                DCHECK(check_and_get_column<ColumnInt32>(col2_const->get_data_column()));
605
118
                int repeat = col2_const->get_int(0);
606
118
                if (repeat <= 0) {
607
18
                    null_map->get_data().resize_fill(input_rows_count, 0);
608
18
                    res->insert_many_defaults(input_rows_count);
609
100
                } else {
610
100
                    vector_const(col1->get_chars(), col1->get_offsets(), repeat, res->get_chars(),
611
100
                                 res->get_offsets(), null_map->get_data());
612
100
                }
613
118
                block.replace_by_position(
614
118
                        result, ColumnNullable::create(std::move(res), std::move(null_map)));
615
118
                return Status::OK();
616
118
            }
617
270
        }
618
619
0
        return Status::RuntimeError("repeat function get error param: {}, {}",
620
0
                                    argument_ptr[0]->get_name(), argument_ptr[1]->get_name());
621
270
    }
622
623
    Status vector_vector(const ColumnString::Chars& data, const ColumnString::Offsets& offsets,
624
                         const ColumnInt32::Container& repeats, ColumnString::Chars& res_data,
625
                         ColumnString::Offsets& res_offsets,
626
152
                         ColumnUInt8::Container& null_map) const {
627
152
        size_t input_row_size = offsets.size();
628
629
152
        fmt::memory_buffer buffer;
630
152
        res_offsets.resize(input_row_size);
631
152
        null_map.resize_fill(input_row_size, 0);
632
397
        for (ssize_t i = 0; i < input_row_size; ++i) {
633
245
            buffer.clear();
634
245
            const char* raw_str = reinterpret_cast<const char*>(&data[offsets[i - 1]]);
635
245
            size_t size = offsets[i] - offsets[i - 1];
636
245
            int repeat = repeats[i];
637
245
            if (repeat <= 0) {
638
66
                StringOP::push_empty_string(i, res_data, res_offsets);
639
179
            } else {
640
179
                ColumnString::check_chars_length(repeat * size + res_data.size(), 0);
641
2.23M
                for (int j = 0; j < repeat; ++j) {
642
2.23M
                    buffer.append(raw_str, raw_str + size);
643
2.23M
                }
644
179
                StringOP::push_value_string(std::string_view(buffer.data(), buffer.size()), i,
645
179
                                            res_data, res_offsets);
646
179
            }
647
245
        }
648
152
        return Status::OK();
649
152
    }
650
651
    // TODO: 1. use pmr::vector<char> replace fmt_buffer may speed up the code
652
    //       2. abstract the `vector_vector` and `vector_const`
653
    //       3. rethink we should use `DEFAULT_MAX_STRING_SIZE` to bigger here
654
    void vector_const(const ColumnString::Chars& data, const ColumnString::Offsets& offsets,
655
                      int repeat, ColumnString::Chars& res_data, ColumnString::Offsets& res_offsets,
656
100
                      ColumnUInt8::Container& null_map) const {
657
100
        size_t input_row_size = offsets.size();
658
659
100
        fmt::memory_buffer buffer;
660
100
        res_offsets.resize(input_row_size);
661
100
        null_map.resize_fill(input_row_size, 0);
662
4.28k
        for (ssize_t i = 0; i < input_row_size; ++i) {
663
4.18k
            buffer.clear();
664
4.18k
            const char* raw_str = reinterpret_cast<const char*>(&data[offsets[i - 1]]);
665
4.18k
            size_t size = offsets[i] - offsets[i - 1];
666
4.18k
            ColumnString::check_chars_length(repeat * size + res_data.size(), 0);
667
668
44.5k
            for (int j = 0; j < repeat; ++j) {
669
40.3k
                buffer.append(raw_str, raw_str + size);
670
40.3k
            }
671
4.18k
            StringOP::push_value_string(std::string_view(buffer.data(), buffer.size()), i, res_data,
672
4.18k
                                        res_offsets);
673
4.18k
        }
674
100
    }
675
};
676
677
/// PaddingChars pre-processes the pad string for efficient padding.
678
/// When is_utf8=false, character count equals byte count — no UTF-8 decoding needed.
679
/// When is_utf8=true, we build a byte-offset table for code points.
680
/// In both cases, the pad string is pre-expanded (doubled) until it has >= 16 characters,
681
/// so that each memcpy in append_to copies at least 16 bytes at a time.
682
template <bool is_utf8>
683
struct PaddingChars {
684
    std::string pad_string;
685
    /// utf8_byte_offsets[i] = byte offset of i-th code point in pad_string.
686
    /// utf8_byte_offsets has (num_chars + 1) entries, with [0]=0 and [num_chars]=pad_string.size().
687
    std::vector<size_t> utf8_byte_offsets;
688
689
    explicit PaddingChars(const uint8_t* data, size_t len)
690
1.05k
            : pad_string(reinterpret_cast<const char*>(data), len) {
691
1.05k
        init();
692
1.05k
    }
_ZN5doris12PaddingCharsILb0EEC2EPKhm
Line
Count
Source
690
61
            : pad_string(reinterpret_cast<const char*>(data), len) {
691
61
        init();
692
61
    }
_ZN5doris12PaddingCharsILb1EEC2EPKhm
Line
Count
Source
690
998
            : pad_string(reinterpret_cast<const char*>(data), len) {
691
998
        init();
692
998
    }
693
694
44.8k
    size_t num_chars() const {
695
44.8k
        if constexpr (is_utf8) {
696
3.68k
            return utf8_byte_offsets.size() - 1;
697
41.1k
        } else {
698
41.1k
            return pad_string.size();
699
41.1k
        }
700
44.8k
    }
_ZNK5doris12PaddingCharsILb0EE9num_charsEv
Line
Count
Source
694
41.1k
    size_t num_chars() const {
695
        if constexpr (is_utf8) {
696
            return utf8_byte_offsets.size() - 1;
697
41.1k
        } else {
698
41.1k
            return pad_string.size();
699
41.1k
        }
700
41.1k
    }
_ZNK5doris12PaddingCharsILb1EE9num_charsEv
Line
Count
Source
694
3.68k
    size_t num_chars() const {
695
3.68k
        if constexpr (is_utf8) {
696
3.68k
            return utf8_byte_offsets.size() - 1;
697
        } else {
698
            return pad_string.size();
699
        }
700
3.68k
    }
701
702
20.8k
    size_t chars_to_bytes(size_t n) const {
703
20.8k
        if constexpr (is_utf8) {
704
334
            return utf8_byte_offsets[n];
705
20.5k
        } else {
706
20.5k
            return n;
707
20.5k
        }
708
20.8k
    }
_ZNK5doris12PaddingCharsILb0EE14chars_to_bytesEm
Line
Count
Source
702
20.5k
    size_t chars_to_bytes(size_t n) const {
703
        if constexpr (is_utf8) {
704
            return utf8_byte_offsets[n];
705
20.5k
        } else {
706
20.5k
            return n;
707
20.5k
        }
708
20.5k
    }
_ZNK5doris12PaddingCharsILb1EE14chars_to_bytesEm
Line
Count
Source
702
334
    size_t chars_to_bytes(size_t n) const {
703
334
        if constexpr (is_utf8) {
704
334
            return utf8_byte_offsets[n];
705
        } else {
706
            return n;
707
        }
708
334
    }
709
710
    /// Append `num_chars_to_pad` padding characters to dst, return bytes written.
711
10.4k
    size_t append_to(uint8_t* dst, size_t num_chars_to_pad) const {
712
10.4k
        if (num_chars_to_pad == 0) {
713
0
            return 0;
714
0
        }
715
10.4k
        const auto* src = reinterpret_cast<const uint8_t*>(pad_string.data());
716
10.4k
        const size_t step = num_chars();
717
10.4k
        uint8_t* dst_start = dst;
718
10.4k
        while (num_chars_to_pad > step) {
719
0
            size_t bytes = chars_to_bytes(step);
720
0
            memcpy(dst, src, bytes);
721
0
            dst += bytes;
722
0
            num_chars_to_pad -= step;
723
0
        }
724
10.4k
        size_t bytes = chars_to_bytes(num_chars_to_pad);
725
10.4k
        memcpy(dst, src, bytes);
726
10.4k
        dst += bytes;
727
10.4k
        return dst - dst_start;
728
10.4k
    }
_ZNK5doris12PaddingCharsILb0EE9append_toEPhm
Line
Count
Source
711
10.2k
    size_t append_to(uint8_t* dst, size_t num_chars_to_pad) const {
712
10.2k
        if (num_chars_to_pad == 0) {
713
0
            return 0;
714
0
        }
715
10.2k
        const auto* src = reinterpret_cast<const uint8_t*>(pad_string.data());
716
10.2k
        const size_t step = num_chars();
717
10.2k
        uint8_t* dst_start = dst;
718
10.2k
        while (num_chars_to_pad > step) {
719
0
            size_t bytes = chars_to_bytes(step);
720
0
            memcpy(dst, src, bytes);
721
0
            dst += bytes;
722
0
            num_chars_to_pad -= step;
723
0
        }
724
10.2k
        size_t bytes = chars_to_bytes(num_chars_to_pad);
725
10.2k
        memcpy(dst, src, bytes);
726
10.2k
        dst += bytes;
727
10.2k
        return dst - dst_start;
728
10.2k
    }
_ZNK5doris12PaddingCharsILb1EE9append_toEPhm
Line
Count
Source
711
167
    size_t append_to(uint8_t* dst, size_t num_chars_to_pad) const {
712
167
        if (num_chars_to_pad == 0) {
713
0
            return 0;
714
0
        }
715
167
        const auto* src = reinterpret_cast<const uint8_t*>(pad_string.data());
716
167
        const size_t step = num_chars();
717
167
        uint8_t* dst_start = dst;
718
167
        while (num_chars_to_pad > step) {
719
0
            size_t bytes = chars_to_bytes(step);
720
0
            memcpy(dst, src, bytes);
721
0
            dst += bytes;
722
0
            num_chars_to_pad -= step;
723
0
        }
724
167
        size_t bytes = chars_to_bytes(num_chars_to_pad);
725
167
        memcpy(dst, src, bytes);
726
167
        dst += bytes;
727
167
        return dst - dst_start;
728
167
    }
729
730
private:
731
1.05k
    void init() {
732
1.05k
        if (pad_string.empty()) {
733
0
            return;
734
0
        }
735
736
1.05k
        if constexpr (is_utf8) {
737
            // Build byte-offset table for each code point.
738
998
            size_t offset = 0;
739
998
            utf8_byte_offsets.reserve(pad_string.size() + 1);
740
8.04k
            while (offset < pad_string.size()) {
741
7.04k
                utf8_byte_offsets.push_back(offset);
742
7.04k
                offset += get_utf8_byte_length(static_cast<uint8_t>(pad_string[offset]));
743
7.04k
                offset = std::min(offset, pad_string.size());
744
7.04k
            }
745
998
            utf8_byte_offsets.push_back(pad_string.size());
746
998
        }
747
748
        // Pre-expand pad_string until it has >= 16 characters.
749
        // This ensures append_to() copies at least 16 bytes per iteration.
750
3.14k
        while (num_chars() < 16) {
751
2.08k
            if constexpr (is_utf8) {
752
1.99k
                size_t old_count = utf8_byte_offsets.size();
753
1.99k
                size_t base = utf8_byte_offsets.back();
754
16.6k
                for (size_t i = 1; i < old_count; ++i) {
755
14.6k
                    utf8_byte_offsets.push_back(utf8_byte_offsets[i] + base);
756
14.6k
                }
757
1.99k
            }
758
2.08k
            pad_string += pad_string;
759
2.08k
        }
760
1.05k
    }
_ZN5doris12PaddingCharsILb0EE4initEv
Line
Count
Source
731
61
    void init() {
732
61
        if (pad_string.empty()) {
733
0
            return;
734
0
        }
735
736
        if constexpr (is_utf8) {
737
            // Build byte-offset table for each code point.
738
            size_t offset = 0;
739
            utf8_byte_offsets.reserve(pad_string.size() + 1);
740
            while (offset < pad_string.size()) {
741
                utf8_byte_offsets.push_back(offset);
742
                offset += get_utf8_byte_length(static_cast<uint8_t>(pad_string[offset]));
743
                offset = std::min(offset, pad_string.size());
744
            }
745
            utf8_byte_offsets.push_back(pad_string.size());
746
        }
747
748
        // Pre-expand pad_string until it has >= 16 characters.
749
        // This ensures append_to() copies at least 16 bytes per iteration.
750
158
        while (num_chars() < 16) {
751
            if constexpr (is_utf8) {
752
                size_t old_count = utf8_byte_offsets.size();
753
                size_t base = utf8_byte_offsets.back();
754
                for (size_t i = 1; i < old_count; ++i) {
755
                    utf8_byte_offsets.push_back(utf8_byte_offsets[i] + base);
756
                }
757
            }
758
97
            pad_string += pad_string;
759
97
        }
760
61
    }
_ZN5doris12PaddingCharsILb1EE4initEv
Line
Count
Source
731
998
    void init() {
732
998
        if (pad_string.empty()) {
733
0
            return;
734
0
        }
735
736
998
        if constexpr (is_utf8) {
737
            // Build byte-offset table for each code point.
738
998
            size_t offset = 0;
739
998
            utf8_byte_offsets.reserve(pad_string.size() + 1);
740
8.04k
            while (offset < pad_string.size()) {
741
7.04k
                utf8_byte_offsets.push_back(offset);
742
7.04k
                offset += get_utf8_byte_length(static_cast<uint8_t>(pad_string[offset]));
743
7.04k
                offset = std::min(offset, pad_string.size());
744
7.04k
            }
745
998
            utf8_byte_offsets.push_back(pad_string.size());
746
998
        }
747
748
        // Pre-expand pad_string until it has >= 16 characters.
749
        // This ensures append_to() copies at least 16 bytes per iteration.
750
2.98k
        while (num_chars() < 16) {
751
1.99k
            if constexpr (is_utf8) {
752
1.99k
                size_t old_count = utf8_byte_offsets.size();
753
1.99k
                size_t base = utf8_byte_offsets.back();
754
16.6k
                for (size_t i = 1; i < old_count; ++i) {
755
14.6k
                    utf8_byte_offsets.push_back(utf8_byte_offsets[i] + base);
756
14.6k
                }
757
1.99k
            }
758
1.99k
            pad_string += pad_string;
759
1.99k
        }
760
998
    }
761
};
762
763
template <typename Impl>
764
class FunctionStringPad : public IFunction {
765
public:
766
    static constexpr auto name = Impl::name;
767
1.62k
    static FunctionPtr create() { return std::make_shared<FunctionStringPad>(); }
_ZN5doris17FunctionStringPadINS_10StringLPadEE6createEv
Line
Count
Source
767
850
    static FunctionPtr create() { return std::make_shared<FunctionStringPad>(); }
_ZN5doris17FunctionStringPadINS_10StringRPadEE6createEv
Line
Count
Source
767
771
    static FunctionPtr create() { return std::make_shared<FunctionStringPad>(); }
768
2
    String get_name() const override { return name; }
_ZNK5doris17FunctionStringPadINS_10StringLPadEE8get_nameB5cxx11Ev
Line
Count
Source
768
1
    String get_name() const override { return name; }
_ZNK5doris17FunctionStringPadINS_10StringRPadEE8get_nameB5cxx11Ev
Line
Count
Source
768
1
    String get_name() const override { return name; }
769
1.60k
    size_t get_number_of_arguments() const override { return 3; }
_ZNK5doris17FunctionStringPadINS_10StringLPadEE23get_number_of_argumentsEv
Line
Count
Source
769
841
    size_t get_number_of_arguments() const override { return 3; }
_ZNK5doris17FunctionStringPadINS_10StringRPadEE23get_number_of_argumentsEv
Line
Count
Source
769
762
    size_t get_number_of_arguments() const override { return 3; }
770
771
1.60k
    DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
772
1.60k
        return make_nullable(std::make_shared<DataTypeString>());
773
1.60k
    }
_ZNK5doris17FunctionStringPadINS_10StringLPadEE20get_return_type_implERKSt6vectorISt10shared_ptrIKNS_9IDataTypeEESaIS7_EE
Line
Count
Source
771
841
    DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
772
841
        return make_nullable(std::make_shared<DataTypeString>());
773
841
    }
_ZNK5doris17FunctionStringPadINS_10StringRPadEE20get_return_type_implERKSt6vectorISt10shared_ptrIKNS_9IDataTypeEESaIS7_EE
Line
Count
Source
771
762
    DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
772
762
        return make_nullable(std::make_shared<DataTypeString>());
773
762
    }
774
775
    Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
776
1.12k
                        uint32_t result, size_t input_rows_count) const override {
777
1.12k
        DCHECK_GE(arguments.size(), 3);
778
1.12k
        auto null_map = ColumnUInt8::create(input_rows_count, 0);
779
1.12k
        auto res = ColumnString::create();
780
781
1.12k
        ColumnPtr col[3];
782
1.12k
        bool col_const[3];
783
4.49k
        for (size_t i = 0; i < 3; ++i) {
784
3.37k
            std::tie(col[i], col_const[i]) =
785
3.37k
                    unpack_if_const(block.get_by_position(arguments[i]).column);
786
3.37k
        }
787
1.12k
        auto& null_map_data = null_map->get_data();
788
1.12k
        auto& res_offsets = res->get_offsets();
789
1.12k
        auto& res_chars = res->get_chars();
790
1.12k
        res_offsets.resize(input_rows_count);
791
792
1.12k
        const auto* strcol = assert_cast<const ColumnString*>(col[0].get());
793
1.12k
        const auto* col_len = assert_cast<const ColumnInt32*>(col[1].get());
794
1.12k
        const auto& col_len_data = col_len->get_data();
795
796
1.12k
        const auto* padcol = assert_cast<const ColumnString*>(col[2].get());
797
798
1.12k
        if (col_const[1] && col_const[2]) {
799
138
            auto pad = padcol->get_data_at(0);
800
138
            const bool pad_all_ascii =
801
138
                    simd::VStringFunctions::is_ascii({pad.data, static_cast<size_t>(pad.size)});
802
138
            const bool all_ascii = pad_all_ascii && strcol->is_ascii();
803
138
            std::visit(
804
138
                    [&](auto str_const) {
805
138
                        if (all_ascii) {
806
83
                            execute_const_len_const_pad<true, str_const>(
807
83
                                    *strcol, col_len_data, *padcol, res_offsets, res_chars,
808
83
                                    null_map_data, input_rows_count);
809
83
                        } else {
810
55
                            execute_const_len_const_pad<false, str_const>(
811
55
                                    *strcol, col_len_data, *padcol, res_offsets, res_chars,
812
55
                                    null_map_data, input_rows_count);
813
55
                        }
814
138
                    },
_ZZNK5doris17FunctionStringPadINS_10StringLPadEE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjmENKUlT_E_clISt17integral_constantIbLb0EEEEDaSC_
Line
Count
Source
804
73
                    [&](auto str_const) {
805
73
                        if (all_ascii) {
806
46
                            execute_const_len_const_pad<true, str_const>(
807
46
                                    *strcol, col_len_data, *padcol, res_offsets, res_chars,
808
46
                                    null_map_data, input_rows_count);
809
46
                        } else {
810
27
                            execute_const_len_const_pad<false, str_const>(
811
27
                                    *strcol, col_len_data, *padcol, res_offsets, res_chars,
812
27
                                    null_map_data, input_rows_count);
813
27
                        }
814
73
                    },
Unexecuted instantiation: _ZZNK5doris17FunctionStringPadINS_10StringLPadEE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjmENKUlT_E_clISt17integral_constantIbLb1EEEEDaSC_
_ZZNK5doris17FunctionStringPadINS_10StringRPadEE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjmENKUlT_E_clISt17integral_constantIbLb0EEEEDaSC_
Line
Count
Source
804
65
                    [&](auto str_const) {
805
65
                        if (all_ascii) {
806
37
                            execute_const_len_const_pad<true, str_const>(
807
37
                                    *strcol, col_len_data, *padcol, res_offsets, res_chars,
808
37
                                    null_map_data, input_rows_count);
809
37
                        } else {
810
28
                            execute_const_len_const_pad<false, str_const>(
811
28
                                    *strcol, col_len_data, *padcol, res_offsets, res_chars,
812
28
                                    null_map_data, input_rows_count);
813
28
                        }
814
65
                    },
Unexecuted instantiation: _ZZNK5doris17FunctionStringPadINS_10StringRPadEE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjmENKUlT_E_clISt17integral_constantIbLb1EEEEDaSC_
815
138
                    make_bool_variant(col_const[0]));
816
986
        } else {
817
986
            std::visit(
818
987
                    [&](auto str_const) {
819
987
                        execute_general<str_const>(*strcol, col_len_data, col_const[1], *padcol,
820
987
                                                   col_const[2], res_offsets, res_chars,
821
987
                                                   null_map_data, input_rows_count);
822
987
                    },
_ZZNK5doris17FunctionStringPadINS_10StringLPadEE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjmENKUlT_E0_clISt17integral_constantIbLb0EEEEDaSC_
Line
Count
Source
818
340
                    [&](auto str_const) {
819
340
                        execute_general<str_const>(*strcol, col_len_data, col_const[1], *padcol,
820
340
                                                   col_const[2], res_offsets, res_chars,
821
340
                                                   null_map_data, input_rows_count);
822
340
                    },
_ZZNK5doris17FunctionStringPadINS_10StringLPadEE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjmENKUlT_E0_clISt17integral_constantIbLb1EEEEDaSC_
Line
Count
Source
818
186
                    [&](auto str_const) {
819
186
                        execute_general<str_const>(*strcol, col_len_data, col_const[1], *padcol,
820
186
                                                   col_const[2], res_offsets, res_chars,
821
186
                                                   null_map_data, input_rows_count);
822
186
                    },
_ZZNK5doris17FunctionStringPadINS_10StringRPadEE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjmENKUlT_E0_clISt17integral_constantIbLb0EEEEDaSC_
Line
Count
Source
818
275
                    [&](auto str_const) {
819
275
                        execute_general<str_const>(*strcol, col_len_data, col_const[1], *padcol,
820
275
                                                   col_const[2], res_offsets, res_chars,
821
275
                                                   null_map_data, input_rows_count);
822
275
                    },
_ZZNK5doris17FunctionStringPadINS_10StringRPadEE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjmENKUlT_E0_clISt17integral_constantIbLb1EEEEDaSC_
Line
Count
Source
818
186
                    [&](auto str_const) {
819
186
                        execute_general<str_const>(*strcol, col_len_data, col_const[1], *padcol,
820
186
                                                   col_const[2], res_offsets, res_chars,
821
186
                                                   null_map_data, input_rows_count);
822
186
                    },
823
986
                    make_bool_variant(col_const[0]));
824
986
        }
825
826
1.12k
        block.get_by_position(result).column =
827
1.12k
                ColumnNullable::create(std::move(res), std::move(null_map));
828
1.12k
        return Status::OK();
829
1.12k
    }
_ZNK5doris17FunctionStringPadINS_10StringLPadEE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjm
Line
Count
Source
776
599
                        uint32_t result, size_t input_rows_count) const override {
777
599
        DCHECK_GE(arguments.size(), 3);
778
599
        auto null_map = ColumnUInt8::create(input_rows_count, 0);
779
599
        auto res = ColumnString::create();
780
781
599
        ColumnPtr col[3];
782
599
        bool col_const[3];
783
2.39k
        for (size_t i = 0; i < 3; ++i) {
784
1.79k
            std::tie(col[i], col_const[i]) =
785
1.79k
                    unpack_if_const(block.get_by_position(arguments[i]).column);
786
1.79k
        }
787
599
        auto& null_map_data = null_map->get_data();
788
599
        auto& res_offsets = res->get_offsets();
789
599
        auto& res_chars = res->get_chars();
790
599
        res_offsets.resize(input_rows_count);
791
792
599
        const auto* strcol = assert_cast<const ColumnString*>(col[0].get());
793
599
        const auto* col_len = assert_cast<const ColumnInt32*>(col[1].get());
794
599
        const auto& col_len_data = col_len->get_data();
795
796
599
        const auto* padcol = assert_cast<const ColumnString*>(col[2].get());
797
798
599
        if (col_const[1] && col_const[2]) {
799
73
            auto pad = padcol->get_data_at(0);
800
73
            const bool pad_all_ascii =
801
73
                    simd::VStringFunctions::is_ascii({pad.data, static_cast<size_t>(pad.size)});
802
73
            const bool all_ascii = pad_all_ascii && strcol->is_ascii();
803
73
            std::visit(
804
73
                    [&](auto str_const) {
805
73
                        if (all_ascii) {
806
73
                            execute_const_len_const_pad<true, str_const>(
807
73
                                    *strcol, col_len_data, *padcol, res_offsets, res_chars,
808
73
                                    null_map_data, input_rows_count);
809
73
                        } else {
810
73
                            execute_const_len_const_pad<false, str_const>(
811
73
                                    *strcol, col_len_data, *padcol, res_offsets, res_chars,
812
73
                                    null_map_data, input_rows_count);
813
73
                        }
814
73
                    },
815
73
                    make_bool_variant(col_const[0]));
816
526
        } else {
817
526
            std::visit(
818
526
                    [&](auto str_const) {
819
526
                        execute_general<str_const>(*strcol, col_len_data, col_const[1], *padcol,
820
526
                                                   col_const[2], res_offsets, res_chars,
821
526
                                                   null_map_data, input_rows_count);
822
526
                    },
823
526
                    make_bool_variant(col_const[0]));
824
526
        }
825
826
599
        block.get_by_position(result).column =
827
599
                ColumnNullable::create(std::move(res), std::move(null_map));
828
599
        return Status::OK();
829
599
    }
_ZNK5doris17FunctionStringPadINS_10StringRPadEE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjm
Line
Count
Source
776
525
                        uint32_t result, size_t input_rows_count) const override {
777
525
        DCHECK_GE(arguments.size(), 3);
778
525
        auto null_map = ColumnUInt8::create(input_rows_count, 0);
779
525
        auto res = ColumnString::create();
780
781
525
        ColumnPtr col[3];
782
525
        bool col_const[3];
783
2.10k
        for (size_t i = 0; i < 3; ++i) {
784
1.57k
            std::tie(col[i], col_const[i]) =
785
1.57k
                    unpack_if_const(block.get_by_position(arguments[i]).column);
786
1.57k
        }
787
525
        auto& null_map_data = null_map->get_data();
788
525
        auto& res_offsets = res->get_offsets();
789
525
        auto& res_chars = res->get_chars();
790
525
        res_offsets.resize(input_rows_count);
791
792
525
        const auto* strcol = assert_cast<const ColumnString*>(col[0].get());
793
525
        const auto* col_len = assert_cast<const ColumnInt32*>(col[1].get());
794
525
        const auto& col_len_data = col_len->get_data();
795
796
525
        const auto* padcol = assert_cast<const ColumnString*>(col[2].get());
797
798
525
        if (col_const[1] && col_const[2]) {
799
65
            auto pad = padcol->get_data_at(0);
800
65
            const bool pad_all_ascii =
801
65
                    simd::VStringFunctions::is_ascii({pad.data, static_cast<size_t>(pad.size)});
802
65
            const bool all_ascii = pad_all_ascii && strcol->is_ascii();
803
65
            std::visit(
804
65
                    [&](auto str_const) {
805
65
                        if (all_ascii) {
806
65
                            execute_const_len_const_pad<true, str_const>(
807
65
                                    *strcol, col_len_data, *padcol, res_offsets, res_chars,
808
65
                                    null_map_data, input_rows_count);
809
65
                        } else {
810
65
                            execute_const_len_const_pad<false, str_const>(
811
65
                                    *strcol, col_len_data, *padcol, res_offsets, res_chars,
812
65
                                    null_map_data, input_rows_count);
813
65
                        }
814
65
                    },
815
65
                    make_bool_variant(col_const[0]));
816
460
        } else {
817
460
            std::visit(
818
460
                    [&](auto str_const) {
819
460
                        execute_general<str_const>(*strcol, col_len_data, col_const[1], *padcol,
820
460
                                                   col_const[2], res_offsets, res_chars,
821
460
                                                   null_map_data, input_rows_count);
822
460
                    },
823
460
                    make_bool_variant(col_const[0]));
824
460
        }
825
826
525
        block.get_by_position(result).column =
827
525
                ColumnNullable::create(std::move(res), std::move(null_map));
828
525
        return Status::OK();
829
525
    }
830
831
private:
832
    template <bool is_utf8>
833
11.0k
    static size_t get_char_length(const uint8_t* str_data, size_t str_byte_len) {
834
11.0k
        if constexpr (is_utf8) {
835
771
            return simd::VStringFunctions::get_char_len(reinterpret_cast<const char*>(str_data),
836
771
                                                        str_byte_len);
837
771
        }
838
0
        return str_byte_len;
839
11.0k
    }
_ZN5doris17FunctionStringPadINS_10StringLPadEE15get_char_lengthILb0EEEmPKhm
Line
Count
Source
833
8.22k
    static size_t get_char_length(const uint8_t* str_data, size_t str_byte_len) {
834
        if constexpr (is_utf8) {
835
            return simd::VStringFunctions::get_char_len(reinterpret_cast<const char*>(str_data),
836
                                                        str_byte_len);
837
        }
838
8.22k
        return str_byte_len;
839
8.22k
    }
_ZN5doris17FunctionStringPadINS_10StringLPadEE15get_char_lengthILb1EEEmPKhm
Line
Count
Source
833
415
    static size_t get_char_length(const uint8_t* str_data, size_t str_byte_len) {
834
415
        if constexpr (is_utf8) {
835
415
            return simd::VStringFunctions::get_char_len(reinterpret_cast<const char*>(str_data),
836
415
                                                        str_byte_len);
837
415
        }
838
0
        return str_byte_len;
839
415
    }
_ZN5doris17FunctionStringPadINS_10StringRPadEE15get_char_lengthILb0EEEmPKhm
Line
Count
Source
833
2.06k
    static size_t get_char_length(const uint8_t* str_data, size_t str_byte_len) {
834
        if constexpr (is_utf8) {
835
            return simd::VStringFunctions::get_char_len(reinterpret_cast<const char*>(str_data),
836
                                                        str_byte_len);
837
        }
838
2.06k
        return str_byte_len;
839
2.06k
    }
_ZN5doris17FunctionStringPadINS_10StringRPadEE15get_char_lengthILb1EEEmPKhm
Line
Count
Source
833
356
    static size_t get_char_length(const uint8_t* str_data, size_t str_byte_len) {
834
356
        if constexpr (is_utf8) {
835
356
            return simd::VStringFunctions::get_char_len(reinterpret_cast<const char*>(str_data),
836
356
                                                        str_byte_len);
837
356
        }
838
0
        return str_byte_len;
839
356
    }
840
841
    template <bool is_utf8>
842
    static size_t get_truncated_byte_length(const uint8_t* str_data, size_t str_byte_len,
843
615
                                            size_t str_char_len, size_t target_len) {
844
615
        if constexpr (!is_utf8) {
845
32
            return target_len;
846
32
        }
847
615
        if (str_char_len == target_len) {
848
100
            return str_byte_len;
849
100
        }
850
515
        auto [byte_len, _] = simd::VStringFunctions::iterate_utf8_with_limit_length(
851
515
                reinterpret_cast<const char*>(str_data),
852
515
                reinterpret_cast<const char*>(str_data) + str_byte_len, target_len);
853
515
        return byte_len;
854
615
    }
_ZN5doris17FunctionStringPadINS_10StringLPadEE25get_truncated_byte_lengthILb0EEEmPKhmmm
Line
Count
Source
843
16
                                            size_t str_char_len, size_t target_len) {
844
16
        if constexpr (!is_utf8) {
845
16
            return target_len;
846
16
        }
847
16
        if (str_char_len == target_len) {
848
0
            return str_byte_len;
849
0
        }
850
16
        auto [byte_len, _] = simd::VStringFunctions::iterate_utf8_with_limit_length(
851
16
                reinterpret_cast<const char*>(str_data),
852
16
                reinterpret_cast<const char*>(str_data) + str_byte_len, target_len);
853
16
        return byte_len;
854
16
    }
_ZN5doris17FunctionStringPadINS_10StringLPadEE25get_truncated_byte_lengthILb1EEEmPKhmmm
Line
Count
Source
843
306
                                            size_t str_char_len, size_t target_len) {
844
        if constexpr (!is_utf8) {
845
            return target_len;
846
        }
847
306
        if (str_char_len == target_len) {
848
55
            return str_byte_len;
849
55
        }
850
251
        auto [byte_len, _] = simd::VStringFunctions::iterate_utf8_with_limit_length(
851
251
                reinterpret_cast<const char*>(str_data),
852
251
                reinterpret_cast<const char*>(str_data) + str_byte_len, target_len);
853
251
        return byte_len;
854
306
    }
_ZN5doris17FunctionStringPadINS_10StringRPadEE25get_truncated_byte_lengthILb0EEEmPKhmmm
Line
Count
Source
843
16
                                            size_t str_char_len, size_t target_len) {
844
16
        if constexpr (!is_utf8) {
845
16
            return target_len;
846
16
        }
847
16
        if (str_char_len == target_len) {
848
0
            return str_byte_len;
849
0
        }
850
16
        auto [byte_len, _] = simd::VStringFunctions::iterate_utf8_with_limit_length(
851
16
                reinterpret_cast<const char*>(str_data),
852
16
                reinterpret_cast<const char*>(str_data) + str_byte_len, target_len);
853
16
        return byte_len;
854
16
    }
_ZN5doris17FunctionStringPadINS_10StringRPadEE25get_truncated_byte_lengthILb1EEEmPKhmmm
Line
Count
Source
843
277
                                            size_t str_char_len, size_t target_len) {
844
        if constexpr (!is_utf8) {
845
            return target_len;
846
        }
847
277
        if (str_char_len == target_len) {
848
45
            return str_byte_len;
849
45
        }
850
232
        auto [byte_len, _] = simd::VStringFunctions::iterate_utf8_with_limit_length(
851
232
                reinterpret_cast<const char*>(str_data),
852
232
                reinterpret_cast<const char*>(str_data) + str_byte_len, target_len);
853
232
        return byte_len;
854
277
    }
855
856
11.0k
    static void ensure_capacity(ColumnString::Chars& res_chars, size_t needed, size_t row) {
857
11.0k
        if (needed <= res_chars.size()) {
858
10.9k
            return;
859
10.9k
        }
860
128
        ColumnString::check_chars_length(needed, row);
861
128
        res_chars.resize(std::max(needed, res_chars.size() * 3 / 2));
862
128
    }
_ZN5doris17FunctionStringPadINS_10StringLPadEE15ensure_capacityERNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEEmm
Line
Count
Source
856
8.62k
    static void ensure_capacity(ColumnString::Chars& res_chars, size_t needed, size_t row) {
857
8.62k
        if (needed <= res_chars.size()) {
858
8.54k
            return;
859
8.54k
        }
860
79
        ColumnString::check_chars_length(needed, row);
861
79
        res_chars.resize(std::max(needed, res_chars.size() * 3 / 2));
862
79
    }
_ZN5doris17FunctionStringPadINS_10StringRPadEE15ensure_capacityERNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEEmm
Line
Count
Source
856
2.41k
    static void ensure_capacity(ColumnString::Chars& res_chars, size_t needed, size_t row) {
857
2.41k
        if (needed <= res_chars.size()) {
858
2.36k
            return;
859
2.36k
        }
860
49
        ColumnString::check_chars_length(needed, row);
861
49
        res_chars.resize(std::max(needed, res_chars.size() * 3 / 2));
862
49
    }
863
864
    template <bool is_utf8>
865
    static size_t estimate_const_output_bytes(const ColumnString::Chars& strcol_chars,
866
                                              int target_len, size_t input_rows_count,
867
138
                                              const PaddingChars<is_utf8>* padding) {
868
138
        if (target_len <= 0) {
869
96
            return 0;
870
96
        }
871
42
        if constexpr (!is_utf8) {
872
29
            return static_cast<size_t>(target_len) * input_rows_count;
873
29
        }
874
42
        if (padding != nullptr && padding->num_chars() > 0) {
875
11
            size_t pad_bytes_per_char =
876
11
                    (padding->pad_string.size() + padding->num_chars() - 1) / padding->num_chars();
877
11
            return strcol_chars.size() +
878
11
                   static_cast<size_t>(target_len) * pad_bytes_per_char * input_rows_count;
879
11
        }
880
31
        return strcol_chars.size();
881
42
    }
_ZN5doris17FunctionStringPadINS_10StringLPadEE27estimate_const_output_bytesILb0EEEmRKNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEEimPKNS_12PaddingCharsIXT_EEE
Line
Count
Source
867
46
                                              const PaddingChars<is_utf8>* padding) {
868
46
        if (target_len <= 0) {
869
27
            return 0;
870
27
        }
871
19
        if constexpr (!is_utf8) {
872
19
            return static_cast<size_t>(target_len) * input_rows_count;
873
19
        }
874
19
        if (padding != nullptr && padding->num_chars() > 0) {
875
0
            size_t pad_bytes_per_char =
876
0
                    (padding->pad_string.size() + padding->num_chars() - 1) / padding->num_chars();
877
0
            return strcol_chars.size() +
878
0
                   static_cast<size_t>(target_len) * pad_bytes_per_char * input_rows_count;
879
0
        }
880
19
        return strcol_chars.size();
881
19
    }
_ZN5doris17FunctionStringPadINS_10StringLPadEE27estimate_const_output_bytesILb1EEEmRKNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEEimPKNS_12PaddingCharsIXT_EEE
Line
Count
Source
867
27
                                              const PaddingChars<is_utf8>* padding) {
868
27
        if (target_len <= 0) {
869
21
            return 0;
870
21
        }
871
        if constexpr (!is_utf8) {
872
            return static_cast<size_t>(target_len) * input_rows_count;
873
        }
874
6
        if (padding != nullptr && padding->num_chars() > 0) {
875
5
            size_t pad_bytes_per_char =
876
5
                    (padding->pad_string.size() + padding->num_chars() - 1) / padding->num_chars();
877
5
            return strcol_chars.size() +
878
5
                   static_cast<size_t>(target_len) * pad_bytes_per_char * input_rows_count;
879
5
        }
880
1
        return strcol_chars.size();
881
6
    }
_ZN5doris17FunctionStringPadINS_10StringRPadEE27estimate_const_output_bytesILb0EEEmRKNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEEimPKNS_12PaddingCharsIXT_EEE
Line
Count
Source
867
37
                                              const PaddingChars<is_utf8>* padding) {
868
37
        if (target_len <= 0) {
869
27
            return 0;
870
27
        }
871
10
        if constexpr (!is_utf8) {
872
10
            return static_cast<size_t>(target_len) * input_rows_count;
873
10
        }
874
10
        if (padding != nullptr && padding->num_chars() > 0) {
875
0
            size_t pad_bytes_per_char =
876
0
                    (padding->pad_string.size() + padding->num_chars() - 1) / padding->num_chars();
877
0
            return strcol_chars.size() +
878
0
                   static_cast<size_t>(target_len) * pad_bytes_per_char * input_rows_count;
879
0
        }
880
10
        return strcol_chars.size();
881
10
    }
_ZN5doris17FunctionStringPadINS_10StringRPadEE27estimate_const_output_bytesILb1EEEmRKNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEEimPKNS_12PaddingCharsIXT_EEE
Line
Count
Source
867
28
                                              const PaddingChars<is_utf8>* padding) {
868
28
        if (target_len <= 0) {
869
21
            return 0;
870
21
        }
871
        if constexpr (!is_utf8) {
872
            return static_cast<size_t>(target_len) * input_rows_count;
873
        }
874
7
        if (padding != nullptr && padding->num_chars() > 0) {
875
6
            size_t pad_bytes_per_char =
876
6
                    (padding->pad_string.size() + padding->num_chars() - 1) / padding->num_chars();
877
6
            return strcol_chars.size() +
878
6
                   static_cast<size_t>(target_len) * pad_bytes_per_char * input_rows_count;
879
6
        }
880
1
        return strcol_chars.size();
881
7
    }
882
883
    template <bool is_utf8>
884
    static void append_result_row(const uint8_t* str_data, size_t str_byte_len, int target_len,
885
                                  const PaddingChars<is_utf8>* padding,
886
                                  ColumnString::Chars& res_chars,
887
                                  ColumnString::Offsets& res_offsets,
888
                                  ColumnUInt8::Container& null_map_data, size_t row,
889
11.6k
                                  size_t& dst_offset) {
890
11.6k
        if (target_len < 0) {
891
568
            null_map_data[row] = true;
892
568
            res_offsets[row] = dst_offset;
893
568
            return;
894
568
        }
895
896
11.0k
        const size_t str_char_len = get_char_length<is_utf8>(str_data, str_byte_len);
897
11.0k
        const size_t target_char_len = static_cast<size_t>(target_len);
898
11.0k
        if (str_char_len >= target_char_len) {
899
615
            const size_t truncated_byte_len = get_truncated_byte_length<is_utf8>(
900
615
                    str_data, str_byte_len, str_char_len, target_char_len);
901
615
            const size_t needed = dst_offset + truncated_byte_len;
902
615
            ensure_capacity(res_chars, needed, row);
903
615
            memcpy(res_chars.data() + dst_offset, str_data, truncated_byte_len);
904
615
            dst_offset += truncated_byte_len;
905
615
            res_offsets[row] = dst_offset;
906
615
            return;
907
615
        }
908
909
10.4k
        if (padding == nullptr || padding->num_chars() == 0) {
910
21
            res_offsets[row] = dst_offset;
911
21
            return;
912
21
        }
913
914
10.4k
        const size_t pad_char_count = target_char_len - str_char_len;
915
10.4k
        const size_t full_cycles = pad_char_count / padding->num_chars();
916
10.4k
        const size_t remainder_chars = pad_char_count % padding->num_chars();
917
10.4k
        const size_t pad_bytes =
918
10.4k
                full_cycles * padding->pad_string.size() + padding->chars_to_bytes(remainder_chars);
919
10.4k
        const size_t needed = dst_offset + str_byte_len + pad_bytes;
920
10.4k
        ensure_capacity(res_chars, needed, row);
921
922
10.4k
        if constexpr (Impl::is_lpad) {
923
8.30k
            dst_offset += padding->append_to(res_chars.data() + dst_offset, pad_char_count);
924
8.30k
            memcpy(res_chars.data() + dst_offset, str_data, str_byte_len);
925
8.30k
            dst_offset += str_byte_len;
926
8.30k
        } else {
927
2.11k
            memcpy(res_chars.data() + dst_offset, str_data, str_byte_len);
928
2.11k
            dst_offset += str_byte_len;
929
2.11k
            dst_offset += padding->append_to(res_chars.data() + dst_offset, pad_char_count);
930
2.11k
        }
931
10.4k
        res_offsets[row] = dst_offset;
932
10.4k
    }
_ZN5doris17FunctionStringPadINS_10StringLPadEE17append_result_rowILb0EEEvPKhmiPKNS_12PaddingCharsIXT_EEERNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEERNSA_IjLm4096ESD_Lm16ELm15EEESF_mRm
Line
Count
Source
889
8.23k
                                  size_t& dst_offset) {
890
8.23k
        if (target_len < 0) {
891
18
            null_map_data[row] = true;
892
18
            res_offsets[row] = dst_offset;
893
18
            return;
894
18
        }
895
896
8.22k
        const size_t str_char_len = get_char_length<is_utf8>(str_data, str_byte_len);
897
8.22k
        const size_t target_char_len = static_cast<size_t>(target_len);
898
8.22k
        if (str_char_len >= target_char_len) {
899
16
            const size_t truncated_byte_len = get_truncated_byte_length<is_utf8>(
900
16
                    str_data, str_byte_len, str_char_len, target_char_len);
901
16
            const size_t needed = dst_offset + truncated_byte_len;
902
16
            ensure_capacity(res_chars, needed, row);
903
16
            memcpy(res_chars.data() + dst_offset, str_data, truncated_byte_len);
904
16
            dst_offset += truncated_byte_len;
905
16
            res_offsets[row] = dst_offset;
906
16
            return;
907
16
        }
908
909
8.20k
        if (padding == nullptr || padding->num_chars() == 0) {
910
0
            res_offsets[row] = dst_offset;
911
0
            return;
912
0
        }
913
914
8.20k
        const size_t pad_char_count = target_char_len - str_char_len;
915
8.20k
        const size_t full_cycles = pad_char_count / padding->num_chars();
916
8.20k
        const size_t remainder_chars = pad_char_count % padding->num_chars();
917
8.20k
        const size_t pad_bytes =
918
8.20k
                full_cycles * padding->pad_string.size() + padding->chars_to_bytes(remainder_chars);
919
8.20k
        const size_t needed = dst_offset + str_byte_len + pad_bytes;
920
8.20k
        ensure_capacity(res_chars, needed, row);
921
922
8.20k
        if constexpr (Impl::is_lpad) {
923
8.20k
            dst_offset += padding->append_to(res_chars.data() + dst_offset, pad_char_count);
924
8.20k
            memcpy(res_chars.data() + dst_offset, str_data, str_byte_len);
925
8.20k
            dst_offset += str_byte_len;
926
        } else {
927
            memcpy(res_chars.data() + dst_offset, str_data, str_byte_len);
928
            dst_offset += str_byte_len;
929
            dst_offset += padding->append_to(res_chars.data() + dst_offset, pad_char_count);
930
        }
931
8.20k
        res_offsets[row] = dst_offset;
932
8.20k
    }
_ZN5doris17FunctionStringPadINS_10StringLPadEE17append_result_rowILb1EEEvPKhmiPKNS_12PaddingCharsIXT_EEERNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEERNSA_IjLm4096ESD_Lm16ELm15EEESF_mRm
Line
Count
Source
889
684
                                  size_t& dst_offset) {
890
684
        if (target_len < 0) {
891
269
            null_map_data[row] = true;
892
269
            res_offsets[row] = dst_offset;
893
269
            return;
894
269
        }
895
896
415
        const size_t str_char_len = get_char_length<is_utf8>(str_data, str_byte_len);
897
415
        const size_t target_char_len = static_cast<size_t>(target_len);
898
415
        if (str_char_len >= target_char_len) {
899
306
            const size_t truncated_byte_len = get_truncated_byte_length<is_utf8>(
900
306
                    str_data, str_byte_len, str_char_len, target_char_len);
901
306
            const size_t needed = dst_offset + truncated_byte_len;
902
306
            ensure_capacity(res_chars, needed, row);
903
306
            memcpy(res_chars.data() + dst_offset, str_data, truncated_byte_len);
904
306
            dst_offset += truncated_byte_len;
905
306
            res_offsets[row] = dst_offset;
906
306
            return;
907
306
        }
908
909
109
        if (padding == nullptr || padding->num_chars() == 0) {
910
11
            res_offsets[row] = dst_offset;
911
11
            return;
912
11
        }
913
914
98
        const size_t pad_char_count = target_char_len - str_char_len;
915
98
        const size_t full_cycles = pad_char_count / padding->num_chars();
916
98
        const size_t remainder_chars = pad_char_count % padding->num_chars();
917
98
        const size_t pad_bytes =
918
98
                full_cycles * padding->pad_string.size() + padding->chars_to_bytes(remainder_chars);
919
98
        const size_t needed = dst_offset + str_byte_len + pad_bytes;
920
98
        ensure_capacity(res_chars, needed, row);
921
922
98
        if constexpr (Impl::is_lpad) {
923
98
            dst_offset += padding->append_to(res_chars.data() + dst_offset, pad_char_count);
924
98
            memcpy(res_chars.data() + dst_offset, str_data, str_byte_len);
925
98
            dst_offset += str_byte_len;
926
        } else {
927
            memcpy(res_chars.data() + dst_offset, str_data, str_byte_len);
928
            dst_offset += str_byte_len;
929
            dst_offset += padding->append_to(res_chars.data() + dst_offset, pad_char_count);
930
        }
931
98
        res_offsets[row] = dst_offset;
932
98
    }
_ZN5doris17FunctionStringPadINS_10StringRPadEE17append_result_rowILb0EEEvPKhmiPKNS_12PaddingCharsIXT_EEERNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEERNSA_IjLm4096ESD_Lm16ELm15EEESF_mRm
Line
Count
Source
889
2.08k
                                  size_t& dst_offset) {
890
2.08k
        if (target_len < 0) {
891
18
            null_map_data[row] = true;
892
18
            res_offsets[row] = dst_offset;
893
18
            return;
894
18
        }
895
896
2.06k
        const size_t str_char_len = get_char_length<is_utf8>(str_data, str_byte_len);
897
2.06k
        const size_t target_char_len = static_cast<size_t>(target_len);
898
2.06k
        if (str_char_len >= target_char_len) {
899
16
            const size_t truncated_byte_len = get_truncated_byte_length<is_utf8>(
900
16
                    str_data, str_byte_len, str_char_len, target_char_len);
901
16
            const size_t needed = dst_offset + truncated_byte_len;
902
16
            ensure_capacity(res_chars, needed, row);
903
16
            memcpy(res_chars.data() + dst_offset, str_data, truncated_byte_len);
904
16
            dst_offset += truncated_byte_len;
905
16
            res_offsets[row] = dst_offset;
906
16
            return;
907
16
        }
908
909
2.04k
        if (padding == nullptr || padding->num_chars() == 0) {
910
0
            res_offsets[row] = dst_offset;
911
0
            return;
912
0
        }
913
914
2.04k
        const size_t pad_char_count = target_char_len - str_char_len;
915
2.04k
        const size_t full_cycles = pad_char_count / padding->num_chars();
916
2.04k
        const size_t remainder_chars = pad_char_count % padding->num_chars();
917
2.04k
        const size_t pad_bytes =
918
2.04k
                full_cycles * padding->pad_string.size() + padding->chars_to_bytes(remainder_chars);
919
2.04k
        const size_t needed = dst_offset + str_byte_len + pad_bytes;
920
2.04k
        ensure_capacity(res_chars, needed, row);
921
922
        if constexpr (Impl::is_lpad) {
923
            dst_offset += padding->append_to(res_chars.data() + dst_offset, pad_char_count);
924
            memcpy(res_chars.data() + dst_offset, str_data, str_byte_len);
925
            dst_offset += str_byte_len;
926
2.04k
        } else {
927
2.04k
            memcpy(res_chars.data() + dst_offset, str_data, str_byte_len);
928
2.04k
            dst_offset += str_byte_len;
929
2.04k
            dst_offset += padding->append_to(res_chars.data() + dst_offset, pad_char_count);
930
2.04k
        }
931
2.04k
        res_offsets[row] = dst_offset;
932
2.04k
    }
_ZN5doris17FunctionStringPadINS_10StringRPadEE17append_result_rowILb1EEEvPKhmiPKNS_12PaddingCharsIXT_EEERNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEERNSA_IjLm4096ESD_Lm16ELm15EEESF_mRm
Line
Count
Source
889
619
                                  size_t& dst_offset) {
890
619
        if (target_len < 0) {
891
263
            null_map_data[row] = true;
892
263
            res_offsets[row] = dst_offset;
893
263
            return;
894
263
        }
895
896
356
        const size_t str_char_len = get_char_length<is_utf8>(str_data, str_byte_len);
897
356
        const size_t target_char_len = static_cast<size_t>(target_len);
898
356
        if (str_char_len >= target_char_len) {
899
277
            const size_t truncated_byte_len = get_truncated_byte_length<is_utf8>(
900
277
                    str_data, str_byte_len, str_char_len, target_char_len);
901
277
            const size_t needed = dst_offset + truncated_byte_len;
902
277
            ensure_capacity(res_chars, needed, row);
903
277
            memcpy(res_chars.data() + dst_offset, str_data, truncated_byte_len);
904
277
            dst_offset += truncated_byte_len;
905
277
            res_offsets[row] = dst_offset;
906
277
            return;
907
277
        }
908
909
79
        if (padding == nullptr || padding->num_chars() == 0) {
910
10
            res_offsets[row] = dst_offset;
911
10
            return;
912
10
        }
913
914
69
        const size_t pad_char_count = target_char_len - str_char_len;
915
69
        const size_t full_cycles = pad_char_count / padding->num_chars();
916
69
        const size_t remainder_chars = pad_char_count % padding->num_chars();
917
69
        const size_t pad_bytes =
918
69
                full_cycles * padding->pad_string.size() + padding->chars_to_bytes(remainder_chars);
919
69
        const size_t needed = dst_offset + str_byte_len + pad_bytes;
920
69
        ensure_capacity(res_chars, needed, row);
921
922
        if constexpr (Impl::is_lpad) {
923
            dst_offset += padding->append_to(res_chars.data() + dst_offset, pad_char_count);
924
            memcpy(res_chars.data() + dst_offset, str_data, str_byte_len);
925
            dst_offset += str_byte_len;
926
69
        } else {
927
69
            memcpy(res_chars.data() + dst_offset, str_data, str_byte_len);
928
69
            dst_offset += str_byte_len;
929
69
            dst_offset += padding->append_to(res_chars.data() + dst_offset, pad_char_count);
930
69
        }
931
69
        res_offsets[row] = dst_offset;
932
69
    }
933
934
    template <bool all_ascii, bool str_const>
935
    static void execute_const_len_const_pad(const ColumnString& strcol,
936
                                            const ColumnInt32::Container& col_len_data,
937
                                            const ColumnString& padcol,
938
                                            ColumnString::Offsets& res_offsets,
939
                                            ColumnString::Chars& res_chars,
940
                                            ColumnUInt8::Container& null_map_data,
941
138
                                            size_t input_rows_count) {
942
138
        constexpr bool is_utf8 = !all_ascii;
943
138
        using PadChars = PaddingChars<is_utf8>;
944
945
138
        const int target_len = col_len_data[0];
946
138
        std::optional<PadChars> padding;
947
138
        const auto pad = padcol.get_data_at(0);
948
138
        if (!pad.empty()) {
949
108
            padding.emplace(reinterpret_cast<const uint8_t*>(pad.data), pad.size);
950
108
        }
951
952
138
        const PadChars* padding_ptr = padding ? &*padding : nullptr;
953
138
        const size_t estimated_total = estimate_const_output_bytes<is_utf8>(
954
138
                strcol.get_chars(), target_len, input_rows_count, padding_ptr);
955
138
        if (estimated_total > 0) {
956
42
            ColumnString::check_chars_length(estimated_total, 0, input_rows_count);
957
42
        }
958
138
        res_chars.resize(estimated_total);
959
960
138
        size_t dst_offset = 0;
961
10.5k
        for (size_t i = 0; i < input_rows_count; ++i) {
962
10.3k
            auto str = strcol.get_data_at(index_check_const<str_const>(i));
963
10.3k
            append_result_row<is_utf8>(reinterpret_cast<const uint8_t*>(str.data), str.size,
964
10.3k
                                       target_len, padding_ptr, res_chars, res_offsets,
965
10.3k
                                       null_map_data, i, dst_offset);
966
10.3k
        }
967
138
        res_chars.resize(dst_offset);
968
138
    }
_ZN5doris17FunctionStringPadINS_10StringLPadEE27execute_const_len_const_padILb1ELb0EEEvRKNS_9ColumnStrIjEERKNS_8PODArrayIiLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEES7_RNS8_IjLm4096ESB_Lm16ELm15EEERNS8_IhLm4096ESB_Lm16ELm15EEESI_m
Line
Count
Source
941
46
                                            size_t input_rows_count) {
942
46
        constexpr bool is_utf8 = !all_ascii;
943
46
        using PadChars = PaddingChars<is_utf8>;
944
945
46
        const int target_len = col_len_data[0];
946
46
        std::optional<PadChars> padding;
947
46
        const auto pad = padcol.get_data_at(0);
948
46
        if (!pad.empty()) {
949
35
            padding.emplace(reinterpret_cast<const uint8_t*>(pad.data), pad.size);
950
35
        }
951
952
46
        const PadChars* padding_ptr = padding ? &*padding : nullptr;
953
46
        const size_t estimated_total = estimate_const_output_bytes<is_utf8>(
954
46
                strcol.get_chars(), target_len, input_rows_count, padding_ptr);
955
46
        if (estimated_total > 0) {
956
19
            ColumnString::check_chars_length(estimated_total, 0, input_rows_count);
957
19
        }
958
46
        res_chars.resize(estimated_total);
959
960
46
        size_t dst_offset = 0;
961
8.28k
        for (size_t i = 0; i < input_rows_count; ++i) {
962
8.23k
            auto str = strcol.get_data_at(index_check_const<str_const>(i));
963
8.23k
            append_result_row<is_utf8>(reinterpret_cast<const uint8_t*>(str.data), str.size,
964
8.23k
                                       target_len, padding_ptr, res_chars, res_offsets,
965
8.23k
                                       null_map_data, i, dst_offset);
966
8.23k
        }
967
46
        res_chars.resize(dst_offset);
968
46
    }
_ZN5doris17FunctionStringPadINS_10StringLPadEE27execute_const_len_const_padILb0ELb0EEEvRKNS_9ColumnStrIjEERKNS_8PODArrayIiLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEES7_RNS8_IjLm4096ESB_Lm16ELm15EEERNS8_IhLm4096ESB_Lm16ELm15EEESI_m
Line
Count
Source
941
27
                                            size_t input_rows_count) {
942
27
        constexpr bool is_utf8 = !all_ascii;
943
27
        using PadChars = PaddingChars<is_utf8>;
944
945
27
        const int target_len = col_len_data[0];
946
27
        std::optional<PadChars> padding;
947
27
        const auto pad = padcol.get_data_at(0);
948
27
        if (!pad.empty()) {
949
23
            padding.emplace(reinterpret_cast<const uint8_t*>(pad.data), pad.size);
950
23
        }
951
952
27
        const PadChars* padding_ptr = padding ? &*padding : nullptr;
953
27
        const size_t estimated_total = estimate_const_output_bytes<is_utf8>(
954
27
                strcol.get_chars(), target_len, input_rows_count, padding_ptr);
955
27
        if (estimated_total > 0) {
956
6
            ColumnString::check_chars_length(estimated_total, 0, input_rows_count);
957
6
        }
958
27
        res_chars.resize(estimated_total);
959
960
27
        size_t dst_offset = 0;
961
54
        for (size_t i = 0; i < input_rows_count; ++i) {
962
27
            auto str = strcol.get_data_at(index_check_const<str_const>(i));
963
27
            append_result_row<is_utf8>(reinterpret_cast<const uint8_t*>(str.data), str.size,
964
27
                                       target_len, padding_ptr, res_chars, res_offsets,
965
27
                                       null_map_data, i, dst_offset);
966
27
        }
967
27
        res_chars.resize(dst_offset);
968
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
941
37
                                            size_t input_rows_count) {
942
37
        constexpr bool is_utf8 = !all_ascii;
943
37
        using PadChars = PaddingChars<is_utf8>;
944
945
37
        const int target_len = col_len_data[0];
946
37
        std::optional<PadChars> padding;
947
37
        const auto pad = padcol.get_data_at(0);
948
37
        if (!pad.empty()) {
949
26
            padding.emplace(reinterpret_cast<const uint8_t*>(pad.data), pad.size);
950
26
        }
951
952
37
        const PadChars* padding_ptr = padding ? &*padding : nullptr;
953
37
        const size_t estimated_total = estimate_const_output_bytes<is_utf8>(
954
37
                strcol.get_chars(), target_len, input_rows_count, padding_ptr);
955
37
        if (estimated_total > 0) {
956
10
            ColumnString::check_chars_length(estimated_total, 0, input_rows_count);
957
10
        }
958
37
        res_chars.resize(estimated_total);
959
960
37
        size_t dst_offset = 0;
961
2.12k
        for (size_t i = 0; i < input_rows_count; ++i) {
962
2.08k
            auto str = strcol.get_data_at(index_check_const<str_const>(i));
963
2.08k
            append_result_row<is_utf8>(reinterpret_cast<const uint8_t*>(str.data), str.size,
964
2.08k
                                       target_len, padding_ptr, res_chars, res_offsets,
965
2.08k
                                       null_map_data, i, dst_offset);
966
2.08k
        }
967
37
        res_chars.resize(dst_offset);
968
37
    }
_ZN5doris17FunctionStringPadINS_10StringRPadEE27execute_const_len_const_padILb0ELb0EEEvRKNS_9ColumnStrIjEERKNS_8PODArrayIiLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEES7_RNS8_IjLm4096ESB_Lm16ELm15EEERNS8_IhLm4096ESB_Lm16ELm15EEESI_m
Line
Count
Source
941
28
                                            size_t input_rows_count) {
942
28
        constexpr bool is_utf8 = !all_ascii;
943
28
        using PadChars = PaddingChars<is_utf8>;
944
945
28
        const int target_len = col_len_data[0];
946
28
        std::optional<PadChars> padding;
947
28
        const auto pad = padcol.get_data_at(0);
948
28
        if (!pad.empty()) {
949
24
            padding.emplace(reinterpret_cast<const uint8_t*>(pad.data), pad.size);
950
24
        }
951
952
28
        const PadChars* padding_ptr = padding ? &*padding : nullptr;
953
28
        const size_t estimated_total = estimate_const_output_bytes<is_utf8>(
954
28
                strcol.get_chars(), target_len, input_rows_count, padding_ptr);
955
28
        if (estimated_total > 0) {
956
7
            ColumnString::check_chars_length(estimated_total, 0, input_rows_count);
957
7
        }
958
28
        res_chars.resize(estimated_total);
959
960
28
        size_t dst_offset = 0;
961
56
        for (size_t i = 0; i < input_rows_count; ++i) {
962
28
            auto str = strcol.get_data_at(index_check_const<str_const>(i));
963
28
            append_result_row<is_utf8>(reinterpret_cast<const uint8_t*>(str.data), str.size,
964
28
                                       target_len, padding_ptr, res_chars, res_offsets,
965
28
                                       null_map_data, i, dst_offset);
966
28
        }
967
28
        res_chars.resize(dst_offset);
968
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
969
970
    template <bool str_const>
971
    static void execute_general(const ColumnString& strcol,
972
                                const ColumnInt32::Container& col_len_data, bool len_const,
973
                                const ColumnString& padcol, bool pad_const,
974
                                ColumnString::Offsets& res_offsets, ColumnString::Chars& res_chars,
975
987
                                ColumnUInt8::Container& null_map_data, size_t input_rows_count) {
976
987
        using PadChars = PaddingChars<true>;
977
987
        std::optional<PadChars> const_padding;
978
987
        const PadChars* const_padding_ptr = nullptr;
979
987
        if (pad_const) {
980
248
            auto pad = padcol.get_data_at(0);
981
248
            if (!pad.empty()) {
982
188
                const_padding.emplace(reinterpret_cast<const uint8_t*>(pad.data), pad.size);
983
188
                const_padding_ptr = &*const_padding;
984
188
            }
985
248
        }
986
987
987
        res_chars.resize(strcol.get_chars().size());
988
987
        size_t dst_offset = 0;
989
2.23k
        for (size_t i = 0; i < input_rows_count; ++i) {
990
1.24k
            auto str = strcol.get_data_at(index_check_const<str_const>(i));
991
1.24k
            const int target_len = col_len_data[len_const ? 0 : i];
992
993
1.24k
            const PadChars* padding_ptr = const_padding_ptr;
994
1.24k
            std::optional<PadChars> row_padding;
995
1.24k
            if (!pad_const) {
996
1.00k
                auto pad = padcol.get_data_at(i);
997
1.00k
                if (!pad.empty()) {
998
763
                    row_padding.emplace(reinterpret_cast<const uint8_t*>(pad.data), pad.size);
999
763
                    padding_ptr = &*row_padding;
1000
763
                } else {
1001
237
                    padding_ptr = nullptr;
1002
237
                }
1003
1.00k
            }
1004
1005
1.24k
            append_result_row<true>(reinterpret_cast<const uint8_t*>(str.data), str.size,
1006
1.24k
                                    target_len, padding_ptr, res_chars, res_offsets, null_map_data,
1007
1.24k
                                    i, dst_offset);
1008
1.24k
        }
1009
987
        res_chars.resize(dst_offset);
1010
987
    }
_ZN5doris17FunctionStringPadINS_10StringLPadEE15execute_generalILb0EEEvRKNS_9ColumnStrIjEERKNS_8PODArrayIiLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEEbS7_bRNS8_IjLm4096ESB_Lm16ELm15EEERNS8_IhLm4096ESB_Lm16ELm15EEESI_m
Line
Count
Source
975
340
                                ColumnUInt8::Container& null_map_data, size_t input_rows_count) {
976
340
        using PadChars = PaddingChars<true>;
977
340
        std::optional<PadChars> const_padding;
978
340
        const PadChars* const_padding_ptr = nullptr;
979
340
        if (pad_const) {
980
62
            auto pad = padcol.get_data_at(0);
981
62
            if (!pad.empty()) {
982
47
                const_padding.emplace(reinterpret_cast<const uint8_t*>(pad.data), pad.size);
983
47
                const_padding_ptr = &*const_padding;
984
47
            }
985
62
        }
986
987
340
        res_chars.resize(strcol.get_chars().size());
988
340
        size_t dst_offset = 0;
989
811
        for (size_t i = 0; i < input_rows_count; ++i) {
990
471
            auto str = strcol.get_data_at(index_check_const<str_const>(i));
991
471
            const int target_len = col_len_data[len_const ? 0 : i];
992
993
471
            const PadChars* padding_ptr = const_padding_ptr;
994
471
            std::optional<PadChars> row_padding;
995
471
            if (!pad_const) {
996
409
                auto pad = padcol.get_data_at(i);
997
409
                if (!pad.empty()) {
998
317
                    row_padding.emplace(reinterpret_cast<const uint8_t*>(pad.data), pad.size);
999
317
                    padding_ptr = &*row_padding;
1000
317
                } else {
1001
92
                    padding_ptr = nullptr;
1002
92
                }
1003
409
            }
1004
1005
471
            append_result_row<true>(reinterpret_cast<const uint8_t*>(str.data), str.size,
1006
471
                                    target_len, padding_ptr, res_chars, res_offsets, null_map_data,
1007
471
                                    i, dst_offset);
1008
471
        }
1009
340
        res_chars.resize(dst_offset);
1010
340
    }
_ZN5doris17FunctionStringPadINS_10StringLPadEE15execute_generalILb1EEEvRKNS_9ColumnStrIjEERKNS_8PODArrayIiLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEEbS7_bRNS8_IjLm4096ESB_Lm16ELm15EEERNS8_IhLm4096ESB_Lm16ELm15EEESI_m
Line
Count
Source
975
186
                                ColumnUInt8::Container& null_map_data, size_t input_rows_count) {
976
186
        using PadChars = PaddingChars<true>;
977
186
        std::optional<PadChars> const_padding;
978
186
        const PadChars* const_padding_ptr = nullptr;
979
186
        if (pad_const) {
980
62
            auto pad = padcol.get_data_at(0);
981
62
            if (!pad.empty()) {
982
47
                const_padding.emplace(reinterpret_cast<const uint8_t*>(pad.data), pad.size);
983
47
                const_padding_ptr = &*const_padding;
984
47
            }
985
62
        }
986
987
186
        res_chars.resize(strcol.get_chars().size());
988
186
        size_t dst_offset = 0;
989
372
        for (size_t i = 0; i < input_rows_count; ++i) {
990
186
            auto str = strcol.get_data_at(index_check_const<str_const>(i));
991
186
            const int target_len = col_len_data[len_const ? 0 : i];
992
993
186
            const PadChars* padding_ptr = const_padding_ptr;
994
186
            std::optional<PadChars> row_padding;
995
186
            if (!pad_const) {
996
124
                auto pad = padcol.get_data_at(i);
997
124
                if (!pad.empty()) {
998
94
                    row_padding.emplace(reinterpret_cast<const uint8_t*>(pad.data), pad.size);
999
94
                    padding_ptr = &*row_padding;
1000
94
                } else {
1001
30
                    padding_ptr = nullptr;
1002
30
                }
1003
124
            }
1004
1005
186
            append_result_row<true>(reinterpret_cast<const uint8_t*>(str.data), str.size,
1006
186
                                    target_len, padding_ptr, res_chars, res_offsets, null_map_data,
1007
186
                                    i, dst_offset);
1008
186
        }
1009
186
        res_chars.resize(dst_offset);
1010
186
    }
_ZN5doris17FunctionStringPadINS_10StringRPadEE15execute_generalILb0EEEvRKNS_9ColumnStrIjEERKNS_8PODArrayIiLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEEbS7_bRNS8_IjLm4096ESB_Lm16ELm15EEERNS8_IhLm4096ESB_Lm16ELm15EEESI_m
Line
Count
Source
975
275
                                ColumnUInt8::Container& null_map_data, size_t input_rows_count) {
976
275
        using PadChars = PaddingChars<true>;
977
275
        std::optional<PadChars> const_padding;
978
275
        const PadChars* const_padding_ptr = nullptr;
979
275
        if (pad_const) {
980
62
            auto pad = padcol.get_data_at(0);
981
62
            if (!pad.empty()) {
982
47
                const_padding.emplace(reinterpret_cast<const uint8_t*>(pad.data), pad.size);
983
47
                const_padding_ptr = &*const_padding;
984
47
            }
985
62
        }
986
987
275
        res_chars.resize(strcol.get_chars().size());
988
275
        size_t dst_offset = 0;
989
680
        for (size_t i = 0; i < input_rows_count; ++i) {
990
405
            auto str = strcol.get_data_at(index_check_const<str_const>(i));
991
405
            const int target_len = col_len_data[len_const ? 0 : i];
992
993
405
            const PadChars* padding_ptr = const_padding_ptr;
994
405
            std::optional<PadChars> row_padding;
995
405
            if (!pad_const) {
996
343
                auto pad = padcol.get_data_at(i);
997
343
                if (!pad.empty()) {
998
258
                    row_padding.emplace(reinterpret_cast<const uint8_t*>(pad.data), pad.size);
999
258
                    padding_ptr = &*row_padding;
1000
258
                } else {
1001
85
                    padding_ptr = nullptr;
1002
85
                }
1003
343
            }
1004
1005
405
            append_result_row<true>(reinterpret_cast<const uint8_t*>(str.data), str.size,
1006
405
                                    target_len, padding_ptr, res_chars, res_offsets, null_map_data,
1007
405
                                    i, dst_offset);
1008
405
        }
1009
275
        res_chars.resize(dst_offset);
1010
275
    }
_ZN5doris17FunctionStringPadINS_10StringRPadEE15execute_generalILb1EEEvRKNS_9ColumnStrIjEERKNS_8PODArrayIiLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEEbS7_bRNS8_IjLm4096ESB_Lm16ELm15EEERNS8_IhLm4096ESB_Lm16ELm15EEESI_m
Line
Count
Source
975
186
                                ColumnUInt8::Container& null_map_data, size_t input_rows_count) {
976
186
        using PadChars = PaddingChars<true>;
977
186
        std::optional<PadChars> const_padding;
978
186
        const PadChars* const_padding_ptr = nullptr;
979
186
        if (pad_const) {
980
62
            auto pad = padcol.get_data_at(0);
981
62
            if (!pad.empty()) {
982
47
                const_padding.emplace(reinterpret_cast<const uint8_t*>(pad.data), pad.size);
983
47
                const_padding_ptr = &*const_padding;
984
47
            }
985
62
        }
986
987
186
        res_chars.resize(strcol.get_chars().size());
988
186
        size_t dst_offset = 0;
989
372
        for (size_t i = 0; i < input_rows_count; ++i) {
990
186
            auto str = strcol.get_data_at(index_check_const<str_const>(i));
991
186
            const int target_len = col_len_data[len_const ? 0 : i];
992
993
186
            const PadChars* padding_ptr = const_padding_ptr;
994
186
            std::optional<PadChars> row_padding;
995
186
            if (!pad_const) {
996
124
                auto pad = padcol.get_data_at(i);
997
124
                if (!pad.empty()) {
998
94
                    row_padding.emplace(reinterpret_cast<const uint8_t*>(pad.data), pad.size);
999
94
                    padding_ptr = &*row_padding;
1000
94
                } else {
1001
30
                    padding_ptr = nullptr;
1002
30
                }
1003
124
            }
1004
1005
186
            append_result_row<true>(reinterpret_cast<const uint8_t*>(str.data), str.size,
1006
186
                                    target_len, padding_ptr, res_chars, res_offsets, null_map_data,
1007
186
                                    i, dst_offset);
1008
186
        }
1009
186
        res_chars.resize(dst_offset);
1010
186
    }
1011
};
1012
1013
#include "common/compile_check_avoid_end.h"
1014
} // namespace doris