Coverage Report

Created: 2026-04-16 13:40

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