Coverage Report

Created: 2026-10-23 09:37

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