Coverage Report

Created: 2026-08-06 20:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
be/src/exec/operator/materialization_opertor.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
20
#include <stdint.h>
21
22
#include <map>
23
#include <string>
24
#include <unordered_map>
25
26
#include "common/status.h"
27
#include "exec/operator/operator.h"
28
29
namespace doris {
30
class RuntimeState;
31
32
class MaterializationOperator;
33
34
struct FetchRpcStruct {
35
    std::shared_ptr<PBackendService_Stub> stub;
36
    std::unique_ptr<brpc::Controller> cntl;
37
    PMultiGetRequestV2 request;
38
    PMultiGetResponseV2 response;
39
    std::string backend_address;
40
};
41
42
struct MaterializationSharedState {
43
public:
44
8
    MaterializationSharedState() = default;
45
46
    Status init_multi_requests(const TMaterializationNode& tnode, RuntimeState* state);
47
    Status create_muiltget_result(const Columns& columns, bool eos);
48
49
    Status validate_rpc_results(int node_id);
50
    Status merge_multi_response(RuntimeProfile* profile);
51
    void get_block(Block* block);
52
53
private:
54
    void _update_profile_info(int64_t backend_id, RuntimeProfile* response_profile);
55
    void _update_topn_lazy_materialization_profile(RuntimeProfile* profile);
56
57
    struct TopNLazyMaterializationBackendStats {
58
        std::string backend;
59
        int64_t rows_read = 0;
60
        int64_t segments_read = 0;
61
        int64_t local_io_count = 0;
62
        int64_t local_io_bytes = 0;
63
        int64_t remote_io_count = 0;
64
        int64_t remote_io_bytes = 0;
65
        int64_t skip_cache_io_count = 0;
66
        int64_t write_cache_bytes = 0;
67
        int64_t local_io_time = 0;
68
        int64_t remote_io_time = 0;
69
        int64_t write_cache_io_time = 0;
70
    };
71
72
public:
73
    bool rpc_struct_inited = false;
74
75
    bool eos = false;
76
    // empty materialization sink block not need to merge block
77
    bool need_merge_block = true;
78
    Block origin_block;
79
    // The rowid column of the origin block. should be replaced by the column of the result block.
80
    std::vector<int> rowid_locs;
81
    std::vector<MutableBlock> response_blocks;
82
    std::map<int64_t, FetchRpcStruct> rpc_struct_map;
83
    // Register each line in which block to ensure the order of the result.
84
    // Zero means NULL value.
85
    std::vector<std::vector<int64_t>> block_order_results;
86
    // backend id => <rpc profile info string key, rpc profile info string value>.
87
    std::map<int64_t, std::map<std::string, fmt::memory_buffer>> backend_profile_info_string;
88
89
    // Store the maximum number of rows processed by a single backend in the current batch
90
    uint32_t _max_rows_per_backend = 0;
91
    // Store the number of rows processed by each backend
92
    std::unordered_map<int64_t, uint32_t> _backend_rows_count; // backend_id => rows_count
93
94
private:
95
    // backend id => accumulated TopN phase-2 profile stats.
96
    std::map<int64_t, TopNLazyMaterializationBackendStats> _topn_lazy_materialization_backend_stats;
97
};
98
99
class MaterializationLocalState final : public PipelineXLocalState<FakeSharedState> {
100
public:
101
    using Parent = MaterializationOperator;
102
    using Base = PipelineXLocalState<FakeSharedState>;
103
104
    ENABLE_FACTORY_CREATOR(MaterializationLocalState);
105
0
    MaterializationLocalState(RuntimeState* state, OperatorXBase* parent) : Base(state, parent) {};
106
107
0
    Status init(RuntimeState* state, LocalStateInfo& info) override {
108
0
        RETURN_IF_ERROR(Base::init(state, info));
109
0
        _max_rpc_timer = ADD_TIMER_WITH_LEVEL(custom_profile(), "MaxRpcTime", 2);
110
0
        _merge_response_timer = ADD_TIMER_WITH_LEVEL(custom_profile(), "MergeResponseTime", 2);
111
0
        _max_rows_per_backend_counter =
112
0
                ADD_COUNTER_WITH_LEVEL(custom_profile(), "MaxRowsPerBackend", TUnit::UNIT, 2);
113
0
        return Status::OK();
114
0
    }
115
116
private:
117
    friend class MaterializationOperator;
118
    template <typename LocalStateType>
119
    friend class StatefulOperatorX;
120
121
    std::unique_ptr<Block> _child_block = Block::create_unique();
122
    bool _child_eos = false;
123
    MaterializationSharedState _materialization_state;
124
    RuntimeProfile::Counter* _max_rpc_timer = nullptr;
125
    RuntimeProfile::Counter* _merge_response_timer = nullptr;
126
    RuntimeProfile::Counter* _max_rows_per_backend_counter = nullptr;
127
};
128
129
class MaterializationOperator final : public StatefulOperatorX<MaterializationLocalState> {
130
public:
131
    using Base = StatefulOperatorX<MaterializationLocalState>;
132
    MaterializationOperator(ObjectPool* pool, const TPlanNode& tnode, int operator_id,
133
                            const DescriptorTbl& descs)
134
0
            : Base(pool, tnode, operator_id, descs) {}
135
136
    Status init(const TPlanNode& tnode, RuntimeState* state) override;
137
138
    Status prepare(RuntimeState* state) override;
139
140
0
    bool is_blockable(RuntimeState* state) const override { return true; }
141
    bool need_more_input_data(RuntimeState* state) const override;
142
    Status pull(RuntimeState* state, Block* output_block, bool* eos) const override;
143
    Status push(RuntimeState* state, Block* input_block, bool eos) const override;
144
145
private:
146
    friend class MaterializationLocalState;
147
148
    // Materialized slot by this node. The i-th result expr list refers to a slot of RowId
149
    TMaterializationNode _materialization_node;
150
    VExprContextSPtrs _rowid_exprs;
151
};
152
153
} // namespace doris