Coverage Report

Created: 2026-06-25 20:59

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