Coverage Report

Created: 2026-07-02 12:30

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
be/src/exprs/vcondition_expr.h
Line
Count
Source
1
// Licensed to the Apache Software Foundation (ASF) under one
2
// or more contributor license agreements.  See the NOTICE file
3
// distributed with this work for additional information
4
// regarding copyright ownership.  The ASF licenses this file
5
// to you under the Apache License, Version 2.0 (the
6
// "License"); you may not use this file except in compliance
7
// with the License.  You may obtain a copy of the License at
8
//
9
//   http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing,
12
// software distributed under the License is distributed on an
13
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
// KIND, either express or implied.  See the License for the
15
// specific language governing permissions and limitations
16
// under the License.
17
18
#pragma once
19
#include <string>
20
21
#include "common/status.h"
22
#include "core/block/column_numbers.h"
23
#include "exprs/function/function.h"
24
#include "exprs/function/if.h"
25
#include "exprs/function_context.h"
26
#include "exprs/vexpr.h"
27
#include "exprs/vexpr_context.h"
28
#include "exprs/vliteral.h"
29
#include "exprs/vslot_ref.h"
30
#include "runtime/runtime_state.h"
31
namespace doris {
32
class RowDescriptor;
33
class RuntimeState;
34
class TExprNode;
35
} // namespace doris
36
37
namespace doris {
38
39
class Block;
40
class VExprContext;
41
42
class VConditionExpr : public VExpr {
43
public:
44
3.39k
    VConditionExpr(const TExprNode& node) : VExpr(node) {}
45
    ~VConditionExpr() override = default;
46
47
    Status prepare(RuntimeState* state, const RowDescriptor& desc, VExprContext* context) final;
48
    Status open(RuntimeState* state, VExprContext* context,
49
                FunctionContext::FunctionStateScope scope) final;
50
    void close(VExprContext* context, FunctionContext::FunctionStateScope scope) final;
51
52
    std::string debug_string() const override;
53
54
protected:
55
    static size_t count_true_with_notnull(const ColumnPtr& col);
56
};
57
58
class VectorizedIfExpr : public VConditionExpr {
59
    ENABLE_FACTORY_CREATOR(VectorizedIfExpr);
60
61
public:
62
3.30k
    VectorizedIfExpr(const TExprNode& node) : VConditionExpr(node) {}
63
64
    Status execute_column_impl(VExprContext* context, const Block* block, const Selector* selector,
65
                               size_t count, ColumnPtr& result_column) const override;
66
67
11.5k
    const std::string& expr_name() const override { return IF_NAME; }
68
3
    Status clone_node(VExprSPtr* cloned_expr) const override {
69
3
        DORIS_CHECK(cloned_expr != nullptr);
70
3
        *cloned_expr = VectorizedIfExpr::create_shared(clone_texpr_node());
71
3
        return Status::OK();
72
3
    }
73
    inline static const std::string IF_NAME = "if";
74
75
protected:
76
    Status _execute_impl_internal(Block& block, const ColumnNumbers& arguments, uint32_t result,
77
                                  size_t input_rows_count) const;
78
79
private:
80
    template <PrimitiveType PType>
81
    Status execute_basic_type(Block& block, const ColumnUInt8* cond_col,
82
                              const ColumnWithTypeAndName& then_col,
83
                              const ColumnWithTypeAndName& else_col, uint32_t result,
84
954
                              Status& status) const {
85
954
        if (then_col.type->get_primitive_type() != else_col.type->get_primitive_type()) {
86
0
            return Status::InternalError(
87
0
                    "then and else column type must be same for function {} , but got {} , {}",
88
0
                    expr_name(), then_col.type->get_name(), else_col.type->get_name());
89
0
        }
90
91
954
        auto res_column =
92
954
                NumIfImpl<PType>::execute_if(cond_col->get_data(), then_col.column, else_col.column,
93
954
                                             block.get_by_position(result).type->get_scale());
94
954
        if (!res_column) {
95
0
            return Status::InternalError("unexpected args column {} , {} , of function {}",
96
0
                                         then_col.column->get_name(), else_col.column->get_name(),
97
0
                                         expr_name());
98
0
        }
99
954
        block.replace_by_position(result, std::move(res_column));
100
954
        return Status::OK();
101
954
    }
_ZNK5doris16VectorizedIfExpr18execute_basic_typeILNS_13PrimitiveTypeE2EEENS_6StatusERNS_5BlockEPKNS_12ColumnVectorILS2_2EEERKNS_21ColumnWithTypeAndNameESC_jRS3_
Line
Count
Source
84
292
                              Status& status) const {
85
292
        if (then_col.type->get_primitive_type() != else_col.type->get_primitive_type()) {
86
0
            return Status::InternalError(
87
0
                    "then and else column type must be same for function {} , but got {} , {}",
88
0
                    expr_name(), then_col.type->get_name(), else_col.type->get_name());
89
0
        }
90
91
292
        auto res_column =
92
292
                NumIfImpl<PType>::execute_if(cond_col->get_data(), then_col.column, else_col.column,
93
292
                                             block.get_by_position(result).type->get_scale());
94
292
        if (!res_column) {
95
0
            return Status::InternalError("unexpected args column {} , {} , of function {}",
96
0
                                         then_col.column->get_name(), else_col.column->get_name(),
97
0
                                         expr_name());
98
0
        }
99
292
        block.replace_by_position(result, std::move(res_column));
100
292
        return Status::OK();
101
292
    }
_ZNK5doris16VectorizedIfExpr18execute_basic_typeILNS_13PrimitiveTypeE3EEENS_6StatusERNS_5BlockEPKNS_12ColumnVectorILS2_2EEERKNS_21ColumnWithTypeAndNameESC_jRS3_
Line
Count
Source
84
311
                              Status& status) const {
85
311
        if (then_col.type->get_primitive_type() != else_col.type->get_primitive_type()) {
86
0
            return Status::InternalError(
87
0
                    "then and else column type must be same for function {} , but got {} , {}",
88
0
                    expr_name(), then_col.type->get_name(), else_col.type->get_name());
89
0
        }
90
91
311
        auto res_column =
92
311
                NumIfImpl<PType>::execute_if(cond_col->get_data(), then_col.column, else_col.column,
93
311
                                             block.get_by_position(result).type->get_scale());
94
311
        if (!res_column) {
95
0
            return Status::InternalError("unexpected args column {} , {} , of function {}",
96
0
                                         then_col.column->get_name(), else_col.column->get_name(),
97
0
                                         expr_name());
98
0
        }
99
311
        block.replace_by_position(result, std::move(res_column));
100
311
        return Status::OK();
101
311
    }
_ZNK5doris16VectorizedIfExpr18execute_basic_typeILNS_13PrimitiveTypeE4EEENS_6StatusERNS_5BlockEPKNS_12ColumnVectorILS2_2EEERKNS_21ColumnWithTypeAndNameESC_jRS3_
Line
Count
Source
84
2
                              Status& status) const {
85
2
        if (then_col.type->get_primitive_type() != else_col.type->get_primitive_type()) {
86
0
            return Status::InternalError(
87
0
                    "then and else column type must be same for function {} , but got {} , {}",
88
0
                    expr_name(), then_col.type->get_name(), else_col.type->get_name());
89
0
        }
90
91
2
        auto res_column =
92
2
                NumIfImpl<PType>::execute_if(cond_col->get_data(), then_col.column, else_col.column,
93
2
                                             block.get_by_position(result).type->get_scale());
94
2
        if (!res_column) {
95
0
            return Status::InternalError("unexpected args column {} , {} , of function {}",
96
0
                                         then_col.column->get_name(), else_col.column->get_name(),
97
0
                                         expr_name());
98
0
        }
99
2
        block.replace_by_position(result, std::move(res_column));
100
2
        return Status::OK();
101
2
    }
_ZNK5doris16VectorizedIfExpr18execute_basic_typeILNS_13PrimitiveTypeE5EEENS_6StatusERNS_5BlockEPKNS_12ColumnVectorILS2_2EEERKNS_21ColumnWithTypeAndNameESC_jRS3_
Line
Count
Source
84
167
                              Status& status) const {
85
167
        if (then_col.type->get_primitive_type() != else_col.type->get_primitive_type()) {
86
0
            return Status::InternalError(
87
0
                    "then and else column type must be same for function {} , but got {} , {}",
88
0
                    expr_name(), then_col.type->get_name(), else_col.type->get_name());
89
0
        }
90
91
167
        auto res_column =
92
167
                NumIfImpl<PType>::execute_if(cond_col->get_data(), then_col.column, else_col.column,
93
167
                                             block.get_by_position(result).type->get_scale());
94
167
        if (!res_column) {
95
0
            return Status::InternalError("unexpected args column {} , {} , of function {}",
96
0
                                         then_col.column->get_name(), else_col.column->get_name(),
97
0
                                         expr_name());
98
0
        }
99
167
        block.replace_by_position(result, std::move(res_column));
100
167
        return Status::OK();
101
167
    }
_ZNK5doris16VectorizedIfExpr18execute_basic_typeILNS_13PrimitiveTypeE6EEENS_6StatusERNS_5BlockEPKNS_12ColumnVectorILS2_2EEERKNS_21ColumnWithTypeAndNameESC_jRS3_
Line
Count
Source
84
121
                              Status& status) const {
85
121
        if (then_col.type->get_primitive_type() != else_col.type->get_primitive_type()) {
86
0
            return Status::InternalError(
87
0
                    "then and else column type must be same for function {} , but got {} , {}",
88
0
                    expr_name(), then_col.type->get_name(), else_col.type->get_name());
89
0
        }
90
91
121
        auto res_column =
92
121
                NumIfImpl<PType>::execute_if(cond_col->get_data(), then_col.column, else_col.column,
93
121
                                             block.get_by_position(result).type->get_scale());
94
121
        if (!res_column) {
95
0
            return Status::InternalError("unexpected args column {} , {} , of function {}",
96
0
                                         then_col.column->get_name(), else_col.column->get_name(),
97
0
                                         expr_name());
98
0
        }
99
121
        block.replace_by_position(result, std::move(res_column));
100
121
        return Status::OK();
101
121
    }
Unexecuted instantiation: _ZNK5doris16VectorizedIfExpr18execute_basic_typeILNS_13PrimitiveTypeE7EEENS_6StatusERNS_5BlockEPKNS_12ColumnVectorILS2_2EEERKNS_21ColumnWithTypeAndNameESC_jRS3_
Unexecuted instantiation: _ZNK5doris16VectorizedIfExpr18execute_basic_typeILNS_13PrimitiveTypeE8EEENS_6StatusERNS_5BlockEPKNS_12ColumnVectorILS2_2EEERKNS_21ColumnWithTypeAndNameESC_jRS3_
_ZNK5doris16VectorizedIfExpr18execute_basic_typeILNS_13PrimitiveTypeE9EEENS_6StatusERNS_5BlockEPKNS_12ColumnVectorILS2_2EEERKNS_21ColumnWithTypeAndNameESC_jRS3_
Line
Count
Source
84
33
                              Status& status) const {
85
33
        if (then_col.type->get_primitive_type() != else_col.type->get_primitive_type()) {
86
0
            return Status::InternalError(
87
0
                    "then and else column type must be same for function {} , but got {} , {}",
88
0
                    expr_name(), then_col.type->get_name(), else_col.type->get_name());
89
0
        }
90
91
33
        auto res_column =
92
33
                NumIfImpl<PType>::execute_if(cond_col->get_data(), then_col.column, else_col.column,
93
33
                                             block.get_by_position(result).type->get_scale());
94
33
        if (!res_column) {
95
0
            return Status::InternalError("unexpected args column {} , {} , of function {}",
96
0
                                         then_col.column->get_name(), else_col.column->get_name(),
97
0
                                         expr_name());
98
0
        }
99
33
        block.replace_by_position(result, std::move(res_column));
100
33
        return Status::OK();
101
33
    }
Unexecuted instantiation: _ZNK5doris16VectorizedIfExpr18execute_basic_typeILNS_13PrimitiveTypeE28EEENS_6StatusERNS_5BlockEPKNS_12ColumnVectorILS2_2EEERKNS_21ColumnWithTypeAndNameESC_jRS3_
_ZNK5doris16VectorizedIfExpr18execute_basic_typeILNS_13PrimitiveTypeE29EEENS_6StatusERNS_5BlockEPKNS_12ColumnVectorILS2_2EEERKNS_21ColumnWithTypeAndNameESC_jRS3_
Line
Count
Source
84
11
                              Status& status) const {
85
11
        if (then_col.type->get_primitive_type() != else_col.type->get_primitive_type()) {
86
0
            return Status::InternalError(
87
0
                    "then and else column type must be same for function {} , but got {} , {}",
88
0
                    expr_name(), then_col.type->get_name(), else_col.type->get_name());
89
0
        }
90
91
11
        auto res_column =
92
11
                NumIfImpl<PType>::execute_if(cond_col->get_data(), then_col.column, else_col.column,
93
11
                                             block.get_by_position(result).type->get_scale());
94
11
        if (!res_column) {
95
0
            return Status::InternalError("unexpected args column {} , {} , of function {}",
96
0
                                         then_col.column->get_name(), else_col.column->get_name(),
97
0
                                         expr_name());
98
0
        }
99
11
        block.replace_by_position(result, std::move(res_column));
100
11
        return Status::OK();
101
11
    }
Unexecuted instantiation: _ZNK5doris16VectorizedIfExpr18execute_basic_typeILNS_13PrimitiveTypeE20EEENS_6StatusERNS_5BlockEPKNS_12ColumnVectorILS2_2EEERKNS_21ColumnWithTypeAndNameESC_jRS3_
_ZNK5doris16VectorizedIfExpr18execute_basic_typeILNS_13PrimitiveTypeE30EEENS_6StatusERNS_5BlockEPKNS_12ColumnVectorILS2_2EEERKNS_21ColumnWithTypeAndNameESC_jRS3_
Line
Count
Source
84
1
                              Status& status) const {
85
1
        if (then_col.type->get_primitive_type() != else_col.type->get_primitive_type()) {
86
0
            return Status::InternalError(
87
0
                    "then and else column type must be same for function {} , but got {} , {}",
88
0
                    expr_name(), then_col.type->get_name(), else_col.type->get_name());
89
0
        }
90
91
1
        auto res_column =
92
1
                NumIfImpl<PType>::execute_if(cond_col->get_data(), then_col.column, else_col.column,
93
1
                                             block.get_by_position(result).type->get_scale());
94
1
        if (!res_column) {
95
0
            return Status::InternalError("unexpected args column {} , {} , of function {}",
96
0
                                         then_col.column->get_name(), else_col.column->get_name(),
97
0
                                         expr_name());
98
0
        }
99
1
        block.replace_by_position(result, std::move(res_column));
100
1
        return Status::OK();
101
1
    }
Unexecuted instantiation: _ZNK5doris16VectorizedIfExpr18execute_basic_typeILNS_13PrimitiveTypeE35EEENS_6StatusERNS_5BlockEPKNS_12ColumnVectorILS2_2EEERKNS_21ColumnWithTypeAndNameESC_jRS3_
Unexecuted instantiation: _ZNK5doris16VectorizedIfExpr18execute_basic_typeILNS_13PrimitiveTypeE11EEENS_6StatusERNS_5BlockEPKNS_12ColumnVectorILS2_2EEERKNS_21ColumnWithTypeAndNameESC_jRS3_
_ZNK5doris16VectorizedIfExpr18execute_basic_typeILNS_13PrimitiveTypeE25EEENS_6StatusERNS_5BlockEPKNS_12ColumnVectorILS2_2EEERKNS_21ColumnWithTypeAndNameESC_jRS3_
Line
Count
Source
84
8
                              Status& status) const {
85
8
        if (then_col.type->get_primitive_type() != else_col.type->get_primitive_type()) {
86
0
            return Status::InternalError(
87
0
                    "then and else column type must be same for function {} , but got {} , {}",
88
0
                    expr_name(), then_col.type->get_name(), else_col.type->get_name());
89
0
        }
90
91
8
        auto res_column =
92
8
                NumIfImpl<PType>::execute_if(cond_col->get_data(), then_col.column, else_col.column,
93
8
                                             block.get_by_position(result).type->get_scale());
94
8
        if (!res_column) {
95
0
            return Status::InternalError("unexpected args column {} , {} , of function {}",
96
0
                                         then_col.column->get_name(), else_col.column->get_name(),
97
0
                                         expr_name());
98
0
        }
99
8
        block.replace_by_position(result, std::move(res_column));
100
8
        return Status::OK();
101
8
    }
_ZNK5doris16VectorizedIfExpr18execute_basic_typeILNS_13PrimitiveTypeE26EEENS_6StatusERNS_5BlockEPKNS_12ColumnVectorILS2_2EEERKNS_21ColumnWithTypeAndNameESC_jRS3_
Line
Count
Source
84
8
                              Status& status) const {
85
8
        if (then_col.type->get_primitive_type() != else_col.type->get_primitive_type()) {
86
0
            return Status::InternalError(
87
0
                    "then and else column type must be same for function {} , but got {} , {}",
88
0
                    expr_name(), then_col.type->get_name(), else_col.type->get_name());
89
0
        }
90
91
8
        auto res_column =
92
8
                NumIfImpl<PType>::execute_if(cond_col->get_data(), then_col.column, else_col.column,
93
8
                                             block.get_by_position(result).type->get_scale());
94
8
        if (!res_column) {
95
0
            return Status::InternalError("unexpected args column {} , {} , of function {}",
96
0
                                         then_col.column->get_name(), else_col.column->get_name(),
97
0
                                         expr_name());
98
0
        }
99
8
        block.replace_by_position(result, std::move(res_column));
100
8
        return Status::OK();
101
8
    }
Unexecuted instantiation: _ZNK5doris16VectorizedIfExpr18execute_basic_typeILNS_13PrimitiveTypeE12EEENS_6StatusERNS_5BlockEPKNS_12ColumnVectorILS2_2EEERKNS_21ColumnWithTypeAndNameESC_jRS3_
Unexecuted instantiation: _ZNK5doris16VectorizedIfExpr18execute_basic_typeILNS_13PrimitiveTypeE27EEENS_6StatusERNS_5BlockEPKNS_12ColumnVectorILS2_2EEERKNS_21ColumnWithTypeAndNameESC_jRS3_
Unexecuted instantiation: _ZNK5doris16VectorizedIfExpr18execute_basic_typeILNS_13PrimitiveTypeE42EEENS_6StatusERNS_5BlockEPKNS_12ColumnVectorILS2_2EEERKNS_21ColumnWithTypeAndNameESC_jRS3_
Unexecuted instantiation: _ZNK5doris16VectorizedIfExpr18execute_basic_typeILNS_13PrimitiveTypeE36EEENS_6StatusERNS_5BlockEPKNS_12ColumnVectorILS2_2EEERKNS_21ColumnWithTypeAndNameESC_jRS3_
Unexecuted instantiation: _ZNK5doris16VectorizedIfExpr18execute_basic_typeILNS_13PrimitiveTypeE37EEENS_6StatusERNS_5BlockEPKNS_12ColumnVectorILS2_2EEERKNS_21ColumnWithTypeAndNameESC_jRS3_
102
103
    Status execute_generic(Block& block, const ColumnUInt8* cond_col,
104
                           const ColumnWithTypeAndName& then_col_type_name,
105
                           const ColumnWithTypeAndName& else_col_type_name, uint32_t result,
106
                           size_t input_row_count) const;
107
108
    Status execute_for_null_then_else(Block& block, const ColumnWithTypeAndName& arg_cond,
109
                                      const ColumnWithTypeAndName& arg_then,
110
                                      const ColumnWithTypeAndName& arg_else, uint32_t result,
111
                                      size_t input_rows_count, bool& handled) const;
112
113
    Status execute_for_null_condition(Block& block, const ColumnNumbers& arguments,
114
                                      const ColumnWithTypeAndName& arg_cond,
115
                                      const ColumnWithTypeAndName& arg_then,
116
                                      const ColumnWithTypeAndName& arg_else, uint32_t result,
117
                                      bool& handled) const;
118
119
    Status execute_for_nullable_then_else(Block& block, const ColumnWithTypeAndName& arg_cond,
120
                                          const ColumnWithTypeAndName& arg_then,
121
                                          const ColumnWithTypeAndName& arg_else, uint32_t result,
122
                                          size_t input_rows_count, bool& handled) const;
123
};
124
125
class VectorizedIfNullExpr : public VectorizedIfExpr {
126
    ENABLE_FACTORY_CREATOR(VectorizedIfNullExpr);
127
128
public:
129
1.27k
    VectorizedIfNullExpr(const TExprNode& node) : VectorizedIfExpr(node) {}
130
344
    const std::string& expr_name() const override { return IF_NULL_NAME; }
131
1
    Status clone_node(VExprSPtr* cloned_expr) const override {
132
1
        DORIS_CHECK(cloned_expr != nullptr);
133
1
        *cloned_expr = VectorizedIfNullExpr::create_shared(clone_texpr_node());
134
1
        return Status::OK();
135
1
    }
136
    inline static const std::string IF_NULL_NAME = "ifnull";
137
138
    Status execute_column_impl(VExprContext* context, const Block* block, const Selector* selector,
139
                               size_t count, ColumnPtr& result_column) const override;
140
};
141
142
class VectorizedCoalesceExpr : public VConditionExpr {
143
    ENABLE_FACTORY_CREATOR(VectorizedCoalesceExpr);
144
145
public:
146
    Status execute_column_impl(VExprContext* context, const Block* block, const Selector* selector,
147
                               size_t count, ColumnPtr& result_column) const override;
148
90
    VectorizedCoalesceExpr(const TExprNode& node) : VConditionExpr(node) {}
149
65
    const std::string& expr_name() const override { return NAME; }
150
4
    Status clone_node(VExprSPtr* cloned_expr) const override {
151
4
        DORIS_CHECK(cloned_expr != nullptr);
152
4
        *cloned_expr = VectorizedCoalesceExpr::create_shared(clone_texpr_node());
153
4
        return Status::OK();
154
4
    }
155
    inline static const std::string NAME = "coalesce";
156
};
157
158
} // namespace doris