Coverage Report

Created: 2026-07-07 16:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
be/src/exprs/short_circuit_evaluation_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
#include <vector>
21
22
#include "common/status.h"
23
#include "exprs/vexpr.h"
24
#include "exprs/vexpr_context.h"
25
#include "runtime/runtime_state.h"
26
27
namespace doris {
28
29
class Block;
30
class VExprContext;
31
struct ColumnAndSelector;
32
33
class ShortCircuitExpr : public VExpr {
34
public:
35
8
    ShortCircuitExpr(const TExprNode& node) : VExpr(node) {}
36
8
    ~ShortCircuitExpr() override = default;
37
    Status prepare(RuntimeState* state, const RowDescriptor& desc, VExprContext* context) final;
38
    Status open(RuntimeState* state, VExprContext* context,
39
                FunctionContext::FunctionStateScope scope) final;
40
    void close(VExprContext* context, FunctionContext::FunctionStateScope scope) final;
41
42
    std::string debug_string() const final;
43
44
protected:
45
    // Helper method to dispatch fill operation for two-branch case (e.g., IF, IFNULL).
46
    // Uses ScalarFillWithSelector for scalar types, NonScalarFillWithSelector otherwise.
47
    [[nodiscard]] ColumnPtr dispatch_fill_columns(const ColumnPtr& true_column,
48
                                                  const Selector& true_selector,
49
                                                  const ColumnPtr& false_column,
50
                                                  const Selector& false_selector,
51
                                                  size_t count) const;
52
53
    // Helper method to dispatch fill operation for multi-branch case (e.g., COALESCE, CASE).
54
    // Uses ScalarFillWithSelector for scalar types, NonScalarFillWithSelector otherwise.
55
    [[nodiscard]] ColumnPtr dispatch_fill_columns(
56
            const std::vector<ColumnAndSelector>& columns_and_selectors, size_t count) const;
57
};
58
59
class ShortCircuitIfExpr final : public ShortCircuitExpr {
60
public:
61
    ENABLE_FACTORY_CREATOR(ShortCircuitIfExpr);
62
2
    ShortCircuitIfExpr(const TExprNode& node) : ShortCircuitExpr(node) {}
63
2
    ~ShortCircuitIfExpr() override = default;
64
65
2
    const std::string& expr_name() const override { return IF_NAME; }
66
1
    Status clone_node(VExprSPtr* cloned_expr) const override {
67
1
        DORIS_CHECK(cloned_expr != nullptr);
68
1
        auto node = clone_texpr_node();
69
1
        node.__set_short_circuit_evaluation(true);
70
1
        *cloned_expr = ShortCircuitIfExpr::create_shared(node);
71
1
        return Status::OK();
72
1
    }
73
74
    Status execute_column_impl(VExprContext* context, const Block* block, const Selector* selector,
75
                               size_t count, ColumnPtr& result_column) const override;
76
77
private:
78
    inline static const std::string IF_NAME = "if";
79
};
80
class ShortCircuitCaseExpr final : public ShortCircuitExpr {
81
public:
82
    ENABLE_FACTORY_CREATOR(ShortCircuitCaseExpr);
83
    ShortCircuitCaseExpr(const TExprNode& node);
84
2
    ~ShortCircuitCaseExpr() override = default;
85
2
    const std::string& expr_name() const override { return CASE_NAME; }
86
0
    bool has_else_expr() const { return _has_else_expr; }
87
1
    Status clone_node(VExprSPtr* cloned_expr) const override {
88
1
        DORIS_CHECK(cloned_expr != nullptr);
89
1
        auto node = clone_texpr_node();
90
1
        TCaseExpr case_node;
91
1
        case_node.__set_has_case_expr(false);
92
1
        case_node.__set_has_else_expr(_has_else_expr);
93
1
        node.__set_case_expr(case_node);
94
1
        node.__set_short_circuit_evaluation(true);
95
1
        *cloned_expr = ShortCircuitCaseExpr::create_shared(node);
96
1
        return Status::OK();
97
1
    }
98
    Status execute_column_impl(VExprContext* context, const Block* block, const Selector* selector,
99
                               size_t count, ColumnPtr& result_column) const override;
100
101
private:
102
    const bool _has_else_expr;
103
    inline static const std::string CASE_NAME = "case";
104
};
105
106
class ShortCircuitIfNullExpr final : public ShortCircuitExpr {
107
public:
108
    ENABLE_FACTORY_CREATOR(ShortCircuitIfNullExpr);
109
2
    ShortCircuitIfNullExpr(const TExprNode& node) : ShortCircuitExpr(node) {}
110
2
    ~ShortCircuitIfNullExpr() override = default;
111
112
2
    const std::string& expr_name() const override { return IFNULL_NAME; }
113
1
    Status clone_node(VExprSPtr* cloned_expr) const override {
114
1
        DORIS_CHECK(cloned_expr != nullptr);
115
1
        auto node = clone_texpr_node();
116
1
        node.__set_short_circuit_evaluation(true);
117
1
        *cloned_expr = ShortCircuitIfNullExpr::create_shared(node);
118
1
        return Status::OK();
119
1
    }
120
    Status execute_column_impl(VExprContext* context, const Block* block, const Selector* selector,
121
                               size_t count, ColumnPtr& result_column) const override;
122
123
private:
124
    inline static const std::string IFNULL_NAME = "ifnull";
125
};
126
127
class ShortCircuitCoalesceExpr final : public ShortCircuitExpr {
128
public:
129
    ENABLE_FACTORY_CREATOR(ShortCircuitCoalesceExpr);
130
2
    ShortCircuitCoalesceExpr(const TExprNode& node) : ShortCircuitExpr(node) {}
131
2
    ~ShortCircuitCoalesceExpr() override = default;
132
2
    const std::string& expr_name() const override { return COALESCE_NAME; }
133
1
    Status clone_node(VExprSPtr* cloned_expr) const override {
134
1
        DORIS_CHECK(cloned_expr != nullptr);
135
1
        auto node = clone_texpr_node();
136
1
        node.__set_short_circuit_evaluation(true);
137
1
        *cloned_expr = ShortCircuitCoalesceExpr::create_shared(node);
138
1
        return Status::OK();
139
1
    }
140
    Status execute_column_impl(VExprContext* context, const Block* block, const Selector* selector,
141
                               size_t count, ColumnPtr& result_column) const override;
142
143
private:
144
    inline static const std::string COALESCE_NAME = "coalesce";
145
};
146
} // namespace doris