Coverage Report

Created: 2026-04-02 08:12

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
be/src/storage/iterators.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 <cstddef>
21
#include <memory>
22
23
#include "common/status.h"
24
#include "core/block/block.h"
25
#include "exprs/score_runtime.h"
26
#include "exprs/vexpr.h"
27
#include "io/io_common.h"
28
#include "runtime/runtime_state.h"
29
#include "storage/index/ann/ann_topn_runtime.h"
30
#include "storage/olap_common.h"
31
#include "storage/predicate/block_column_predicate.h"
32
#include "storage/predicate/column_predicate.h"
33
#include "storage/row_cursor.h"
34
#include "storage/segment/row_ranges.h"
35
#include "storage/tablet/tablet_schema.h"
36
37
namespace doris {
38
39
class Schema;
40
class ColumnPredicate;
41
42
struct IteratorRowRef;
43
44
namespace segment_v2 {
45
struct SubstreamIterator;
46
}
47
class StorageReadOptions {
48
public:
49
    struct KeyRange {
50
        KeyRange()
51
                : lower_key(nullptr),
52
                  include_lower(false),
53
                  upper_key(nullptr),
54
0
                  include_upper(false) {}
55
56
        KeyRange(const RowCursor* lower_key_, bool include_lower_, const RowCursor* upper_key_,
57
                 bool include_upper_)
58
4.48M
                : lower_key(lower_key_),
59
4.48M
                  include_lower(include_lower_),
60
4.48M
                  upper_key(upper_key_),
61
4.48M
                  include_upper(include_upper_) {}
62
63
        // the lower bound of the range, nullptr if not existed
64
        const RowCursor* lower_key = nullptr;
65
        // whether `lower_key` is included in the range
66
        bool include_lower;
67
        // the upper bound of the range, nullptr if not existed
68
        const RowCursor* upper_key = nullptr;
69
        // whether `upper_key` is included in the range
70
        bool include_upper;
71
72
4.42M
        uint64_t get_digest(uint64_t seed) const {
73
4.42M
            if (lower_key != nullptr) {
74
4.42M
                auto key_str = lower_key->to_string();
75
4.42M
                seed = HashUtil::hash64(key_str.c_str(), key_str.size(), seed);
76
4.42M
                seed = HashUtil::hash64(&include_lower, sizeof(include_lower), seed);
77
4.42M
            }
78
79
4.42M
            if (upper_key != nullptr) {
80
4.41M
                auto key_str = upper_key->to_string();
81
4.41M
                seed = HashUtil::hash64(key_str.c_str(), key_str.size(), seed);
82
4.41M
                seed = HashUtil::hash64(&include_upper, sizeof(include_upper), seed);
83
4.41M
            }
84
85
4.42M
            return seed;
86
4.42M
        }
87
    };
88
89
    // reader's key ranges, empty if not existed.
90
    // used by short key index to filter row blocks
91
    std::vector<KeyRange> key_ranges;
92
93
    // For unique-key merge-on-write, the effect is similar to delete_conditions
94
    // that filters out rows that are deleted in realtime.
95
    // For a particular row, if delete_bitmap.contains(rowid) means that row is
96
    // marked deleted and invisible to user anymore.
97
    // segment_id -> roaring::Roaring*
98
    std::unordered_map<uint32_t, std::shared_ptr<roaring::Roaring>> delete_bitmap;
99
100
    std::shared_ptr<AndBlockColumnPredicate> delete_condition_predicates =
101
            AndBlockColumnPredicate::create_shared();
102
    // reader's column predicate, nullptr if not existed
103
    // used to fiter rows in row block
104
    std::vector<std::shared_ptr<ColumnPredicate>> column_predicates;
105
    std::unordered_map<int32_t, std::shared_ptr<AndBlockColumnPredicate>> col_id_to_predicates;
106
    std::unordered_map<int32_t, std::vector<std::shared_ptr<const ColumnPredicate>>>
107
            del_predicates_for_zone_map;
108
    TPushAggOp::type push_down_agg_type_opt = TPushAggOp::NONE;
109
110
    // REQUIRED (null is not allowed)
111
    OlapReaderStatistics* stats = nullptr;
112
    bool use_page_cache = false;
113
    uint32_t block_row_max = 4096 - 32; // see https://github.com/apache/doris/pull/11816
114
    // Adaptive batch size target (bytes). 0 = disabled.
115
    size_t preferred_block_size_bytes = 0;
116
    // Adaptive batch size target (rows). Default 65535.
117
    size_t preferred_block_size_rows = 65535;
118
    // Per-column byte limit for the EWMA predictor. 0 = no column limit.
119
    size_t preferred_max_col_bytes = 1048576;
120
    // True output columns of the final block. Used by AdaptiveBlockSizePredictor.
121
    // Must match the order and count of columns in the block passed to next_batch().
122
    std::vector<ColumnId> adaptive_batch_output_columns;
123
124
    TabletSchemaSPtr tablet_schema = nullptr;
125
    bool enable_unique_key_merge_on_write = false;
126
    bool record_rowids = false;
127
    std::vector<int> topn_filter_source_node_ids;
128
    int topn_filter_target_node_id = -1;
129
    // used for special optimization for query : ORDER BY key DESC LIMIT n
130
    bool read_orderby_key_reverse = false;
131
    // columns for orderby keys
132
    std::vector<uint32_t>* read_orderby_key_columns = nullptr;
133
    io::IOContext io_ctx;
134
    VExpr* remaining_vconjunct_root = nullptr;
135
    std::vector<VExprSPtr> remaining_conjunct_roots;
136
    VExprContextSPtrs common_expr_ctxs_push_down;
137
    const std::set<int32_t>* output_columns = nullptr;
138
    // runtime state
139
    RuntimeState* runtime_state = nullptr;
140
    RowsetId rowset_id;
141
    Version version;
142
    int64_t tablet_id = 0;
143
    // slots that cast may be eliminated in storage layer
144
    std::map<std::string, DataTypePtr> target_cast_type_for_variants;
145
    RowRanges row_ranges;
146
    size_t topn_limit = 0;
147
148
    std::map<ColumnId, VExprContextSPtr> virtual_column_exprs;
149
    std::shared_ptr<segment_v2::AnnTopNRuntime> ann_topn_runtime;
150
    std::map<ColumnId, size_t> vir_cid_to_idx_in_block;
151
    std::map<size_t, DataTypePtr> vir_col_idx_to_type;
152
153
    std::map<int32_t, TColumnAccessPaths> all_access_paths;
154
    std::map<int32_t, TColumnAccessPaths> predicate_access_paths;
155
156
    std::shared_ptr<ScoreRuntime> score_runtime;
157
    CollectionStatisticsPtr collection_statistics;
158
159
    // Cache for sparse column data to avoid redundant reads
160
    // col_unique_id -> cached column_ptr
161
    std::unordered_map<int32_t, ColumnPtr> sparse_column_cache;
162
163
    uint64_t condition_cache_digest = 0;
164
};
165
166
struct CompactionSampleInfo {
167
    int64_t bytes = 0;
168
    int64_t rows = 0;
169
    int64_t group_data_size = 0;
170
    int64_t null_count = 0; // Number of NULL cells in this column group
171
};
172
173
struct BlockWithSameBit {
174
    Block* block;
175
    std::vector<bool>& same_bit;
176
177
201
    bool empty() const { return block->rows() == 0; }
178
};
179
180
class RowwiseIterator;
181
using RowwiseIteratorUPtr = std::unique_ptr<RowwiseIterator>;
182
class RowwiseIterator {
183
public:
184
5.78M
    RowwiseIterator() = default;
185
5.78M
    virtual ~RowwiseIterator() = default;
186
187
    // Initialize this iterator and make it ready to read with
188
    // input options.
189
    // Input options may contain scan range in which this scan.
190
    // Return Status::OK() if init successfully,
191
    // Return other error otherwise
192
0
    virtual Status init(const StorageReadOptions& opts) {
193
0
        return Status::InternalError("to be implemented, current class: " +
194
0
                                     demangle(typeid(*this).name()));
195
0
    }
196
197
0
    virtual Status init(const StorageReadOptions& opts, CompactionSampleInfo* sample_info) {
198
0
        return Status::InternalError("should not reach here, current class: " +
199
0
                                     demangle(typeid(*this).name()));
200
0
    }
201
202
    // If there is any valid data, this function will load data
203
    // into input batch with Status::OK() returned
204
    // If there is no data to read, will return Status::EndOfFile.
205
    // If other error happens, other error code will be returned.
206
0
    virtual Status next_batch(Block* block) {
207
0
        return Status::InternalError("should not reach here, current class: " +
208
0
                                     demangle(typeid(*this).name()));
209
0
    }
210
211
0
    virtual Status next_batch(BlockWithSameBit* block_with_same_bit) {
212
0
        return Status::InternalError("should not reach here, current class: " +
213
0
                                     demangle(typeid(*this).name()));
214
0
    }
215
216
0
    virtual Status next_batch(BlockView* block_view) {
217
0
        return Status::InternalError("should not reach here, current class: " +
218
0
                                     demangle(typeid(*this).name()));
219
0
    }
220
221
0
    virtual Status next_row(IteratorRowRef* ref) {
222
0
        return Status::InternalError("should not reach here, current class: " +
223
0
                                     demangle(typeid(*this).name()));
224
0
    }
225
0
    virtual Status unique_key_next_row(IteratorRowRef* ref) {
226
0
        return Status::InternalError("should not reach here, current class: " +
227
0
                                     demangle(typeid(*this).name()));
228
0
    }
229
230
0
    virtual bool is_merge_iterator() const { return false; }
231
232
0
    virtual Status current_block_row_locations(std::vector<RowLocation>* block_row_locations) {
233
0
        return Status::InternalError("should not reach here, current class: " +
234
0
                                     demangle(typeid(*this).name()));
235
0
    }
236
237
    // return schema for this Iterator
238
    virtual const Schema& schema() const = 0;
239
240
    // Return the data id such as segment id, used for keep the insert order when do
241
    // merge sort in priority queue
242
26.2k
    virtual uint64_t data_id() const { return 0; }
243
244
9.64k
    virtual void update_profile(RuntimeProfile* profile) {}
245
    // return rows merged count by iterator
246
0
    virtual uint64_t merged_rows() const { return 0; }
247
248
    // return if it's an empty iterator
249
2.07M
    virtual bool empty() const { return false; }
250
};
251
252
} // namespace doris