Coverage Report

Created: 2026-07-09 20:43

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
be/src/format/table/iceberg_reader_mixin.h
Line
Count
Source
1
// Licensed to the Apache Software Foundation (ASF) under one
2
// or more contributor license agreements.  See the NOTICE file
3
// distributed with this work for additional information
4
// regarding copyright ownership.  The ASF licenses this file
5
// to you under the Apache License, Version 2.0 (the
6
// "License"); you may not use this file except in compliance
7
// with the License.  You may obtain a copy of the License at
8
//
9
//   http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing,
12
// software distributed under the License is distributed on an
13
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
// KIND, either express or implied.  See the License for the
15
// specific language governing permissions and limitations
16
// under the License.
17
18
#pragma once
19
20
#include <cstddef>
21
#include <cstdint>
22
#include <memory>
23
#include <string>
24
#include <unordered_map>
25
#include <vector>
26
27
#include "common/consts.h"
28
#include "common/status.h"
29
#include "core/block/block.h"
30
#include "core/column/column_dictionary.h"
31
#include "core/column/column_nullable.h"
32
#include "core/column/column_string.h"
33
#include "core/column/column_struct.h"
34
#include "core/data_type/data_type_number.h"
35
#include "core/data_type/data_type_string.h"
36
#include "format/generic_reader.h"
37
#include "format/table/equality_delete.h"
38
#include "format/table/iceberg_delete_file_reader_helper.h"
39
#include "format/table/table_schema_change_helper.h"
40
#include "runtime/runtime_profile.h"
41
#include "runtime/runtime_state.h"
42
#include "storage/olap_common.h"
43
44
namespace doris {
45
class TIcebergDeleteFileDesc;
46
} // namespace doris
47
48
namespace doris {
49
50
class ShardedKVCache;
51
52
// CRTP mixin for Iceberg reader functionality.
53
// BaseReader should be ParquetReader or OrcReader.
54
// Inherits BaseReader + TableSchemaChangeHelper, providing shared Iceberg logic
55
// (delete files, deletion vectors, equality delete, $row_id synthesis).
56
//
57
// Inheritance chain:
58
//   IcebergParquetReader -> IcebergReaderMixin<ParquetReader> -> ParquetReader -> GenericReader
59
//   IcebergOrcReader     -> IcebergReaderMixin<OrcReader>     -> OrcReader     -> GenericReader
60
template <typename BaseReader>
61
class IcebergReaderMixin : public BaseReader, public TableSchemaChangeHelper {
62
public:
63
    struct PositionDeleteRange {
64
        std::vector<std::string> data_file_path;
65
        std::vector<std::pair<int, int>> range;
66
    };
67
68
    // Forward BaseReader constructor arguments + Iceberg-specific kv_cache
69
    template <typename... Args>
70
    IcebergReaderMixin(ShardedKVCache* kv_cache, Args&&... args)
71
16
            : BaseReader(std::forward<Args>(args)...), _kv_cache(kv_cache) {
72
16
        static const char* iceberg_profile = "IcebergProfile";
73
16
        ADD_TIMER(this->get_profile(), iceberg_profile);
74
16
        _iceberg_profile.num_delete_files = ADD_CHILD_COUNTER(this->get_profile(), "NumDeleteFiles",
75
16
                                                              TUnit::UNIT, iceberg_profile);
76
16
        _iceberg_profile.num_delete_rows = ADD_CHILD_COUNTER(this->get_profile(), "NumDeleteRows",
77
16
                                                             TUnit::UNIT, iceberg_profile);
78
16
        _iceberg_profile.delete_files_read_time =
79
16
                ADD_CHILD_TIMER(this->get_profile(), "DeleteFileReadTime", iceberg_profile);
80
16
        _iceberg_profile.delete_rows_sort_time =
81
16
                ADD_CHILD_TIMER(this->get_profile(), "DeleteRowsSortTime", iceberg_profile);
82
16
        _iceberg_profile.parse_delete_file_time =
83
16
                ADD_CHILD_TIMER(this->get_profile(), "ParseDeleteFileTime", iceberg_profile);
84
16
    }
_ZN5doris18IcebergReaderMixinINS_13ParquetReaderEEC2IJRPNS_14RuntimeProfileERKNS_20TFileScanRangeParamsERKNS_14TFileRangeDescERmRPKN4cctz9time_zoneERPNS_2io9IOContextERPNS_12RuntimeStateERPNS_13FileMetaCacheEEEEPNS_14ShardedKVCacheEDpOT_
Line
Count
Source
71
9
            : BaseReader(std::forward<Args>(args)...), _kv_cache(kv_cache) {
72
9
        static const char* iceberg_profile = "IcebergProfile";
73
9
        ADD_TIMER(this->get_profile(), iceberg_profile);
74
9
        _iceberg_profile.num_delete_files = ADD_CHILD_COUNTER(this->get_profile(), "NumDeleteFiles",
75
9
                                                              TUnit::UNIT, iceberg_profile);
76
9
        _iceberg_profile.num_delete_rows = ADD_CHILD_COUNTER(this->get_profile(), "NumDeleteRows",
77
9
                                                             TUnit::UNIT, iceberg_profile);
78
9
        _iceberg_profile.delete_files_read_time =
79
9
                ADD_CHILD_TIMER(this->get_profile(), "DeleteFileReadTime", iceberg_profile);
80
9
        _iceberg_profile.delete_rows_sort_time =
81
9
                ADD_CHILD_TIMER(this->get_profile(), "DeleteRowsSortTime", iceberg_profile);
82
9
        _iceberg_profile.parse_delete_file_time =
83
9
                ADD_CHILD_TIMER(this->get_profile(), "ParseDeleteFileTime", iceberg_profile);
84
9
    }
_ZN5doris18IcebergReaderMixinINS_9OrcReaderEEC2IJRPNS_14RuntimeProfileERPNS_12RuntimeStateERKNS_20TFileScanRangeParamsERKNS_14TFileRangeDescERmRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERPNS_2io9IOContextERPNS_13FileMetaCacheEEEEPNS_14ShardedKVCacheEDpOT_
Line
Count
Source
71
7
            : BaseReader(std::forward<Args>(args)...), _kv_cache(kv_cache) {
72
7
        static const char* iceberg_profile = "IcebergProfile";
73
7
        ADD_TIMER(this->get_profile(), iceberg_profile);
74
7
        _iceberg_profile.num_delete_files = ADD_CHILD_COUNTER(this->get_profile(), "NumDeleteFiles",
75
7
                                                              TUnit::UNIT, iceberg_profile);
76
7
        _iceberg_profile.num_delete_rows = ADD_CHILD_COUNTER(this->get_profile(), "NumDeleteRows",
77
7
                                                             TUnit::UNIT, iceberg_profile);
78
7
        _iceberg_profile.delete_files_read_time =
79
7
                ADD_CHILD_TIMER(this->get_profile(), "DeleteFileReadTime", iceberg_profile);
80
7
        _iceberg_profile.delete_rows_sort_time =
81
7
                ADD_CHILD_TIMER(this->get_profile(), "DeleteRowsSortTime", iceberg_profile);
82
7
        _iceberg_profile.parse_delete_file_time =
83
7
                ADD_CHILD_TIMER(this->get_profile(), "ParseDeleteFileTime", iceberg_profile);
84
7
    }
Unexecuted instantiation: _ZN5doris18IcebergReaderMixinINS_13ParquetReaderEEC2IJRPNS_14RuntimeProfileERKNS_20TFileScanRangeParamsERKNS_14TFileRangeDescERmRPKN4cctz9time_zoneESt10shared_ptrINS_2io9IOContextEERPNS_12RuntimeStateERPNS_13FileMetaCacheEEEEPNS_14ShardedKVCacheEDpOT_
Unexecuted instantiation: _ZN5doris18IcebergReaderMixinINS_9OrcReaderEEC2IJRPNS_14RuntimeProfileERPNS_12RuntimeStateERKNS_20TFileScanRangeParamsERKNS_14TFileRangeDescERmRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt10shared_ptrINS_2io9IOContextEERPNS_13FileMetaCacheEEEEPNS_14ShardedKVCacheEDpOT_
85
86
16
    ~IcebergReaderMixin() override = default;
_ZN5doris18IcebergReaderMixinINS_13ParquetReaderEED2Ev
Line
Count
Source
86
9
    ~IcebergReaderMixin() override = default;
_ZN5doris18IcebergReaderMixinINS_9OrcReaderEED2Ev
Line
Count
Source
86
7
    ~IcebergReaderMixin() override = default;
87
88
    void set_current_file_info(const std::string& file_path, int32_t partition_spec_id,
89
0
                               const std::string& partition_data_json) {
90
0
        _current_file_path = file_path;
91
0
        _partition_spec_id = partition_spec_id;
92
0
        _partition_data_json = partition_data_json;
93
0
    }
Unexecuted instantiation: _ZN5doris18IcebergReaderMixinINS_13ParquetReaderEE21set_current_file_infoERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEiSA_
Unexecuted instantiation: _ZN5doris18IcebergReaderMixinINS_9OrcReaderEE21set_current_file_infoERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEiSA_
94
95
    enum { DATA, POSITION_DELETE, EQUALITY_DELETE, DELETION_VECTOR };
96
    enum Fileformat { NONE, PARQUET, ORC, AVRO };
97
98
    virtual void set_delete_rows() = 0;
99
100
    // Table-level COUNT(*) is handled by CountReader (created by FileScanner after
101
    // init_reader). If _do_get_next_block is called, COUNT must have been resolved.
102
2
    Status _do_get_next_block(Block* block, size_t* read_rows, bool* eof) override {
103
2
        DCHECK(this->_push_down_agg_type != TPushAggOp::type::COUNT);
104
2
        return BaseReader::_do_get_next_block(block, read_rows, eof);
105
2
    }
_ZN5doris18IcebergReaderMixinINS_13ParquetReaderEE18_do_get_next_blockEPNS_5BlockEPmPb
Line
Count
Source
102
1
    Status _do_get_next_block(Block* block, size_t* read_rows, bool* eof) override {
103
        DCHECK(this->_push_down_agg_type != TPushAggOp::type::COUNT);
104
1
        return BaseReader::_do_get_next_block(block, read_rows, eof);
105
1
    }
_ZN5doris18IcebergReaderMixinINS_9OrcReaderEE18_do_get_next_blockEPNS_5BlockEPmPb
Line
Count
Source
102
1
    Status _do_get_next_block(Block* block, size_t* read_rows, bool* eof) override {
103
        DCHECK(this->_push_down_agg_type != TPushAggOp::type::COUNT);
104
1
        return BaseReader::_do_get_next_block(block, read_rows, eof);
105
1
    }
106
107
    void set_create_row_id_column_iterator_func(
108
0
            std::function<std::shared_ptr<segment_v2::RowIdColumnIteratorV2>()> create_func) {
109
0
        _create_topn_row_id_column_iterator = create_func;
110
0
    }
Unexecuted instantiation: _ZN5doris18IcebergReaderMixinINS_13ParquetReaderEE38set_create_row_id_column_iterator_funcESt8functionIFSt10shared_ptrINS_10segment_v221RowIdColumnIteratorV2EEvEE
Unexecuted instantiation: _ZN5doris18IcebergReaderMixinINS_9OrcReaderEE38set_create_row_id_column_iterator_funcESt8functionIFSt10shared_ptrINS_10segment_v221RowIdColumnIteratorV2EEvEE
111
112
    Status TEST_read_deletion_vector(const std::string& data_file_path,
113
1
                                     const TIcebergDeleteFileDesc& delete_file_desc) {
114
1
        return read_deletion_vector(data_file_path, delete_file_desc);
115
1
    }
116
117
    Status TEST_position_delete_base(const std::string& data_file_path,
118
1
                                     const std::vector<TIcebergDeleteFileDesc>& delete_files) {
119
1
        return _position_delete_base(data_file_path, delete_files);
120
1
    }
121
122
protected:
123
    // ---- Hook implementations ----
124
125
    // Called before reading a block: expand block for equality delete columns + detect row_id
126
2
    Status on_before_read_block(Block* block) override {
127
2
        RETURN_IF_ERROR(_expand_block_if_need(block));
128
2
        return Status::OK();
129
2
    }
_ZN5doris18IcebergReaderMixinINS_13ParquetReaderEE20on_before_read_blockEPNS_5BlockE
Line
Count
Source
126
1
    Status on_before_read_block(Block* block) override {
127
1
        RETURN_IF_ERROR(_expand_block_if_need(block));
128
1
        return Status::OK();
129
1
    }
_ZN5doris18IcebergReaderMixinINS_9OrcReaderEE20on_before_read_blockEPNS_5BlockE
Line
Count
Source
126
1
    Status on_before_read_block(Block* block) override {
127
1
        RETURN_IF_ERROR(_expand_block_if_need(block));
128
1
        return Status::OK();
129
1
    }
130
131
    /// Fill Iceberg $row_id synthesized column. Registered as handler during init.
132
0
    Status _fill_iceberg_row_id(Block* block, size_t rows) {
133
0
        int row_id_pos = block->get_position_by_name(BeConsts::ICEBERG_ROWID_COL);
134
0
        DORIS_CHECK(row_id_pos >= 0);
135
136
        // Lazy-init file info: only set when $row_id is actually needed.
137
0
        const auto& table_desc = this->get_scan_range().table_format_params.iceberg_params;
138
0
        std::string file_path = table_desc.original_file_path;
139
0
        int32_t partition_spec_id =
140
0
                table_desc.__isset.partition_spec_id ? table_desc.partition_spec_id : 0;
141
0
        std::string partition_data_json;
142
0
        if (table_desc.__isset.partition_data_json) {
143
0
            partition_data_json = table_desc.partition_data_json;
144
0
        }
145
0
        set_current_file_info(file_path, partition_spec_id, partition_data_json);
146
147
0
        const auto& row_ids = this->current_batch_row_positions();
148
0
        auto& col_with_type = block->get_by_position(static_cast<size_t>(row_id_pos));
149
0
        MutableColumnPtr row_id_column;
150
0
        RETURN_IF_ERROR(_build_iceberg_rowid_column(col_with_type.type, _current_file_path, row_ids,
151
0
                                                    _partition_spec_id, _partition_data_json,
152
0
                                                    &row_id_column));
153
0
        col_with_type.column = std::move(row_id_column);
154
0
        return Status::OK();
155
0
    }
Unexecuted instantiation: _ZN5doris18IcebergReaderMixinINS_13ParquetReaderEE20_fill_iceberg_row_idEPNS_5BlockEm
Unexecuted instantiation: _ZN5doris18IcebergReaderMixinINS_9OrcReaderEE20_fill_iceberg_row_idEPNS_5BlockEm
156
157
0
    void _init_row_lineage_columns() {
158
0
        const auto& table_desc = this->get_scan_range().table_format_params.iceberg_params;
159
0
        if (table_desc.__isset.first_row_id) {
160
0
            _row_lineage_columns.first_row_id = table_desc.first_row_id;
161
0
        }
162
0
        if (table_desc.__isset.last_updated_sequence_number) {
163
0
            _row_lineage_columns.last_updated_sequence_number =
164
0
                    table_desc.last_updated_sequence_number;
165
0
        }
166
0
    }
Unexecuted instantiation: _ZN5doris18IcebergReaderMixinINS_13ParquetReaderEE25_init_row_lineage_columnsEv
Unexecuted instantiation: _ZN5doris18IcebergReaderMixinINS_9OrcReaderEE25_init_row_lineage_columnsEv
167
168
0
    Status _fill_row_lineage_row_id(Block* block, size_t rows) {
169
0
        int col_pos = block->get_position_by_name(ROW_LINEAGE_ROW_ID);
170
0
        DORIS_CHECK(col_pos >= 0);
171
172
0
        if (_row_lineage_columns.first_row_id >= 0) {
173
0
            auto column_guard = block->mutate_column_scoped(col_pos);
174
0
            auto* nullable_column =
175
0
                    assert_cast<ColumnNullable*>(column_guard.mutable_column().get());
176
0
            auto& null_map = nullable_column->get_null_map_data();
177
0
            auto& data =
178
0
                    assert_cast<ColumnInt64&>(*nullable_column->get_nested_column_ptr()).get_data();
179
0
            const auto& row_ids = this->current_batch_row_positions();
180
0
            for (size_t i = 0; i < rows; ++i) {
181
0
                if (null_map[i] != 0) {
182
0
                    null_map[i] = 0;
183
0
                    data[i] = _row_lineage_columns.first_row_id + static_cast<int64_t>(row_ids[i]);
184
0
                }
185
0
            }
186
0
        }
187
0
        return Status::OK();
188
0
    }
Unexecuted instantiation: _ZN5doris18IcebergReaderMixinINS_13ParquetReaderEE24_fill_row_lineage_row_idEPNS_5BlockEm
Unexecuted instantiation: _ZN5doris18IcebergReaderMixinINS_9OrcReaderEE24_fill_row_lineage_row_idEPNS_5BlockEm
189
190
0
    Status _fill_row_lineage_last_updated_sequence_number(Block* block, size_t rows) {
191
0
        int col_pos = block->get_position_by_name(ROW_LINEAGE_LAST_UPDATED_SEQ_NUMBER);
192
0
        DORIS_CHECK(col_pos >= 0);
193
194
0
        if (_row_lineage_columns.last_updated_sequence_number >= 0) {
195
0
            auto column_guard = block->mutate_column_scoped(col_pos);
196
0
            auto* nullable_column =
197
0
                    assert_cast<ColumnNullable*>(column_guard.mutable_column().get());
198
0
            auto& null_map = nullable_column->get_null_map_data();
199
0
            auto& data =
200
0
                    assert_cast<ColumnInt64&>(*nullable_column->get_nested_column_ptr()).get_data();
201
0
            for (size_t i = 0; i < rows; ++i) {
202
0
                if (null_map[i] != 0) {
203
0
                    null_map[i] = 0;
204
0
                    data[i] = _row_lineage_columns.last_updated_sequence_number;
205
0
                }
206
0
            }
207
0
        }
208
0
        return Status::OK();
209
0
    }
Unexecuted instantiation: _ZN5doris18IcebergReaderMixinINS_13ParquetReaderEE46_fill_row_lineage_last_updated_sequence_numberEPNS_5BlockEm
Unexecuted instantiation: _ZN5doris18IcebergReaderMixinINS_9OrcReaderEE46_fill_row_lineage_last_updated_sequence_numberEPNS_5BlockEm
210
211
    // Called after reading a block: apply equality delete filter + shrink block
212
2
    Status on_after_read_block(Block* block, size_t* read_rows) override {
213
2
        if (!_equality_delete_impls.empty()) {
214
0
            std::unique_ptr<IColumn::Filter> filter =
215
0
                    std::make_unique<IColumn::Filter>(block->rows(), 1);
216
0
            for (auto& equality_delete_impl : _equality_delete_impls) {
217
0
                RETURN_IF_ERROR(equality_delete_impl->filter_data_block(
218
0
                        block, this->col_name_to_block_idx_ref(), _id_to_block_column_name,
219
0
                        *filter));
220
0
            }
221
0
            Block::filter_block_internal(block, *filter, block->columns());
222
0
            *read_rows = block->rows();
223
0
        }
224
2
        return _shrink_block_if_need(block);
225
2
    }
_ZN5doris18IcebergReaderMixinINS_13ParquetReaderEE19on_after_read_blockEPNS_5BlockEPm
Line
Count
Source
212
1
    Status on_after_read_block(Block* block, size_t* read_rows) override {
213
1
        if (!_equality_delete_impls.empty()) {
214
0
            std::unique_ptr<IColumn::Filter> filter =
215
0
                    std::make_unique<IColumn::Filter>(block->rows(), 1);
216
0
            for (auto& equality_delete_impl : _equality_delete_impls) {
217
0
                RETURN_IF_ERROR(equality_delete_impl->filter_data_block(
218
0
                        block, this->col_name_to_block_idx_ref(), _id_to_block_column_name,
219
0
                        *filter));
220
0
            }
221
0
            Block::filter_block_internal(block, *filter, block->columns());
222
0
            *read_rows = block->rows();
223
0
        }
224
1
        return _shrink_block_if_need(block);
225
1
    }
_ZN5doris18IcebergReaderMixinINS_9OrcReaderEE19on_after_read_blockEPNS_5BlockEPm
Line
Count
Source
212
1
    Status on_after_read_block(Block* block, size_t* read_rows) override {
213
1
        if (!_equality_delete_impls.empty()) {
214
0
            std::unique_ptr<IColumn::Filter> filter =
215
0
                    std::make_unique<IColumn::Filter>(block->rows(), 1);
216
0
            for (auto& equality_delete_impl : _equality_delete_impls) {
217
0
                RETURN_IF_ERROR(equality_delete_impl->filter_data_block(
218
0
                        block, this->col_name_to_block_idx_ref(), _id_to_block_column_name,
219
0
                        *filter));
220
0
            }
221
0
            Block::filter_block_internal(block, *filter, block->columns());
222
0
            *read_rows = block->rows();
223
0
        }
224
1
        return _shrink_block_if_need(block);
225
1
    }
226
227
    // ---- Shared Iceberg methods ----
228
229
    Status _init_row_filters();
230
    Status _position_delete_base(const std::string data_file_path,
231
                                 const std::vector<TIcebergDeleteFileDesc>& delete_files);
232
    Status _equality_delete_base(const std::vector<TIcebergDeleteFileDesc>& delete_files);
233
    Status read_deletion_vector(const std::string& data_file_path,
234
                                const TIcebergDeleteFileDesc& delete_file_desc);
235
236
    Status _expand_block_if_need(Block* block);
237
    Status _shrink_block_if_need(Block* block);
238
239
    // Type aliases — must be defined before member function declarations that use them.
240
    using DeleteRows = std::vector<int64_t>;
241
    using DeleteFile = phmap::parallel_flat_hash_map<
242
            std::string, std::unique_ptr<DeleteRows>, std::hash<std::string>, std::equal_to<>,
243
            std::allocator<std::pair<const std::string, std::unique_ptr<DeleteRows>>>, 8,
244
            std::mutex>;
245
246
    PositionDeleteRange _get_range(const ColumnDictI32& file_path_column);
247
    PositionDeleteRange _get_range(const ColumnString& file_path_column);
248
    static void _sort_delete_rows(const std::vector<std::vector<int64_t>*>& delete_rows_array,
249
                                  int64_t num_delete_rows, std::vector<int64_t>& result);
250
    void _gen_position_delete_file_range(Block& block, DeleteFile* position_delete,
251
                                         size_t read_rows, bool file_path_column_dictionary_coded);
252
    void _generate_equality_delete_block(Block* block,
253
                                         const std::vector<std::string>& equality_delete_col_names,
254
                                         const std::vector<DataTypePtr>& equality_delete_col_types);
255
256
    // Pure virtual: format-specific delete file reading
257
    virtual Status _read_position_delete_file(const TFileRangeDesc*, DeleteFile*) = 0;
258
    virtual std::unique_ptr<GenericReader> _create_equality_reader(
259
            const TFileRangeDesc& delete_desc) = 0;
260
261
1
    static std::string _delet_file_cache_key(const std::string& path) { return "delete_" + path; }
_ZN5doris18IcebergReaderMixinINS_13ParquetReaderEE21_delet_file_cache_keyERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
Line
Count
Source
261
1
    static std::string _delet_file_cache_key(const std::string& path) { return "delete_" + path; }
Unexecuted instantiation: _ZN5doris18IcebergReaderMixinINS_9OrcReaderEE21_delet_file_cache_keyERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
262
263
    /// Build the Iceberg V2 row-id struct column.
264
    static Status _build_iceberg_rowid_column(const DataTypePtr& type, const std::string& file_path,
265
                                              const std::vector<rowid_t>& row_ids,
266
                                              int32_t partition_spec_id,
267
                                              const std::string& partition_data_json,
268
0
                                              MutableColumnPtr* column_out) {
269
0
        if (type == nullptr || column_out == nullptr) {
270
0
            return Status::InvalidArgument("Invalid iceberg rowid column type or output column");
271
0
        }
272
0
        MutableColumnPtr column = type->create_column();
273
0
        ColumnNullable* nullable_col = check_and_get_column<ColumnNullable>(column.get());
274
0
        ColumnStruct* struct_col = nullptr;
275
0
        if (nullable_col != nullptr) {
276
0
            struct_col =
277
0
                    check_and_get_column<ColumnStruct>(nullable_col->get_nested_column_ptr().get());
278
0
        } else {
279
0
            struct_col = check_and_get_column<ColumnStruct>(column.get());
280
0
        }
281
0
        if (struct_col == nullptr || struct_col->tuple_size() < 4) {
282
0
            return Status::InternalError("Invalid iceberg rowid column structure");
283
0
        }
284
0
        size_t num_rows = row_ids.size();
285
0
        auto& file_path_col = struct_col->get_column(0);
286
0
        auto& row_pos_col = struct_col->get_column(1);
287
0
        auto& spec_id_col = struct_col->get_column(2);
288
0
        auto& partition_data_col = struct_col->get_column(3);
289
0
        file_path_col.reserve(num_rows);
290
0
        row_pos_col.reserve(num_rows);
291
0
        spec_id_col.reserve(num_rows);
292
0
        partition_data_col.reserve(num_rows);
293
0
        for (size_t i = 0; i < num_rows; ++i) {
294
0
            file_path_col.insert_data(file_path.data(), file_path.size());
295
0
        }
296
0
        for (size_t i = 0; i < num_rows; ++i) {
297
0
            int64_t row_pos = static_cast<int64_t>(row_ids[i]);
298
0
            row_pos_col.insert_data(reinterpret_cast<const char*>(&row_pos), sizeof(row_pos));
299
0
        }
300
0
        for (size_t i = 0; i < num_rows; ++i) {
301
0
            int32_t spec_id = partition_spec_id;
302
0
            spec_id_col.insert_data(reinterpret_cast<const char*>(&spec_id), sizeof(spec_id));
303
0
        }
304
0
        for (size_t i = 0; i < num_rows; ++i) {
305
0
            partition_data_col.insert_data(partition_data_json.data(), partition_data_json.size());
306
0
        }
307
0
        if (nullable_col != nullptr) {
308
0
            nullable_col->get_null_map_data().resize_fill(num_rows, 0);
309
0
        }
310
0
        *column_out = std::move(column);
311
0
        return Status::OK();
312
0
    }
Unexecuted instantiation: _ZN5doris18IcebergReaderMixinINS_13ParquetReaderEE27_build_iceberg_rowid_columnERKSt10shared_ptrIKNS_9IDataTypeEERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKSt6vectorIjSaIjEEiSG_PNS_3COWINS_7IColumnEE11mutable_ptrISN_EE
Unexecuted instantiation: _ZN5doris18IcebergReaderMixinINS_9OrcReaderEE27_build_iceberg_rowid_columnERKSt10shared_ptrIKNS_9IDataTypeEERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKSt6vectorIjSaIjEEiSG_PNS_3COWINS_7IColumnEE11mutable_ptrISN_EE
313
314
    struct IcebergProfile {
315
        RuntimeProfile::Counter* num_delete_files;
316
        RuntimeProfile::Counter* num_delete_rows;
317
        RuntimeProfile::Counter* delete_files_read_time;
318
        RuntimeProfile::Counter* delete_rows_sort_time;
319
        RuntimeProfile::Counter* parse_delete_file_time;
320
    };
321
322
    bool _need_row_id_column = false;
323
    std::string _current_file_path;
324
    int32_t _partition_spec_id = 0;
325
    std::string _partition_data_json;
326
327
    ShardedKVCache* _kv_cache;
328
    IcebergProfile _iceberg_profile;
329
    const std::vector<int64_t>* _iceberg_delete_rows = nullptr;
330
    std::vector<std::string> _expand_col_names;
331
    std::vector<ColumnWithTypeAndName> _expand_columns;
332
    std::vector<std::string> _all_required_col_names;
333
    Fileformat _file_format = Fileformat::NONE;
334
335
    const int64_t MIN_SUPPORT_DELETE_FILES_VERSION = 2;
336
    const std::string ICEBERG_FILE_PATH = "file_path";
337
    const std::string ICEBERG_ROW_POS = "pos";
338
    const std::vector<std::string> delete_file_col_names {ICEBERG_FILE_PATH, ICEBERG_ROW_POS};
339
    const std::unordered_map<std::string, uint32_t> DELETE_COL_NAME_TO_BLOCK_IDX = {
340
            {ICEBERG_FILE_PATH, 0}, {ICEBERG_ROW_POS, 1}};
341
    const int ICEBERG_FILE_PATH_INDEX = 0;
342
    const int ICEBERG_FILE_POS_INDEX = 1;
343
    const int READ_DELETE_FILE_BATCH_SIZE = 102400;
344
345
    // all ids that need read for eq delete (from all eq delete files)
346
    std::set<int> _equality_delete_col_ids;
347
    // eq delete column ids -> location of _equality_delete_blocks / _equality_delete_impls
348
    std::map<std::vector<int>, int> _equality_delete_block_map;
349
    // EqualityDeleteBase stores raw pointers to these blocks, so do not modify this vector after
350
    // creating entries in _equality_delete_impls.
351
    std::vector<Block> _equality_delete_blocks;
352
    std::vector<std::unique_ptr<EqualityDeleteBase>> _equality_delete_impls;
353
354
    // id -> block column name
355
    std::unordered_map<int, std::string> _id_to_block_column_name;
356
357
    std::function<std::shared_ptr<segment_v2::RowIdColumnIteratorV2>()>
358
            _create_topn_row_id_column_iterator;
359
360
    static constexpr const char* ROW_LINEAGE_ROW_ID = "_row_id";
361
    static constexpr const char* ROW_LINEAGE_LAST_UPDATED_SEQ_NUMBER =
362
            "_last_updated_sequence_number";
363
    struct RowLineageColumns {
364
        int64_t first_row_id = -1;
365
        int64_t last_updated_sequence_number = -1;
366
    };
367
    RowLineageColumns _row_lineage_columns;
368
};
369
370
// ============================================================================
371
// Template method implementations (must be in header for templates)
372
// ============================================================================
373
374
template <typename BaseReader>
375
2
Status IcebergReaderMixin<BaseReader>::_init_row_filters() {
376
    // COUNT(*) short-circuit. A table-level row count of 0 (e.g. an all-deleted table read with
377
    // ignore_iceberg_dangling_delete, where total-records == total-position-deletes) is still a
378
    // valid pushed-down count, so accept >= 0 -- matching FileScanner and the Paimon readers. FE
379
    // sends -1 when there is no table-level count; using > 0 here would drop a genuine 0 into the
380
    // delete-applying path below and never produce the intended CountReader(0).
381
2
    if (this->_push_down_agg_type == TPushAggOp::type::COUNT &&
382
2
        this->get_scan_range().table_format_params.__isset.table_level_row_count &&
383
2
        this->get_scan_range().table_format_params.table_level_row_count >= 0) {
384
0
        return Status::OK();
385
0
    }
386
387
2
    const auto& table_desc = this->get_scan_range().table_format_params.iceberg_params;
388
2
    const auto& version = table_desc.format_version;
389
2
    if (version < MIN_SUPPORT_DELETE_FILES_VERSION) {
390
2
        return Status::OK();
391
2
    }
392
393
0
    std::vector<TIcebergDeleteFileDesc> position_delete_files;
394
0
    std::vector<TIcebergDeleteFileDesc> equality_delete_files;
395
0
    std::vector<TIcebergDeleteFileDesc> deletion_vector_files;
396
0
    for (const TIcebergDeleteFileDesc& desc : table_desc.delete_files) {
397
0
        if (desc.content == POSITION_DELETE) {
398
0
            position_delete_files.emplace_back(desc);
399
0
        } else if (desc.content == EQUALITY_DELETE) {
400
0
            equality_delete_files.emplace_back(desc);
401
0
        } else if (desc.content == DELETION_VECTOR) {
402
0
            deletion_vector_files.emplace_back(desc);
403
0
        }
404
0
    }
405
406
0
    if (!equality_delete_files.empty()) {
407
0
        RETURN_IF_ERROR(_equality_delete_base(equality_delete_files));
408
0
        this->set_push_down_agg_type(TPushAggOp::NONE);
409
0
    }
410
411
0
    if (!deletion_vector_files.empty()) {
412
0
        if (deletion_vector_files.size() != 1) [[unlikely]] {
413
            /*
414
             * Deletion vectors are a binary representation of deletes for a single data file that is more efficient
415
             * at execution time than position delete files. Unlike equality or position delete files, there can be
416
             * at most one deletion vector for a given data file in a snapshot.
417
             */
418
0
            return Status::DataQualityError("This iceberg data file has multiple DVs.");
419
0
        }
420
0
        RETURN_IF_ERROR(
421
0
                read_deletion_vector(table_desc.original_file_path, deletion_vector_files[0]));
422
0
        this->set_push_down_agg_type(TPushAggOp::NONE);
423
0
    } else if (!position_delete_files.empty()) {
424
0
        RETURN_IF_ERROR(
425
0
                _position_delete_base(table_desc.original_file_path, position_delete_files));
426
0
        this->set_push_down_agg_type(TPushAggOp::NONE);
427
0
    }
428
429
0
    COUNTER_UPDATE(_iceberg_profile.num_delete_files, table_desc.delete_files.size());
430
0
    return Status::OK();
431
0
}
_ZN5doris18IcebergReaderMixinINS_13ParquetReaderEE17_init_row_filtersEv
Line
Count
Source
375
1
Status IcebergReaderMixin<BaseReader>::_init_row_filters() {
376
    // COUNT(*) short-circuit. A table-level row count of 0 (e.g. an all-deleted table read with
377
    // ignore_iceberg_dangling_delete, where total-records == total-position-deletes) is still a
378
    // valid pushed-down count, so accept >= 0 -- matching FileScanner and the Paimon readers. FE
379
    // sends -1 when there is no table-level count; using > 0 here would drop a genuine 0 into the
380
    // delete-applying path below and never produce the intended CountReader(0).
381
1
    if (this->_push_down_agg_type == TPushAggOp::type::COUNT &&
382
1
        this->get_scan_range().table_format_params.__isset.table_level_row_count &&
383
1
        this->get_scan_range().table_format_params.table_level_row_count >= 0) {
384
0
        return Status::OK();
385
0
    }
386
387
1
    const auto& table_desc = this->get_scan_range().table_format_params.iceberg_params;
388
1
    const auto& version = table_desc.format_version;
389
1
    if (version < MIN_SUPPORT_DELETE_FILES_VERSION) {
390
1
        return Status::OK();
391
1
    }
392
393
0
    std::vector<TIcebergDeleteFileDesc> position_delete_files;
394
0
    std::vector<TIcebergDeleteFileDesc> equality_delete_files;
395
0
    std::vector<TIcebergDeleteFileDesc> deletion_vector_files;
396
0
    for (const TIcebergDeleteFileDesc& desc : table_desc.delete_files) {
397
0
        if (desc.content == POSITION_DELETE) {
398
0
            position_delete_files.emplace_back(desc);
399
0
        } else if (desc.content == EQUALITY_DELETE) {
400
0
            equality_delete_files.emplace_back(desc);
401
0
        } else if (desc.content == DELETION_VECTOR) {
402
0
            deletion_vector_files.emplace_back(desc);
403
0
        }
404
0
    }
405
406
0
    if (!equality_delete_files.empty()) {
407
0
        RETURN_IF_ERROR(_equality_delete_base(equality_delete_files));
408
0
        this->set_push_down_agg_type(TPushAggOp::NONE);
409
0
    }
410
411
0
    if (!deletion_vector_files.empty()) {
412
0
        if (deletion_vector_files.size() != 1) [[unlikely]] {
413
            /*
414
             * Deletion vectors are a binary representation of deletes for a single data file that is more efficient
415
             * at execution time than position delete files. Unlike equality or position delete files, there can be
416
             * at most one deletion vector for a given data file in a snapshot.
417
             */
418
0
            return Status::DataQualityError("This iceberg data file has multiple DVs.");
419
0
        }
420
0
        RETURN_IF_ERROR(
421
0
                read_deletion_vector(table_desc.original_file_path, deletion_vector_files[0]));
422
0
        this->set_push_down_agg_type(TPushAggOp::NONE);
423
0
    } else if (!position_delete_files.empty()) {
424
0
        RETURN_IF_ERROR(
425
0
                _position_delete_base(table_desc.original_file_path, position_delete_files));
426
0
        this->set_push_down_agg_type(TPushAggOp::NONE);
427
0
    }
428
429
0
    COUNTER_UPDATE(_iceberg_profile.num_delete_files, table_desc.delete_files.size());
430
0
    return Status::OK();
431
0
}
_ZN5doris18IcebergReaderMixinINS_9OrcReaderEE17_init_row_filtersEv
Line
Count
Source
375
1
Status IcebergReaderMixin<BaseReader>::_init_row_filters() {
376
    // COUNT(*) short-circuit. A table-level row count of 0 (e.g. an all-deleted table read with
377
    // ignore_iceberg_dangling_delete, where total-records == total-position-deletes) is still a
378
    // valid pushed-down count, so accept >= 0 -- matching FileScanner and the Paimon readers. FE
379
    // sends -1 when there is no table-level count; using > 0 here would drop a genuine 0 into the
380
    // delete-applying path below and never produce the intended CountReader(0).
381
1
    if (this->_push_down_agg_type == TPushAggOp::type::COUNT &&
382
1
        this->get_scan_range().table_format_params.__isset.table_level_row_count &&
383
1
        this->get_scan_range().table_format_params.table_level_row_count >= 0) {
384
0
        return Status::OK();
385
0
    }
386
387
1
    const auto& table_desc = this->get_scan_range().table_format_params.iceberg_params;
388
1
    const auto& version = table_desc.format_version;
389
1
    if (version < MIN_SUPPORT_DELETE_FILES_VERSION) {
390
1
        return Status::OK();
391
1
    }
392
393
0
    std::vector<TIcebergDeleteFileDesc> position_delete_files;
394
0
    std::vector<TIcebergDeleteFileDesc> equality_delete_files;
395
0
    std::vector<TIcebergDeleteFileDesc> deletion_vector_files;
396
0
    for (const TIcebergDeleteFileDesc& desc : table_desc.delete_files) {
397
0
        if (desc.content == POSITION_DELETE) {
398
0
            position_delete_files.emplace_back(desc);
399
0
        } else if (desc.content == EQUALITY_DELETE) {
400
0
            equality_delete_files.emplace_back(desc);
401
0
        } else if (desc.content == DELETION_VECTOR) {
402
0
            deletion_vector_files.emplace_back(desc);
403
0
        }
404
0
    }
405
406
0
    if (!equality_delete_files.empty()) {
407
0
        RETURN_IF_ERROR(_equality_delete_base(equality_delete_files));
408
0
        this->set_push_down_agg_type(TPushAggOp::NONE);
409
0
    }
410
411
0
    if (!deletion_vector_files.empty()) {
412
0
        if (deletion_vector_files.size() != 1) [[unlikely]] {
413
            /*
414
             * Deletion vectors are a binary representation of deletes for a single data file that is more efficient
415
             * at execution time than position delete files. Unlike equality or position delete files, there can be
416
             * at most one deletion vector for a given data file in a snapshot.
417
             */
418
0
            return Status::DataQualityError("This iceberg data file has multiple DVs.");
419
0
        }
420
0
        RETURN_IF_ERROR(
421
0
                read_deletion_vector(table_desc.original_file_path, deletion_vector_files[0]));
422
0
        this->set_push_down_agg_type(TPushAggOp::NONE);
423
0
    } else if (!position_delete_files.empty()) {
424
0
        RETURN_IF_ERROR(
425
0
                _position_delete_base(table_desc.original_file_path, position_delete_files));
426
0
        this->set_push_down_agg_type(TPushAggOp::NONE);
427
0
    }
428
429
0
    COUNTER_UPDATE(_iceberg_profile.num_delete_files, table_desc.delete_files.size());
430
0
    return Status::OK();
431
0
}
432
433
template <typename BaseReader>
434
Status IcebergReaderMixin<BaseReader>::_equality_delete_base(
435
0
        const std::vector<TIcebergDeleteFileDesc>& delete_files) {
436
0
    std::unordered_map<std::string, std::tuple<std::string, const SlotDescriptor*>>
437
0
            partition_columns;
438
0
    std::unordered_map<std::string, VExprContextSPtr> missing_columns;
439
440
0
    for (const auto& delete_file : delete_files) {
441
0
        TFileRangeDesc delete_desc;
442
0
        delete_desc.__set_fs_name(this->get_scan_range().fs_name);
443
0
        delete_desc.path = delete_file.path;
444
0
        delete_desc.start_offset = 0;
445
0
        delete_desc.size = -1;
446
0
        delete_desc.file_size = -1;
447
448
0
        if (!delete_file.__isset.field_ids) [[unlikely]] {
449
0
            return Status::InternalError(
450
0
                    "missing delete field ids when reading equality delete file");
451
0
        }
452
0
        auto& read_column_field_ids = delete_file.field_ids;
453
0
        std::set<int> read_column_field_ids_set;
454
0
        for (const auto& field_id : read_column_field_ids) {
455
0
            read_column_field_ids_set.insert(field_id);
456
0
            _equality_delete_col_ids.insert(field_id);
457
0
        }
458
459
0
        std::unique_ptr<GenericReader> delete_reader = _create_equality_reader(delete_desc);
460
0
        RETURN_IF_ERROR(delete_reader->init_schema_reader());
461
462
0
        std::vector<std::string> equality_delete_col_names;
463
0
        std::vector<DataTypePtr> equality_delete_col_types;
464
465
        // Build delete col names/types/ids by matching field_ids from delete file schema.
466
        // Master iterates delete file's FieldDescriptor and uses field_id to match,
467
        // NOT idx-based pairing (get_parsed_schema order != field_ids order).
468
0
        std::vector<std::string> delete_col_names;
469
0
        std::vector<DataTypePtr> delete_col_types;
470
0
        std::vector<int> delete_col_ids;
471
0
        std::unordered_map<std::string, uint32_t> delete_col_name_to_block_idx;
472
473
0
        if (auto* parquet_reader = typeid_cast<ParquetReader*>(delete_reader.get())) {
474
0
            const FieldDescriptor* delete_field_desc = nullptr;
475
0
            RETURN_IF_ERROR(parquet_reader->get_file_metadata_schema(&delete_field_desc));
476
0
            DCHECK(delete_field_desc != nullptr);
477
478
0
            for (const auto& delete_file_field : delete_field_desc->get_fields_schema()) {
479
0
                if (delete_file_field.field_id == -1) [[unlikely]] {
480
0
                    return Status::DataQualityError(
481
0
                            "missing field id when reading equality delete file");
482
0
                }
483
0
                if (!read_column_field_ids_set.contains(delete_file_field.field_id)) {
484
0
                    continue;
485
0
                }
486
0
                if (delete_file_field.children.size() > 0) [[unlikely]] {
487
0
                    return Status::InternalError(
488
0
                            "can not support read complex column in equality delete file");
489
0
                }
490
491
0
                delete_col_ids.emplace_back(delete_file_field.field_id);
492
0
                delete_col_names.emplace_back(delete_file_field.name);
493
0
                delete_col_types.emplace_back(make_nullable(delete_file_field.data_type));
494
495
0
                int field_id = delete_file_field.field_id;
496
0
                if (!_id_to_block_column_name.contains(field_id)) {
497
0
                    _id_to_block_column_name.emplace(field_id, delete_file_field.name);
498
0
                    _expand_col_names.emplace_back(delete_file_field.name);
499
0
                    _expand_columns.emplace_back(
500
0
                            make_nullable(delete_file_field.data_type)->create_column(),
501
0
                            make_nullable(delete_file_field.data_type), delete_file_field.name);
502
0
                }
503
0
            }
504
0
            for (uint32_t idx = 0; idx < delete_col_names.size(); ++idx) {
505
0
                delete_col_name_to_block_idx[delete_col_names[idx]] = idx;
506
0
            }
507
            // Delete files have TFileRangeDesc.size=-1, which would cause
508
            // set_fill_columns to return EndOfFile("No row group to read")
509
            // when _filter_groups is true. Master passes filter_groups=false.
510
0
            ParquetInitContext eq_delete_ctx;
511
0
            eq_delete_ctx.filter_groups = false;
512
0
            eq_delete_ctx.column_names = delete_col_names;
513
0
            eq_delete_ctx.col_name_to_block_idx = &delete_col_name_to_block_idx;
514
0
            auto st2 = parquet_reader->init_reader(&eq_delete_ctx);
515
0
            if (!st2.ok()) {
516
0
                return st2;
517
0
            }
518
0
        } else if (auto* orc_reader = typeid_cast<OrcReader*>(delete_reader.get())) {
519
            // For ORC: use get_parsed_schema with field_ids from delete_file
520
            // ORC field_ids come from the Thrift descriptor, not from ORC metadata
521
0
            RETURN_IF_ERROR(delete_reader->get_parsed_schema(&equality_delete_col_names,
522
0
                                                             &equality_delete_col_types));
523
0
            for (uint32_t idx = 0; idx < equality_delete_col_names.size(); ++idx) {
524
0
                if (idx < read_column_field_ids.size()) {
525
0
                    int field_id = read_column_field_ids[idx];
526
0
                    if (!read_column_field_ids_set.contains(field_id)) continue;
527
0
                    delete_col_ids.emplace_back(field_id);
528
0
                    delete_col_names.emplace_back(equality_delete_col_names[idx]);
529
0
                    delete_col_types.emplace_back(make_nullable(equality_delete_col_types[idx]));
530
0
                    if (!_id_to_block_column_name.contains(field_id)) {
531
0
                        _id_to_block_column_name.emplace(field_id, equality_delete_col_names[idx]);
532
0
                        _expand_col_names.emplace_back(equality_delete_col_names[idx]);
533
0
                        _expand_columns.emplace_back(
534
0
                                make_nullable(equality_delete_col_types[idx])->create_column(),
535
0
                                make_nullable(equality_delete_col_types[idx]),
536
0
                                equality_delete_col_names[idx]);
537
0
                    }
538
0
                }
539
0
            }
540
0
            for (uint32_t idx = 0; idx < delete_col_names.size(); ++idx) {
541
0
                delete_col_name_to_block_idx[delete_col_names[idx]] = idx;
542
0
            }
543
0
            OrcInitContext eq_delete_ctx;
544
0
            eq_delete_ctx.column_names = delete_col_names;
545
0
            eq_delete_ctx.col_name_to_block_idx = &delete_col_name_to_block_idx;
546
0
            RETURN_IF_ERROR(orc_reader->init_reader(&eq_delete_ctx));
547
0
        } else {
548
0
            return Status::InternalError("Unsupported format of delete file");
549
0
        }
550
551
0
        if (!_equality_delete_block_map.contains(delete_col_ids)) {
552
0
            _equality_delete_block_map.emplace(delete_col_ids, _equality_delete_blocks.size());
553
0
            Block block;
554
0
            _generate_equality_delete_block(&block, delete_col_names, delete_col_types);
555
0
            _equality_delete_blocks.emplace_back(block);
556
0
        }
557
0
        Block& eq_file_block = _equality_delete_blocks[_equality_delete_block_map[delete_col_ids]];
558
559
0
        bool eof = false;
560
0
        while (!eof) {
561
0
            Block tmp_block;
562
0
            _generate_equality_delete_block(&tmp_block, delete_col_names, delete_col_types);
563
0
            size_t read_rows = 0;
564
0
            auto st = delete_reader->get_next_block(&tmp_block, &read_rows, &eof);
565
0
            if (!st.ok()) {
566
0
                return st;
567
0
            }
568
0
            if (read_rows > 0) {
569
0
                ScopedMutableBlock scoped_mutable_block(&eq_file_block);
570
0
                auto& mutable_block = scoped_mutable_block.mutable_block();
571
0
                RETURN_IF_ERROR(mutable_block.merge(tmp_block));
572
0
            }
573
0
        }
574
0
    }
575
576
0
    for (const auto& [delete_col_ids, block_idx] : _equality_delete_block_map) {
577
0
        auto& eq_file_block = _equality_delete_blocks[block_idx];
578
0
        auto equality_delete_impl =
579
0
                EqualityDeleteBase::get_delete_impl(&eq_file_block, delete_col_ids);
580
0
        RETURN_IF_ERROR(equality_delete_impl->init(this->get_profile()));
581
0
        _equality_delete_impls.emplace_back(std::move(equality_delete_impl));
582
0
    }
583
0
    return Status::OK();
584
0
}
Unexecuted instantiation: _ZN5doris18IcebergReaderMixinINS_13ParquetReaderEE21_equality_delete_baseERKSt6vectorINS_22TIcebergDeleteFileDescESaIS4_EE
Unexecuted instantiation: _ZN5doris18IcebergReaderMixinINS_9OrcReaderEE21_equality_delete_baseERKSt6vectorINS_22TIcebergDeleteFileDescESaIS4_EE
585
586
template <typename BaseReader>
587
void IcebergReaderMixin<BaseReader>::_generate_equality_delete_block(
588
        Block* block, const std::vector<std::string>& equality_delete_col_names,
589
0
        const std::vector<DataTypePtr>& equality_delete_col_types) {
590
0
    for (int i = 0; i < equality_delete_col_names.size(); ++i) {
591
0
        DataTypePtr data_type = make_nullable(equality_delete_col_types[i]);
592
0
        MutableColumnPtr data_column = data_type->create_column();
593
0
        block->insert(ColumnWithTypeAndName(std::move(data_column), data_type,
594
0
                                            equality_delete_col_names[i]));
595
0
    }
596
0
}
Unexecuted instantiation: _ZN5doris18IcebergReaderMixinINS_13ParquetReaderEE31_generate_equality_delete_blockEPNS_5BlockERKSt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaISB_EERKS5_ISt10shared_ptrIKNS_9IDataTypeEESaISJ_EE
Unexecuted instantiation: _ZN5doris18IcebergReaderMixinINS_9OrcReaderEE31_generate_equality_delete_blockEPNS_5BlockERKSt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaISB_EERKS5_ISt10shared_ptrIKNS_9IDataTypeEESaISJ_EE
597
598
template <typename BaseReader>
599
2
Status IcebergReaderMixin<BaseReader>::_expand_block_if_need(Block* block) {
600
2
    std::set<std::string> names;
601
2
    auto block_names = block->get_names();
602
2
    names.insert(block_names.begin(), block_names.end());
603
2
    for (auto& col : _expand_columns) {
604
0
        if (names.contains(col.name)) {
605
0
            return Status::InternalError("Wrong expand column '{}'", col.name);
606
0
        }
607
0
        names.insert(col.name);
608
0
        (*this->col_name_to_block_idx_ref())[col.name] = block->columns();
609
0
        block->insert({col.type->create_column(), col.type, col.name});
610
0
    }
611
2
    return Status::OK();
612
2
}
_ZN5doris18IcebergReaderMixinINS_13ParquetReaderEE21_expand_block_if_needEPNS_5BlockE
Line
Count
Source
599
1
Status IcebergReaderMixin<BaseReader>::_expand_block_if_need(Block* block) {
600
1
    std::set<std::string> names;
601
1
    auto block_names = block->get_names();
602
1
    names.insert(block_names.begin(), block_names.end());
603
1
    for (auto& col : _expand_columns) {
604
0
        if (names.contains(col.name)) {
605
0
            return Status::InternalError("Wrong expand column '{}'", col.name);
606
0
        }
607
0
        names.insert(col.name);
608
0
        (*this->col_name_to_block_idx_ref())[col.name] = block->columns();
609
0
        block->insert({col.type->create_column(), col.type, col.name});
610
0
    }
611
1
    return Status::OK();
612
1
}
_ZN5doris18IcebergReaderMixinINS_9OrcReaderEE21_expand_block_if_needEPNS_5BlockE
Line
Count
Source
599
1
Status IcebergReaderMixin<BaseReader>::_expand_block_if_need(Block* block) {
600
1
    std::set<std::string> names;
601
1
    auto block_names = block->get_names();
602
1
    names.insert(block_names.begin(), block_names.end());
603
1
    for (auto& col : _expand_columns) {
604
0
        if (names.contains(col.name)) {
605
0
            return Status::InternalError("Wrong expand column '{}'", col.name);
606
0
        }
607
0
        names.insert(col.name);
608
0
        (*this->col_name_to_block_idx_ref())[col.name] = block->columns();
609
0
        block->insert({col.type->create_column(), col.type, col.name});
610
0
    }
611
1
    return Status::OK();
612
1
}
613
614
template <typename BaseReader>
615
2
Status IcebergReaderMixin<BaseReader>::_shrink_block_if_need(Block* block) {
616
2
    std::set<size_t> positions_to_erase;
617
2
    for (const std::string& expand_col : _expand_col_names) {
618
0
        if (!this->col_name_to_block_idx_ref()->contains(expand_col)) {
619
0
            return Status::InternalError("Wrong erase column '{}', block: {}", expand_col,
620
0
                                         block->dump_names());
621
0
        }
622
0
        positions_to_erase.emplace((*this->col_name_to_block_idx_ref())[expand_col]);
623
0
    }
624
2
    block->erase(positions_to_erase);
625
2
    for (const std::string& expand_col : _expand_col_names) {
626
0
        this->col_name_to_block_idx_ref()->erase(expand_col);
627
0
    }
628
2
    return Status::OK();
629
2
}
_ZN5doris18IcebergReaderMixinINS_13ParquetReaderEE21_shrink_block_if_needEPNS_5BlockE
Line
Count
Source
615
1
Status IcebergReaderMixin<BaseReader>::_shrink_block_if_need(Block* block) {
616
1
    std::set<size_t> positions_to_erase;
617
1
    for (const std::string& expand_col : _expand_col_names) {
618
0
        if (!this->col_name_to_block_idx_ref()->contains(expand_col)) {
619
0
            return Status::InternalError("Wrong erase column '{}', block: {}", expand_col,
620
0
                                         block->dump_names());
621
0
        }
622
0
        positions_to_erase.emplace((*this->col_name_to_block_idx_ref())[expand_col]);
623
0
    }
624
1
    block->erase(positions_to_erase);
625
1
    for (const std::string& expand_col : _expand_col_names) {
626
0
        this->col_name_to_block_idx_ref()->erase(expand_col);
627
0
    }
628
1
    return Status::OK();
629
1
}
_ZN5doris18IcebergReaderMixinINS_9OrcReaderEE21_shrink_block_if_needEPNS_5BlockE
Line
Count
Source
615
1
Status IcebergReaderMixin<BaseReader>::_shrink_block_if_need(Block* block) {
616
1
    std::set<size_t> positions_to_erase;
617
1
    for (const std::string& expand_col : _expand_col_names) {
618
0
        if (!this->col_name_to_block_idx_ref()->contains(expand_col)) {
619
0
            return Status::InternalError("Wrong erase column '{}', block: {}", expand_col,
620
0
                                         block->dump_names());
621
0
        }
622
0
        positions_to_erase.emplace((*this->col_name_to_block_idx_ref())[expand_col]);
623
0
    }
624
1
    block->erase(positions_to_erase);
625
1
    for (const std::string& expand_col : _expand_col_names) {
626
0
        this->col_name_to_block_idx_ref()->erase(expand_col);
627
0
    }
628
1
    return Status::OK();
629
1
}
630
631
template <typename BaseReader>
632
Status IcebergReaderMixin<BaseReader>::_position_delete_base(
633
1
        const std::string data_file_path, const std::vector<TIcebergDeleteFileDesc>& delete_files) {
634
1
    std::vector<DeleteRows*> delete_rows_array;
635
1
    int64_t num_delete_rows = 0;
636
1
    for (const auto& delete_file : delete_files) {
637
1
        SCOPED_TIMER(_iceberg_profile.delete_files_read_time);
638
1
        Status create_status = Status::OK();
639
1
        auto* delete_file_cache = _kv_cache->template get<DeleteFile>(
640
1
                _delet_file_cache_key(delete_file.path), [&]() -> DeleteFile* {
641
1
                    auto position_delete = std::make_unique<DeleteFile>();
642
1
                    TFileRangeDesc delete_file_range;
643
1
                    delete_file_range.__set_fs_name(this->get_scan_range().fs_name);
644
1
                    delete_file_range.path = delete_file.path;
645
1
                    delete_file_range.start_offset = 0;
646
1
                    delete_file_range.size = -1;
647
1
                    delete_file_range.file_size = -1;
648
1
                    create_status =
649
1
                            _read_position_delete_file(&delete_file_range, position_delete.get());
650
1
                    if (!create_status) {
651
1
                        return nullptr;
652
1
                    }
653
0
                    return position_delete.release();
654
1
                });
_ZZN5doris18IcebergReaderMixinINS_13ParquetReaderEE21_position_delete_baseENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKSt6vectorINS_22TIcebergDeleteFileDescESaISA_EEENKUlvE_clB5cxx11Ev
Line
Count
Source
640
1
                _delet_file_cache_key(delete_file.path), [&]() -> DeleteFile* {
641
1
                    auto position_delete = std::make_unique<DeleteFile>();
642
1
                    TFileRangeDesc delete_file_range;
643
1
                    delete_file_range.__set_fs_name(this->get_scan_range().fs_name);
644
1
                    delete_file_range.path = delete_file.path;
645
1
                    delete_file_range.start_offset = 0;
646
1
                    delete_file_range.size = -1;
647
1
                    delete_file_range.file_size = -1;
648
1
                    create_status =
649
1
                            _read_position_delete_file(&delete_file_range, position_delete.get());
650
1
                    if (!create_status) {
651
1
                        return nullptr;
652
1
                    }
653
0
                    return position_delete.release();
654
1
                });
Unexecuted instantiation: _ZZN5doris18IcebergReaderMixinINS_9OrcReaderEE21_position_delete_baseENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKSt6vectorINS_22TIcebergDeleteFileDescESaISA_EEENKUlvE_clB5cxx11Ev
655
1
        if (create_status.is<ErrorCode::END_OF_FILE>()) {
656
0
            continue;
657
1
        } else if (!create_status.ok()) {
658
1
            return create_status;
659
1
        }
660
661
0
        DeleteFile& delete_file_map = *((DeleteFile*)delete_file_cache);
662
0
        auto get_value = [&](const auto& v) {
663
0
            DeleteRows* row_ids = v.second.get();
664
0
            if (!row_ids->empty()) {
665
0
                delete_rows_array.emplace_back(row_ids);
666
0
                num_delete_rows += row_ids->size();
667
0
            }
668
0
        };
Unexecuted instantiation: _ZZN5doris18IcebergReaderMixinINS_13ParquetReaderEE21_position_delete_baseENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKSt6vectorINS_22TIcebergDeleteFileDescESaISA_EEENKUlRKT_E_clISt4pairIKS8_St10unique_ptrIS9_IlSaIlEESt14default_deleteISO_EEEEEDaSH_
Unexecuted instantiation: _ZZN5doris18IcebergReaderMixinINS_9OrcReaderEE21_position_delete_baseENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKSt6vectorINS_22TIcebergDeleteFileDescESaISA_EEENKUlRKT_E_clISt4pairIKS8_St10unique_ptrIS9_IlSaIlEESt14default_deleteISO_EEEEEDaSH_
669
0
        delete_file_map.if_contains(data_file_path, get_value);
670
0
    }
671
0
    if (num_delete_rows > 0) {
672
0
        SCOPED_TIMER(_iceberg_profile.delete_rows_sort_time);
673
0
        _iceberg_delete_rows =
674
0
                _kv_cache->template get<DeleteRows>(data_file_path, [&]() -> DeleteRows* {
675
0
                    auto data_file_position_delete = std::make_unique<DeleteRows>();
676
0
                    _sort_delete_rows(delete_rows_array, num_delete_rows,
677
0
                                      *data_file_position_delete);
678
0
                    return data_file_position_delete.release();
679
0
                });
Unexecuted instantiation: _ZZN5doris18IcebergReaderMixinINS_13ParquetReaderEE21_position_delete_baseENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKSt6vectorINS_22TIcebergDeleteFileDescESaISA_EEENKUlvE0_clEv
Unexecuted instantiation: _ZZN5doris18IcebergReaderMixinINS_9OrcReaderEE21_position_delete_baseENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKSt6vectorINS_22TIcebergDeleteFileDescESaISA_EEENKUlvE0_clEv
680
0
        set_delete_rows();
681
0
        COUNTER_UPDATE(_iceberg_profile.num_delete_rows, num_delete_rows);
682
0
    }
683
0
    return Status::OK();
684
1
}
_ZN5doris18IcebergReaderMixinINS_13ParquetReaderEE21_position_delete_baseENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKSt6vectorINS_22TIcebergDeleteFileDescESaISA_EE
Line
Count
Source
633
1
        const std::string data_file_path, const std::vector<TIcebergDeleteFileDesc>& delete_files) {
634
1
    std::vector<DeleteRows*> delete_rows_array;
635
1
    int64_t num_delete_rows = 0;
636
1
    for (const auto& delete_file : delete_files) {
637
1
        SCOPED_TIMER(_iceberg_profile.delete_files_read_time);
638
1
        Status create_status = Status::OK();
639
1
        auto* delete_file_cache = _kv_cache->template get<DeleteFile>(
640
1
                _delet_file_cache_key(delete_file.path), [&]() -> DeleteFile* {
641
1
                    auto position_delete = std::make_unique<DeleteFile>();
642
1
                    TFileRangeDesc delete_file_range;
643
1
                    delete_file_range.__set_fs_name(this->get_scan_range().fs_name);
644
1
                    delete_file_range.path = delete_file.path;
645
1
                    delete_file_range.start_offset = 0;
646
1
                    delete_file_range.size = -1;
647
1
                    delete_file_range.file_size = -1;
648
1
                    create_status =
649
1
                            _read_position_delete_file(&delete_file_range, position_delete.get());
650
1
                    if (!create_status) {
651
1
                        return nullptr;
652
1
                    }
653
1
                    return position_delete.release();
654
1
                });
655
1
        if (create_status.is<ErrorCode::END_OF_FILE>()) {
656
0
            continue;
657
1
        } else if (!create_status.ok()) {
658
1
            return create_status;
659
1
        }
660
661
0
        DeleteFile& delete_file_map = *((DeleteFile*)delete_file_cache);
662
0
        auto get_value = [&](const auto& v) {
663
0
            DeleteRows* row_ids = v.second.get();
664
0
            if (!row_ids->empty()) {
665
0
                delete_rows_array.emplace_back(row_ids);
666
0
                num_delete_rows += row_ids->size();
667
0
            }
668
0
        };
669
0
        delete_file_map.if_contains(data_file_path, get_value);
670
0
    }
671
0
    if (num_delete_rows > 0) {
672
0
        SCOPED_TIMER(_iceberg_profile.delete_rows_sort_time);
673
0
        _iceberg_delete_rows =
674
0
                _kv_cache->template get<DeleteRows>(data_file_path, [&]() -> DeleteRows* {
675
0
                    auto data_file_position_delete = std::make_unique<DeleteRows>();
676
0
                    _sort_delete_rows(delete_rows_array, num_delete_rows,
677
0
                                      *data_file_position_delete);
678
0
                    return data_file_position_delete.release();
679
0
                });
680
0
        set_delete_rows();
681
0
        COUNTER_UPDATE(_iceberg_profile.num_delete_rows, num_delete_rows);
682
0
    }
683
0
    return Status::OK();
684
1
}
Unexecuted instantiation: _ZN5doris18IcebergReaderMixinINS_9OrcReaderEE21_position_delete_baseENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKSt6vectorINS_22TIcebergDeleteFileDescESaISA_EE
685
686
template <typename BaseReader>
687
typename IcebergReaderMixin<BaseReader>::PositionDeleteRange
688
0
IcebergReaderMixin<BaseReader>::_get_range(const ColumnDictI32& file_path_column) {
689
0
    PositionDeleteRange range;
690
0
    size_t read_rows = file_path_column.get_data().size();
691
0
    const int* code_path = file_path_column.get_data().data();
692
0
    const int* code_path_start = code_path;
693
0
    const int* code_path_end = code_path + read_rows;
694
0
    while (code_path < code_path_end) {
695
0
        int code = code_path[0];
696
0
        const int* code_end = std::upper_bound(code_path, code_path_end, code);
697
0
        range.data_file_path.emplace_back(file_path_column.get_value(code).to_string());
698
0
        range.range.emplace_back(code_path - code_path_start, code_end - code_path_start);
699
0
        code_path = code_end;
700
0
    }
701
0
    return range;
702
0
}
Unexecuted instantiation: _ZN5doris18IcebergReaderMixinINS_13ParquetReaderEE10_get_rangeERKNS_13ColumnDictI32E
Unexecuted instantiation: _ZN5doris18IcebergReaderMixinINS_9OrcReaderEE10_get_rangeERKNS_13ColumnDictI32E
703
704
template <typename BaseReader>
705
typename IcebergReaderMixin<BaseReader>::PositionDeleteRange
706
0
IcebergReaderMixin<BaseReader>::_get_range(const ColumnString& file_path_column) {
707
0
    PositionDeleteRange range;
708
0
    size_t read_rows = file_path_column.size();
709
0
    size_t index = 0;
710
0
    while (index < read_rows) {
711
0
        StringRef data_path = file_path_column.get_data_at(index);
712
0
        size_t left = index - 1;
713
0
        size_t right = read_rows;
714
0
        while (left + 1 != right) {
715
0
            size_t mid = left + (right - left) / 2;
716
0
            if (file_path_column.get_data_at(mid) > data_path) {
717
0
                right = mid;
718
0
            } else {
719
0
                left = mid;
720
0
            }
721
0
        }
722
0
        range.data_file_path.emplace_back(data_path.to_string());
723
0
        range.range.emplace_back(index, left + 1);
724
0
        index = left + 1;
725
0
    }
726
0
    return range;
727
0
}
Unexecuted instantiation: _ZN5doris18IcebergReaderMixinINS_13ParquetReaderEE10_get_rangeERKNS_9ColumnStrIjEE
Unexecuted instantiation: _ZN5doris18IcebergReaderMixinINS_9OrcReaderEE10_get_rangeERKNS_9ColumnStrIjEE
728
729
template <typename BaseReader>
730
void IcebergReaderMixin<BaseReader>::_sort_delete_rows(
731
        const std::vector<std::vector<int64_t>*>& delete_rows_array, int64_t num_delete_rows,
732
0
        std::vector<int64_t>& result) {
733
0
    if (delete_rows_array.empty()) {
734
0
        return;
735
0
    }
736
0
    if (delete_rows_array.size() == 1) {
737
0
        result.resize(num_delete_rows);
738
0
        memcpy(result.data(), delete_rows_array.front()->data(), sizeof(int64_t) * num_delete_rows);
739
0
        return;
740
0
    }
741
0
    if (delete_rows_array.size() == 2) {
742
0
        result.resize(num_delete_rows);
743
0
        std::merge(delete_rows_array.front()->begin(), delete_rows_array.front()->end(),
744
0
                   delete_rows_array.back()->begin(), delete_rows_array.back()->end(),
745
0
                   result.begin());
746
0
        return;
747
0
    }
748
749
0
    using vec_pair = std::pair<std::vector<int64_t>::iterator, std::vector<int64_t>::iterator>;
750
0
    result.resize(num_delete_rows);
751
0
    auto row_id_iter = result.begin();
752
0
    auto iter_end = result.end();
753
0
    std::vector<vec_pair> rows_array;
754
0
    for (auto* rows : delete_rows_array) {
755
0
        if (!rows->empty()) {
756
0
            rows_array.emplace_back(rows->begin(), rows->end());
757
0
        }
758
0
    }
759
0
    size_t array_size = rows_array.size();
760
0
    while (row_id_iter != iter_end) {
761
0
        int64_t min_index = 0;
762
0
        int64_t min = *rows_array[0].first;
763
0
        for (size_t i = 0; i < array_size; ++i) {
764
0
            if (*rows_array[i].first < min) {
765
0
                min_index = i;
766
0
                min = *rows_array[i].first;
767
0
            }
768
0
        }
769
0
        *row_id_iter++ = min;
770
0
        rows_array[min_index].first++;
771
0
        if (UNLIKELY(rows_array[min_index].first == rows_array[min_index].second)) {
772
0
            rows_array.erase(rows_array.begin() + min_index);
773
0
            array_size--;
774
0
        }
775
0
    }
776
0
}
Unexecuted instantiation: _ZN5doris18IcebergReaderMixinINS_13ParquetReaderEE17_sort_delete_rowsERKSt6vectorIPS3_IlSaIlEESaIS6_EElRS5_
Unexecuted instantiation: _ZN5doris18IcebergReaderMixinINS_9OrcReaderEE17_sort_delete_rowsERKSt6vectorIPS3_IlSaIlEESaIS6_EElRS5_
777
778
template <typename BaseReader>
779
void IcebergReaderMixin<BaseReader>::_gen_position_delete_file_range(
780
        Block& block, DeleteFile* position_delete, size_t read_rows,
781
0
        bool file_path_column_dictionary_coded) {
782
0
    SCOPED_TIMER(_iceberg_profile.parse_delete_file_time);
783
0
    auto name_to_pos_map = block.get_name_to_pos_map();
784
0
    ColumnPtr path_column = block.get_by_position(name_to_pos_map[ICEBERG_FILE_PATH]).column;
785
0
    DCHECK_EQ(path_column->size(), read_rows);
786
0
    ColumnPtr pos_column = block.get_by_position(name_to_pos_map[ICEBERG_ROW_POS]).column;
787
0
    using ColumnType = typename PrimitiveTypeTraits<TYPE_BIGINT>::ColumnType;
788
0
    const int64_t* src_data = assert_cast<const ColumnType&>(*pos_column).get_data().data();
789
0
    PositionDeleteRange range;
790
0
    if (file_path_column_dictionary_coded) {
791
0
        range = _get_range(assert_cast<const ColumnDictI32&>(*path_column));
792
0
    } else {
793
0
        range = _get_range(assert_cast<const ColumnString&>(*path_column));
794
0
    }
795
0
    for (int i = 0; i < range.range.size(); ++i) {
796
0
        std::string key = range.data_file_path[i];
797
0
        auto iter = position_delete->find(key);
798
0
        DeleteRows* delete_rows;
799
0
        if (iter == position_delete->end()) {
800
0
            delete_rows = new DeleteRows;
801
0
            std::unique_ptr<DeleteRows> delete_rows_ptr(delete_rows);
802
0
            (*position_delete)[key] = std::move(delete_rows_ptr);
803
0
        } else {
804
0
            delete_rows = iter->second.get();
805
0
        }
806
0
        const int64_t* cpy_start = src_data + range.range[i].first;
807
0
        const int64_t cpy_count = range.range[i].second - range.range[i].first;
808
0
        int64_t origin_size = delete_rows->size();
809
0
        delete_rows->resize(origin_size + cpy_count);
810
0
        int64_t* dest_position = &(*delete_rows)[origin_size];
811
0
        memcpy(dest_position, cpy_start, cpy_count * sizeof(int64_t));
812
0
    }
813
0
}
Unexecuted instantiation: _ZN5doris18IcebergReaderMixinINS_13ParquetReaderEE31_gen_position_delete_file_rangeERNS_5BlockEPN5phmap22parallel_flat_hash_mapINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt10unique_ptrISt6vectorIlSaIlEESt14default_deleteISG_EESt4hashISC_ESt8equal_toIvESaISt4pairIKSC_SJ_EELm8ESt5mutexEEmb
Unexecuted instantiation: _ZN5doris18IcebergReaderMixinINS_9OrcReaderEE31_gen_position_delete_file_rangeERNS_5BlockEPN5phmap22parallel_flat_hash_mapINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt10unique_ptrISt6vectorIlSaIlEESt14default_deleteISG_EESt4hashISC_ESt8equal_toIvESaISt4pairIKSC_SJ_EELm8ESt5mutexEEmb
814
815
template <typename BaseReader>
816
Status IcebergReaderMixin<BaseReader>::read_deletion_vector(
817
1
        const std::string& data_file_path, const TIcebergDeleteFileDesc& delete_file_desc) {
818
1
    Status create_status = Status::OK();
819
1
    SCOPED_TIMER(_iceberg_profile.delete_files_read_time);
820
1
    _iceberg_delete_rows = _kv_cache->template get<DeleteRows>(
821
1
            build_iceberg_deletion_vector_cache_key(data_file_path, delete_file_desc),
822
1
            [&]() -> DeleteRows* {
823
1
                auto delete_rows = std::make_unique<DeleteRows>();
824
825
1
                roaring::Roaring64Map bitmap;
826
1
                IcebergDeleteFileReaderOptions options;
827
1
                options.state = this->get_state();
828
1
                options.profile = this->get_profile();
829
1
                options.scan_params = &this->get_scan_params();
830
1
                options.io_ctx = this->get_io_ctx();
831
1
                options.fs_name = &this->get_scan_range().fs_name;
832
1
                create_status = read_iceberg_deletion_vector(delete_file_desc, options, &bitmap);
833
1
                if (!create_status.ok()) [[unlikely]] {
834
1
                    return nullptr;
835
1
                }
836
837
0
                SCOPED_TIMER(_iceberg_profile.parse_delete_file_time);
838
0
                delete_rows->reserve(bitmap.cardinality());
839
0
                for (auto it = bitmap.begin(); it != bitmap.end(); it++) {
840
0
                    delete_rows->push_back(*it);
841
0
                }
842
0
                COUNTER_UPDATE(_iceberg_profile.num_delete_rows, delete_rows->size());
843
0
                return delete_rows.release();
844
1
            });
_ZZN5doris18IcebergReaderMixinINS_13ParquetReaderEE20read_deletion_vectorERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKNS_22TIcebergDeleteFileDescEENKUlvE_clEv
Line
Count
Source
822
1
            [&]() -> DeleteRows* {
823
1
                auto delete_rows = std::make_unique<DeleteRows>();
824
825
1
                roaring::Roaring64Map bitmap;
826
1
                IcebergDeleteFileReaderOptions options;
827
1
                options.state = this->get_state();
828
1
                options.profile = this->get_profile();
829
1
                options.scan_params = &this->get_scan_params();
830
1
                options.io_ctx = this->get_io_ctx();
831
1
                options.fs_name = &this->get_scan_range().fs_name;
832
1
                create_status = read_iceberg_deletion_vector(delete_file_desc, options, &bitmap);
833
1
                if (!create_status.ok()) [[unlikely]] {
834
1
                    return nullptr;
835
1
                }
836
837
0
                SCOPED_TIMER(_iceberg_profile.parse_delete_file_time);
838
0
                delete_rows->reserve(bitmap.cardinality());
839
0
                for (auto it = bitmap.begin(); it != bitmap.end(); it++) {
840
0
                    delete_rows->push_back(*it);
841
0
                }
842
0
                COUNTER_UPDATE(_iceberg_profile.num_delete_rows, delete_rows->size());
843
0
                return delete_rows.release();
844
1
            });
Unexecuted instantiation: _ZZN5doris18IcebergReaderMixinINS_9OrcReaderEE20read_deletion_vectorERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKNS_22TIcebergDeleteFileDescEENKUlvE_clEv
845
846
1
    RETURN_IF_ERROR(create_status);
847
0
    if (!_iceberg_delete_rows->empty()) [[likely]] {
848
0
        set_delete_rows();
849
0
    }
850
0
    return Status::OK();
851
1
}
_ZN5doris18IcebergReaderMixinINS_13ParquetReaderEE20read_deletion_vectorERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKNS_22TIcebergDeleteFileDescE
Line
Count
Source
817
1
        const std::string& data_file_path, const TIcebergDeleteFileDesc& delete_file_desc) {
818
1
    Status create_status = Status::OK();
819
1
    SCOPED_TIMER(_iceberg_profile.delete_files_read_time);
820
1
    _iceberg_delete_rows = _kv_cache->template get<DeleteRows>(
821
1
            build_iceberg_deletion_vector_cache_key(data_file_path, delete_file_desc),
822
1
            [&]() -> DeleteRows* {
823
1
                auto delete_rows = std::make_unique<DeleteRows>();
824
825
1
                roaring::Roaring64Map bitmap;
826
1
                IcebergDeleteFileReaderOptions options;
827
1
                options.state = this->get_state();
828
1
                options.profile = this->get_profile();
829
1
                options.scan_params = &this->get_scan_params();
830
1
                options.io_ctx = this->get_io_ctx();
831
1
                options.fs_name = &this->get_scan_range().fs_name;
832
1
                create_status = read_iceberg_deletion_vector(delete_file_desc, options, &bitmap);
833
1
                if (!create_status.ok()) [[unlikely]] {
834
1
                    return nullptr;
835
1
                }
836
837
1
                SCOPED_TIMER(_iceberg_profile.parse_delete_file_time);
838
1
                delete_rows->reserve(bitmap.cardinality());
839
1
                for (auto it = bitmap.begin(); it != bitmap.end(); it++) {
840
1
                    delete_rows->push_back(*it);
841
1
                }
842
1
                COUNTER_UPDATE(_iceberg_profile.num_delete_rows, delete_rows->size());
843
1
                return delete_rows.release();
844
1
            });
845
846
1
    RETURN_IF_ERROR(create_status);
847
0
    if (!_iceberg_delete_rows->empty()) [[likely]] {
848
0
        set_delete_rows();
849
0
    }
850
0
    return Status::OK();
851
1
}
Unexecuted instantiation: _ZN5doris18IcebergReaderMixinINS_9OrcReaderEE20read_deletion_vectorERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKNS_22TIcebergDeleteFileDescE
852
853
} // namespace doris