Coverage Report

Created: 2026-08-14 00:03

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