Coverage Report

Created: 2026-03-13 12:15

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
0
std::pair<const IColumn*, ColumnPtr> get_nested_and_null_column(const IColumn* column) {
76
0
    auto null_column = check_and_get_column<const ColumnNullable>(column);
77
0
    if (null_column) {
78
0
        return {null_column->get_nested_column_ptr().get(), null_column->get_null_map_column_ptr()};
79
0
    } else {
80
0
        return {column, ColumnUInt8::create(column->size(), 0)};
81
0
    }
82
0
}
83
84
template <class Op>
85
void vector_const_null(const IColumn* left, const ColumnConst* right, IColumn* res, IColumn* nulls,
86
0
                       size_t rows) {
87
0
    auto [data_column, null_column_ptr] = get_nested_and_null_column(left);
88
0
    const auto* __restrict l_datas =
89
0
            assert_cast<const ColumnUInt8*>(data_column)->get_data().data();
90
0
    const auto* __restrict l_nulls =
91
0
            assert_cast<const ColumnUInt8*>(null_column_ptr.get())->get_data().data();
92
93
0
    auto* __restrict res_datas = assert_cast<ColumnUInt8*>(res)->get_data().data();
94
0
    auto* __restrict res_nulls = assert_cast<ColumnUInt8*>(nulls)->get_data().data();
95
96
0
    auto r_data_ptr = right->get_data_at(0);
97
98
0
    if (r_data_ptr.data == nullptr) {
99
0
        for (size_t i = 0; i < rows; ++i) {
100
0
            res_nulls[i] = Op::apply_null(l_datas[i], l_nulls[i], 1, true);
101
0
            res_datas[i] = Op::apply(l_datas[i], 1);
102
0
        }
103
0
    } 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
0
}
Unexecuted instantiation: functions_logical.cpp:_ZN5doris12_GLOBAL__N_117vector_const_nullINS_22FunctionsLogicalDetail7AndImplEEEvPKNS_7IColumnEPKNS_11ColumnConstEPS4_SA_m
Unexecuted instantiation: functions_logical.cpp:_ZN5doris12_GLOBAL__N_117vector_const_nullINS_22FunctionsLogicalDetail6OrImplEEEvPKNS_7IColumnEPKNS_11ColumnConstEPS4_SA_m
111
112
template <class Op>
113
void vector_vector_null(const IColumn* left, const IColumn* right, IColumn* res, IColumn* nulls,
114
0
                        size_t rows) {
115
0
    auto [l_datas_ptr, l_nulls_ptr] = get_nested_and_null_column(left);
116
0
    auto [r_datas_ptr, r_nulls_ptr] = get_nested_and_null_column(right);
117
118
0
    const auto* __restrict l_datas =
119
0
            assert_cast<const ColumnUInt8*>(l_datas_ptr)->get_data().data();
120
0
    const auto* __restrict r_datas =
121
0
            assert_cast<const ColumnUInt8*>(r_datas_ptr)->get_data().data();
122
0
    const auto* __restrict l_nulls =
123
0
            assert_cast<const ColumnUInt8*>(l_nulls_ptr.get())->get_data().data();
124
0
    const auto* __restrict r_nulls =
125
0
            assert_cast<const ColumnUInt8*>(r_nulls_ptr.get())->get_data().data();
126
127
0
    auto* __restrict res_datas = assert_cast<ColumnUInt8*>(res)->get_data().data();
128
0
    auto* __restrict res_nulls = assert_cast<ColumnUInt8*>(nulls)->get_data().data();
129
130
0
    for (size_t i = 0; i < rows; ++i) {
131
0
        res_nulls[i] = Op::apply_null(l_datas[i], l_nulls[i], r_datas[i], r_nulls[i]);
132
0
        res_datas[i] = Op::apply(l_datas[i], r_datas[i]);
133
0
    }
134
0
}
Unexecuted instantiation: functions_logical.cpp:_ZN5doris12_GLOBAL__N_118vector_vector_nullINS_22FunctionsLogicalDetail7AndImplEEEvPKNS_7IColumnES6_PS4_S7_m
Unexecuted instantiation: functions_logical.cpp:_ZN5doris12_GLOBAL__N_118vector_vector_nullINS_22FunctionsLogicalDetail6OrImplEEEvPKNS_7IColumnES6_PS4_S7_m
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
0
                       size_t input_rows_count) {
153
0
    auto col_nulls = ColumnUInt8::create(input_rows_count);
154
0
    auto col_res = ColumnUInt8::create(input_rows_count);
155
0
    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
0
    } else if (auto r = check_and_get_column<ColumnConst>(arguments[1])) {
158
0
        vector_const_null<Op>(arguments[0], r, col_res.get(), col_nulls.get(), input_rows_count);
159
0
    } else {
160
0
        vector_vector_null<Op>(arguments[0], arguments[1], col_res.get(), col_nulls.get(),
161
0
                               input_rows_count);
162
0
    }
163
0
    result_info.column = ColumnNullable::create(std::move(col_res), std::move(col_nulls));
164
0
}
Unexecuted instantiation: functions_logical.cpp:_ZN5doris12_GLOBAL__N_117null_execute_implINS_22FunctionsLogicalDetail7AndImplEEEvSt6vectorIPKNS_7IColumnESaIS7_EERNS_21ColumnWithTypeAndNameEm
Unexecuted instantiation: functions_logical.cpp:_ZN5doris12_GLOBAL__N_117null_execute_implINS_22FunctionsLogicalDetail6OrImplEEEvSt6vectorIPKNS_7IColumnESaIS7_EERNS_21ColumnWithTypeAndNameEm
165
166
} // namespace
167
168
1.21k
bool is_native_number(PrimitiveType type) {
169
1.21k
    return (is_int_or_bool(type) && type != TYPE_LARGEINT) || is_float_or_double(type);
170
1.21k
}
171
172
template <typename Impl, typename Name>
173
DataTypePtr FunctionAnyArityLogical<Impl, Name>::get_return_type_impl(
174
531
        const DataTypes& arguments) const {
175
531
    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
531
    bool has_nullable_arguments = false;
183
1.59k
    for (size_t i = 0; i < arguments.size(); ++i) {
184
1.06k
        const auto& arg_type = arguments[i];
185
186
1.06k
        if (!has_nullable_arguments) {
187
669
            has_nullable_arguments = arg_type->is_nullable();
188
669
            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
669
        }
195
196
1.06k
        auto arg_primitive_type = arg_type->get_primitive_type();
197
1.06k
        if (!(is_native_number(arg_primitive_type) ||
198
1.06k
              (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
1.06k
    }
204
205
531
    auto result_type = std::make_shared<DataTypeUInt8>();
206
531
    return has_nullable_arguments ? make_nullable(result_type) : result_type;
207
531
}
_ZNK5doris22FunctionsLogicalDetail23FunctionAnyArityLogicalINS0_7AndImplENS_7NameAndEE20get_return_type_implERKSt6vectorISt10shared_ptrIKNS_9IDataTypeEESaIS9_EE
Line
Count
Source
174
144
        const DataTypes& arguments) const {
175
144
    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
144
    bool has_nullable_arguments = false;
183
432
    for (size_t i = 0; i < arguments.size(); ++i) {
184
288
        const auto& arg_type = arguments[i];
185
186
288
        if (!has_nullable_arguments) {
187
225
            has_nullable_arguments = arg_type->is_nullable();
188
225
            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
225
        }
195
196
288
        auto arg_primitive_type = arg_type->get_primitive_type();
197
288
        if (!(is_native_number(arg_primitive_type) ||
198
288
              (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
288
    }
204
205
144
    auto result_type = std::make_shared<DataTypeUInt8>();
206
144
    return has_nullable_arguments ? make_nullable(result_type) : result_type;
207
144
}
_ZNK5doris22FunctionsLogicalDetail23FunctionAnyArityLogicalINS0_6OrImplENS_6NameOrEE20get_return_type_implERKSt6vectorISt10shared_ptrIKNS_9IDataTypeEESaIS9_EE
Line
Count
Source
174
386
        const DataTypes& arguments) const {
175
386
    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
386
    bool has_nullable_arguments = false;
183
1.15k
    for (size_t i = 0; i < arguments.size(); ++i) {
184
772
        const auto& arg_type = arguments[i];
185
186
772
        if (!has_nullable_arguments) {
187
442
            has_nullable_arguments = arg_type->is_nullable();
188
442
            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
442
        }
195
196
772
        auto arg_primitive_type = arg_type->get_primitive_type();
197
772
        if (!(is_native_number(arg_primitive_type) ||
198
772
              (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
772
    }
204
205
386
    auto result_type = std::make_shared<DataTypeUInt8>();
206
386
    return has_nullable_arguments ? make_nullable(result_type) : result_type;
207
386
}
_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
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
1
    if constexpr (Impl::special_implementation_for_nulls()) {
220
0
        if (result_info.type->is_nullable()) {
221
0
            null_execute_impl<Impl>(std::move(args_in), result_info, input_rows_count);
222
0
        } else {
223
0
            basic_execute_impl<Impl>(std::move(args_in), result_info, input_rows_count);
224
0
        }
225
1
    } 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
1
    return Status::OK();
230
1
}
Unexecuted instantiation: _ZNK5doris22FunctionsLogicalDetail23FunctionAnyArityLogicalINS0_7AndImplENS_7NameAndEE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjm
Unexecuted instantiation: _ZNK5doris22FunctionsLogicalDetail23FunctionAnyArityLogicalINS0_6OrImplENS_6NameOrEE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjm
_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
331
    static void NO_INLINE vector(const ArrayA& a, ArrayC& c) {
238
482k
        std::transform(a.cbegin(), a.cend(), c.begin(), [](const auto x) { return Op::apply(x); });
239
331
    }
240
};
241
242
template <template <PrimitiveType> class Impl, typename Name>
243
DataTypePtr FunctionUnaryLogical<Impl, Name>::get_return_type_impl(
244
152
        const DataTypes& arguments) const {
245
152
    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
152
    return std::make_shared<DataTypeUInt8>();
252
152
}
253
254
template <template <PrimitiveType> class Impl, PrimitiveType T>
255
329
bool functionUnaryExecuteType(Block& block, const ColumnNumbers& arguments, size_t result) {
256
329
    if (auto col = check_and_get_column<ColumnVector<T>>(
257
331
                block.get_by_position(arguments[0]).column.get())) {
258
331
        auto col_res = ColumnUInt8::create();
259
260
331
        typename ColumnUInt8::Container& vec_res = col_res->get_data();
261
331
        vec_res.resize(col->get_data().size());
262
331
        UnaryOperationImpl<T, Impl<T>>::vector(col->get_data(), vec_res);
263
264
331
        block.replace_by_position(result, std::move(col_res));
265
331
        return true;
266
331
    }
267
268
18.4E
    return false;
269
329
}
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
329
                                                      size_t /*input_rows_count*/) const {
276
329
    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
329
    return Status::OK();
283
329
}
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