Coverage Report

Created: 2026-04-11 14:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
be/src/storage/segment/column_reader.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 <gen_cpp/Descriptors_types.h>
21
#include <gen_cpp/segment_v2.pb.h>
22
#include <sys/types.h>
23
24
#include <cstddef> // for size_t
25
#include <cstdint> // for uint32_t
26
#include <memory>  // for unique_ptr
27
#include <string>
28
#include <utility>
29
#include <vector>
30
31
#include "common/config.h"
32
#include "common/logging.h"
33
#include "common/status.h"            // for Status
34
#include "core/column/column_array.h" // ColumnArray
35
#include "core/data_type/data_type.h"
36
#include "io/cache/cached_remote_file_reader.h"
37
#include "io/fs/file_reader_writer_fwd.h"
38
#include "io/io_common.h"
39
#include "storage/index/index_reader.h"
40
#include "storage/index/ordinal_page_index.h" // for OrdinalPageIndexIterator
41
#include "storage/index/zone_map/zone_map_index.h"
42
#include "storage/olap_common.h"
43
#include "storage/predicate/column_predicate.h"
44
#include "storage/segment/common.h"
45
#include "storage/segment/page_handle.h" // for PageHandle
46
#include "storage/segment/page_pointer.h"
47
#include "storage/segment/parsed_page.h" // for ParsedPage
48
#include "storage/segment/segment_prefetcher.h"
49
#include "storage/segment/stream_reader.h"
50
#include "storage/tablet/tablet_schema.h"
51
#include "storage/types.h"
52
#include "storage/utils.h"
53
#include "util/once.h"
54
55
namespace doris {
56
57
class BlockCompressionCodec;
58
class AndBlockColumnPredicate;
59
class ColumnPredicate;
60
class TabletIndex;
61
class StorageReadOptions;
62
63
namespace io {
64
class FileReader;
65
} // namespace io
66
struct Slice;
67
struct StringRef;
68
69
using TColumnAccessPaths = std::vector<TColumnAccessPath>;
70
71
namespace segment_v2 {
72
class EncodingInfo;
73
class ColumnIterator;
74
class BloomFilterIndexReader;
75
class InvertedIndexIterator;
76
class InvertedIndexReader;
77
class IndexFileReader;
78
class PageDecoder;
79
class RowRanges;
80
class ZoneMapIndexReader;
81
class IndexIterator;
82
class ColumnMetaAccessor;
83
84
struct ColumnReaderOptions {
85
    // whether verify checksum when read page
86
    bool verify_checksum = true;
87
    // for in memory olap table, use DURABLE CachePriority in page cache
88
    bool kept_in_memory = false;
89
90
    int be_exec_version = -1;
91
92
    TabletSchemaSPtr tablet_schema = nullptr;
93
};
94
95
struct ColumnIteratorOptions {
96
    bool use_page_cache = false;
97
    bool is_predicate_column = false;
98
    // for page cache allocation
99
    // page types are divided into DATA_PAGE & INDEX_PAGE
100
    // INDEX_PAGE including index_page, dict_page and short_key_page
101
    PageTypePB type = PageTypePB::UNKNOWN_PAGE_TYPE;
102
    io::FileReader* file_reader = nullptr; // Ref
103
    // reader statistics
104
    OlapReaderStatistics* stats = nullptr; // Ref
105
    io::IOContext io_ctx;
106
    bool only_read_offsets = false;
107
108
2.10M
    void sanity_check() const {
109
2.10M
        CHECK_NOTNULL(file_reader);
110
2.10M
        CHECK_NOTNULL(stats);
111
2.10M
    }
112
};
113
114
class ColumnIterator;
115
class OffsetFileColumnIterator;
116
class FileColumnIterator;
117
118
using ColumnIteratorUPtr = std::unique_ptr<ColumnIterator>;
119
using OffsetFileColumnIteratorUPtr = std::unique_ptr<OffsetFileColumnIterator>;
120
using FileColumnIteratorUPtr = std::unique_ptr<FileColumnIterator>;
121
using ColumnIteratorSPtr = std::shared_ptr<ColumnIterator>;
122
123
// There will be concurrent users to read the same column. So
124
// we should do our best to reduce resource usage through share
125
// same information, such as OrdinalPageIndex and Page data.
126
// This will cache data shared by all reader
127
class ColumnReader : public MetadataAdder<ColumnReader>,
128
                     public std::enable_shared_from_this<ColumnReader> {
129
public:
130
    ColumnReader();
131
    // Create an initialized ColumnReader in *reader.
132
    // This should be a lightweight operation without I/O.
133
    static Status create(const ColumnReaderOptions& opts, const ColumnMetaPB& meta,
134
                         uint64_t num_rows, const io::FileReaderSPtr& file_reader,
135
                         std::shared_ptr<ColumnReader>* reader);
136
137
    static Status create_array(const ColumnReaderOptions& opts, const ColumnMetaPB& meta,
138
                               const io::FileReaderSPtr& file_reader,
139
                               std::shared_ptr<ColumnReader>* reader);
140
    static Status create_map(const ColumnReaderOptions& opts, const ColumnMetaPB& meta,
141
                             const io::FileReaderSPtr& file_reader,
142
                             std::shared_ptr<ColumnReader>* reader);
143
    static Status create_struct(const ColumnReaderOptions& opts, const ColumnMetaPB& meta,
144
                                uint64_t num_rows, const io::FileReaderSPtr& file_reader,
145
                                std::shared_ptr<ColumnReader>* reader);
146
    static Status create_agg_state(const ColumnReaderOptions& opts, const ColumnMetaPB& meta,
147
                                   uint64_t num_rows, const io::FileReaderSPtr& file_reader,
148
                                   std::shared_ptr<ColumnReader>* reader);
149
150
    enum DictEncodingType { UNKNOWN_DICT_ENCODING, PARTIAL_DICT_ENCODING, ALL_DICT_ENCODING };
151
152
    static bool is_compaction_reader_type(ReaderType type);
153
154
    ~ColumnReader() override;
155
156
    // create a new column iterator. Client should delete returned iterator
157
    virtual Status new_iterator(ColumnIteratorUPtr* iterator, const TabletColumn* col,
158
                                const StorageReadOptions*);
159
    Status new_iterator(ColumnIteratorUPtr* iterator, const TabletColumn* tablet_column);
160
    Status new_array_iterator(ColumnIteratorUPtr* iterator, const TabletColumn* tablet_column);
161
    Status new_struct_iterator(ColumnIteratorUPtr* iterator, const TabletColumn* tablet_column);
162
    Status new_map_iterator(ColumnIteratorUPtr* iterator, const TabletColumn* tablet_column);
163
    Status new_agg_state_iterator(ColumnIteratorUPtr* iterator);
164
165
    Status new_index_iterator(const std::shared_ptr<IndexFileReader>& index_file_reader,
166
                              const TabletIndex* index_meta,
167
                              std::unique_ptr<IndexIterator>* iterator);
168
169
    Status seek_at_or_before(ordinal_t ordinal, OrdinalPageIndexIterator* iter,
170
                             const ColumnIteratorOptions& iter_opts);
171
    Status get_ordinal_index_reader(OrdinalIndexReader*& reader,
172
                                    OlapReaderStatistics* index_load_stats);
173
174
    // read a page from file into a page handle
175
    Status read_page(const ColumnIteratorOptions& iter_opts, const PagePointer& pp,
176
                     PageHandle* handle, Slice* page_body, PageFooterPB* footer,
177
                     BlockCompressionCodec* codec, bool is_dict_page = false) const;
178
179
902k
    bool is_nullable() const { return _meta_is_nullable; }
180
181
30.3M
    const EncodingInfo* encoding_info() const { return _encoding_info; }
182
183
1.91M
    bool has_zone_map() const { return _zone_map_index != nullptr; }
184
    bool has_bloom_filter_index(bool ngram) const;
185
    // Check if this column could match `cond' using segment zone map.
186
    // Since segment zone map is stored in metadata, this function is fast without I/O.
187
    // set matched to true if segment zone map is absent or `cond' could be satisfied, false otherwise.
188
    Status match_condition(const AndBlockColumnPredicate* col_predicates, bool* matched) const;
189
190
    Status next_batch_of_zone_map(size_t* n, MutableColumnPtr& dst) const;
191
192
    // get row ranges with zone map
193
    // - cond_column is user's query predicate
194
    // - delete_condition is a delete predicate of one version
195
    Status get_row_ranges_by_zone_map(
196
            const AndBlockColumnPredicate* col_predicates,
197
            const std::vector<std::shared_ptr<const ColumnPredicate>>* delete_predicates,
198
            RowRanges* row_ranges, const ColumnIteratorOptions& iter_opts);
199
200
    // get row ranges with bloom filter index
201
    Status get_row_ranges_by_bloom_filter(const AndBlockColumnPredicate* col_predicates,
202
                                          RowRanges* row_ranges,
203
                                          const ColumnIteratorOptions& iter_opts);
204
205
395k
    PagePointer get_dict_page_pointer() const { return _meta_dict_page; }
206
207
27.2M
    bool is_empty() const { return _num_rows == 0; }
208
209
    Status prune_predicates_by_zone_map(std::vector<std::shared_ptr<ColumnPredicate>>& predicates,
210
                                        const int column_id, bool* pruned) const;
211
212
27.0M
    CompressionTypePB get_compression() const { return _meta_compression; }
213
214
380k
    uint64_t num_rows() const { return _num_rows; }
215
216
15.3k
    void set_dict_encoding_type(DictEncodingType type) {
217
15.3k
        static_cast<void>(_set_dict_encoding_type_once.call([&] {
218
15.3k
            _dict_encoding_type = type;
219
15.3k
            return Status::OK();
220
15.3k
        }));
221
15.3k
    }
222
223
16.1M
    DictEncodingType get_dict_encoding_type() { return _dict_encoding_type; }
224
225
26.9M
    void disable_index_meta_cache() { _use_index_page_cache = false; }
226
227
26.8k
    DataTypePtr get_vec_data_type() { return _data_type; }
228
229
53.3M
    virtual FieldType get_meta_type() { return _meta_type; }
230
231
    int64_t get_metadata_size() const override;
232
233
#ifdef BE_TEST
234
    void check_data_by_zone_map_for_test(const MutableColumnPtr& dst) const;
235
#endif
236
237
private:
238
    friend class VariantColumnReader;
239
    friend class FileColumnIterator;
240
    friend class SegmentPrefetcher;
241
242
    ColumnReader(const ColumnReaderOptions& opts, const ColumnMetaPB& meta, uint64_t num_rows,
243
                 io::FileReaderSPtr file_reader);
244
    Status init(const ColumnMetaPB* meta);
245
246
    [[nodiscard]] Status _load_zone_map_index(bool use_page_cache, bool kept_in_memory,
247
                                              const ColumnIteratorOptions& iter_opts);
248
    [[nodiscard]] Status _load_ordinal_index(bool use_page_cache, bool kept_in_memory,
249
                                             const ColumnIteratorOptions& iter_opts);
250
251
    [[nodiscard]] Status _load_index(const std::shared_ptr<IndexFileReader>& index_file_reader,
252
                                     const TabletIndex* index_meta);
253
    [[nodiscard]] Status _load_bloom_filter_index(bool use_page_cache, bool kept_in_memory,
254
                                                  const ColumnIteratorOptions& iter_opts);
255
256
    bool _zone_map_match_condition(const segment_v2::ZoneMap& zone_map,
257
                                   const AndBlockColumnPredicate* col_predicates) const;
258
259
    Status _get_filtered_pages(
260
            const AndBlockColumnPredicate* col_predicates,
261
            const std::vector<std::shared_ptr<const ColumnPredicate>>* delete_predicates,
262
            std::vector<uint32_t>* page_indexes, const ColumnIteratorOptions& iter_opts);
263
264
    Status _calculate_row_ranges(const std::vector<uint32_t>& page_indexes, RowRanges* row_ranges,
265
                                 const ColumnIteratorOptions& iter_opts);
266
267
    int64_t _meta_length;
268
    FieldType _meta_type;
269
    FieldType _meta_children_column_type;
270
    bool _meta_is_nullable;
271
    bool _use_index_page_cache;
272
    int _be_exec_version = -1;
273
274
    PagePointer _meta_dict_page;
275
    CompressionTypePB _meta_compression;
276
277
    ColumnReaderOptions _opts;
278
    uint64_t _num_rows;
279
280
    io::FileReaderSPtr _file_reader;
281
282
    DictEncodingType _dict_encoding_type;
283
284
    DataTypePtr _data_type;
285
286
    TypeInfoPtr _type_info =
287
            TypeInfoPtr(nullptr,
288
                        nullptr); // initialized in init(), may changed by subclasses.
289
    const EncodingInfo* _encoding_info =
290
            nullptr; // initialized in init(), used for create PageDecoder
291
292
    // meta for various column indexes (null if the index is absent)
293
    std::unique_ptr<ZoneMapPB> _segment_zone_map;
294
295
    mutable std::shared_mutex _load_index_lock;
296
    std::unique_ptr<ZoneMapIndexReader> _zone_map_index;
297
    std::unique_ptr<OrdinalIndexReader> _ordinal_index;
298
    std::shared_ptr<BloomFilterIndexReader> _bloom_filter_index;
299
300
    std::unordered_map<int64_t, IndexReaderPtr> _index_readers;
301
302
    std::vector<std::shared_ptr<ColumnReader>> _sub_readers;
303
304
    DorisCallOnce<Status> _set_dict_encoding_type_once;
305
};
306
307
// Base iterator to read one column data
308
class ColumnIterator {
309
public:
310
27.3M
    ColumnIterator() = default;
311
27.3M
    virtual ~ColumnIterator() = default;
312
313
40.9k
    virtual Status init(const ColumnIteratorOptions& opts) {
314
40.9k
        _opts = opts;
315
40.9k
        return Status::OK();
316
40.9k
    }
317
318
    // Seek to the given ordinal entry in the column.
319
    // Entry 0 is the first entry written to the column.
320
    // If provided seek point is past the end of the file,
321
    // then returns false.
322
    virtual Status seek_to_ordinal(ordinal_t ord) = 0;
323
324
1.81M
    Status next_batch(size_t* n, MutableColumnPtr& dst) {
325
1.81M
        bool has_null;
326
1.81M
        return next_batch(n, dst, &has_null);
327
1.81M
    }
328
329
0
    virtual Status next_batch(size_t* n, MutableColumnPtr& dst, bool* has_null) {
330
0
        return Status::NotSupported("next_batch not implement");
331
0
    }
332
333
0
    virtual Status next_batch_of_zone_map(size_t* n, MutableColumnPtr& dst) {
334
0
        return Status::NotSupported("next_batch_of_zone_map not implement");
335
0
    }
336
337
    virtual Status read_by_rowids(const rowid_t* rowids, const size_t count,
338
0
                                  MutableColumnPtr& dst) {
339
0
        return Status::NotSupported("read_by_rowids not implement");
340
0
    }
341
342
    virtual ordinal_t get_current_ordinal() const = 0;
343
344
    virtual Status get_row_ranges_by_zone_map(
345
            const AndBlockColumnPredicate* col_predicates,
346
            const std::vector<std::shared_ptr<const ColumnPredicate>>* delete_predicates,
347
22
            RowRanges* row_ranges) {
348
22
        return Status::OK();
349
22
    }
350
351
    virtual Status get_row_ranges_by_bloom_filter(const AndBlockColumnPredicate* col_predicates,
352
22
                                                  RowRanges* row_ranges) {
353
22
        return Status::OK();
354
22
    }
355
356
    virtual Status get_row_ranges_by_dict(const AndBlockColumnPredicate* col_predicates,
357
22
                                          RowRanges* row_ranges) {
358
22
        return Status::OK();
359
22
    }
360
361
2
    virtual bool is_all_dict_encoding() const { return false; }
362
363
    virtual Status set_access_paths(const TColumnAccessPaths& all_access_paths,
364
13.9k
                                    const TColumnAccessPaths& predicate_access_paths) {
365
13.9k
        if (!predicate_access_paths.empty()) {
366
179
            _reading_flag = ReadingFlag::READING_FOR_PREDICATE;
367
179
        }
368
13.9k
        return Status::OK();
369
13.9k
    }
370
371
27.2M
    void set_column_name(const std::string& column_name) { _column_name = column_name; }
372
373
25.5k
    const std::string& column_name() const { return _column_name; }
374
375
    // Since there may be multiple paths with conflicts or overlaps,
376
    // we need to define several reading flags:
377
    //
378
    // NORMAL_READING — Default value, indicating that the column should be read.
379
    // SKIP_READING — The column should not be read.
380
    // NEED_TO_READ — The column must be read.
381
    // READING_FOR_PREDICATE — The column is required for predicate evaluation.
382
    //
383
    // For example, suppose there are two paths:
384
    // - Path 1 specifies that column A needs to be read, so it is marked as NEED_TO_READ.
385
    // - Path 2 specifies that the column should not be read, but since it is already marked as NEED_TO_READ,
386
    //   it should not be changed to SKIP_READING.
387
    enum class ReadingFlag : int {
388
        NORMAL_READING,
389
        SKIP_READING,
390
        NEED_TO_READ,
391
        READING_FOR_PREDICATE
392
    };
393
193k
    void set_reading_flag(ReadingFlag flag) {
394
193k
        if (static_cast<int>(flag) > static_cast<int>(_reading_flag)) {
395
143k
            _reading_flag = flag;
396
143k
        }
397
193k
    }
398
399
53.7k
    ReadingFlag reading_flag() const { return _reading_flag; }
400
401
80.3k
    virtual void set_need_to_read() { set_reading_flag(ReadingFlag::NEED_TO_READ); }
402
403
83.4k
    virtual void remove_pruned_sub_iterators() {};
404
405
17.6k
    virtual Status init_prefetcher(const SegmentPrefetchParams& params) { return Status::OK(); }
406
407
    virtual void collect_prefetchers(
408
            std::map<PrefetcherInitMethod, std::vector<SegmentPrefetcher*>>& prefetchers,
409
17.6k
            PrefetcherInitMethod init_method) {}
410
411
    static constexpr const char* ACCESS_OFFSET = "OFFSET";
412
    static constexpr const char* ACCESS_ALL = "*";
413
    static constexpr const char* ACCESS_MAP_KEYS = "KEYS";
414
    static constexpr const char* ACCESS_MAP_VALUES = "VALUES";
415
    static constexpr const char* ACCESS_NULL = "NULL";
416
417
    // Meta-only read modes:
418
    // - OFFSET_ONLY: only read offset information (e.g., for array_size/map_size/string_length)
419
    // - NULL_MAP_ONLY: only read null map (e.g., for IS NULL / IS NOT NULL predicates)
420
    // When these modes are enabled, actual content data is skipped.
421
    enum class ReadMode : int { DEFAULT, OFFSET_ONLY, NULL_MAP_ONLY };
422
423
16.8M
    bool read_offset_only() const { return _read_mode == ReadMode::OFFSET_ONLY; }
424
4.15M
    bool read_null_map_only() const { return _read_mode == ReadMode::NULL_MAP_ONLY; }
425
426
protected:
427
    // Checks sub access paths for OFFSET or NULL meta-only modes and
428
    // updates _read_mode accordingly. Use the accessor helpers
429
    // read_offset_only() / read_null_map_only() to query the current mode.
430
    void _check_and_set_meta_read_mode(const TColumnAccessPaths& sub_all_access_paths);
431
432
    Result<TColumnAccessPaths> _get_sub_access_paths(const TColumnAccessPaths& access_paths);
433
    ColumnIteratorOptions _opts;
434
435
    ReadingFlag _reading_flag {ReadingFlag::NORMAL_READING};
436
    ReadMode _read_mode = ReadMode::DEFAULT;
437
    std::string _column_name;
438
};
439
440
// This iterator is used to read column data from file
441
// for scalar type
442
class FileColumnIterator : public ColumnIterator {
443
public:
444
    explicit FileColumnIterator(std::shared_ptr<ColumnReader> reader);
445
    ~FileColumnIterator() override;
446
447
    Status init(const ColumnIteratorOptions& opts) override;
448
449
    Status seek_to_ordinal(ordinal_t ord) override;
450
451
    Status seek_to_page_start();
452
453
    Status next_batch(size_t* n, MutableColumnPtr& dst, bool* has_null) override;
454
455
    Status next_batch_of_zone_map(size_t* n, MutableColumnPtr& dst) override;
456
457
    Status read_by_rowids(const rowid_t* rowids, const size_t count,
458
                          MutableColumnPtr& dst) override;
459
460
2
    ordinal_t get_current_ordinal() const override { return _current_ordinal; }
461
462
    // get row ranges by zone map
463
    // - cond_column is user's query predicate
464
    // - delete_condition is delete predicate of one version
465
    Status get_row_ranges_by_zone_map(
466
            const AndBlockColumnPredicate* col_predicates,
467
            const std::vector<std::shared_ptr<const ColumnPredicate>>* delete_predicates,
468
            RowRanges* row_ranges) override;
469
470
    Status get_row_ranges_by_bloom_filter(const AndBlockColumnPredicate* col_predicates,
471
                                          RowRanges* row_ranges) override;
472
473
    Status get_row_ranges_by_dict(const AndBlockColumnPredicate* col_predicates,
474
                                  RowRanges* row_ranges) override;
475
476
1.43M
    ParsedPage* get_current_page() { return &_page; }
477
478
0
    bool is_nullable() { return _reader->is_nullable(); }
479
480
11.0k
    bool is_all_dict_encoding() const override { return _is_all_dict_encoding; }
481
482
    Status init_prefetcher(const SegmentPrefetchParams& params) override;
483
    void collect_prefetchers(
484
            std::map<PrefetcherInitMethod, std::vector<SegmentPrefetcher*>>& prefetchers,
485
            PrefetcherInitMethod init_method) override;
486
487
private:
488
    Status _seek_to_pos_in_page(ParsedPage* page, ordinal_t offset_in_page) const;
489
    Status _load_next_page(bool* eos);
490
    Status _read_data_page(const OrdinalPageIndexIterator& iter);
491
    Status _read_dict_data();
492
    void _trigger_prefetch_if_eligible(ordinal_t ord);
493
494
    std::shared_ptr<ColumnReader> _reader = nullptr;
495
496
    BlockCompressionCodec* _compress_codec = nullptr;
497
498
    // 1. The _page represents current page.
499
    // 2. We define an operation is one seek and following read,
500
    //    If new seek is issued, the _page will be reset.
501
    ParsedPage _page;
502
503
    // keep dict page decoder
504
    std::unique_ptr<PageDecoder> _dict_decoder;
505
506
    // keep dict page handle to avoid released
507
    PageHandle _dict_page_handle;
508
509
    // page iterator used to get next page when current page is finished.
510
    // This value will be reset when a new seek is issued
511
    OrdinalPageIndexIterator _page_iter;
512
513
    // current value ordinal
514
    ordinal_t _current_ordinal = 0;
515
516
    bool _is_all_dict_encoding = false;
517
518
    std::unique_ptr<StringRef[]> _dict_word_info;
519
520
    bool _enable_prefetch {false};
521
    std::unique_ptr<SegmentPrefetcher> _prefetcher;
522
    std::shared_ptr<io::CachedRemoteFileReader> _cached_remote_file_reader {nullptr};
523
};
524
525
class EmptyFileColumnIterator final : public ColumnIterator {
526
public:
527
21.7k
    Status seek_to_ordinal(ordinal_t ord) override { return Status::OK(); }
528
0
    ordinal_t get_current_ordinal() const override { return 0; }
529
};
530
531
// StringFileColumnIterator extends FileColumnIterator with meta-only reading
532
// support for string/binary column types. When the OFFSET path is detected in
533
// set_access_paths, it sets only_read_offsets on the ColumnIteratorOptions so
534
// that the BinaryPlainPageDecoder skips chars memcpy and only fills offsets.
535
class StringFileColumnIterator final : public FileColumnIterator {
536
public:
537
    explicit StringFileColumnIterator(std::shared_ptr<ColumnReader> reader);
538
    ~StringFileColumnIterator() override = default;
539
540
    Status init(const ColumnIteratorOptions& opts) override;
541
542
    Status set_access_paths(const TColumnAccessPaths& all_access_paths,
543
                            const TColumnAccessPaths& predicate_access_paths) override;
544
};
545
546
// This iterator make offset operation write once for
547
class OffsetFileColumnIterator final : public ColumnIterator {
548
public:
549
99.7k
    explicit OffsetFileColumnIterator(FileColumnIteratorUPtr offset_reader) {
550
99.7k
        _offset_iterator = std::move(offset_reader);
551
99.7k
    }
552
553
99.9k
    ~OffsetFileColumnIterator() override = default;
554
555
    Status init(const ColumnIteratorOptions& opts) override;
556
557
    Status next_batch(size_t* n, MutableColumnPtr& dst, bool* has_null) override;
558
559
0
    Status next_batch(size_t* n, MutableColumnPtr& dst) {
560
0
        bool has_null;
561
0
        return next_batch(n, dst, &has_null);
562
0
    }
563
564
0
    ordinal_t get_current_ordinal() const override {
565
0
        return _offset_iterator->get_current_ordinal();
566
0
    }
567
366k
    Status seek_to_ordinal(ordinal_t ord) override {
568
366k
        RETURN_IF_ERROR(_offset_iterator->seek_to_ordinal(ord));
569
366k
        return Status::OK();
570
366k
    }
571
572
    Status _peek_one_offset(ordinal_t* offset);
573
574
    Status _calculate_offsets(ssize_t start, ColumnArray::ColumnOffsets& column_offsets);
575
576
    Status read_by_rowids(const rowid_t* rowids, const size_t count,
577
27.5k
                          MutableColumnPtr& dst) override {
578
27.5k
        return _offset_iterator->read_by_rowids(rowids, count, dst);
579
27.5k
    }
580
581
    Status init_prefetcher(const SegmentPrefetchParams& params) override;
582
    void collect_prefetchers(
583
            std::map<PrefetcherInitMethod, std::vector<SegmentPrefetcher*>>& prefetchers,
584
            PrefetcherInitMethod init_method) override;
585
586
private:
587
    std::unique_ptr<FileColumnIterator> _offset_iterator;
588
    // reuse a tiny column for peek to avoid frequent allocations
589
    MutableColumnPtr _peek_tmp_col;
590
};
591
592
// This iterator is used to read map value column
593
class MapFileColumnIterator final : public ColumnIterator {
594
public:
595
    explicit MapFileColumnIterator(std::shared_ptr<ColumnReader> reader,
596
                                   ColumnIteratorUPtr null_iterator,
597
                                   OffsetFileColumnIteratorUPtr offsets_iterator,
598
                                   ColumnIteratorUPtr key_iterator,
599
                                   ColumnIteratorUPtr val_iterator);
600
601
31.9k
    ~MapFileColumnIterator() override = default;
602
603
    Status init(const ColumnIteratorOptions& opts) override;
604
605
    Status next_batch(size_t* n, MutableColumnPtr& dst, bool* has_null) override;
606
607
    Status read_by_rowids(const rowid_t* rowids, const size_t count,
608
                          MutableColumnPtr& dst) override;
609
610
    Status seek_to_ordinal(ordinal_t ord) override;
611
612
0
    ordinal_t get_current_ordinal() const override {
613
0
        if (read_null_map_only() && _null_iterator) {
614
0
            return _null_iterator->get_current_ordinal();
615
0
        }
616
0
        return _offsets_iterator->get_current_ordinal();
617
0
    }
618
    Status init_prefetcher(const SegmentPrefetchParams& params) override;
619
    void collect_prefetchers(
620
            std::map<PrefetcherInitMethod, std::vector<SegmentPrefetcher*>>& prefetchers,
621
            PrefetcherInitMethod init_method) override;
622
623
    Status set_access_paths(const TColumnAccessPaths& all_access_paths,
624
                            const TColumnAccessPaths& predicate_access_paths) override;
625
626
    void set_need_to_read() override;
627
628
    void remove_pruned_sub_iterators() override;
629
630
private:
631
    std::shared_ptr<ColumnReader> _map_reader = nullptr;
632
    ColumnIteratorUPtr _null_iterator;
633
    OffsetFileColumnIteratorUPtr _offsets_iterator; //OffsetFileIterator
634
    ColumnIteratorUPtr _key_iterator;
635
    ColumnIteratorUPtr _val_iterator;
636
};
637
638
class StructFileColumnIterator final : public ColumnIterator {
639
public:
640
    explicit StructFileColumnIterator(std::shared_ptr<ColumnReader> reader,
641
                                      ColumnIteratorUPtr null_iterator,
642
                                      std::vector<ColumnIteratorUPtr>&& sub_column_iterators);
643
644
7.85k
    ~StructFileColumnIterator() override = default;
645
646
    Status init(const ColumnIteratorOptions& opts) override;
647
648
    Status next_batch(size_t* n, MutableColumnPtr& dst, bool* has_null) override;
649
650
2.68k
    Status next_batch(size_t* n, MutableColumnPtr& dst) {
651
2.68k
        bool has_null;
652
2.68k
        return next_batch(n, dst, &has_null);
653
2.68k
    }
654
655
    Status read_by_rowids(const rowid_t* rowids, const size_t count,
656
                          MutableColumnPtr& dst) override;
657
658
    Status seek_to_ordinal(ordinal_t ord) override;
659
660
0
    ordinal_t get_current_ordinal() const override {
661
0
        if (read_null_map_only() && _null_iterator) {
662
0
            return _null_iterator->get_current_ordinal();
663
0
        }
664
0
        return _sub_column_iterators[0]->get_current_ordinal();
665
0
    }
666
667
    Status set_access_paths(const TColumnAccessPaths& all_access_paths,
668
                            const TColumnAccessPaths& predicate_access_paths) override;
669
670
    void set_need_to_read() override;
671
672
    void remove_pruned_sub_iterators() override;
673
674
    Status init_prefetcher(const SegmentPrefetchParams& params) override;
675
    void collect_prefetchers(
676
            std::map<PrefetcherInitMethod, std::vector<SegmentPrefetcher*>>& prefetchers,
677
            PrefetcherInitMethod init_method) override;
678
679
private:
680
    std::shared_ptr<ColumnReader> _struct_reader = nullptr;
681
    ColumnIteratorUPtr _null_iterator;
682
    std::vector<ColumnIteratorUPtr> _sub_column_iterators;
683
};
684
685
class ArrayFileColumnIterator final : public ColumnIterator {
686
public:
687
    explicit ArrayFileColumnIterator(std::shared_ptr<ColumnReader> reader,
688
                                     OffsetFileColumnIteratorUPtr offset_reader,
689
                                     ColumnIteratorUPtr item_iterator,
690
                                     ColumnIteratorUPtr null_iterator);
691
692
68.0k
    ~ArrayFileColumnIterator() override = default;
693
694
    Status init(const ColumnIteratorOptions& opts) override;
695
696
    Status next_batch(size_t* n, MutableColumnPtr& dst, bool* has_null) override;
697
698
309k
    Status next_batch(size_t* n, MutableColumnPtr& dst) {
699
309k
        bool has_null;
700
309k
        return next_batch(n, dst, &has_null);
701
309k
    }
702
703
    Status read_by_rowids(const rowid_t* rowids, const size_t count,
704
                          MutableColumnPtr& dst) override;
705
706
    Status seek_to_ordinal(ordinal_t ord) override;
707
708
0
    ordinal_t get_current_ordinal() const override {
709
0
        if (read_null_map_only() && _null_iterator) {
710
0
            return _null_iterator->get_current_ordinal();
711
0
        }
712
0
        return _offset_iterator->get_current_ordinal();
713
0
    }
714
715
    Status set_access_paths(const TColumnAccessPaths& all_access_paths,
716
                            const TColumnAccessPaths& predicate_access_paths) override;
717
    void set_need_to_read() override;
718
719
    void remove_pruned_sub_iterators() override;
720
721
    Status init_prefetcher(const SegmentPrefetchParams& params) override;
722
    void collect_prefetchers(
723
            std::map<PrefetcherInitMethod, std::vector<SegmentPrefetcher*>>& prefetchers,
724
            PrefetcherInitMethod init_method) override;
725
726
private:
727
    std::shared_ptr<ColumnReader> _array_reader = nullptr;
728
    std::unique_ptr<OffsetFileColumnIterator> _offset_iterator;
729
    std::unique_ptr<ColumnIterator> _null_iterator;
730
    std::unique_ptr<ColumnIterator> _item_iterator;
731
732
    Status _seek_by_offsets(ordinal_t ord);
733
};
734
735
class RowIdColumnIterator : public ColumnIterator {
736
public:
737
    RowIdColumnIterator() = delete;
738
    RowIdColumnIterator(int64_t tid, RowsetId rid, int32_t segid)
739
11
            : _tablet_id(tid), _rowset_id(rid), _segment_id(segid) {}
740
741
7
    Status seek_to_ordinal(ordinal_t ord_idx) override {
742
7
        _current_rowid = cast_set<uint32_t>(ord_idx);
743
7
        return Status::OK();
744
7
    }
745
746
0
    Status next_batch(size_t* n, MutableColumnPtr& dst) {
747
0
        bool has_null;
748
0
        return next_batch(n, dst, &has_null);
749
0
    }
750
751
7
    Status next_batch(size_t* n, MutableColumnPtr& dst, bool* has_null) override {
752
28
        for (size_t i = 0; i < *n; ++i) {
753
21
            const auto row_id = cast_set<uint32_t>(_current_rowid + i);
754
21
            GlobalRowLoacation location(_tablet_id, _rowset_id, _segment_id, row_id);
755
21
            dst->insert_data(reinterpret_cast<const char*>(&location), sizeof(GlobalRowLoacation));
756
21
        }
757
7
        _current_rowid += *n;
758
7
        return Status::OK();
759
7
    }
760
761
    Status read_by_rowids(const rowid_t* rowids, const size_t count,
762
4
                          MutableColumnPtr& dst) override {
763
8
        for (size_t i = 0; i < count; ++i) {
764
4
            rowid_t row_id = rowids[i];
765
4
            GlobalRowLoacation location(_tablet_id, _rowset_id, _segment_id, row_id);
766
4
            dst->insert_data(reinterpret_cast<const char*>(&location), sizeof(GlobalRowLoacation));
767
4
        }
768
4
        return Status::OK();
769
4
    }
770
771
0
    ordinal_t get_current_ordinal() const override { return _current_rowid; }
772
773
private:
774
    rowid_t _current_rowid = 0;
775
    int64_t _tablet_id = 0;
776
    RowsetId _rowset_id;
777
    int32_t _segment_id = 0;
778
};
779
780
// Add new RowIdColumnIteratorV2
781
class RowIdColumnIteratorV2 : public ColumnIterator {
782
public:
783
    RowIdColumnIteratorV2(uint8_t version, int64_t backend_id, uint32_t file_id)
784
15.7k
            : _version(version), _backend_id(backend_id), _file_id(file_id) {}
785
786
10.2k
    Status seek_to_ordinal(ordinal_t ord_idx) override {
787
10.2k
        _current_rowid = cast_set<uint32_t>(ord_idx);
788
10.2k
        return Status::OK();
789
10.2k
    }
790
791
6.93k
    Status next_batch(size_t* n, MutableColumnPtr& dst) {
792
6.93k
        bool has_null;
793
6.93k
        return next_batch(n, dst, &has_null);
794
6.93k
    }
795
796
    Status next_batch(size_t* n, MutableColumnPtr& dst, bool* has_null) override;
797
798
    Status read_by_rowids(const rowid_t* rowids, const size_t count,
799
                          MutableColumnPtr& dst) override;
800
801
0
    ordinal_t get_current_ordinal() const override { return _current_rowid; }
802
803
private:
804
    uint32_t _current_rowid = 0;
805
    uint8_t _version;
806
    int64_t _backend_id;
807
    uint32_t _file_id;
808
};
809
810
// This iterator is used to read default value column
811
class DefaultValueColumnIterator : public ColumnIterator {
812
public:
813
    DefaultValueColumnIterator(bool has_default_value, std::string default_value, bool is_nullable,
814
                               TypeInfoPtr type_info, int precision, int scale, int len)
815
10.6k
            : _has_default_value(has_default_value),
816
10.6k
              _default_value(std::move(default_value)),
817
10.6k
              _is_nullable(is_nullable),
818
10.6k
              _type_info(std::move(type_info)),
819
10.6k
              _precision(precision),
820
10.6k
              _scale(scale),
821
10.6k
              _len(len) {}
822
823
    Status init(const ColumnIteratorOptions& opts) override;
824
825
2.76k
    Status seek_to_ordinal(ordinal_t ord_idx) override {
826
2.76k
        _current_rowid = ord_idx;
827
2.76k
        return Status::OK();
828
2.76k
    }
829
830
8
    Status next_batch(size_t* n, MutableColumnPtr& dst) {
831
8
        bool has_null;
832
8
        return next_batch(n, dst, &has_null);
833
8
    }
834
835
    Status next_batch(size_t* n, MutableColumnPtr& dst, bool* has_null) override;
836
837
8
    Status next_batch_of_zone_map(size_t* n, MutableColumnPtr& dst) override {
838
8
        return next_batch(n, dst);
839
8
    }
840
841
    Status read_by_rowids(const rowid_t* rowids, const size_t count,
842
                          MutableColumnPtr& dst) override;
843
844
0
    ordinal_t get_current_ordinal() const override { return _current_rowid; }
845
846
private:
847
    void _insert_many_default(MutableColumnPtr& dst, size_t n);
848
849
    bool _has_default_value;
850
    std::string _default_value;
851
    bool _is_nullable;
852
    TypeInfoPtr _type_info;
853
    int _precision;
854
    int _scale;
855
    const int _len;
856
    Field _default_value_field;
857
858
    // current rowid
859
    ordinal_t _current_rowid = 0;
860
};
861
862
} // namespace segment_v2
863
} // namespace doris