Coverage Report

Created: 2026-05-09 01:07

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
be/src/exprs/function/function_format.cpp
Line
Count
Source
1
// Licensed to the Apache Software Foundation (ASF) under one
2
// or more contributor license agreements.  See the NOTICE file
3
// distributed with this work for additional information
4
// regarding copyright ownership.  The ASF licenses this file
5
// to you under the Apache License, Version 2.0 (the
6
// "License"); you may not use this file except in compliance
7
// with the License.  You may obtain a copy of the License at
8
//
9
//   http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing,
12
// software distributed under the License is distributed on an
13
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
// KIND, either express or implied.  See the License for the
15
// specific language governing permissions and limitations
16
// under the License.
17
18
#include <glog/logging.h>
19
20
#include <cstdio>
21
#include <regex>
22
#include <vector>
23
24
#include "common/status.h"
25
#include "core/assert_cast.h"
26
#include "core/column/column.h"
27
#include "core/column/column_vector.h"
28
#include "core/data_type/data_type_number.h"
29
#include "core/data_type/define_primitive_type.h"
30
#include "core/types.h"
31
#include "exprs/function/cast_type_to_either.h"
32
#include "exprs/function/simple_function_factory.h"
33
34
namespace doris {
35
36
class FunctionFormatNumber : public IFunction {
37
public:
38
    static constexpr auto name = "format_number";
39
40
    static constexpr const char* UNITS[6] = {"", "K", "M", "B", "T", "Q"};
41
42
48
    static FunctionPtr create() { return std::make_shared<FunctionFormatNumber>(); }
43
44
1
    String get_name() const override { return name; }
45
46
39
    size_t get_number_of_arguments() const override { return 1; }
47
48
40
    bool is_variadic() const override { return false; }
49
50
39
    DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
51
39
        return std::make_shared<DataTypeString>();
52
39
    }
53
54
    Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
55
46
                        uint32_t result, size_t input_rows_count) const override {
56
46
        auto column = block.get_by_position(arguments[0]).column;
57
46
        const auto& column_data = assert_cast<const ColumnFloat64*>(column.get())->get_data();
58
46
        auto col_res = ColumnString::create();
59
46
        fmt::memory_buffer buffer;
60
61
96
        for (auto i = 0; i < input_rows_count; ++i) {
62
50
            auto res_data = format_number(buffer, column_data[i]);
63
50
            col_res->insert_data(res_data.data(), res_data.length());
64
50
        }
65
46
        block.replace_by_position(result, std::move(col_res));
66
46
        return Status::OK();
67
46
    }
68
69
50
    std::string format_number(fmt::memory_buffer& buffer, double number) const {
70
50
        buffer.clear();
71
50
        double abs_number = std::abs(number);
72
50
        int unit_index = 0;
73
140
        while (abs_number >= 1000 && unit_index < 5) {
74
90
            abs_number /= 1000;
75
90
            ++unit_index;
76
90
        }
77
50
        if (number < 0) {
78
13
            fmt::format_to(buffer, "-");
79
13
        }
80
50
        if (abs_number == 1) {
81
            //eg: 1000 ---> 1K
82
8
            fmt::format_to(buffer, "{}", abs_number);
83
42
        } else if (abs_number < 10) {
84
            //eg: 1239 ---> 1.24K only want to show 2 decimal
85
19
            fmt::format_to(buffer, "{:.2f}", abs_number);
86
23
        } else if (abs_number < 100) {
87
            //eg: 12399999 ---> 12.4M only want to show 1 decimal
88
8
            fmt::format_to(buffer, "{:.1f}", abs_number);
89
15
        } else {
90
            // eg: 999999999999999 ---> 1000T only want to show 0 decimal
91
15
            fmt::format_to(buffer, "{:.0f}", abs_number);
92
15
        }
93
50
        fmt::format_to(buffer, UNITS[unit_index]);
94
50
        return fmt::to_string(buffer);
95
50
    }
96
};
97
98
class FunctionFormat : public IFunction {
99
public:
100
    static constexpr auto name = "format";
101
102
32
    static FunctionPtr create() { return std::make_shared<FunctionFormat>(); }
103
104
0
    String get_name() const override { return name; }
105
106
0
    size_t get_number_of_arguments() const override { return 0; }
107
108
24
    bool is_variadic() const override { return true; }
109
110
23
    DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
111
23
        return std::make_shared<DataTypeString>();
112
23
    }
113
114
    Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
115
28
                        uint32_t result, size_t input_rows_count) const override {
116
28
        DCHECK_GE(arguments.size(), 2);
117
28
        bool valid =
118
28
                cast_type(block.get_by_position(arguments[1]).type.get(), [&](const auto& type) {
119
28
                    using DataType = std::decay_t<decltype(type)>;
120
28
                    using ColVecData =
121
28
                            std::conditional_t<is_number(DataType::PType),
122
28
                                               ColumnVector<DataType::PType>, ColumnString>;
123
28
                    if (auto col = check_and_get_column<ColVecData>(
124
28
                                           block.get_by_position(arguments[1]).column.get()) ||
125
28
                                   is_column_const(*block.get_by_position(arguments[1]).column)) {
126
28
                        execute_inner<ColVecData, DataType::PType>(block, arguments, result,
127
28
                                                                   input_rows_count);
128
28
                        return true;
129
28
                    }
130
0
                    return false;
131
28
                });
_ZZNK5doris14FunctionFormat12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjmENKUlRKT_E_clINS_14DataTypeNumberILNS_13PrimitiveTypeE3EEEEEDaSC_
Line
Count
Source
118
5
                cast_type(block.get_by_position(arguments[1]).type.get(), [&](const auto& type) {
119
5
                    using DataType = std::decay_t<decltype(type)>;
120
5
                    using ColVecData =
121
5
                            std::conditional_t<is_number(DataType::PType),
122
5
                                               ColumnVector<DataType::PType>, ColumnString>;
123
5
                    if (auto col = check_and_get_column<ColVecData>(
124
5
                                           block.get_by_position(arguments[1]).column.get()) ||
125
5
                                   is_column_const(*block.get_by_position(arguments[1]).column)) {
126
5
                        execute_inner<ColVecData, DataType::PType>(block, arguments, result,
127
5
                                                                   input_rows_count);
128
5
                        return true;
129
5
                    }
130
0
                    return false;
131
5
                });
_ZZNK5doris14FunctionFormat12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjmENKUlRKT_E_clINS_14DataTypeNumberILNS_13PrimitiveTypeE4EEEEEDaSC_
Line
Count
Source
118
1
                cast_type(block.get_by_position(arguments[1]).type.get(), [&](const auto& type) {
119
1
                    using DataType = std::decay_t<decltype(type)>;
120
1
                    using ColVecData =
121
1
                            std::conditional_t<is_number(DataType::PType),
122
1
                                               ColumnVector<DataType::PType>, ColumnString>;
123
1
                    if (auto col = check_and_get_column<ColVecData>(
124
1
                                           block.get_by_position(arguments[1]).column.get()) ||
125
1
                                   is_column_const(*block.get_by_position(arguments[1]).column)) {
126
1
                        execute_inner<ColVecData, DataType::PType>(block, arguments, result,
127
1
                                                                   input_rows_count);
128
1
                        return true;
129
1
                    }
130
0
                    return false;
131
1
                });
Unexecuted instantiation: _ZZNK5doris14FunctionFormat12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjmENKUlRKT_E_clINS_14DataTypeNumberILNS_13PrimitiveTypeE5EEEEEDaSC_
Unexecuted instantiation: _ZZNK5doris14FunctionFormat12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjmENKUlRKT_E_clINS_14DataTypeNumberILNS_13PrimitiveTypeE6EEEEEDaSC_
_ZZNK5doris14FunctionFormat12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjmENKUlRKT_E_clINS_14DataTypeNumberILNS_13PrimitiveTypeE7EEEEEDaSC_
Line
Count
Source
118
4
                cast_type(block.get_by_position(arguments[1]).type.get(), [&](const auto& type) {
119
4
                    using DataType = std::decay_t<decltype(type)>;
120
4
                    using ColVecData =
121
4
                            std::conditional_t<is_number(DataType::PType),
122
4
                                               ColumnVector<DataType::PType>, ColumnString>;
123
4
                    if (auto col = check_and_get_column<ColVecData>(
124
4
                                           block.get_by_position(arguments[1]).column.get()) ||
125
4
                                   is_column_const(*block.get_by_position(arguments[1]).column)) {
126
4
                        execute_inner<ColVecData, DataType::PType>(block, arguments, result,
127
4
                                                                   input_rows_count);
128
4
                        return true;
129
4
                    }
130
0
                    return false;
131
4
                });
Unexecuted instantiation: _ZZNK5doris14FunctionFormat12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjmENKUlRKT_E_clINS_14DataTypeNumberILNS_13PrimitiveTypeE8EEEEEDaSC_
_ZZNK5doris14FunctionFormat12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjmENKUlRKT_E_clINS_14DataTypeNumberILNS_13PrimitiveTypeE9EEEEEDaSC_
Line
Count
Source
118
10
                cast_type(block.get_by_position(arguments[1]).type.get(), [&](const auto& type) {
119
10
                    using DataType = std::decay_t<decltype(type)>;
120
10
                    using ColVecData =
121
10
                            std::conditional_t<is_number(DataType::PType),
122
10
                                               ColumnVector<DataType::PType>, ColumnString>;
123
10
                    if (auto col = check_and_get_column<ColVecData>(
124
10
                                           block.get_by_position(arguments[1]).column.get()) ||
125
10
                                   is_column_const(*block.get_by_position(arguments[1]).column)) {
126
10
                        execute_inner<ColVecData, DataType::PType>(block, arguments, result,
127
10
                                                                   input_rows_count);
128
10
                        return true;
129
10
                    }
130
0
                    return false;
131
10
                });
_ZZNK5doris14FunctionFormat12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjmENKUlRKT_E_clINS_14DataTypeStringEEEDaSC_
Line
Count
Source
118
8
                cast_type(block.get_by_position(arguments[1]).type.get(), [&](const auto& type) {
119
8
                    using DataType = std::decay_t<decltype(type)>;
120
8
                    using ColVecData =
121
8
                            std::conditional_t<is_number(DataType::PType),
122
8
                                               ColumnVector<DataType::PType>, ColumnString>;
123
8
                    if (auto col = check_and_get_column<ColVecData>(
124
8
                                           block.get_by_position(arguments[1]).column.get()) ||
125
8
                                   is_column_const(*block.get_by_position(arguments[1]).column)) {
126
8
                        execute_inner<ColVecData, DataType::PType>(block, arguments, result,
127
8
                                                                   input_rows_count);
128
8
                        return true;
129
8
                    }
130
0
                    return false;
131
8
                });
132
28
        if (!valid) {
133
0
            return Status::RuntimeError(
134
0
                    "{}'s argument does not match the expected data type, type: {}, column: {}",
135
0
                    get_name(), block.get_by_position(arguments[1]).type->get_name(),
136
0
                    block.get_by_position(arguments[1]).column->dump_structure());
137
0
        }
138
28
        return Status::OK();
139
28
    }
140
141
    template <typename F>
142
28
    static bool cast_type(const IDataType* type, F&& f) {
143
28
        return cast_type_to_either<DataTypeInt8, DataTypeInt16, DataTypeInt32, DataTypeInt64,
144
28
                                   DataTypeInt128, DataTypeFloat32, DataTypeFloat64,
145
28
                                   DataTypeString>(type, std::forward<F>(f));
146
28
    }
147
148
    template <typename ColVecData, PrimitiveType T>
149
    void execute_inner(Block& block, const ColumnNumbers& arguments, uint32_t result,
150
28
                       size_t input_rows_count) const {
151
28
        size_t argument_size = arguments.size();
152
28
        std::vector<ColumnPtr> argument_columns(argument_size);
153
28
        auto result_column = ColumnString::create();
154
155
        // maybe most user is format(const, column), so only handle this case const column
156
28
        if (argument_size == 2) {
157
19
            std::vector<uint8_t> is_consts(argument_size);
158
19
            std::tie(argument_columns[0], is_consts[0]) =
159
19
                    unpack_if_const(block.get_by_position(arguments[0]).column);
160
19
            std::tie(argument_columns[1], is_consts[1]) =
161
19
                    unpack_if_const(block.get_by_position(arguments[1]).column);
162
19
            execute_for_two_argument<ColVecData, T>(argument_columns, is_consts,
163
19
                                                    result_column.get(), input_rows_count);
164
19
        } else {
165
36
            for (size_t i = 0; i < argument_size; ++i) {
166
27
                argument_columns[i] = block.get_by_position(arguments[i])
167
27
                                              .column->convert_to_full_column_if_const();
168
27
            }
169
9
            execute_for_others_arg<ColVecData, T>(argument_columns, result_column.get(),
170
9
                                                  argument_size, input_rows_count);
171
9
        }
172
173
28
        block.replace_by_position(result, std::move(result_column));
174
28
    }
_ZNK5doris14FunctionFormat13execute_innerINS_12ColumnVectorILNS_13PrimitiveTypeE3EEELS3_3EEEvRNS_5BlockERKSt6vectorIjSaIjEEjm
Line
Count
Source
150
5
                       size_t input_rows_count) const {
151
5
        size_t argument_size = arguments.size();
152
5
        std::vector<ColumnPtr> argument_columns(argument_size);
153
5
        auto result_column = ColumnString::create();
154
155
        // maybe most user is format(const, column), so only handle this case const column
156
5
        if (argument_size == 2) {
157
5
            std::vector<uint8_t> is_consts(argument_size);
158
5
            std::tie(argument_columns[0], is_consts[0]) =
159
5
                    unpack_if_const(block.get_by_position(arguments[0]).column);
160
5
            std::tie(argument_columns[1], is_consts[1]) =
161
5
                    unpack_if_const(block.get_by_position(arguments[1]).column);
162
5
            execute_for_two_argument<ColVecData, T>(argument_columns, is_consts,
163
5
                                                    result_column.get(), input_rows_count);
164
5
        } else {
165
0
            for (size_t i = 0; i < argument_size; ++i) {
166
0
                argument_columns[i] = block.get_by_position(arguments[i])
167
0
                                              .column->convert_to_full_column_if_const();
168
0
            }
169
0
            execute_for_others_arg<ColVecData, T>(argument_columns, result_column.get(),
170
0
                                                  argument_size, input_rows_count);
171
0
        }
172
173
5
        block.replace_by_position(result, std::move(result_column));
174
5
    }
_ZNK5doris14FunctionFormat13execute_innerINS_12ColumnVectorILNS_13PrimitiveTypeE4EEELS3_4EEEvRNS_5BlockERKSt6vectorIjSaIjEEjm
Line
Count
Source
150
1
                       size_t input_rows_count) const {
151
1
        size_t argument_size = arguments.size();
152
1
        std::vector<ColumnPtr> argument_columns(argument_size);
153
1
        auto result_column = ColumnString::create();
154
155
        // maybe most user is format(const, column), so only handle this case const column
156
1
        if (argument_size == 2) {
157
0
            std::vector<uint8_t> is_consts(argument_size);
158
0
            std::tie(argument_columns[0], is_consts[0]) =
159
0
                    unpack_if_const(block.get_by_position(arguments[0]).column);
160
0
            std::tie(argument_columns[1], is_consts[1]) =
161
0
                    unpack_if_const(block.get_by_position(arguments[1]).column);
162
0
            execute_for_two_argument<ColVecData, T>(argument_columns, is_consts,
163
0
                                                    result_column.get(), input_rows_count);
164
1
        } else {
165
4
            for (size_t i = 0; i < argument_size; ++i) {
166
3
                argument_columns[i] = block.get_by_position(arguments[i])
167
3
                                              .column->convert_to_full_column_if_const();
168
3
            }
169
1
            execute_for_others_arg<ColVecData, T>(argument_columns, result_column.get(),
170
1
                                                  argument_size, input_rows_count);
171
1
        }
172
173
1
        block.replace_by_position(result, std::move(result_column));
174
1
    }
Unexecuted instantiation: _ZNK5doris14FunctionFormat13execute_innerINS_12ColumnVectorILNS_13PrimitiveTypeE5EEELS3_5EEEvRNS_5BlockERKSt6vectorIjSaIjEEjm
Unexecuted instantiation: _ZNK5doris14FunctionFormat13execute_innerINS_12ColumnVectorILNS_13PrimitiveTypeE6EEELS3_6EEEvRNS_5BlockERKSt6vectorIjSaIjEEjm
_ZNK5doris14FunctionFormat13execute_innerINS_12ColumnVectorILNS_13PrimitiveTypeE7EEELS3_7EEEvRNS_5BlockERKSt6vectorIjSaIjEEjm
Line
Count
Source
150
4
                       size_t input_rows_count) const {
151
4
        size_t argument_size = arguments.size();
152
4
        std::vector<ColumnPtr> argument_columns(argument_size);
153
4
        auto result_column = ColumnString::create();
154
155
        // maybe most user is format(const, column), so only handle this case const column
156
4
        if (argument_size == 2) {
157
4
            std::vector<uint8_t> is_consts(argument_size);
158
4
            std::tie(argument_columns[0], is_consts[0]) =
159
4
                    unpack_if_const(block.get_by_position(arguments[0]).column);
160
4
            std::tie(argument_columns[1], is_consts[1]) =
161
4
                    unpack_if_const(block.get_by_position(arguments[1]).column);
162
4
            execute_for_two_argument<ColVecData, T>(argument_columns, is_consts,
163
4
                                                    result_column.get(), input_rows_count);
164
4
        } else {
165
0
            for (size_t i = 0; i < argument_size; ++i) {
166
0
                argument_columns[i] = block.get_by_position(arguments[i])
167
0
                                              .column->convert_to_full_column_if_const();
168
0
            }
169
0
            execute_for_others_arg<ColVecData, T>(argument_columns, result_column.get(),
170
0
                                                  argument_size, input_rows_count);
171
0
        }
172
173
4
        block.replace_by_position(result, std::move(result_column));
174
4
    }
Unexecuted instantiation: _ZNK5doris14FunctionFormat13execute_innerINS_12ColumnVectorILNS_13PrimitiveTypeE8EEELS3_8EEEvRNS_5BlockERKSt6vectorIjSaIjEEjm
_ZNK5doris14FunctionFormat13execute_innerINS_12ColumnVectorILNS_13PrimitiveTypeE9EEELS3_9EEEvRNS_5BlockERKSt6vectorIjSaIjEEjm
Line
Count
Source
150
10
                       size_t input_rows_count) const {
151
10
        size_t argument_size = arguments.size();
152
10
        std::vector<ColumnPtr> argument_columns(argument_size);
153
10
        auto result_column = ColumnString::create();
154
155
        // maybe most user is format(const, column), so only handle this case const column
156
10
        if (argument_size == 2) {
157
9
            std::vector<uint8_t> is_consts(argument_size);
158
9
            std::tie(argument_columns[0], is_consts[0]) =
159
9
                    unpack_if_const(block.get_by_position(arguments[0]).column);
160
9
            std::tie(argument_columns[1], is_consts[1]) =
161
9
                    unpack_if_const(block.get_by_position(arguments[1]).column);
162
9
            execute_for_two_argument<ColVecData, T>(argument_columns, is_consts,
163
9
                                                    result_column.get(), input_rows_count);
164
9
        } else {
165
4
            for (size_t i = 0; i < argument_size; ++i) {
166
3
                argument_columns[i] = block.get_by_position(arguments[i])
167
3
                                              .column->convert_to_full_column_if_const();
168
3
            }
169
1
            execute_for_others_arg<ColVecData, T>(argument_columns, result_column.get(),
170
1
                                                  argument_size, input_rows_count);
171
1
        }
172
173
10
        block.replace_by_position(result, std::move(result_column));
174
10
    }
_ZNK5doris14FunctionFormat13execute_innerINS_9ColumnStrIjEELNS_13PrimitiveTypeE23EEEvRNS_5BlockERKSt6vectorIjSaIjEEjm
Line
Count
Source
150
8
                       size_t input_rows_count) const {
151
8
        size_t argument_size = arguments.size();
152
8
        std::vector<ColumnPtr> argument_columns(argument_size);
153
8
        auto result_column = ColumnString::create();
154
155
        // maybe most user is format(const, column), so only handle this case const column
156
8
        if (argument_size == 2) {
157
1
            std::vector<uint8_t> is_consts(argument_size);
158
1
            std::tie(argument_columns[0], is_consts[0]) =
159
1
                    unpack_if_const(block.get_by_position(arguments[0]).column);
160
1
            std::tie(argument_columns[1], is_consts[1]) =
161
1
                    unpack_if_const(block.get_by_position(arguments[1]).column);
162
1
            execute_for_two_argument<ColVecData, T>(argument_columns, is_consts,
163
1
                                                    result_column.get(), input_rows_count);
164
7
        } else {
165
28
            for (size_t i = 0; i < argument_size; ++i) {
166
21
                argument_columns[i] = block.get_by_position(arguments[i])
167
21
                                              .column->convert_to_full_column_if_const();
168
21
            }
169
7
            execute_for_others_arg<ColVecData, T>(argument_columns, result_column.get(),
170
7
                                                  argument_size, input_rows_count);
171
7
        }
172
173
8
        block.replace_by_position(result, std::move(result_column));
174
8
    }
175
176
    template <typename ColVecData, PrimitiveType T>
177
    void execute_for_two_argument(std::vector<ColumnPtr>& argument_columns,
178
                                  std::vector<uint8_t>& is_consts, ColumnString* result_data_column,
179
19
                                  size_t input_rows_count) const {
180
19
        const auto& format_column = assert_cast<const ColumnString&>(*argument_columns[0].get());
181
19
        const auto& value_column = assert_cast<const ColVecData&>(*argument_columns[1].get());
182
37
        for (int i = 0; i < input_rows_count; ++i) {
183
19
            auto format =
184
19
                    format_column.get_data_at(index_check_const(i, is_consts[0])).to_string_view();
185
19
            std::string res;
186
19
            try {
187
19
                if constexpr (is_string_type(T)) {
188
1
                    auto value = value_column.get_data_at(index_check_const(i, is_consts[1]));
189
1
                    res = fmt::format(format, value);
190
18
                } else {
191
18
                    auto value = value_column.get_data()[index_check_const(i, is_consts[1])];
192
18
                    res = fmt::format(format, value);
193
18
                }
194
19
            } catch (const std::exception& e) {
195
1
                throw doris::Exception(
196
1
                        ErrorCode::INVALID_ARGUMENT,
197
1
                        "Invalid Input argument \"{}\" of function format, error: {}", format,
198
1
                        e.what());
199
1
            }
200
18
            result_data_column->insert_data(res.data(), res.length());
201
18
        }
202
19
    }
_ZNK5doris14FunctionFormat24execute_for_two_argumentINS_12ColumnVectorILNS_13PrimitiveTypeE3EEELS3_3EEEvRSt6vectorINS_3COWINS_7IColumnEE13immutable_ptrIS7_EESaISA_EERS5_IhSaIhEEPNS_9ColumnStrIjEEm
Line
Count
Source
179
5
                                  size_t input_rows_count) const {
180
5
        const auto& format_column = assert_cast<const ColumnString&>(*argument_columns[0].get());
181
5
        const auto& value_column = assert_cast<const ColVecData&>(*argument_columns[1].get());
182
10
        for (int i = 0; i < input_rows_count; ++i) {
183
5
            auto format =
184
5
                    format_column.get_data_at(index_check_const(i, is_consts[0])).to_string_view();
185
5
            std::string res;
186
5
            try {
187
                if constexpr (is_string_type(T)) {
188
                    auto value = value_column.get_data_at(index_check_const(i, is_consts[1]));
189
                    res = fmt::format(format, value);
190
5
                } else {
191
5
                    auto value = value_column.get_data()[index_check_const(i, is_consts[1])];
192
5
                    res = fmt::format(format, value);
193
5
                }
194
5
            } catch (const std::exception& e) {
195
0
                throw doris::Exception(
196
0
                        ErrorCode::INVALID_ARGUMENT,
197
0
                        "Invalid Input argument \"{}\" of function format, error: {}", format,
198
0
                        e.what());
199
0
            }
200
5
            result_data_column->insert_data(res.data(), res.length());
201
5
        }
202
5
    }
Unexecuted instantiation: _ZNK5doris14FunctionFormat24execute_for_two_argumentINS_12ColumnVectorILNS_13PrimitiveTypeE4EEELS3_4EEEvRSt6vectorINS_3COWINS_7IColumnEE13immutable_ptrIS7_EESaISA_EERS5_IhSaIhEEPNS_9ColumnStrIjEEm
Unexecuted instantiation: _ZNK5doris14FunctionFormat24execute_for_two_argumentINS_12ColumnVectorILNS_13PrimitiveTypeE5EEELS3_5EEEvRSt6vectorINS_3COWINS_7IColumnEE13immutable_ptrIS7_EESaISA_EERS5_IhSaIhEEPNS_9ColumnStrIjEEm
Unexecuted instantiation: _ZNK5doris14FunctionFormat24execute_for_two_argumentINS_12ColumnVectorILNS_13PrimitiveTypeE6EEELS3_6EEEvRSt6vectorINS_3COWINS_7IColumnEE13immutable_ptrIS7_EESaISA_EERS5_IhSaIhEEPNS_9ColumnStrIjEEm
_ZNK5doris14FunctionFormat24execute_for_two_argumentINS_12ColumnVectorILNS_13PrimitiveTypeE7EEELS3_7EEEvRSt6vectorINS_3COWINS_7IColumnEE13immutable_ptrIS7_EESaISA_EERS5_IhSaIhEEPNS_9ColumnStrIjEEm
Line
Count
Source
179
4
                                  size_t input_rows_count) const {
180
4
        const auto& format_column = assert_cast<const ColumnString&>(*argument_columns[0].get());
181
4
        const auto& value_column = assert_cast<const ColVecData&>(*argument_columns[1].get());
182
8
        for (int i = 0; i < input_rows_count; ++i) {
183
4
            auto format =
184
4
                    format_column.get_data_at(index_check_const(i, is_consts[0])).to_string_view();
185
4
            std::string res;
186
4
            try {
187
                if constexpr (is_string_type(T)) {
188
                    auto value = value_column.get_data_at(index_check_const(i, is_consts[1]));
189
                    res = fmt::format(format, value);
190
4
                } else {
191
4
                    auto value = value_column.get_data()[index_check_const(i, is_consts[1])];
192
4
                    res = fmt::format(format, value);
193
4
                }
194
4
            } catch (const std::exception& e) {
195
0
                throw doris::Exception(
196
0
                        ErrorCode::INVALID_ARGUMENT,
197
0
                        "Invalid Input argument \"{}\" of function format, error: {}", format,
198
0
                        e.what());
199
0
            }
200
4
            result_data_column->insert_data(res.data(), res.length());
201
4
        }
202
4
    }
Unexecuted instantiation: _ZNK5doris14FunctionFormat24execute_for_two_argumentINS_12ColumnVectorILNS_13PrimitiveTypeE8EEELS3_8EEEvRSt6vectorINS_3COWINS_7IColumnEE13immutable_ptrIS7_EESaISA_EERS5_IhSaIhEEPNS_9ColumnStrIjEEm
_ZNK5doris14FunctionFormat24execute_for_two_argumentINS_12ColumnVectorILNS_13PrimitiveTypeE9EEELS3_9EEEvRSt6vectorINS_3COWINS_7IColumnEE13immutable_ptrIS7_EESaISA_EERS5_IhSaIhEEPNS_9ColumnStrIjEEm
Line
Count
Source
179
9
                                  size_t input_rows_count) const {
180
9
        const auto& format_column = assert_cast<const ColumnString&>(*argument_columns[0].get());
181
9
        const auto& value_column = assert_cast<const ColVecData&>(*argument_columns[1].get());
182
18
        for (int i = 0; i < input_rows_count; ++i) {
183
9
            auto format =
184
9
                    format_column.get_data_at(index_check_const(i, is_consts[0])).to_string_view();
185
9
            std::string res;
186
9
            try {
187
                if constexpr (is_string_type(T)) {
188
                    auto value = value_column.get_data_at(index_check_const(i, is_consts[1]));
189
                    res = fmt::format(format, value);
190
9
                } else {
191
9
                    auto value = value_column.get_data()[index_check_const(i, is_consts[1])];
192
9
                    res = fmt::format(format, value);
193
9
                }
194
9
            } catch (const std::exception& e) {
195
0
                throw doris::Exception(
196
0
                        ErrorCode::INVALID_ARGUMENT,
197
0
                        "Invalid Input argument \"{}\" of function format, error: {}", format,
198
0
                        e.what());
199
0
            }
200
9
            result_data_column->insert_data(res.data(), res.length());
201
9
        }
202
9
    }
_ZNK5doris14FunctionFormat24execute_for_two_argumentINS_9ColumnStrIjEELNS_13PrimitiveTypeE23EEEvRSt6vectorINS_3COWINS_7IColumnEE13immutable_ptrIS7_EESaISA_EERS5_IhSaIhEEPS3_m
Line
Count
Source
179
1
                                  size_t input_rows_count) const {
180
1
        const auto& format_column = assert_cast<const ColumnString&>(*argument_columns[0].get());
181
1
        const auto& value_column = assert_cast<const ColVecData&>(*argument_columns[1].get());
182
1
        for (int i = 0; i < input_rows_count; ++i) {
183
1
            auto format =
184
1
                    format_column.get_data_at(index_check_const(i, is_consts[0])).to_string_view();
185
1
            std::string res;
186
1
            try {
187
1
                if constexpr (is_string_type(T)) {
188
1
                    auto value = value_column.get_data_at(index_check_const(i, is_consts[1]));
189
1
                    res = fmt::format(format, value);
190
                } else {
191
                    auto value = value_column.get_data()[index_check_const(i, is_consts[1])];
192
                    res = fmt::format(format, value);
193
                }
194
1
            } catch (const std::exception& e) {
195
1
                throw doris::Exception(
196
1
                        ErrorCode::INVALID_ARGUMENT,
197
1
                        "Invalid Input argument \"{}\" of function format, error: {}", format,
198
1
                        e.what());
199
1
            }
200
0
            result_data_column->insert_data(res.data(), res.length());
201
0
        }
202
1
    }
203
204
    template <typename ColVecData, PrimitiveType T>
205
    void execute_for_others_arg(std::vector<ColumnPtr>& argument_columns,
206
                                ColumnString* result_data_column, size_t argument_size,
207
9
                                size_t input_rows_count) const {
208
9
        const auto& format_column = assert_cast<const ColumnString&>(*argument_columns[0].get());
209
18
        for (int i = 0; i < input_rows_count; ++i) {
210
9
            auto format = format_column.get_data_at(i).to_string_view();
211
9
            std::string res;
212
9
            fmt::dynamic_format_arg_store<fmt::format_context> args;
213
9
            if constexpr (is_string_type(T)) {
214
21
                for (int col = 1; col < argument_size; ++col) {
215
14
                    const auto& arg_column_data =
216
14
                            assert_cast<const ColVecData&>(*argument_columns[col].get());
217
14
                    args.push_back(arg_column_data.get_data_at(i).to_string());
218
14
                }
219
7
            } else {
220
6
                for (int col = 1; col < argument_size; ++col) {
221
4
                    const auto& arg_column_data =
222
4
                            assert_cast<const ColVecData&>(*argument_columns[col].get()).get_data();
223
4
                    args.push_back(arg_column_data[i]);
224
4
                }
225
2
            }
226
9
            try {
227
9
                res = fmt::vformat(format, args);
228
9
            } catch (const std::exception& e) {
229
0
                throw doris::Exception(
230
0
                        ErrorCode::INVALID_ARGUMENT,
231
0
                        "Invalid Input argument \"{}\" of function format, error: {}", format,
232
0
                        e.what());
233
0
            }
234
9
            result_data_column->insert_data(res.data(), res.length());
235
9
        }
236
9
    }
Unexecuted instantiation: _ZNK5doris14FunctionFormat22execute_for_others_argINS_12ColumnVectorILNS_13PrimitiveTypeE3EEELS3_3EEEvRSt6vectorINS_3COWINS_7IColumnEE13immutable_ptrIS7_EESaISA_EEPNS_9ColumnStrIjEEmm
_ZNK5doris14FunctionFormat22execute_for_others_argINS_12ColumnVectorILNS_13PrimitiveTypeE4EEELS3_4EEEvRSt6vectorINS_3COWINS_7IColumnEE13immutable_ptrIS7_EESaISA_EEPNS_9ColumnStrIjEEmm
Line
Count
Source
207
1
                                size_t input_rows_count) const {
208
1
        const auto& format_column = assert_cast<const ColumnString&>(*argument_columns[0].get());
209
2
        for (int i = 0; i < input_rows_count; ++i) {
210
1
            auto format = format_column.get_data_at(i).to_string_view();
211
1
            std::string res;
212
1
            fmt::dynamic_format_arg_store<fmt::format_context> args;
213
            if constexpr (is_string_type(T)) {
214
                for (int col = 1; col < argument_size; ++col) {
215
                    const auto& arg_column_data =
216
                            assert_cast<const ColVecData&>(*argument_columns[col].get());
217
                    args.push_back(arg_column_data.get_data_at(i).to_string());
218
                }
219
1
            } else {
220
3
                for (int col = 1; col < argument_size; ++col) {
221
2
                    const auto& arg_column_data =
222
2
                            assert_cast<const ColVecData&>(*argument_columns[col].get()).get_data();
223
2
                    args.push_back(arg_column_data[i]);
224
2
                }
225
1
            }
226
1
            try {
227
1
                res = fmt::vformat(format, args);
228
1
            } catch (const std::exception& e) {
229
0
                throw doris::Exception(
230
0
                        ErrorCode::INVALID_ARGUMENT,
231
0
                        "Invalid Input argument \"{}\" of function format, error: {}", format,
232
0
                        e.what());
233
0
            }
234
1
            result_data_column->insert_data(res.data(), res.length());
235
1
        }
236
1
    }
Unexecuted instantiation: _ZNK5doris14FunctionFormat22execute_for_others_argINS_12ColumnVectorILNS_13PrimitiveTypeE5EEELS3_5EEEvRSt6vectorINS_3COWINS_7IColumnEE13immutable_ptrIS7_EESaISA_EEPNS_9ColumnStrIjEEmm
Unexecuted instantiation: _ZNK5doris14FunctionFormat22execute_for_others_argINS_12ColumnVectorILNS_13PrimitiveTypeE6EEELS3_6EEEvRSt6vectorINS_3COWINS_7IColumnEE13immutable_ptrIS7_EESaISA_EEPNS_9ColumnStrIjEEmm
Unexecuted instantiation: _ZNK5doris14FunctionFormat22execute_for_others_argINS_12ColumnVectorILNS_13PrimitiveTypeE7EEELS3_7EEEvRSt6vectorINS_3COWINS_7IColumnEE13immutable_ptrIS7_EESaISA_EEPNS_9ColumnStrIjEEmm
Unexecuted instantiation: _ZNK5doris14FunctionFormat22execute_for_others_argINS_12ColumnVectorILNS_13PrimitiveTypeE8EEELS3_8EEEvRSt6vectorINS_3COWINS_7IColumnEE13immutable_ptrIS7_EESaISA_EEPNS_9ColumnStrIjEEmm
_ZNK5doris14FunctionFormat22execute_for_others_argINS_12ColumnVectorILNS_13PrimitiveTypeE9EEELS3_9EEEvRSt6vectorINS_3COWINS_7IColumnEE13immutable_ptrIS7_EESaISA_EEPNS_9ColumnStrIjEEmm
Line
Count
Source
207
1
                                size_t input_rows_count) const {
208
1
        const auto& format_column = assert_cast<const ColumnString&>(*argument_columns[0].get());
209
2
        for (int i = 0; i < input_rows_count; ++i) {
210
1
            auto format = format_column.get_data_at(i).to_string_view();
211
1
            std::string res;
212
1
            fmt::dynamic_format_arg_store<fmt::format_context> args;
213
            if constexpr (is_string_type(T)) {
214
                for (int col = 1; col < argument_size; ++col) {
215
                    const auto& arg_column_data =
216
                            assert_cast<const ColVecData&>(*argument_columns[col].get());
217
                    args.push_back(arg_column_data.get_data_at(i).to_string());
218
                }
219
1
            } else {
220
3
                for (int col = 1; col < argument_size; ++col) {
221
2
                    const auto& arg_column_data =
222
2
                            assert_cast<const ColVecData&>(*argument_columns[col].get()).get_data();
223
2
                    args.push_back(arg_column_data[i]);
224
2
                }
225
1
            }
226
1
            try {
227
1
                res = fmt::vformat(format, args);
228
1
            } catch (const std::exception& e) {
229
0
                throw doris::Exception(
230
0
                        ErrorCode::INVALID_ARGUMENT,
231
0
                        "Invalid Input argument \"{}\" of function format, error: {}", format,
232
0
                        e.what());
233
0
            }
234
1
            result_data_column->insert_data(res.data(), res.length());
235
1
        }
236
1
    }
_ZNK5doris14FunctionFormat22execute_for_others_argINS_9ColumnStrIjEELNS_13PrimitiveTypeE23EEEvRSt6vectorINS_3COWINS_7IColumnEE13immutable_ptrIS7_EESaISA_EEPS3_mm
Line
Count
Source
207
7
                                size_t input_rows_count) const {
208
7
        const auto& format_column = assert_cast<const ColumnString&>(*argument_columns[0].get());
209
14
        for (int i = 0; i < input_rows_count; ++i) {
210
7
            auto format = format_column.get_data_at(i).to_string_view();
211
7
            std::string res;
212
7
            fmt::dynamic_format_arg_store<fmt::format_context> args;
213
7
            if constexpr (is_string_type(T)) {
214
21
                for (int col = 1; col < argument_size; ++col) {
215
14
                    const auto& arg_column_data =
216
14
                            assert_cast<const ColVecData&>(*argument_columns[col].get());
217
14
                    args.push_back(arg_column_data.get_data_at(i).to_string());
218
14
                }
219
            } else {
220
                for (int col = 1; col < argument_size; ++col) {
221
                    const auto& arg_column_data =
222
                            assert_cast<const ColVecData&>(*argument_columns[col].get()).get_data();
223
                    args.push_back(arg_column_data[i]);
224
                }
225
            }
226
7
            try {
227
7
                res = fmt::vformat(format, args);
228
7
            } catch (const std::exception& e) {
229
0
                throw doris::Exception(
230
0
                        ErrorCode::INVALID_ARGUMENT,
231
0
                        "Invalid Input argument \"{}\" of function format, error: {}", format,
232
0
                        e.what());
233
0
            }
234
7
            result_data_column->insert_data(res.data(), res.length());
235
7
        }
236
7
    }
237
};
238
239
8
void register_function_format(SimpleFunctionFactory& factory) {
240
8
    factory.register_function<FunctionFormatNumber>();
241
8
    factory.register_function<FunctionFormat>();
242
8
}
243
244
} // namespace doris