Coverage Report

Created: 2026-03-13 14:44

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
be/src/exprs/function/functions_logical.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/FunctionsLogical.cpp
19
// and modified by Doris
20
21
#include "exprs/function/functions_logical.h"
22
23
#include <glog/logging.h>
24
25
#include <algorithm>
26
#include <ranges>
27
#include <utility>
28
29
#include "common/compiler_util.h" // IWYU pragma: keep
30
#include "common/status.h"
31
#include "core/assert_cast.h"
32
#include "core/block/block.h"
33
#include "core/block/column_with_type_and_name.h"
34
#include "core/column/column.h"
35
#include "core/column/column_const.h"
36
#include "core/column/column_nullable.h"
37
#include "core/column/column_vector.h"
38
#include "core/data_type/data_type_nullable.h"
39
#include "core/data_type/data_type_number.h"
40
#include "core/string_ref.h"
41
#include "exprs/aggregate/aggregate_function.h"
42
#include "exprs/function/simple_function_factory.h"
43
44
namespace doris {
45
class FunctionContext;
46
} // namespace doris
47
48
namespace doris {
49
50
namespace {
51
using namespace FunctionsLogicalDetail;
52
53
template <class Op>
54
0
void vector_const(const IColumn* left, const ColumnConst* right, IColumn* res, size_t rows) {
55
0
    const auto* __restrict l_datas = assert_cast<const ColumnUInt8*>(left)->get_data().data();
56
0
    auto r_data = (uint8_t)right->get_bool(0);
57
0
    auto* __restrict res_datas = assert_cast<ColumnUInt8*>(res)->get_data().data();
58
59
0
    for (size_t i = 0; i < rows; ++i) {
60
0
        res_datas[i] = Op::apply(l_datas[i], r_data);
61
0
    }
62
0
}
Unexecuted instantiation: functions_logical.cpp:_ZN5doris12_GLOBAL__N_112vector_constINS_22FunctionsLogicalDetail7AndImplEEEvPKNS_7IColumnEPKNS_11ColumnConstEPS4_m
Unexecuted instantiation: functions_logical.cpp:_ZN5doris12_GLOBAL__N_112vector_constINS_22FunctionsLogicalDetail6OrImplEEEvPKNS_7IColumnEPKNS_11ColumnConstEPS4_m
Unexecuted instantiation: functions_logical.cpp:_ZN5doris12_GLOBAL__N_112vector_constINS_22FunctionsLogicalDetail7XorImplEEEvPKNS_7IColumnEPKNS_11ColumnConstEPS4_m
63
64
template <class Op>
65
1
void vector_vector(const IColumn* left, const IColumn* right, IColumn* res, size_t rows) {
66
1
    const auto* __restrict l_datas = assert_cast<const ColumnUInt8*>(left)->get_data().data();
67
1
    const auto* __restrict r_datas = assert_cast<const ColumnUInt8*>(right)->get_data().data();
68
1
    auto* __restrict res_datas = assert_cast<ColumnUInt8*>(res)->get_data().data();
69
70
10
    for (size_t i = 0; i < rows; ++i) {
71
9
        res_datas[i] = Op::apply(l_datas[i], r_datas[i]);
72
9
    }
73
1
}
Unexecuted instantiation: functions_logical.cpp:_ZN5doris12_GLOBAL__N_113vector_vectorINS_22FunctionsLogicalDetail7AndImplEEEvPKNS_7IColumnES6_PS4_m
Unexecuted instantiation: functions_logical.cpp:_ZN5doris12_GLOBAL__N_113vector_vectorINS_22FunctionsLogicalDetail6OrImplEEEvPKNS_7IColumnES6_PS4_m
functions_logical.cpp:_ZN5doris12_GLOBAL__N_113vector_vectorINS_22FunctionsLogicalDetail7XorImplEEEvPKNS_7IColumnES6_PS4_m
Line
Count
Source
65
1
void vector_vector(const IColumn* left, const IColumn* right, IColumn* res, size_t rows) {
66
1
    const auto* __restrict l_datas = assert_cast<const ColumnUInt8*>(left)->get_data().data();
67
1
    const auto* __restrict r_datas = assert_cast<const ColumnUInt8*>(right)->get_data().data();
68
1
    auto* __restrict res_datas = assert_cast<ColumnUInt8*>(res)->get_data().data();
69
70
10
    for (size_t i = 0; i < rows; ++i) {
71
9
        res_datas[i] = Op::apply(l_datas[i], r_datas[i]);
72
9
    }
73
1
}
74
75
31
std::pair<const IColumn*, ColumnPtr> get_nested_and_null_column(const IColumn* column) {
76
31
    auto null_column = check_and_get_column<const ColumnNullable>(column);
77
31
    if (null_column) {
78
11
        return {null_column->get_nested_column_ptr().get(), null_column->get_null_map_column_ptr()};
79
20
    } else {
80
20
        return {column, ColumnUInt8::create(column->size(), 0)};
81
20
    }
82
31
}
83
84
template <class Op>
85
void vector_const_null(const IColumn* left, const ColumnConst* right, IColumn* res, IColumn* nulls,
86
17
                       size_t rows) {
87
17
    auto [data_column, null_column_ptr] = get_nested_and_null_column(left);
88
17
    const auto* __restrict l_datas =
89
17
            assert_cast<const ColumnUInt8*>(data_column)->get_data().data();
90
17
    const auto* __restrict l_nulls =
91
17
            assert_cast<const ColumnUInt8*>(null_column_ptr.get())->get_data().data();
92
93
17
    auto* __restrict res_datas = assert_cast<ColumnUInt8*>(res)->get_data().data();
94
17
    auto* __restrict res_nulls = assert_cast<ColumnUInt8*>(nulls)->get_data().data();
95
96
17
    auto r_data_ptr = right->get_data_at(0);
97
98
17
    if (r_data_ptr.data == nullptr) {
99
41
        for (size_t i = 0; i < rows; ++i) {
100
24
            res_nulls[i] = Op::apply_null(l_datas[i], l_nulls[i], 1, true);
101
24
            res_datas[i] = Op::apply(l_datas[i], 1);
102
24
        }
103
17
    } else {
104
0
        UInt8 r_data = *(UInt8*)r_data_ptr.data;
105
0
        for (size_t i = 0; i < rows; ++i) {
106
0
            res_nulls[i] = Op::apply_null(l_datas[i], l_nulls[i], r_data, false);
107
0
            res_datas[i] = Op::apply(l_datas[i], r_data);
108
0
        }
109
0
    }
110
17
}
functions_logical.cpp:_ZN5doris12_GLOBAL__N_117vector_const_nullINS_22FunctionsLogicalDetail7AndImplEEEvPKNS_7IColumnEPKNS_11ColumnConstEPS4_SA_m
Line
Count
Source
86
14
                       size_t rows) {
87
14
    auto [data_column, null_column_ptr] = get_nested_and_null_column(left);
88
14
    const auto* __restrict l_datas =
89
14
            assert_cast<const ColumnUInt8*>(data_column)->get_data().data();
90
14
    const auto* __restrict l_nulls =
91
14
            assert_cast<const ColumnUInt8*>(null_column_ptr.get())->get_data().data();
92
93
14
    auto* __restrict res_datas = assert_cast<ColumnUInt8*>(res)->get_data().data();
94
14
    auto* __restrict res_nulls = assert_cast<ColumnUInt8*>(nulls)->get_data().data();
95
96
14
    auto r_data_ptr = right->get_data_at(0);
97
98
14
    if (r_data_ptr.data == nullptr) {
99
29
        for (size_t i = 0; i < rows; ++i) {
100
15
            res_nulls[i] = Op::apply_null(l_datas[i], l_nulls[i], 1, true);
101
15
            res_datas[i] = Op::apply(l_datas[i], 1);
102
15
        }
103
14
    } else {
104
0
        UInt8 r_data = *(UInt8*)r_data_ptr.data;
105
0
        for (size_t i = 0; i < rows; ++i) {
106
0
            res_nulls[i] = Op::apply_null(l_datas[i], l_nulls[i], r_data, false);
107
0
            res_datas[i] = Op::apply(l_datas[i], r_data);
108
0
        }
109
0
    }
110
14
}
functions_logical.cpp:_ZN5doris12_GLOBAL__N_117vector_const_nullINS_22FunctionsLogicalDetail6OrImplEEEvPKNS_7IColumnEPKNS_11ColumnConstEPS4_SA_m
Line
Count
Source
86
3
                       size_t rows) {
87
3
    auto [data_column, null_column_ptr] = get_nested_and_null_column(left);
88
3
    const auto* __restrict l_datas =
89
3
            assert_cast<const ColumnUInt8*>(data_column)->get_data().data();
90
3
    const auto* __restrict l_nulls =
91
3
            assert_cast<const ColumnUInt8*>(null_column_ptr.get())->get_data().data();
92
93
3
    auto* __restrict res_datas = assert_cast<ColumnUInt8*>(res)->get_data().data();
94
3
    auto* __restrict res_nulls = assert_cast<ColumnUInt8*>(nulls)->get_data().data();
95
96
3
    auto r_data_ptr = right->get_data_at(0);
97
98
3
    if (r_data_ptr.data == nullptr) {
99
12
        for (size_t i = 0; i < rows; ++i) {
100
9
            res_nulls[i] = Op::apply_null(l_datas[i], l_nulls[i], 1, true);
101
9
            res_datas[i] = Op::apply(l_datas[i], 1);
102
9
        }
103
3
    } else {
104
0
        UInt8 r_data = *(UInt8*)r_data_ptr.data;
105
0
        for (size_t i = 0; i < rows; ++i) {
106
0
            res_nulls[i] = Op::apply_null(l_datas[i], l_nulls[i], r_data, false);
107
0
            res_datas[i] = Op::apply(l_datas[i], r_data);
108
0
        }
109
0
    }
110
3
}
111
112
template <class Op>
113
void vector_vector_null(const IColumn* left, const IColumn* right, IColumn* res, IColumn* nulls,
114
7
                        size_t rows) {
115
7
    auto [l_datas_ptr, l_nulls_ptr] = get_nested_and_null_column(left);
116
7
    auto [r_datas_ptr, r_nulls_ptr] = get_nested_and_null_column(right);
117
118
7
    const auto* __restrict l_datas =
119
7
            assert_cast<const ColumnUInt8*>(l_datas_ptr)->get_data().data();
120
7
    const auto* __restrict r_datas =
121
7
            assert_cast<const ColumnUInt8*>(r_datas_ptr)->get_data().data();
122
7
    const auto* __restrict l_nulls =
123
7
            assert_cast<const ColumnUInt8*>(l_nulls_ptr.get())->get_data().data();
124
7
    const auto* __restrict r_nulls =
125
7
            assert_cast<const ColumnUInt8*>(r_nulls_ptr.get())->get_data().data();
126
127
7
    auto* __restrict res_datas = assert_cast<ColumnUInt8*>(res)->get_data().data();
128
7
    auto* __restrict res_nulls = assert_cast<ColumnUInt8*>(nulls)->get_data().data();
129
130
14
    for (size_t i = 0; i < rows; ++i) {
131
7
        res_nulls[i] = Op::apply_null(l_datas[i], l_nulls[i], r_datas[i], r_nulls[i]);
132
7
        res_datas[i] = Op::apply(l_datas[i], r_datas[i]);
133
7
    }
134
7
}
functions_logical.cpp:_ZN5doris12_GLOBAL__N_118vector_vector_nullINS_22FunctionsLogicalDetail7AndImplEEEvPKNS_7IColumnES6_PS4_S7_m
Line
Count
Source
114
2
                        size_t rows) {
115
2
    auto [l_datas_ptr, l_nulls_ptr] = get_nested_and_null_column(left);
116
2
    auto [r_datas_ptr, r_nulls_ptr] = get_nested_and_null_column(right);
117
118
2
    const auto* __restrict l_datas =
119
2
            assert_cast<const ColumnUInt8*>(l_datas_ptr)->get_data().data();
120
2
    const auto* __restrict r_datas =
121
2
            assert_cast<const ColumnUInt8*>(r_datas_ptr)->get_data().data();
122
2
    const auto* __restrict l_nulls =
123
2
            assert_cast<const ColumnUInt8*>(l_nulls_ptr.get())->get_data().data();
124
2
    const auto* __restrict r_nulls =
125
2
            assert_cast<const ColumnUInt8*>(r_nulls_ptr.get())->get_data().data();
126
127
2
    auto* __restrict res_datas = assert_cast<ColumnUInt8*>(res)->get_data().data();
128
2
    auto* __restrict res_nulls = assert_cast<ColumnUInt8*>(nulls)->get_data().data();
129
130
4
    for (size_t i = 0; i < rows; ++i) {
131
2
        res_nulls[i] = Op::apply_null(l_datas[i], l_nulls[i], r_datas[i], r_nulls[i]);
132
2
        res_datas[i] = Op::apply(l_datas[i], r_datas[i]);
133
2
    }
134
2
}
functions_logical.cpp:_ZN5doris12_GLOBAL__N_118vector_vector_nullINS_22FunctionsLogicalDetail6OrImplEEEvPKNS_7IColumnES6_PS4_S7_m
Line
Count
Source
114
5
                        size_t rows) {
115
5
    auto [l_datas_ptr, l_nulls_ptr] = get_nested_and_null_column(left);
116
5
    auto [r_datas_ptr, r_nulls_ptr] = get_nested_and_null_column(right);
117
118
5
    const auto* __restrict l_datas =
119
5
            assert_cast<const ColumnUInt8*>(l_datas_ptr)->get_data().data();
120
5
    const auto* __restrict r_datas =
121
5
            assert_cast<const ColumnUInt8*>(r_datas_ptr)->get_data().data();
122
5
    const auto* __restrict l_nulls =
123
5
            assert_cast<const ColumnUInt8*>(l_nulls_ptr.get())->get_data().data();
124
5
    const auto* __restrict r_nulls =
125
5
            assert_cast<const ColumnUInt8*>(r_nulls_ptr.get())->get_data().data();
126
127
5
    auto* __restrict res_datas = assert_cast<ColumnUInt8*>(res)->get_data().data();
128
5
    auto* __restrict res_nulls = assert_cast<ColumnUInt8*>(nulls)->get_data().data();
129
130
10
    for (size_t i = 0; i < rows; ++i) {
131
5
        res_nulls[i] = Op::apply_null(l_datas[i], l_nulls[i], r_datas[i], r_nulls[i]);
132
5
        res_datas[i] = Op::apply(l_datas[i], r_datas[i]);
133
5
    }
134
5
}
135
136
template <class Op>
137
void basic_execute_impl(ColumnRawPtrs arguments, ColumnWithTypeAndName& result_info,
138
1
                        size_t input_rows_count) {
139
1
    auto col_res = ColumnUInt8::create(input_rows_count);
140
1
    if (auto l = check_and_get_column<ColumnConst>(arguments[0])) {
141
0
        vector_const<Op>(arguments[1], l, col_res.get(), input_rows_count);
142
1
    } else if (auto r = check_and_get_column<ColumnConst>(arguments[1])) {
143
0
        vector_const<Op>(arguments[0], r, col_res.get(), input_rows_count);
144
1
    } else {
145
1
        vector_vector<Op>(arguments[0], arguments[1], col_res.get(), input_rows_count);
146
1
    }
147
1
    result_info.column = std::move(col_res);
148
1
}
Unexecuted instantiation: functions_logical.cpp:_ZN5doris12_GLOBAL__N_118basic_execute_implINS_22FunctionsLogicalDetail7AndImplEEEvSt6vectorIPKNS_7IColumnESaIS7_EERNS_21ColumnWithTypeAndNameEm
Unexecuted instantiation: functions_logical.cpp:_ZN5doris12_GLOBAL__N_118basic_execute_implINS_22FunctionsLogicalDetail6OrImplEEEvSt6vectorIPKNS_7IColumnESaIS7_EERNS_21ColumnWithTypeAndNameEm
functions_logical.cpp:_ZN5doris12_GLOBAL__N_118basic_execute_implINS_22FunctionsLogicalDetail7XorImplEEEvSt6vectorIPKNS_7IColumnESaIS7_EERNS_21ColumnWithTypeAndNameEm
Line
Count
Source
138
1
                        size_t input_rows_count) {
139
1
    auto col_res = ColumnUInt8::create(input_rows_count);
140
1
    if (auto l = check_and_get_column<ColumnConst>(arguments[0])) {
141
0
        vector_const<Op>(arguments[1], l, col_res.get(), input_rows_count);
142
1
    } else if (auto r = check_and_get_column<ColumnConst>(arguments[1])) {
143
0
        vector_const<Op>(arguments[0], r, col_res.get(), input_rows_count);
144
1
    } else {
145
1
        vector_vector<Op>(arguments[0], arguments[1], col_res.get(), input_rows_count);
146
1
    }
147
1
    result_info.column = std::move(col_res);
148
1
}
149
150
template <class Op>
151
void null_execute_impl(ColumnRawPtrs arguments, ColumnWithTypeAndName& result_info,
152
24
                       size_t input_rows_count) {
153
24
    auto col_nulls = ColumnUInt8::create(input_rows_count);
154
24
    auto col_res = ColumnUInt8::create(input_rows_count);
155
24
    if (auto l = check_and_get_column<ColumnConst>(arguments[0])) {
156
0
        vector_const_null<Op>(arguments[1], l, col_res.get(), col_nulls.get(), input_rows_count);
157
24
    } else if (auto r = check_and_get_column<ColumnConst>(arguments[1])) {
158
17
        vector_const_null<Op>(arguments[0], r, col_res.get(), col_nulls.get(), input_rows_count);
159
17
    } else {
160
7
        vector_vector_null<Op>(arguments[0], arguments[1], col_res.get(), col_nulls.get(),
161
7
                               input_rows_count);
162
7
    }
163
24
    result_info.column = ColumnNullable::create(std::move(col_res), std::move(col_nulls));
164
24
}
functions_logical.cpp:_ZN5doris12_GLOBAL__N_117null_execute_implINS_22FunctionsLogicalDetail7AndImplEEEvSt6vectorIPKNS_7IColumnESaIS7_EERNS_21ColumnWithTypeAndNameEm
Line
Count
Source
152
16
                       size_t input_rows_count) {
153
16
    auto col_nulls = ColumnUInt8::create(input_rows_count);
154
16
    auto col_res = ColumnUInt8::create(input_rows_count);
155
16
    if (auto l = check_and_get_column<ColumnConst>(arguments[0])) {
156
0
        vector_const_null<Op>(arguments[1], l, col_res.get(), col_nulls.get(), input_rows_count);
157
16
    } else if (auto r = check_and_get_column<ColumnConst>(arguments[1])) {
158
14
        vector_const_null<Op>(arguments[0], r, col_res.get(), col_nulls.get(), input_rows_count);
159
14
    } else {
160
2
        vector_vector_null<Op>(arguments[0], arguments[1], col_res.get(), col_nulls.get(),
161
2
                               input_rows_count);
162
2
    }
163
16
    result_info.column = ColumnNullable::create(std::move(col_res), std::move(col_nulls));
164
16
}
functions_logical.cpp:_ZN5doris12_GLOBAL__N_117null_execute_implINS_22FunctionsLogicalDetail6OrImplEEEvSt6vectorIPKNS_7IColumnESaIS7_EERNS_21ColumnWithTypeAndNameEm
Line
Count
Source
152
8
                       size_t input_rows_count) {
153
8
    auto col_nulls = ColumnUInt8::create(input_rows_count);
154
8
    auto col_res = ColumnUInt8::create(input_rows_count);
155
8
    if (auto l = check_and_get_column<ColumnConst>(arguments[0])) {
156
0
        vector_const_null<Op>(arguments[1], l, col_res.get(), col_nulls.get(), input_rows_count);
157
8
    } else if (auto r = check_and_get_column<ColumnConst>(arguments[1])) {
158
3
        vector_const_null<Op>(arguments[0], r, col_res.get(), col_nulls.get(), input_rows_count);
159
5
    } else {
160
5
        vector_vector_null<Op>(arguments[0], arguments[1], col_res.get(), col_nulls.get(),
161
5
                               input_rows_count);
162
5
    }
163
8
    result_info.column = ColumnNullable::create(std::move(col_res), std::move(col_nulls));
164
8
}
165
166
} // namespace
167
168
6.55k
bool is_native_number(PrimitiveType type) {
169
6.55k
    return (is_int_or_bool(type) && type != TYPE_LARGEINT) || is_float_or_double(type);
170
6.55k
}
171
172
template <typename Impl, typename Name>
173
DataTypePtr FunctionAnyArityLogical<Impl, Name>::get_return_type_impl(
174
2.97k
        const DataTypes& arguments) const {
175
2.97k
    if (arguments.size() < 2) {
176
0
        throw doris::Exception(
177
0
                ErrorCode::INVALID_ARGUMENT,
178
0
                "Number of arguments for function \"{}\" should be at least 2: passed {}",
179
0
                get_name(), arguments.size());
180
0
    }
181
182
2.97k
    bool has_nullable_arguments = false;
183
8.91k
    for (size_t i = 0; i < arguments.size(); ++i) {
184
5.94k
        const auto& arg_type = arguments[i];
185
186
5.94k
        if (!has_nullable_arguments) {
187
3.83k
            has_nullable_arguments = arg_type->is_nullable();
188
3.83k
            if (has_nullable_arguments && !Impl::special_implementation_for_nulls()) {
189
0
                LOG(WARNING) << fmt::format(
190
0
                        "Logical error: Unexpected type of argument for function \"{}\" argument "
191
0
                        "{} is of type {}",
192
0
                        get_name(), i + 1, arg_type->get_name());
193
0
            }
194
3.83k
        }
195
196
5.94k
        auto arg_primitive_type = arg_type->get_primitive_type();
197
5.94k
        if (!(is_native_number(arg_primitive_type) ||
198
5.94k
              (Impl::special_implementation_for_nulls() && is_native_number(arg_primitive_type)))) {
199
0
            throw doris::Exception(ErrorCode::INVALID_ARGUMENT,
200
0
                                   "Illegal type ({}) of {} argument of function {}",
201
0
                                   arg_type->get_name(), i + 1, get_name());
202
0
        }
203
5.94k
    }
204
205
2.97k
    auto result_type = std::make_shared<DataTypeUInt8>();
206
2.97k
    return has_nullable_arguments ? make_nullable(result_type) : result_type;
207
2.97k
}
_ZNK5doris22FunctionsLogicalDetail23FunctionAnyArityLogicalINS0_7AndImplENS_7NameAndEE20get_return_type_implERKSt6vectorISt10shared_ptrIKNS_9IDataTypeEESaIS9_EE
Line
Count
Source
174
1.14k
        const DataTypes& arguments) const {
175
1.14k
    if (arguments.size() < 2) {
176
0
        throw doris::Exception(
177
0
                ErrorCode::INVALID_ARGUMENT,
178
0
                "Number of arguments for function \"{}\" should be at least 2: passed {}",
179
0
                get_name(), arguments.size());
180
0
    }
181
182
1.14k
    bool has_nullable_arguments = false;
183
3.42k
    for (size_t i = 0; i < arguments.size(); ++i) {
184
2.28k
        const auto& arg_type = arguments[i];
185
186
2.28k
        if (!has_nullable_arguments) {
187
1.72k
            has_nullable_arguments = arg_type->is_nullable();
188
1.72k
            if (has_nullable_arguments && !Impl::special_implementation_for_nulls()) {
189
0
                LOG(WARNING) << fmt::format(
190
0
                        "Logical error: Unexpected type of argument for function \"{}\" argument "
191
0
                        "{} is of type {}",
192
0
                        get_name(), i + 1, arg_type->get_name());
193
0
            }
194
1.72k
        }
195
196
2.28k
        auto arg_primitive_type = arg_type->get_primitive_type();
197
2.28k
        if (!(is_native_number(arg_primitive_type) ||
198
2.28k
              (Impl::special_implementation_for_nulls() && is_native_number(arg_primitive_type)))) {
199
0
            throw doris::Exception(ErrorCode::INVALID_ARGUMENT,
200
0
                                   "Illegal type ({}) of {} argument of function {}",
201
0
                                   arg_type->get_name(), i + 1, get_name());
202
0
        }
203
2.28k
    }
204
205
1.14k
    auto result_type = std::make_shared<DataTypeUInt8>();
206
1.14k
    return has_nullable_arguments ? make_nullable(result_type) : result_type;
207
1.14k
}
_ZNK5doris22FunctionsLogicalDetail23FunctionAnyArityLogicalINS0_6OrImplENS_6NameOrEE20get_return_type_implERKSt6vectorISt10shared_ptrIKNS_9IDataTypeEESaIS9_EE
Line
Count
Source
174
1.82k
        const DataTypes& arguments) const {
175
1.82k
    if (arguments.size() < 2) {
176
0
        throw doris::Exception(
177
0
                ErrorCode::INVALID_ARGUMENT,
178
0
                "Number of arguments for function \"{}\" should be at least 2: passed {}",
179
0
                get_name(), arguments.size());
180
0
    }
181
182
1.82k
    bool has_nullable_arguments = false;
183
5.48k
    for (size_t i = 0; i < arguments.size(); ++i) {
184
3.65k
        const auto& arg_type = arguments[i];
185
186
3.65k
        if (!has_nullable_arguments) {
187
2.11k
            has_nullable_arguments = arg_type->is_nullable();
188
2.11k
            if (has_nullable_arguments && !Impl::special_implementation_for_nulls()) {
189
0
                LOG(WARNING) << fmt::format(
190
0
                        "Logical error: Unexpected type of argument for function \"{}\" argument "
191
0
                        "{} is of type {}",
192
0
                        get_name(), i + 1, arg_type->get_name());
193
0
            }
194
2.11k
        }
195
196
3.65k
        auto arg_primitive_type = arg_type->get_primitive_type();
197
3.65k
        if (!(is_native_number(arg_primitive_type) ||
198
3.65k
              (Impl::special_implementation_for_nulls() && is_native_number(arg_primitive_type)))) {
199
0
            throw doris::Exception(ErrorCode::INVALID_ARGUMENT,
200
0
                                   "Illegal type ({}) of {} argument of function {}",
201
0
                                   arg_type->get_name(), i + 1, get_name());
202
0
        }
203
3.65k
    }
204
205
1.82k
    auto result_type = std::make_shared<DataTypeUInt8>();
206
1.82k
    return has_nullable_arguments ? make_nullable(result_type) : result_type;
207
1.82k
}
_ZNK5doris22FunctionsLogicalDetail23FunctionAnyArityLogicalINS0_7XorImplENS_7NameXorEE20get_return_type_implERKSt6vectorISt10shared_ptrIKNS_9IDataTypeEESaIS9_EE
Line
Count
Source
174
1
        const DataTypes& arguments) const {
175
1
    if (arguments.size() < 2) {
176
0
        throw doris::Exception(
177
0
                ErrorCode::INVALID_ARGUMENT,
178
0
                "Number of arguments for function \"{}\" should be at least 2: passed {}",
179
0
                get_name(), arguments.size());
180
0
    }
181
182
1
    bool has_nullable_arguments = false;
183
3
    for (size_t i = 0; i < arguments.size(); ++i) {
184
2
        const auto& arg_type = arguments[i];
185
186
2
        if (!has_nullable_arguments) {
187
2
            has_nullable_arguments = arg_type->is_nullable();
188
2
            if (has_nullable_arguments && !Impl::special_implementation_for_nulls()) {
189
0
                LOG(WARNING) << fmt::format(
190
0
                        "Logical error: Unexpected type of argument for function \"{}\" argument "
191
0
                        "{} is of type {}",
192
0
                        get_name(), i + 1, arg_type->get_name());
193
0
            }
194
2
        }
195
196
2
        auto arg_primitive_type = arg_type->get_primitive_type();
197
2
        if (!(is_native_number(arg_primitive_type) ||
198
2
              (Impl::special_implementation_for_nulls() && is_native_number(arg_primitive_type)))) {
199
0
            throw doris::Exception(ErrorCode::INVALID_ARGUMENT,
200
0
                                   "Illegal type ({}) of {} argument of function {}",
201
0
                                   arg_type->get_name(), i + 1, get_name());
202
0
        }
203
2
    }
204
205
1
    auto result_type = std::make_shared<DataTypeUInt8>();
206
1
    return has_nullable_arguments ? make_nullable(result_type) : result_type;
207
1
}
208
209
template <typename Impl, typename Name>
210
Status FunctionAnyArityLogical<Impl, Name>::execute_impl(FunctionContext* context, Block& block,
211
                                                         const ColumnNumbers& arguments,
212
                                                         uint32_t result_index,
213
25
                                                         size_t input_rows_count) const {
214
25
    ColumnRawPtrs args_in;
215
25
    for (const auto arg_index : arguments)
216
50
        args_in.push_back(block.get_by_position(arg_index).column.get());
217
218
25
    auto& result_info = block.get_by_position(result_index);
219
25
    if constexpr (Impl::special_implementation_for_nulls()) {
220
24
        if (result_info.type->is_nullable()) {
221
24
            null_execute_impl<Impl>(std::move(args_in), result_info, input_rows_count);
222
24
        } else {
223
0
            basic_execute_impl<Impl>(std::move(args_in), result_info, input_rows_count);
224
0
        }
225
24
    } else {
226
1
        DCHECK(std::ranges::all_of(args_in, [](const auto& arg) { return !arg->is_nullable(); }));
227
1
        basic_execute_impl<Impl>(std::move(args_in), result_info, input_rows_count);
228
1
    }
229
25
    return Status::OK();
230
25
}
_ZNK5doris22FunctionsLogicalDetail23FunctionAnyArityLogicalINS0_7AndImplENS_7NameAndEE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjm
Line
Count
Source
213
16
                                                         size_t input_rows_count) const {
214
16
    ColumnRawPtrs args_in;
215
16
    for (const auto arg_index : arguments)
216
32
        args_in.push_back(block.get_by_position(arg_index).column.get());
217
218
16
    auto& result_info = block.get_by_position(result_index);
219
16
    if constexpr (Impl::special_implementation_for_nulls()) {
220
16
        if (result_info.type->is_nullable()) {
221
16
            null_execute_impl<Impl>(std::move(args_in), result_info, input_rows_count);
222
16
        } else {
223
0
            basic_execute_impl<Impl>(std::move(args_in), result_info, input_rows_count);
224
0
        }
225
    } else {
226
        DCHECK(std::ranges::all_of(args_in, [](const auto& arg) { return !arg->is_nullable(); }));
227
        basic_execute_impl<Impl>(std::move(args_in), result_info, input_rows_count);
228
    }
229
16
    return Status::OK();
230
16
}
_ZNK5doris22FunctionsLogicalDetail23FunctionAnyArityLogicalINS0_6OrImplENS_6NameOrEE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjm
Line
Count
Source
213
8
                                                         size_t input_rows_count) const {
214
8
    ColumnRawPtrs args_in;
215
8
    for (const auto arg_index : arguments)
216
16
        args_in.push_back(block.get_by_position(arg_index).column.get());
217
218
8
    auto& result_info = block.get_by_position(result_index);
219
8
    if constexpr (Impl::special_implementation_for_nulls()) {
220
8
        if (result_info.type->is_nullable()) {
221
8
            null_execute_impl<Impl>(std::move(args_in), result_info, input_rows_count);
222
8
        } else {
223
0
            basic_execute_impl<Impl>(std::move(args_in), result_info, input_rows_count);
224
0
        }
225
    } else {
226
        DCHECK(std::ranges::all_of(args_in, [](const auto& arg) { return !arg->is_nullable(); }));
227
        basic_execute_impl<Impl>(std::move(args_in), result_info, input_rows_count);
228
    }
229
8
    return Status::OK();
230
8
}
_ZNK5doris22FunctionsLogicalDetail23FunctionAnyArityLogicalINS0_7XorImplENS_7NameXorEE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjm
Line
Count
Source
213
1
                                                         size_t input_rows_count) const {
214
1
    ColumnRawPtrs args_in;
215
1
    for (const auto arg_index : arguments)
216
2
        args_in.push_back(block.get_by_position(arg_index).column.get());
217
218
1
    auto& result_info = block.get_by_position(result_index);
219
    if constexpr (Impl::special_implementation_for_nulls()) {
220
        if (result_info.type->is_nullable()) {
221
            null_execute_impl<Impl>(std::move(args_in), result_info, input_rows_count);
222
        } else {
223
            basic_execute_impl<Impl>(std::move(args_in), result_info, input_rows_count);
224
        }
225
1
    } else {
226
        DCHECK(std::ranges::all_of(args_in, [](const auto& arg) { return !arg->is_nullable(); }));
227
1
        basic_execute_impl<Impl>(std::move(args_in), result_info, input_rows_count);
228
1
    }
229
1
    return Status::OK();
230
1
}
231
232
template <PrimitiveType A, typename Op>
233
struct UnaryOperationImpl {
234
    using ArrayA = typename ColumnVector<A>::Container;
235
    using ArrayC = typename ColumnVector<Op::ResultType>::Container;
236
237
1.01k
    static void NO_INLINE vector(const ArrayA& a, ArrayC& c) {
238
799k
        std::transform(a.cbegin(), a.cend(), c.begin(), [](const auto x) { return Op::apply(x); });
239
1.01k
    }
240
};
241
242
template <template <PrimitiveType> class Impl, typename Name>
243
DataTypePtr FunctionUnaryLogical<Impl, Name>::get_return_type_impl(
244
615
        const DataTypes& arguments) const {
245
615
    if (!is_native_number(arguments[0]->get_primitive_type())) {
246
0
        throw doris::Exception(ErrorCode::INVALID_ARGUMENT,
247
0
                               "Illegal type ({}) of argument of function {}",
248
0
                               arguments[0]->get_name(), get_name());
249
0
    }
250
251
615
    return std::make_shared<DataTypeUInt8>();
252
615
}
253
254
template <template <PrimitiveType> class Impl, PrimitiveType T>
255
1.01k
bool functionUnaryExecuteType(Block& block, const ColumnNumbers& arguments, size_t result) {
256
1.01k
    if (auto col = check_and_get_column<ColumnVector<T>>(
257
1.01k
                block.get_by_position(arguments[0]).column.get())) {
258
1.01k
        auto col_res = ColumnUInt8::create();
259
260
1.01k
        typename ColumnUInt8::Container& vec_res = col_res->get_data();
261
1.01k
        vec_res.resize(col->get_data().size());
262
1.01k
        UnaryOperationImpl<T, Impl<T>>::vector(col->get_data(), vec_res);
263
264
1.01k
        block.replace_by_position(result, std::move(col_res));
265
1.01k
        return true;
266
1.01k
    }
267
268
1
    return false;
269
1.01k
}
270
271
template <template <PrimitiveType> class Impl, typename Name>
272
Status FunctionUnaryLogical<Impl, Name>::execute_impl(FunctionContext* context, Block& block,
273
                                                      const ColumnNumbers& arguments,
274
                                                      uint32_t result,
275
1.01k
                                                      size_t /*input_rows_count*/) const {
276
1.01k
    if (!functionUnaryExecuteType<Impl, TYPE_BOOLEAN>(block, arguments, result)) {
277
0
        throw doris::Exception(ErrorCode::INVALID_ARGUMENT,
278
0
                               "Illegal column {} of argument of function {}",
279
0
                               block.get_by_position(arguments[0]).column->get_name(), get_name());
280
0
    }
281
282
1.01k
    return Status::OK();
283
1.01k
}
284
285
8
void register_function_logical(SimpleFunctionFactory& instance) {
286
8
    instance.register_function<FunctionAnd>();
287
8
    instance.register_function<FunctionOr>();
288
8
    instance.register_function<FunctionNot>();
289
8
    instance.register_function<FunctionXor>();
290
8
}
291
292
} // namespace doris