Coverage Report

Created: 2026-06-24 02:03

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