Coverage Report

Created: 2026-07-18 01:24

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