Coverage Report

Created: 2026-03-12 14:02

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
be/src/exprs/function/function_helpers.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
// This file is copied from
18
// https://github.com/ClickHouse/ClickHouse/blob/master/src/Functions/FunctionHelpers.cpp
19
// and modified by Doris
20
21
#include "exprs/function/function_helpers.h"
22
23
#include <fmt/format.h>
24
#include <glog/logging.h>
25
26
#include <algorithm>
27
#include <memory>
28
#include <ostream>
29
#include <string>
30
#include <vector>
31
32
#include "common/consts.h"
33
#include "common/status.h"
34
#include "core/block/column_with_type_and_name.h"
35
#include "core/column/column_nullable.h"
36
#include "core/column/column_string.h"
37
#include "core/data_type/data_type_nullable.h"
38
#include "exprs/function/function.h"
39
#include "util/string_util.h"
40
41
namespace doris {
42
#include "common/compile_check_begin.h"
43
std::tuple<Block, ColumnNumbers> create_block_with_nested_columns(const Block& block,
44
                                                                  const ColumnNumbers& args,
45
46.4k
                                                                  const bool need_check_same) {
46
46.4k
    Block res;
47
46.4k
    ColumnNumbers res_args(args.size());
48
46.4k
    res.reserve(args.size() + 1);
49
50
    // only build temp block by args column, if args[i] == args[j]
51
    // just keep one
52
154k
    for (size_t i = 0; i < args.size(); ++i) {
53
108k
        bool is_in_res = false;
54
108k
        size_t pre_loc = 0;
55
56
108k
        if (need_check_same) {
57
24
            for (int j = 0; j < i; ++j) {
58
10
                if (args[j] == args[i]) {
59
0
                    is_in_res = true;
60
0
                    pre_loc = res_args[j];
61
0
                    break;
62
0
                }
63
10
            }
64
14
        }
65
66
108k
        if (!is_in_res) {
67
108k
            const auto& col = block.get_by_position(args[i]);
68
108k
            if (col.type->is_nullable()) {
69
77.6k
                const DataTypePtr& nested_type =
70
77.6k
                        static_cast<const DataTypeNullable&>(*col.type).get_nested_type();
71
72
77.6k
                if (!col.column) {
73
38.8k
                    res.insert({nullptr, nested_type, col.name});
74
38.8k
                } else if (const auto* nullable =
75
38.7k
                                   check_and_get_column<ColumnNullable>(*col.column)) {
76
15.3k
                    const auto& nested_col = nullable->get_nested_column_ptr();
77
15.3k
                    res.insert({nested_col, nested_type, col.name});
78
23.4k
                } else if (const auto* const_column =
79
23.4k
                                   check_and_get_column<ColumnConst>(*col.column)) {
80
23.4k
                    const auto& nested_col =
81
23.4k
                            check_and_get_column<ColumnNullable>(const_column->get_data_column())
82
23.4k
                                    ->get_nested_column_ptr();
83
23.4k
                    res.insert({ColumnConst::create(nested_col, col.column->size()), nested_type,
84
23.4k
                                col.name});
85
23.4k
                } else {
86
0
                    throw doris::Exception(
87
0
                            ErrorCode::INTERNAL_ERROR,
88
0
                            "Illegal column= {},  for DataTypeNullable" + col.column->get_name());
89
0
                }
90
77.6k
            } else {
91
30.6k
                res.insert(col);
92
30.6k
            }
93
94
108k
            res_args[i] = res.columns() - 1;
95
108k
        } else {
96
10
            res_args[i] = (int)pre_loc;
97
10
        }
98
108k
    }
99
100
46.4k
    return {std::move(res), std::move(res_args)};
101
46.4k
}
102
103
std::tuple<Block, ColumnNumbers, size_t> create_block_with_nested_columns(const Block& block,
104
                                                                          const ColumnNumbers& args,
105
6
                                                                          uint32_t result) {
106
6
    auto [res, res_args] = create_block_with_nested_columns(block, args, true);
107
    // insert result column in temp block
108
6
    res.insert(block.get_by_position(result));
109
6
    return {std::move(res), std::move(res_args), res.columns() - 1};
110
6
}
111
112
void validate_argument_type(const IFunction& func, const DataTypes& arguments,
113
                            size_t argument_index, bool (*validator_func)(const IDataType&),
114
0
                            const char* expected_type_description) {
115
0
    if (arguments.size() <= argument_index) {
116
0
        throw doris::Exception(ErrorCode::INVALID_ARGUMENT,
117
0
                               "Incorrect number of arguments of function {}" + func.get_name());
118
0
    }
119
120
0
    const auto& argument = arguments[argument_index];
121
0
    if (!validator_func(*argument)) {
122
0
        throw doris::Exception(ErrorCode::INVALID_ARGUMENT,
123
0
                               "Illegal type {} of {} argument of function {} expected {}",
124
0
                               argument->get_name(), argument_index, func.get_name(),
125
0
                               expected_type_description);
126
0
    }
127
0
}
128
129
22.2k
const ColumnConst* check_and_get_column_const_string_or_fixedstring(const IColumn* column) {
130
22.2k
    if (!is_column_const(*column)) return {};
131
132
11.1k
    const ColumnConst* res = assert_cast<const ColumnConst*, TypeCheckOnRelease::DISABLE>(column);
133
134
11.1k
    if (is_column<ColumnString>(&res->get_data_column())) return res;
135
136
18.4E
    return {};
137
11.1k
}
138
#include "common/compile_check_end.h"
139
} // namespace doris