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 <gen_cpp/ExternalTableSchema_types.h> |
21 | | |
22 | | #include <algorithm> |
23 | | #include <cstddef> |
24 | | #include <cstdint> |
25 | | #include <memory> |
26 | | #include <string> |
27 | | #include <unordered_map> |
28 | | #include <vector> |
29 | | |
30 | | #include "common/consts.h" |
31 | | #include "common/status.h" |
32 | | #include "core/block/block.h" |
33 | | #include "core/column/column_dictionary.h" |
34 | | #include "core/column/column_nullable.h" |
35 | | #include "core/column/column_string.h" |
36 | | #include "core/column/column_struct.h" |
37 | | #include "core/data_type/data_type_number.h" |
38 | | #include "core/data_type/data_type_string.h" |
39 | | #include "core/data_type/data_type_struct.h" |
40 | | #include "core/data_type/primitive_type.h" |
41 | | #include "format/generic_reader.h" |
42 | | #include "format/table/equality_delete.h" |
43 | | #include "format/table/iceberg_default_value.h" |
44 | | #include "format/table/iceberg_delete_file_reader_helper.h" |
45 | | #include "format/table/iceberg_scan_semantics.h" |
46 | | #include "format/table/table_schema_change_helper.h" |
47 | | #include "runtime/runtime_profile.h" |
48 | | #include "runtime/runtime_state.h" |
49 | | #include "storage/olap_common.h" |
50 | | #include "util/string_util.h" |
51 | | |
52 | | namespace doris { |
53 | | class TIcebergDeleteFileDesc; |
54 | | } // namespace doris |
55 | | |
56 | | namespace doris { |
57 | | |
58 | | class ShardedKVCache; |
59 | | |
60 | | // CRTP mixin for Iceberg reader functionality. |
61 | | // BaseReader should be ParquetReader or OrcReader. |
62 | | // Inherits BaseReader + TableSchemaChangeHelper, providing shared Iceberg logic |
63 | | // (delete files, deletion vectors, equality delete, $row_id synthesis). |
64 | | // |
65 | | // Inheritance chain: |
66 | | // IcebergParquetReader -> IcebergReaderMixin<ParquetReader> -> ParquetReader -> GenericReader |
67 | | // IcebergOrcReader -> IcebergReaderMixin<OrcReader> -> OrcReader -> GenericReader |
68 | | template <typename BaseReader> |
69 | | class IcebergReaderMixin : public BaseReader, public TableSchemaChangeHelper { |
70 | | public: |
71 | | struct PositionDeleteRange { |
72 | | std::vector<std::string> data_file_path; |
73 | | std::vector<std::pair<int, int>> range; |
74 | | }; |
75 | | |
76 | | // Forward BaseReader constructor arguments + Iceberg-specific kv_cache |
77 | | template <typename... Args> |
78 | | IcebergReaderMixin(ShardedKVCache* kv_cache, Args&&... args) |
79 | 83 | : BaseReader(std::forward<Args>(args)...), _kv_cache(kv_cache) { |
80 | 83 | static const char* iceberg_profile = "IcebergProfile"; |
81 | 83 | ADD_TIMER(this->get_profile(), iceberg_profile); |
82 | 83 | _iceberg_profile.num_delete_files = ADD_CHILD_COUNTER(this->get_profile(), "NumDeleteFiles", |
83 | 83 | TUnit::UNIT, iceberg_profile); |
84 | 83 | _iceberg_profile.num_delete_rows = ADD_CHILD_COUNTER(this->get_profile(), "NumDeleteRows", |
85 | 83 | TUnit::UNIT, iceberg_profile); |
86 | 83 | _iceberg_profile.delete_files_read_time = |
87 | 83 | ADD_CHILD_TIMER(this->get_profile(), "DeleteFileReadTime", iceberg_profile); |
88 | 83 | _iceberg_profile.delete_rows_sort_time = |
89 | 83 | ADD_CHILD_TIMER(this->get_profile(), "DeleteRowsSortTime", iceberg_profile); |
90 | 83 | _iceberg_profile.parse_delete_file_time = |
91 | 83 | ADD_CHILD_TIMER(this->get_profile(), "ParseDeleteFileTime", iceberg_profile); |
92 | 83 | _iceberg_profile.decoded_cache_hit_count = |
93 | 83 | ADD_CHILD_COUNTER(this->get_profile(), "DeletionVectorDecodedCacheHitCount", |
94 | 83 | TUnit::UNIT, iceberg_profile); |
95 | 83 | _iceberg_profile.decoded_cache_miss_count = |
96 | 83 | ADD_CHILD_COUNTER(this->get_profile(), "DeletionVectorDecodedCacheMissCount", |
97 | 83 | TUnit::UNIT, iceberg_profile); |
98 | 83 | _iceberg_profile.file_cache_hit_count = |
99 | 83 | ADD_CHILD_COUNTER(this->get_profile(), "DeletionVectorFileCacheHitCount", |
100 | 83 | TUnit::UNIT, iceberg_profile); |
101 | 83 | _iceberg_profile.file_cache_miss_count = |
102 | 83 | ADD_CHILD_COUNTER(this->get_profile(), "DeletionVectorFileCacheMissCount", |
103 | 83 | TUnit::UNIT, iceberg_profile); |
104 | 83 | _iceberg_profile.file_cache_peer_read_count = |
105 | 83 | ADD_CHILD_COUNTER(this->get_profile(), "DeletionVectorFileCachePeerReadCount", |
106 | 83 | TUnit::UNIT, iceberg_profile); |
107 | 83 | } _ZN5doris18IcebergReaderMixinINS_13ParquetReaderEEC2IJRPNS_14RuntimeProfileERKNS_20TFileScanRangeParamsERKNS_14TFileRangeDescERmRPKN4cctz9time_zoneERPNS_2io9IOContextERPNS_12RuntimeStateERPNS_13FileMetaCacheEEEEPNS_14ShardedKVCacheEDpOT_ Line | Count | Source | 79 | 52 | : BaseReader(std::forward<Args>(args)...), _kv_cache(kv_cache) { | 80 | 52 | static const char* iceberg_profile = "IcebergProfile"; | 81 | 52 | ADD_TIMER(this->get_profile(), iceberg_profile); | 82 | 52 | _iceberg_profile.num_delete_files = ADD_CHILD_COUNTER(this->get_profile(), "NumDeleteFiles", | 83 | 52 | TUnit::UNIT, iceberg_profile); | 84 | 52 | _iceberg_profile.num_delete_rows = ADD_CHILD_COUNTER(this->get_profile(), "NumDeleteRows", | 85 | 52 | TUnit::UNIT, iceberg_profile); | 86 | 52 | _iceberg_profile.delete_files_read_time = | 87 | 52 | ADD_CHILD_TIMER(this->get_profile(), "DeleteFileReadTime", iceberg_profile); | 88 | 52 | _iceberg_profile.delete_rows_sort_time = | 89 | 52 | ADD_CHILD_TIMER(this->get_profile(), "DeleteRowsSortTime", iceberg_profile); | 90 | 52 | _iceberg_profile.parse_delete_file_time = | 91 | 52 | ADD_CHILD_TIMER(this->get_profile(), "ParseDeleteFileTime", iceberg_profile); | 92 | 52 | _iceberg_profile.decoded_cache_hit_count = | 93 | 52 | ADD_CHILD_COUNTER(this->get_profile(), "DeletionVectorDecodedCacheHitCount", | 94 | 52 | TUnit::UNIT, iceberg_profile); | 95 | 52 | _iceberg_profile.decoded_cache_miss_count = | 96 | 52 | ADD_CHILD_COUNTER(this->get_profile(), "DeletionVectorDecodedCacheMissCount", | 97 | 52 | TUnit::UNIT, iceberg_profile); | 98 | 52 | _iceberg_profile.file_cache_hit_count = | 99 | 52 | ADD_CHILD_COUNTER(this->get_profile(), "DeletionVectorFileCacheHitCount", | 100 | 52 | TUnit::UNIT, iceberg_profile); | 101 | 52 | _iceberg_profile.file_cache_miss_count = | 102 | 52 | ADD_CHILD_COUNTER(this->get_profile(), "DeletionVectorFileCacheMissCount", | 103 | 52 | TUnit::UNIT, iceberg_profile); | 104 | 52 | _iceberg_profile.file_cache_peer_read_count = | 105 | 52 | ADD_CHILD_COUNTER(this->get_profile(), "DeletionVectorFileCachePeerReadCount", | 106 | 52 | TUnit::UNIT, iceberg_profile); | 107 | 52 | } |
_ZN5doris18IcebergReaderMixinINS_9OrcReaderEEC2IJRPNS_14RuntimeProfileERPNS_12RuntimeStateERKNS_20TFileScanRangeParamsERKNS_14TFileRangeDescERmRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERPNS_2io9IOContextERPNS_13FileMetaCacheEEEEPNS_14ShardedKVCacheEDpOT_ Line | Count | Source | 79 | 30 | : BaseReader(std::forward<Args>(args)...), _kv_cache(kv_cache) { | 80 | 30 | static const char* iceberg_profile = "IcebergProfile"; | 81 | 30 | ADD_TIMER(this->get_profile(), iceberg_profile); | 82 | 30 | _iceberg_profile.num_delete_files = ADD_CHILD_COUNTER(this->get_profile(), "NumDeleteFiles", | 83 | 30 | TUnit::UNIT, iceberg_profile); | 84 | 30 | _iceberg_profile.num_delete_rows = ADD_CHILD_COUNTER(this->get_profile(), "NumDeleteRows", | 85 | 30 | TUnit::UNIT, iceberg_profile); | 86 | 30 | _iceberg_profile.delete_files_read_time = | 87 | 30 | ADD_CHILD_TIMER(this->get_profile(), "DeleteFileReadTime", iceberg_profile); | 88 | 30 | _iceberg_profile.delete_rows_sort_time = | 89 | 30 | ADD_CHILD_TIMER(this->get_profile(), "DeleteRowsSortTime", iceberg_profile); | 90 | 30 | _iceberg_profile.parse_delete_file_time = | 91 | 30 | ADD_CHILD_TIMER(this->get_profile(), "ParseDeleteFileTime", iceberg_profile); | 92 | 30 | _iceberg_profile.decoded_cache_hit_count = | 93 | 30 | ADD_CHILD_COUNTER(this->get_profile(), "DeletionVectorDecodedCacheHitCount", | 94 | 30 | TUnit::UNIT, iceberg_profile); | 95 | 30 | _iceberg_profile.decoded_cache_miss_count = | 96 | 30 | ADD_CHILD_COUNTER(this->get_profile(), "DeletionVectorDecodedCacheMissCount", | 97 | 30 | TUnit::UNIT, iceberg_profile); | 98 | 30 | _iceberg_profile.file_cache_hit_count = | 99 | 30 | ADD_CHILD_COUNTER(this->get_profile(), "DeletionVectorFileCacheHitCount", | 100 | 30 | TUnit::UNIT, iceberg_profile); | 101 | 30 | _iceberg_profile.file_cache_miss_count = | 102 | 30 | ADD_CHILD_COUNTER(this->get_profile(), "DeletionVectorFileCacheMissCount", | 103 | 30 | TUnit::UNIT, iceberg_profile); | 104 | 30 | _iceberg_profile.file_cache_peer_read_count = | 105 | 30 | ADD_CHILD_COUNTER(this->get_profile(), "DeletionVectorFileCachePeerReadCount", | 106 | 30 | TUnit::UNIT, iceberg_profile); | 107 | 30 | } |
_ZN5doris18IcebergReaderMixinINS_13ParquetReaderEEC2IJRPNS_14RuntimeProfileERKNS_20TFileScanRangeParamsERKNS_14TFileRangeDescERmRPKN4cctz9time_zoneESt10shared_ptrINS_2io9IOContextEERPNS_12RuntimeStateERPNS_13FileMetaCacheEEEEPNS_14ShardedKVCacheEDpOT_ Line | Count | Source | 79 | 1 | : BaseReader(std::forward<Args>(args)...), _kv_cache(kv_cache) { | 80 | 1 | static const char* iceberg_profile = "IcebergProfile"; | 81 | 1 | ADD_TIMER(this->get_profile(), iceberg_profile); | 82 | 1 | _iceberg_profile.num_delete_files = ADD_CHILD_COUNTER(this->get_profile(), "NumDeleteFiles", | 83 | 1 | TUnit::UNIT, iceberg_profile); | 84 | 1 | _iceberg_profile.num_delete_rows = ADD_CHILD_COUNTER(this->get_profile(), "NumDeleteRows", | 85 | 1 | TUnit::UNIT, iceberg_profile); | 86 | 1 | _iceberg_profile.delete_files_read_time = | 87 | 1 | ADD_CHILD_TIMER(this->get_profile(), "DeleteFileReadTime", iceberg_profile); | 88 | 1 | _iceberg_profile.delete_rows_sort_time = | 89 | 1 | ADD_CHILD_TIMER(this->get_profile(), "DeleteRowsSortTime", iceberg_profile); | 90 | 1 | _iceberg_profile.parse_delete_file_time = | 91 | 1 | ADD_CHILD_TIMER(this->get_profile(), "ParseDeleteFileTime", iceberg_profile); | 92 | 1 | _iceberg_profile.decoded_cache_hit_count = | 93 | 1 | ADD_CHILD_COUNTER(this->get_profile(), "DeletionVectorDecodedCacheHitCount", | 94 | 1 | TUnit::UNIT, iceberg_profile); | 95 | 1 | _iceberg_profile.decoded_cache_miss_count = | 96 | 1 | ADD_CHILD_COUNTER(this->get_profile(), "DeletionVectorDecodedCacheMissCount", | 97 | 1 | TUnit::UNIT, iceberg_profile); | 98 | 1 | _iceberg_profile.file_cache_hit_count = | 99 | 1 | ADD_CHILD_COUNTER(this->get_profile(), "DeletionVectorFileCacheHitCount", | 100 | 1 | TUnit::UNIT, iceberg_profile); | 101 | 1 | _iceberg_profile.file_cache_miss_count = | 102 | 1 | ADD_CHILD_COUNTER(this->get_profile(), "DeletionVectorFileCacheMissCount", | 103 | 1 | TUnit::UNIT, iceberg_profile); | 104 | 1 | _iceberg_profile.file_cache_peer_read_count = | 105 | 1 | ADD_CHILD_COUNTER(this->get_profile(), "DeletionVectorFileCachePeerReadCount", | 106 | 1 | TUnit::UNIT, iceberg_profile); | 107 | 1 | } |
Unexecuted instantiation: _ZN5doris18IcebergReaderMixinINS_9OrcReaderEEC2IJRPNS_14RuntimeProfileERPNS_12RuntimeStateERKNS_20TFileScanRangeParamsERKNS_14TFileRangeDescERmRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt10shared_ptrINS_2io9IOContextEERPNS_13FileMetaCacheEEEEPNS_14ShardedKVCacheEDpOT_ |
108 | | |
109 | 83 | ~IcebergReaderMixin() override = default; _ZN5doris18IcebergReaderMixinINS_13ParquetReaderEED2Ev Line | Count | Source | 109 | 53 | ~IcebergReaderMixin() override = default; |
_ZN5doris18IcebergReaderMixinINS_9OrcReaderEED2Ev Line | Count | Source | 109 | 30 | ~IcebergReaderMixin() override = default; |
|
110 | | |
111 | | void set_current_file_info(const std::string& file_path, int32_t partition_spec_id, |
112 | 0 | const std::string& partition_data_json) { |
113 | 0 | _current_file_path = file_path; |
114 | 0 | _partition_spec_id = partition_spec_id; |
115 | 0 | _partition_data_json = partition_data_json; |
116 | 0 | } Unexecuted instantiation: _ZN5doris18IcebergReaderMixinINS_13ParquetReaderEE21set_current_file_infoERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEiSA_ Unexecuted instantiation: _ZN5doris18IcebergReaderMixinINS_9OrcReaderEE21set_current_file_infoERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEiSA_ |
117 | | |
118 | | enum { DATA, POSITION_DELETE, EQUALITY_DELETE, DELETION_VECTOR }; |
119 | | enum Fileformat { NONE, PARQUET, ORC, AVRO }; |
120 | | |
121 | | virtual void set_delete_rows() = 0; |
122 | | virtual void set_deletion_vector() = 0; |
123 | | |
124 | | // Table-level COUNT(*) is handled by CountReader (created by FileScanner after |
125 | | // init_reader). If _do_get_next_block is called, COUNT must have been resolved. |
126 | 61 | Status _do_get_next_block(Block* block, size_t* read_rows, bool* eof) override { |
127 | 61 | DCHECK(this->_push_down_agg_type != TPushAggOp::type::COUNT); |
128 | 61 | return BaseReader::_do_get_next_block(block, read_rows, eof); |
129 | 61 | } _ZN5doris18IcebergReaderMixinINS_13ParquetReaderEE18_do_get_next_blockEPNS_5BlockEPmPb Line | Count | Source | 126 | 37 | Status _do_get_next_block(Block* block, size_t* read_rows, bool* eof) override { | 127 | | DCHECK(this->_push_down_agg_type != TPushAggOp::type::COUNT); | 128 | 37 | return BaseReader::_do_get_next_block(block, read_rows, eof); | 129 | 37 | } |
_ZN5doris18IcebergReaderMixinINS_9OrcReaderEE18_do_get_next_blockEPNS_5BlockEPmPb Line | Count | Source | 126 | 24 | Status _do_get_next_block(Block* block, size_t* read_rows, bool* eof) override { | 127 | | DCHECK(this->_push_down_agg_type != TPushAggOp::type::COUNT); | 128 | 24 | return BaseReader::_do_get_next_block(block, read_rows, eof); | 129 | 24 | } |
|
130 | | |
131 | | void set_create_row_id_column_iterator_func( |
132 | 1 | std::function<std::shared_ptr<segment_v2::RowIdColumnIteratorV2>()> create_func) { |
133 | 1 | _create_topn_row_id_column_iterator = create_func; |
134 | 1 | } _ZN5doris18IcebergReaderMixinINS_13ParquetReaderEE38set_create_row_id_column_iterator_funcESt8functionIFSt10shared_ptrINS_10segment_v221RowIdColumnIteratorV2EEvEE Line | Count | Source | 132 | 1 | std::function<std::shared_ptr<segment_v2::RowIdColumnIteratorV2>()> create_func) { | 133 | 1 | _create_topn_row_id_column_iterator = create_func; | 134 | 1 | } |
Unexecuted instantiation: _ZN5doris18IcebergReaderMixinINS_9OrcReaderEE38set_create_row_id_column_iterator_funcESt8functionIFSt10shared_ptrINS_10segment_v221RowIdColumnIteratorV2EEvEE |
135 | | |
136 | | Status TEST_read_deletion_vector(const std::string& data_file_path, |
137 | 1 | const TIcebergDeleteFileDesc& delete_file_desc) { |
138 | 1 | return read_deletion_vector(data_file_path, delete_file_desc); |
139 | 1 | } |
140 | | |
141 | | Status TEST_position_delete_base(const std::string& data_file_path, |
142 | 2 | const std::vector<TIcebergDeleteFileDesc>& delete_files) { |
143 | 2 | return _position_delete_base(data_file_path, delete_files); |
144 | 2 | } |
145 | | |
146 | 1 | Status TEST_read_equality_delete_file(const TIcebergDeleteFileDesc& delete_file) { |
147 | 1 | return _read_equality_delete_file(delete_file); |
148 | 1 | } |
149 | | |
150 | | void TEST_set_column_name_to_block_index( |
151 | 5 | std::unordered_map<std::string, uint32_t>* column_name_to_block_index) { |
152 | 5 | this->col_name_to_block_idx_ref() = column_name_to_block_index; |
153 | 5 | } |
154 | | |
155 | | Status TEST_register_missing_equality_delete_column(int32_t field_id, const std::string& name, |
156 | 6 | const DataTypePtr& delete_key_type) { |
157 | 6 | return _register_missing_equality_delete_column(field_id, name, delete_key_type); |
158 | 6 | } |
159 | | |
160 | 3 | Status TEST_materialize_missing_equality_delete_columns(Block* block, size_t rows) { |
161 | 3 | return _materialize_missing_equality_delete_columns(block, rows); |
162 | 3 | } |
163 | | |
164 | 8 | const std::vector<int32_t>& TEST_expand_col_field_ids() const { return _expand_col_field_ids; }_ZNK5doris18IcebergReaderMixinINS_13ParquetReaderEE25TEST_expand_col_field_idsEv Line | Count | Source | 164 | 4 | const std::vector<int32_t>& TEST_expand_col_field_ids() const { return _expand_col_field_ids; } |
_ZNK5doris18IcebergReaderMixinINS_9OrcReaderEE25TEST_expand_col_field_idsEv Line | Count | Source | 164 | 4 | const std::vector<int32_t>& TEST_expand_col_field_ids() const { return _expand_col_field_ids; } |
|
165 | | |
166 | | protected: |
167 | | // ---- Hook implementations ---- |
168 | | |
169 | | // Called before reading a block: expand block for equality delete columns + detect row_id |
170 | 61 | Status on_before_read_block(Block* block) override { |
171 | 61 | RETURN_IF_ERROR(_expand_block_if_need(block)); |
172 | 61 | return Status::OK(); |
173 | 61 | } _ZN5doris18IcebergReaderMixinINS_13ParquetReaderEE20on_before_read_blockEPNS_5BlockE Line | Count | Source | 170 | 37 | Status on_before_read_block(Block* block) override { | 171 | 37 | RETURN_IF_ERROR(_expand_block_if_need(block)); | 172 | 37 | return Status::OK(); | 173 | 37 | } |
_ZN5doris18IcebergReaderMixinINS_9OrcReaderEE20on_before_read_blockEPNS_5BlockE Line | Count | Source | 170 | 24 | Status on_before_read_block(Block* block) override { | 171 | 24 | RETURN_IF_ERROR(_expand_block_if_need(block)); | 172 | 24 | return Status::OK(); | 173 | 24 | } |
|
174 | | |
175 | | // Iceberg initial defaults belong to the table schema, not to the generic FE slot default. |
176 | | // V1 keeps master's primitive-default behavior; V2 also materializes missing optional/required |
177 | | // fields and complex defaults through the recursive Iceberg schema metadata. |
178 | | Status on_fill_missing_columns(Block* block, size_t rows, |
179 | 70 | const std::vector<std::string>& cols) override { |
180 | 70 | if (!supports_iceberg_scan_semantics_v1(&this->get_scan_params())) { |
181 | 5 | return BaseReader::on_fill_missing_columns(block, rows, cols); |
182 | 5 | } |
183 | 65 | const bool use_v2_semantics = supports_iceberg_scan_semantics_v2(&this->get_scan_params()); |
184 | 65 | std::vector<std::string> base_reader_columns; |
185 | 65 | for (const auto& col_name : cols) { |
186 | 5 | const auto* field = _find_current_schema_field(col_name); |
187 | 5 | if (field == nullptr || (!use_v2_semantics && !field->__isset.initial_default_value)) { |
188 | 0 | base_reader_columns.push_back(col_name); |
189 | 0 | continue; |
190 | 0 | } |
191 | | |
192 | 5 | DORIS_CHECK(this->_fill_col_name_to_block_idx != nullptr); |
193 | 5 | const auto position = this->_fill_col_name_to_block_idx->find(col_name); |
194 | 5 | if (position == this->_fill_col_name_to_block_idx->end()) { |
195 | 0 | return Status::InternalError("Missing column: {} not found in block {}", col_name, |
196 | 0 | block->dump_structure()); |
197 | 0 | } |
198 | 5 | DORIS_CHECK(position->second < block->columns()); |
199 | | |
200 | 5 | auto default_value = _missing_initial_default_values.find(col_name); |
201 | 5 | if (default_value == _missing_initial_default_values.end()) { |
202 | 4 | ColumnPtr value; |
203 | 4 | RETURN_IF_ERROR(iceberg::create_initial_default_column( |
204 | 4 | *field, block->get_by_position(position->second).type, &value)); |
205 | 4 | default_value = |
206 | 4 | _missing_initial_default_values.emplace(col_name, std::move(value)).first; |
207 | 4 | } |
208 | 5 | auto column_guard = block->mutate_column_scoped(position->second); |
209 | 5 | auto& mutable_column = column_guard.mutable_column(); |
210 | 5 | mutable_column->insert_many_from(*default_value->second, 0, rows); |
211 | 5 | } |
212 | 65 | return BaseReader::on_fill_missing_columns(block, rows, base_reader_columns); |
213 | 65 | } _ZN5doris18IcebergReaderMixinINS_13ParquetReaderEE23on_fill_missing_columnsEPNS_5BlockEmRKSt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaISB_EE Line | Count | Source | 179 | 45 | const std::vector<std::string>& cols) override { | 180 | 45 | if (!supports_iceberg_scan_semantics_v1(&this->get_scan_params())) { | 181 | 4 | return BaseReader::on_fill_missing_columns(block, rows, cols); | 182 | 4 | } | 183 | 41 | const bool use_v2_semantics = supports_iceberg_scan_semantics_v2(&this->get_scan_params()); | 184 | 41 | std::vector<std::string> base_reader_columns; | 185 | 41 | for (const auto& col_name : cols) { | 186 | 4 | const auto* field = _find_current_schema_field(col_name); | 187 | 4 | if (field == nullptr || (!use_v2_semantics && !field->__isset.initial_default_value)) { | 188 | 0 | base_reader_columns.push_back(col_name); | 189 | 0 | continue; | 190 | 0 | } | 191 | | | 192 | 4 | DORIS_CHECK(this->_fill_col_name_to_block_idx != nullptr); | 193 | 4 | const auto position = this->_fill_col_name_to_block_idx->find(col_name); | 194 | 4 | if (position == this->_fill_col_name_to_block_idx->end()) { | 195 | 0 | return Status::InternalError("Missing column: {} not found in block {}", col_name, | 196 | 0 | block->dump_structure()); | 197 | 0 | } | 198 | 4 | DORIS_CHECK(position->second < block->columns()); | 199 | | | 200 | 4 | auto default_value = _missing_initial_default_values.find(col_name); | 201 | 4 | if (default_value == _missing_initial_default_values.end()) { | 202 | 3 | ColumnPtr value; | 203 | 3 | RETURN_IF_ERROR(iceberg::create_initial_default_column( | 204 | 3 | *field, block->get_by_position(position->second).type, &value)); | 205 | 3 | default_value = | 206 | 3 | _missing_initial_default_values.emplace(col_name, std::move(value)).first; | 207 | 3 | } | 208 | 4 | auto column_guard = block->mutate_column_scoped(position->second); | 209 | 4 | auto& mutable_column = column_guard.mutable_column(); | 210 | 4 | mutable_column->insert_many_from(*default_value->second, 0, rows); | 211 | 4 | } | 212 | 41 | return BaseReader::on_fill_missing_columns(block, rows, base_reader_columns); | 213 | 41 | } |
_ZN5doris18IcebergReaderMixinINS_9OrcReaderEE23on_fill_missing_columnsEPNS_5BlockEmRKSt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaISB_EE Line | Count | Source | 179 | 25 | const std::vector<std::string>& cols) override { | 180 | 25 | if (!supports_iceberg_scan_semantics_v1(&this->get_scan_params())) { | 181 | 1 | return BaseReader::on_fill_missing_columns(block, rows, cols); | 182 | 1 | } | 183 | 24 | const bool use_v2_semantics = supports_iceberg_scan_semantics_v2(&this->get_scan_params()); | 184 | 24 | std::vector<std::string> base_reader_columns; | 185 | 24 | for (const auto& col_name : cols) { | 186 | 1 | const auto* field = _find_current_schema_field(col_name); | 187 | 1 | if (field == nullptr || (!use_v2_semantics && !field->__isset.initial_default_value)) { | 188 | 0 | base_reader_columns.push_back(col_name); | 189 | 0 | continue; | 190 | 0 | } | 191 | | | 192 | 1 | DORIS_CHECK(this->_fill_col_name_to_block_idx != nullptr); | 193 | 1 | const auto position = this->_fill_col_name_to_block_idx->find(col_name); | 194 | 1 | if (position == this->_fill_col_name_to_block_idx->end()) { | 195 | 0 | return Status::InternalError("Missing column: {} not found in block {}", col_name, | 196 | 0 | block->dump_structure()); | 197 | 0 | } | 198 | 1 | DORIS_CHECK(position->second < block->columns()); | 199 | | | 200 | 1 | auto default_value = _missing_initial_default_values.find(col_name); | 201 | 1 | if (default_value == _missing_initial_default_values.end()) { | 202 | 1 | ColumnPtr value; | 203 | 1 | RETURN_IF_ERROR(iceberg::create_initial_default_column( | 204 | 1 | *field, block->get_by_position(position->second).type, &value)); | 205 | 1 | default_value = | 206 | 1 | _missing_initial_default_values.emplace(col_name, std::move(value)).first; | 207 | 1 | } | 208 | 1 | auto column_guard = block->mutate_column_scoped(position->second); | 209 | 1 | auto& mutable_column = column_guard.mutable_column(); | 210 | 1 | mutable_column->insert_many_from(*default_value->second, 0, rows); | 211 | 1 | } | 212 | 24 | return BaseReader::on_fill_missing_columns(block, rows, base_reader_columns); | 213 | 24 | } |
|
214 | | |
215 | | /// Fill Iceberg $row_id synthesized column. Registered as handler during init. |
216 | 0 | Status _fill_iceberg_row_id(Block* block, size_t rows) { |
217 | 0 | int row_id_pos = block->get_position_by_name(BeConsts::ICEBERG_ROWID_COL); |
218 | 0 | DORIS_CHECK(row_id_pos >= 0); |
219 | | |
220 | | // Lazy-init file info: only set when $row_id is actually needed. |
221 | 0 | const auto& table_desc = this->get_scan_range().table_format_params.iceberg_params; |
222 | 0 | std::string file_path = table_desc.original_file_path; |
223 | 0 | int32_t partition_spec_id = |
224 | 0 | table_desc.__isset.partition_spec_id ? table_desc.partition_spec_id : 0; |
225 | 0 | std::string partition_data_json; |
226 | 0 | if (table_desc.__isset.partition_data_json) { |
227 | 0 | partition_data_json = table_desc.partition_data_json; |
228 | 0 | } |
229 | 0 | set_current_file_info(file_path, partition_spec_id, partition_data_json); |
230 | |
|
231 | 0 | const auto& row_ids = this->current_batch_row_positions(); |
232 | 0 | auto& col_with_type = block->get_by_position(static_cast<size_t>(row_id_pos)); |
233 | 0 | MutableColumnPtr row_id_column; |
234 | 0 | RETURN_IF_ERROR(_build_iceberg_rowid_column(col_with_type.type, _current_file_path, row_ids, |
235 | 0 | _partition_spec_id, _partition_data_json, |
236 | 0 | &row_id_column)); |
237 | 0 | col_with_type.column = std::move(row_id_column); |
238 | 0 | return Status::OK(); |
239 | 0 | } Unexecuted instantiation: _ZN5doris18IcebergReaderMixinINS_13ParquetReaderEE20_fill_iceberg_row_idEPNS_5BlockEm Unexecuted instantiation: _ZN5doris18IcebergReaderMixinINS_9OrcReaderEE20_fill_iceberg_row_idEPNS_5BlockEm |
240 | | |
241 | 0 | void _init_row_lineage_columns() { |
242 | 0 | const auto& table_desc = this->get_scan_range().table_format_params.iceberg_params; |
243 | 0 | if (table_desc.__isset.first_row_id) { |
244 | 0 | _row_lineage_columns.first_row_id = table_desc.first_row_id; |
245 | 0 | } |
246 | 0 | if (table_desc.__isset.last_updated_sequence_number) { |
247 | 0 | _row_lineage_columns.last_updated_sequence_number = |
248 | 0 | table_desc.last_updated_sequence_number; |
249 | 0 | } |
250 | 0 | } Unexecuted instantiation: _ZN5doris18IcebergReaderMixinINS_13ParquetReaderEE25_init_row_lineage_columnsEv Unexecuted instantiation: _ZN5doris18IcebergReaderMixinINS_9OrcReaderEE25_init_row_lineage_columnsEv |
251 | | |
252 | 0 | Status _fill_row_lineage_row_id(Block* block, size_t rows) { |
253 | 0 | int col_pos = block->get_position_by_name(ROW_LINEAGE_ROW_ID); |
254 | 0 | DORIS_CHECK(col_pos >= 0); |
255 | |
|
256 | 0 | if (_row_lineage_columns.first_row_id >= 0) { |
257 | 0 | auto column_guard = block->mutate_column_scoped(col_pos); |
258 | 0 | auto* nullable_column = |
259 | 0 | assert_cast<ColumnNullable*>(column_guard.mutable_column().get()); |
260 | 0 | auto& null_map = nullable_column->get_null_map_data(); |
261 | 0 | auto& data = |
262 | 0 | assert_cast<ColumnInt64&>(*nullable_column->get_nested_column_ptr()).get_data(); |
263 | 0 | const auto& row_ids = this->current_batch_row_positions(); |
264 | 0 | for (size_t i = 0; i < rows; ++i) { |
265 | 0 | if (null_map[i] != 0) { |
266 | 0 | null_map[i] = 0; |
267 | 0 | data[i] = _row_lineage_columns.first_row_id + static_cast<int64_t>(row_ids[i]); |
268 | 0 | } |
269 | 0 | } |
270 | 0 | } |
271 | 0 | return Status::OK(); |
272 | 0 | } Unexecuted instantiation: _ZN5doris18IcebergReaderMixinINS_13ParquetReaderEE24_fill_row_lineage_row_idEPNS_5BlockEm Unexecuted instantiation: _ZN5doris18IcebergReaderMixinINS_9OrcReaderEE24_fill_row_lineage_row_idEPNS_5BlockEm |
273 | | |
274 | 0 | Status _fill_row_lineage_last_updated_sequence_number(Block* block, size_t rows) { |
275 | 0 | int col_pos = block->get_position_by_name(ROW_LINEAGE_LAST_UPDATED_SEQ_NUMBER); |
276 | 0 | DORIS_CHECK(col_pos >= 0); |
277 | |
|
278 | 0 | if (_row_lineage_columns.last_updated_sequence_number >= 0) { |
279 | 0 | auto column_guard = block->mutate_column_scoped(col_pos); |
280 | 0 | auto* nullable_column = |
281 | 0 | assert_cast<ColumnNullable*>(column_guard.mutable_column().get()); |
282 | 0 | auto& null_map = nullable_column->get_null_map_data(); |
283 | 0 | auto& data = |
284 | 0 | assert_cast<ColumnInt64&>(*nullable_column->get_nested_column_ptr()).get_data(); |
285 | 0 | for (size_t i = 0; i < rows; ++i) { |
286 | 0 | if (null_map[i] != 0) { |
287 | 0 | null_map[i] = 0; |
288 | 0 | data[i] = _row_lineage_columns.last_updated_sequence_number; |
289 | 0 | } |
290 | 0 | } |
291 | 0 | } |
292 | 0 | return Status::OK(); |
293 | 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 |
294 | | |
295 | | // Called after reading a block: apply equality delete filter + shrink block |
296 | 61 | Status on_after_read_block(Block* block, size_t* read_rows) override { |
297 | 61 | RETURN_IF_ERROR(_materialize_missing_equality_delete_columns(block, block->rows())); |
298 | 61 | RETURN_IF_ERROR(_materialize_nested_equality_delete_columns(block)); |
299 | 61 | if (!_equality_delete_impls.empty()) { |
300 | 53 | std::unique_ptr<IColumn::Filter> filter = |
301 | 53 | std::make_unique<IColumn::Filter>(block->rows(), 1); |
302 | 55 | for (auto& equality_delete_impl : _equality_delete_impls) { |
303 | 55 | RETURN_IF_ERROR(equality_delete_impl->filter_data_block( |
304 | 55 | block, this->col_name_to_block_idx_ref(), _id_to_block_column_name, |
305 | 55 | *filter)); |
306 | 55 | } |
307 | 53 | Block::filter_block_internal(block, *filter, block->columns()); |
308 | 53 | *read_rows = block->rows(); |
309 | 53 | } |
310 | 61 | return _shrink_block_if_need(block); |
311 | 61 | } _ZN5doris18IcebergReaderMixinINS_13ParquetReaderEE19on_after_read_blockEPNS_5BlockEPm Line | Count | Source | 296 | 37 | Status on_after_read_block(Block* block, size_t* read_rows) override { | 297 | 37 | RETURN_IF_ERROR(_materialize_missing_equality_delete_columns(block, block->rows())); | 298 | 37 | RETURN_IF_ERROR(_materialize_nested_equality_delete_columns(block)); | 299 | 37 | if (!_equality_delete_impls.empty()) { | 300 | 32 | std::unique_ptr<IColumn::Filter> filter = | 301 | 32 | std::make_unique<IColumn::Filter>(block->rows(), 1); | 302 | 33 | for (auto& equality_delete_impl : _equality_delete_impls) { | 303 | 33 | RETURN_IF_ERROR(equality_delete_impl->filter_data_block( | 304 | 33 | block, this->col_name_to_block_idx_ref(), _id_to_block_column_name, | 305 | 33 | *filter)); | 306 | 33 | } | 307 | 32 | Block::filter_block_internal(block, *filter, block->columns()); | 308 | 32 | *read_rows = block->rows(); | 309 | 32 | } | 310 | 37 | return _shrink_block_if_need(block); | 311 | 37 | } |
_ZN5doris18IcebergReaderMixinINS_9OrcReaderEE19on_after_read_blockEPNS_5BlockEPm Line | Count | Source | 296 | 24 | Status on_after_read_block(Block* block, size_t* read_rows) override { | 297 | 24 | RETURN_IF_ERROR(_materialize_missing_equality_delete_columns(block, block->rows())); | 298 | 24 | RETURN_IF_ERROR(_materialize_nested_equality_delete_columns(block)); | 299 | 24 | if (!_equality_delete_impls.empty()) { | 300 | 21 | std::unique_ptr<IColumn::Filter> filter = | 301 | 21 | std::make_unique<IColumn::Filter>(block->rows(), 1); | 302 | 22 | for (auto& equality_delete_impl : _equality_delete_impls) { | 303 | 22 | RETURN_IF_ERROR(equality_delete_impl->filter_data_block( | 304 | 22 | block, this->col_name_to_block_idx_ref(), _id_to_block_column_name, | 305 | 22 | *filter)); | 306 | 22 | } | 307 | 21 | Block::filter_block_internal(block, *filter, block->columns()); | 308 | 21 | *read_rows = block->rows(); | 309 | 21 | } | 310 | 24 | return _shrink_block_if_need(block); | 311 | 24 | } |
|
312 | | |
313 | | // ---- Shared Iceberg methods ---- |
314 | | |
315 | | Status _init_row_filters(); |
316 | | Status _position_delete_base(const std::string data_file_path, |
317 | | const std::vector<TIcebergDeleteFileDesc>& delete_files); |
318 | | Status _equality_delete_base(const std::vector<TIcebergDeleteFileDesc>& delete_files); |
319 | | Status read_deletion_vector(const std::string& data_file_path, |
320 | | const TIcebergDeleteFileDesc& delete_file_desc); |
321 | | |
322 | | Status _expand_block_if_need(Block* block); |
323 | | Status _shrink_block_if_need(Block* block); |
324 | | const schema::external::TStructField* _current_schema_root() const; |
325 | | const schema::external::TField* _find_current_schema_field(const std::string& name) const; |
326 | | const schema::external::TField* _find_schema_field(int32_t field_id) const; |
327 | | static bool _find_schema_field_path_in_field( |
328 | | const schema::external::TField* field, int32_t field_id, |
329 | | std::vector<const schema::external::TField*>* path); |
330 | | static bool _find_schema_field_path_in_root(const schema::external::TStructField* root, |
331 | | int32_t field_id, |
332 | | std::vector<const schema::external::TField*>* path); |
333 | | std::vector<const schema::external::TField*> _find_schema_field_path(int32_t field_id) const; |
334 | | Status _create_missing_equality_delete_value(int32_t field_id, |
335 | | const DataTypePtr& delete_key_type, |
336 | | size_t physical_path_size, |
337 | | ColumnPtr* const value) const; |
338 | | Status _register_missing_equality_delete_column(int32_t field_id, const std::string& name, |
339 | | const DataTypePtr& delete_key_type); |
340 | | bool _is_derived_equality_delete_column(const std::string& name) const; |
341 | | Status _materialize_missing_equality_delete_column(Block* block, const std::string& name, |
342 | | const ColumnPtr& value, size_t rows); |
343 | | Status _materialize_missing_equality_delete_columns(Block* block, size_t rows); |
344 | | |
345 | | // Type aliases — must be defined before member function declarations that use them. |
346 | | using DeleteRows = std::vector<int64_t>; |
347 | | using DeleteFile = phmap::parallel_flat_hash_map< |
348 | | std::string, std::unique_ptr<DeleteRows>, std::hash<std::string>, std::equal_to<>, |
349 | | std::allocator<std::pair<const std::string, std::unique_ptr<DeleteRows>>>, 8, |
350 | | std::mutex>; |
351 | | |
352 | | PositionDeleteRange _get_range(const ColumnDictI32& file_path_column); |
353 | | PositionDeleteRange _get_range(const ColumnString& file_path_column); |
354 | | static void _sort_delete_rows(const std::vector<std::vector<int64_t>*>& delete_rows_array, |
355 | | int64_t num_delete_rows, std::vector<int64_t>& result); |
356 | | Status _gen_position_delete_file_range(Block& block, DeleteFile* position_delete, |
357 | | size_t read_rows, |
358 | | bool file_path_column_dictionary_coded); |
359 | | void _generate_equality_delete_block(Block* block, |
360 | | const std::vector<std::string>& equality_delete_col_names, |
361 | | const std::vector<DataTypePtr>& equality_delete_col_types); |
362 | | struct NestedEqualityDeleteColumn { |
363 | | int32_t field_id = -1; |
364 | | std::string block_name; |
365 | | // The type the key is compared in (equality_delete_key_type). |
366 | | DataTypePtr leaf_type; |
367 | | // The type of the leaf in the column it is extracted from, widened to leaf_type afterwards. |
368 | | // A file written before a type promotion holds the old type: payload.existing promoted from |
369 | | // INT to BIGINT is still INT in the delete files and data files written before. |
370 | | DataTypePtr source_leaf_type; |
371 | | std::vector<size_t> child_indexes; |
372 | | ColumnPtr missing_value; |
373 | | // Block column holding the key's root struct. Empty when the key's own column reads the |
374 | | // root; otherwise the projected root, or the carrier that reads a shared physical root. |
375 | | std::string source_block_name {}; |
376 | | }; |
377 | | struct EqualityDeleteReadSpec { |
378 | | NestedEqualityDeleteColumn nested_field; |
379 | | std::string leaf_name; |
380 | | std::string root_name; |
381 | | DataTypePtr root_type; |
382 | | }; |
383 | | static bool _find_parquet_equality_delete_path(const FieldSchema& field, int32_t field_id, |
384 | | std::vector<const FieldSchema*>* path, |
385 | | std::vector<size_t>* child_indexes); |
386 | | static bool _find_orc_equality_delete_path(const orc::Type* field, |
387 | | const std::string& field_name, int32_t field_id, |
388 | | std::vector<const orc::Type*>* path, |
389 | | std::vector<std::string>* names, |
390 | | std::vector<size_t>* child_indexes); |
391 | | Status _build_parquet_equality_delete_read_specs( |
392 | | ParquetReader* reader, const TIcebergDeleteFileDesc& delete_file, |
393 | | std::vector<EqualityDeleteReadSpec>* read_specs) const; |
394 | | Status _build_orc_equality_delete_read_specs( |
395 | | OrcReader* reader, const TIcebergDeleteFileDesc& delete_file, |
396 | | std::vector<EqualityDeleteReadSpec>* read_specs) const; |
397 | | Status _build_equality_delete_read_specs(GenericReader* reader, |
398 | | const TIcebergDeleteFileDesc& delete_file, |
399 | | std::vector<EqualityDeleteReadSpec>* read_specs) const; |
400 | | void _register_equality_delete_read_specs( |
401 | | const std::vector<EqualityDeleteReadSpec>& read_specs, |
402 | | std::vector<std::string>* delete_col_names, std::vector<DataTypePtr>* delete_col_types, |
403 | | std::vector<int>* delete_col_ids, std::vector<std::string>* read_root_names, |
404 | | std::vector<DataTypePtr>* read_root_types, |
405 | | std::unordered_map<std::string, uint32_t>* read_root_positions); |
406 | | static Status _initialize_equality_delete_reader( |
407 | | GenericReader* reader, const std::vector<std::string>& read_root_names, |
408 | | std::unordered_map<std::string, uint32_t>* read_root_positions); |
409 | | Status _merge_equality_delete_rows( |
410 | | GenericReader* reader, const std::vector<EqualityDeleteReadSpec>& read_specs, |
411 | | const std::vector<std::string>& read_root_names, |
412 | | const std::vector<DataTypePtr>& read_root_types, |
413 | | const std::unordered_map<std::string, uint32_t>& read_root_positions, |
414 | | Block* eq_file_block) const; |
415 | | Status _read_equality_delete_file(const TIcebergDeleteFileDesc& delete_file); |
416 | | Status _extract_nested_equality_delete_column(const ColumnPtr& root_column, |
417 | | const NestedEqualityDeleteColumn& nested_field, |
418 | | ColumnPtr* leaf_column) const; |
419 | | Status _materialize_nested_equality_delete_columns(Block* block); |
420 | | |
421 | | // Pure virtual: format-specific delete file reading |
422 | | virtual Status _read_position_delete_file(const TFileRangeDesc*, DeleteFile*) = 0; |
423 | | virtual std::unique_ptr<GenericReader> _create_equality_reader( |
424 | | const TFileRangeDesc& delete_desc) = 0; |
425 | | |
426 | 2 | 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 | 426 | 2 | 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 |
427 | | |
428 | | /// Build the Iceberg V2 row-id struct column. |
429 | | static Status _build_iceberg_rowid_column(const DataTypePtr& type, const std::string& file_path, |
430 | | const std::vector<rowid_t>& row_ids, |
431 | | int32_t partition_spec_id, |
432 | | const std::string& partition_data_json, |
433 | 0 | MutableColumnPtr* column_out) { |
434 | 0 | if (type == nullptr || column_out == nullptr) { |
435 | 0 | return Status::InvalidArgument("Invalid iceberg rowid column type or output column"); |
436 | 0 | } |
437 | 0 | MutableColumnPtr column = type->create_column(); |
438 | 0 | auto* nullable_col = check_and_get_column<ColumnNullable>(column.get()); |
439 | 0 | ColumnStruct* struct_col = nullptr; |
440 | 0 | if (nullable_col != nullptr) { |
441 | 0 | struct_col = |
442 | 0 | check_and_get_column<ColumnStruct>(nullable_col->get_nested_column_ptr().get()); |
443 | 0 | } else { |
444 | 0 | struct_col = check_and_get_column<ColumnStruct>(column.get()); |
445 | 0 | } |
446 | 0 | if (struct_col == nullptr || struct_col->tuple_size() < 4) { |
447 | 0 | return Status::InternalError("Invalid iceberg rowid column structure"); |
448 | 0 | } |
449 | 0 | size_t num_rows = row_ids.size(); |
450 | 0 | auto& file_path_col = struct_col->get_column(0); |
451 | 0 | auto& row_pos_col = struct_col->get_column(1); |
452 | 0 | auto& spec_id_col = struct_col->get_column(2); |
453 | 0 | auto& partition_data_col = struct_col->get_column(3); |
454 | 0 | file_path_col.reserve(num_rows); |
455 | 0 | row_pos_col.reserve(num_rows); |
456 | 0 | spec_id_col.reserve(num_rows); |
457 | 0 | partition_data_col.reserve(num_rows); |
458 | 0 | for (size_t i = 0; i < num_rows; ++i) { |
459 | 0 | file_path_col.insert_data(file_path.data(), file_path.size()); |
460 | 0 | } |
461 | 0 | for (size_t i = 0; i < num_rows; ++i) { |
462 | 0 | auto row_pos = static_cast<int64_t>(row_ids[i]); |
463 | 0 | row_pos_col.insert_data(reinterpret_cast<const char*>(&row_pos), sizeof(row_pos)); |
464 | 0 | } |
465 | 0 | for (size_t i = 0; i < num_rows; ++i) { |
466 | 0 | int32_t spec_id = partition_spec_id; |
467 | 0 | spec_id_col.insert_data(reinterpret_cast<const char*>(&spec_id), sizeof(spec_id)); |
468 | 0 | } |
469 | 0 | for (size_t i = 0; i < num_rows; ++i) { |
470 | 0 | partition_data_col.insert_data(partition_data_json.data(), partition_data_json.size()); |
471 | 0 | } |
472 | 0 | if (nullable_col != nullptr) { |
473 | 0 | nullable_col->get_null_map_data().resize_fill(num_rows, 0); |
474 | 0 | } |
475 | 0 | *column_out = std::move(column); |
476 | 0 | return Status::OK(); |
477 | 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 |
478 | | |
479 | | struct IcebergProfile { |
480 | | RuntimeProfile::Counter* num_delete_files; |
481 | | RuntimeProfile::Counter* num_delete_rows; |
482 | | RuntimeProfile::Counter* delete_files_read_time; |
483 | | RuntimeProfile::Counter* delete_rows_sort_time; |
484 | | RuntimeProfile::Counter* parse_delete_file_time; |
485 | | RuntimeProfile::Counter* decoded_cache_hit_count; |
486 | | RuntimeProfile::Counter* decoded_cache_miss_count; |
487 | | RuntimeProfile::Counter* file_cache_hit_count; |
488 | | RuntimeProfile::Counter* file_cache_miss_count; |
489 | | RuntimeProfile::Counter* file_cache_peer_read_count; |
490 | | }; |
491 | | |
492 | | bool _need_row_id_column = false; |
493 | | std::string _current_file_path; |
494 | | int32_t _partition_spec_id = 0; |
495 | | std::string _partition_data_json; |
496 | | |
497 | | ShardedKVCache* _kv_cache; |
498 | | IcebergProfile _iceberg_profile; |
499 | | const std::vector<int64_t>* _iceberg_delete_rows = nullptr; |
500 | | const DeletionVector* _iceberg_deletion_vector = nullptr; |
501 | | std::vector<std::string> _expand_col_names; |
502 | | std::vector<int32_t> _expand_col_field_ids; |
503 | | std::vector<ColumnWithTypeAndName> _expand_columns; |
504 | | std::unordered_map<std::string, ColumnPtr> _missing_initial_default_values; |
505 | | std::unordered_map<std::string, ColumnPtr> _missing_equality_delete_values; |
506 | | std::vector<NestedEqualityDeleteColumn> _nested_equality_delete_columns; |
507 | | std::vector<std::string> _all_required_col_names; |
508 | | Fileformat _file_format = Fileformat::NONE; |
509 | | |
510 | | const int64_t MIN_SUPPORT_DELETE_FILES_VERSION = 2; |
511 | | const std::string ICEBERG_FILE_PATH = "file_path"; |
512 | | const std::string ICEBERG_ROW_POS = "pos"; |
513 | | const std::vector<std::string> delete_file_col_names {ICEBERG_FILE_PATH, ICEBERG_ROW_POS}; |
514 | | const std::unordered_map<std::string, uint32_t> DELETE_COL_NAME_TO_BLOCK_IDX = { |
515 | | {ICEBERG_FILE_PATH, 0}, {ICEBERG_ROW_POS, 1}}; |
516 | | const int ICEBERG_FILE_PATH_INDEX = 0; |
517 | | const int ICEBERG_FILE_POS_INDEX = 1; |
518 | | const int READ_DELETE_FILE_BATCH_SIZE = 102400; |
519 | | |
520 | | // all ids that need read for eq delete (from all eq delete files) |
521 | | std::set<int> _equality_delete_col_ids; |
522 | | // eq delete column ids -> location of _equality_delete_blocks / _equality_delete_impls |
523 | | std::map<std::vector<int>, int> _equality_delete_block_map; |
524 | | // EqualityDeleteBase stores raw pointers to these blocks, so do not modify this vector after |
525 | | // creating entries in _equality_delete_impls. |
526 | | std::vector<Block> _equality_delete_blocks; |
527 | | std::vector<std::unique_ptr<EqualityDeleteBase>> _equality_delete_impls; |
528 | | |
529 | | // id -> block column name |
530 | | std::unordered_map<int, std::string> _id_to_block_column_name; |
531 | | |
532 | | std::function<std::shared_ptr<segment_v2::RowIdColumnIteratorV2>()> |
533 | | _create_topn_row_id_column_iterator; |
534 | | |
535 | | static constexpr const char* ROW_LINEAGE_ROW_ID = "_row_id"; |
536 | | static constexpr const char* ROW_LINEAGE_LAST_UPDATED_SEQ_NUMBER = |
537 | | "_last_updated_sequence_number"; |
538 | | struct RowLineageColumns { |
539 | | int64_t first_row_id = -1; |
540 | | int64_t last_updated_sequence_number = -1; |
541 | | }; |
542 | | RowLineageColumns _row_lineage_columns; |
543 | | }; |
544 | | |
545 | | // ============================================================================ |
546 | | // Template method implementations (must be in header for templates) |
547 | | // ============================================================================ |
548 | | |
549 | | template <typename BaseReader> |
550 | 61 | Status IcebergReaderMixin<BaseReader>::_init_row_filters() { |
551 | | // COUNT(*) short-circuit. A table-level row count of 0 (an empty current snapshot) is still a |
552 | | // valid pushed-down count, so accept >= 0 -- matching FileScanner and the Paimon readers. FE sends |
553 | | // -1 when there is no table-level count; using > 0 here would drop a genuine 0 into the normal read |
554 | | // path below and never produce the intended CountReader(0). |
555 | 61 | if (this->_push_down_agg_type == TPushAggOp::type::COUNT && |
556 | 61 | this->get_scan_range().table_format_params.__isset.table_level_row_count && |
557 | 61 | this->get_scan_range().table_format_params.table_level_row_count >= 0) { |
558 | 0 | return Status::OK(); |
559 | 0 | } |
560 | | |
561 | 61 | const auto& table_desc = this->get_scan_range().table_format_params.iceberg_params; |
562 | 61 | const auto& version = table_desc.format_version; |
563 | 61 | if (version < MIN_SUPPORT_DELETE_FILES_VERSION) { |
564 | 6 | return Status::OK(); |
565 | 6 | } |
566 | | |
567 | 55 | std::vector<TIcebergDeleteFileDesc> position_delete_files; |
568 | 55 | std::vector<TIcebergDeleteFileDesc> equality_delete_files; |
569 | 55 | std::vector<TIcebergDeleteFileDesc> deletion_vector_files; |
570 | 59 | for (const TIcebergDeleteFileDesc& desc : table_desc.delete_files) { |
571 | 59 | if (desc.content == POSITION_DELETE) { |
572 | 0 | position_delete_files.emplace_back(desc); |
573 | 59 | } else if (desc.content == EQUALITY_DELETE) { |
574 | 59 | equality_delete_files.emplace_back(desc); |
575 | 59 | } else if (desc.content == DELETION_VECTOR) { |
576 | 0 | deletion_vector_files.emplace_back(desc); |
577 | 0 | } |
578 | 59 | } |
579 | | |
580 | 55 | if (!equality_delete_files.empty()) { |
581 | 53 | RETURN_IF_ERROR(_equality_delete_base(equality_delete_files)); |
582 | 53 | this->set_push_down_agg_type(TPushAggOp::NONE); |
583 | 53 | } |
584 | | |
585 | 55 | if (!deletion_vector_files.empty()) { |
586 | 0 | if (deletion_vector_files.size() != 1) [[unlikely]] { |
587 | | /* |
588 | | * Deletion vectors are a binary representation of deletes for a single data file that is more efficient |
589 | | * at execution time than position delete files. Unlike equality or position delete files, there can be |
590 | | * at most one deletion vector for a given data file in a snapshot. |
591 | | */ |
592 | 0 | return Status::DataQualityError("This iceberg data file has multiple DVs."); |
593 | 0 | } |
594 | 0 | RETURN_IF_ERROR( |
595 | 0 | read_deletion_vector(table_desc.original_file_path, deletion_vector_files[0])); |
596 | 0 | this->set_push_down_agg_type(TPushAggOp::NONE); |
597 | 55 | } else if (!position_delete_files.empty()) { |
598 | 0 | RETURN_IF_ERROR( |
599 | 0 | _position_delete_base(table_desc.original_file_path, position_delete_files)); |
600 | 0 | this->set_push_down_agg_type(TPushAggOp::NONE); |
601 | 0 | } |
602 | | |
603 | 55 | COUNTER_UPDATE(_iceberg_profile.num_delete_files, table_desc.delete_files.size()); |
604 | 55 | return Status::OK(); |
605 | 55 | } _ZN5doris18IcebergReaderMixinINS_13ParquetReaderEE17_init_row_filtersEv Line | Count | Source | 550 | 37 | Status IcebergReaderMixin<BaseReader>::_init_row_filters() { | 551 | | // COUNT(*) short-circuit. A table-level row count of 0 (an empty current snapshot) is still a | 552 | | // valid pushed-down count, so accept >= 0 -- matching FileScanner and the Paimon readers. FE sends | 553 | | // -1 when there is no table-level count; using > 0 here would drop a genuine 0 into the normal read | 554 | | // path below and never produce the intended CountReader(0). | 555 | 37 | if (this->_push_down_agg_type == TPushAggOp::type::COUNT && | 556 | 37 | this->get_scan_range().table_format_params.__isset.table_level_row_count && | 557 | 37 | this->get_scan_range().table_format_params.table_level_row_count >= 0) { | 558 | 0 | return Status::OK(); | 559 | 0 | } | 560 | | | 561 | 37 | const auto& table_desc = this->get_scan_range().table_format_params.iceberg_params; | 562 | 37 | const auto& version = table_desc.format_version; | 563 | 37 | if (version < MIN_SUPPORT_DELETE_FILES_VERSION) { | 564 | 4 | return Status::OK(); | 565 | 4 | } | 566 | | | 567 | 33 | std::vector<TIcebergDeleteFileDesc> position_delete_files; | 568 | 33 | std::vector<TIcebergDeleteFileDesc> equality_delete_files; | 569 | 33 | std::vector<TIcebergDeleteFileDesc> deletion_vector_files; | 570 | 35 | for (const TIcebergDeleteFileDesc& desc : table_desc.delete_files) { | 571 | 35 | if (desc.content == POSITION_DELETE) { | 572 | 0 | position_delete_files.emplace_back(desc); | 573 | 35 | } else if (desc.content == EQUALITY_DELETE) { | 574 | 35 | equality_delete_files.emplace_back(desc); | 575 | 35 | } else if (desc.content == DELETION_VECTOR) { | 576 | 0 | deletion_vector_files.emplace_back(desc); | 577 | 0 | } | 578 | 35 | } | 579 | | | 580 | 33 | if (!equality_delete_files.empty()) { | 581 | 32 | RETURN_IF_ERROR(_equality_delete_base(equality_delete_files)); | 582 | 32 | this->set_push_down_agg_type(TPushAggOp::NONE); | 583 | 32 | } | 584 | | | 585 | 33 | if (!deletion_vector_files.empty()) { | 586 | 0 | if (deletion_vector_files.size() != 1) [[unlikely]] { | 587 | | /* | 588 | | * Deletion vectors are a binary representation of deletes for a single data file that is more efficient | 589 | | * at execution time than position delete files. Unlike equality or position delete files, there can be | 590 | | * at most one deletion vector for a given data file in a snapshot. | 591 | | */ | 592 | 0 | return Status::DataQualityError("This iceberg data file has multiple DVs."); | 593 | 0 | } | 594 | 0 | RETURN_IF_ERROR( | 595 | 0 | read_deletion_vector(table_desc.original_file_path, deletion_vector_files[0])); | 596 | 0 | this->set_push_down_agg_type(TPushAggOp::NONE); | 597 | 33 | } else if (!position_delete_files.empty()) { | 598 | 0 | RETURN_IF_ERROR( | 599 | 0 | _position_delete_base(table_desc.original_file_path, position_delete_files)); | 600 | 0 | this->set_push_down_agg_type(TPushAggOp::NONE); | 601 | 0 | } | 602 | | | 603 | 33 | COUNTER_UPDATE(_iceberg_profile.num_delete_files, table_desc.delete_files.size()); | 604 | 33 | return Status::OK(); | 605 | 33 | } |
_ZN5doris18IcebergReaderMixinINS_9OrcReaderEE17_init_row_filtersEv Line | Count | Source | 550 | 24 | Status IcebergReaderMixin<BaseReader>::_init_row_filters() { | 551 | | // COUNT(*) short-circuit. A table-level row count of 0 (an empty current snapshot) is still a | 552 | | // valid pushed-down count, so accept >= 0 -- matching FileScanner and the Paimon readers. FE sends | 553 | | // -1 when there is no table-level count; using > 0 here would drop a genuine 0 into the normal read | 554 | | // path below and never produce the intended CountReader(0). | 555 | 24 | if (this->_push_down_agg_type == TPushAggOp::type::COUNT && | 556 | 24 | this->get_scan_range().table_format_params.__isset.table_level_row_count && | 557 | 24 | this->get_scan_range().table_format_params.table_level_row_count >= 0) { | 558 | 0 | return Status::OK(); | 559 | 0 | } | 560 | | | 561 | 24 | const auto& table_desc = this->get_scan_range().table_format_params.iceberg_params; | 562 | 24 | const auto& version = table_desc.format_version; | 563 | 24 | if (version < MIN_SUPPORT_DELETE_FILES_VERSION) { | 564 | 2 | return Status::OK(); | 565 | 2 | } | 566 | | | 567 | 22 | std::vector<TIcebergDeleteFileDesc> position_delete_files; | 568 | 22 | std::vector<TIcebergDeleteFileDesc> equality_delete_files; | 569 | 22 | std::vector<TIcebergDeleteFileDesc> deletion_vector_files; | 570 | 24 | for (const TIcebergDeleteFileDesc& desc : table_desc.delete_files) { | 571 | 24 | if (desc.content == POSITION_DELETE) { | 572 | 0 | position_delete_files.emplace_back(desc); | 573 | 24 | } else if (desc.content == EQUALITY_DELETE) { | 574 | 24 | equality_delete_files.emplace_back(desc); | 575 | 24 | } else if (desc.content == DELETION_VECTOR) { | 576 | 0 | deletion_vector_files.emplace_back(desc); | 577 | 0 | } | 578 | 24 | } | 579 | | | 580 | 22 | if (!equality_delete_files.empty()) { | 581 | 21 | RETURN_IF_ERROR(_equality_delete_base(equality_delete_files)); | 582 | 21 | this->set_push_down_agg_type(TPushAggOp::NONE); | 583 | 21 | } | 584 | | | 585 | 22 | if (!deletion_vector_files.empty()) { | 586 | 0 | if (deletion_vector_files.size() != 1) [[unlikely]] { | 587 | | /* | 588 | | * Deletion vectors are a binary representation of deletes for a single data file that is more efficient | 589 | | * at execution time than position delete files. Unlike equality or position delete files, there can be | 590 | | * at most one deletion vector for a given data file in a snapshot. | 591 | | */ | 592 | 0 | return Status::DataQualityError("This iceberg data file has multiple DVs."); | 593 | 0 | } | 594 | 0 | RETURN_IF_ERROR( | 595 | 0 | read_deletion_vector(table_desc.original_file_path, deletion_vector_files[0])); | 596 | 0 | this->set_push_down_agg_type(TPushAggOp::NONE); | 597 | 22 | } else if (!position_delete_files.empty()) { | 598 | 0 | RETURN_IF_ERROR( | 599 | 0 | _position_delete_base(table_desc.original_file_path, position_delete_files)); | 600 | 0 | this->set_push_down_agg_type(TPushAggOp::NONE); | 601 | 0 | } | 602 | | | 603 | 22 | COUNTER_UPDATE(_iceberg_profile.num_delete_files, table_desc.delete_files.size()); | 604 | 22 | return Status::OK(); | 605 | 22 | } |
|
606 | | |
607 | | template <typename BaseReader> |
608 | | bool IcebergReaderMixin<BaseReader>::_find_parquet_equality_delete_path( |
609 | | const FieldSchema& field, int32_t field_id, std::vector<const FieldSchema*>* path, |
610 | 75 | std::vector<size_t>* child_indexes) { |
611 | 75 | DORIS_CHECK(path != nullptr); |
612 | 75 | DORIS_CHECK(child_indexes != nullptr); |
613 | 75 | path->push_back(&field); |
614 | 75 | if (field.field_id == field_id) { |
615 | 43 | return true; |
616 | 43 | } |
617 | 39 | for (size_t index = 0; index < field.children.size(); ++index) { |
618 | 26 | child_indexes->push_back(index); |
619 | 26 | if (_find_parquet_equality_delete_path(field.children[index], field_id, path, |
620 | 26 | child_indexes)) { |
621 | 19 | return true; |
622 | 19 | } |
623 | 7 | child_indexes->pop_back(); |
624 | 7 | } |
625 | 13 | path->pop_back(); |
626 | 13 | return false; |
627 | 32 | } _ZN5doris18IcebergReaderMixinINS_13ParquetReaderEE34_find_parquet_equality_delete_pathERKNS_11FieldSchemaEiPSt6vectorIPS4_SaIS7_EEPS6_ImSaImEE Line | Count | Source | 610 | 75 | std::vector<size_t>* child_indexes) { | 611 | 75 | DORIS_CHECK(path != nullptr); | 612 | 75 | DORIS_CHECK(child_indexes != nullptr); | 613 | 75 | path->push_back(&field); | 614 | 75 | if (field.field_id == field_id) { | 615 | 43 | return true; | 616 | 43 | } | 617 | 39 | for (size_t index = 0; index < field.children.size(); ++index) { | 618 | 26 | child_indexes->push_back(index); | 619 | 26 | if (_find_parquet_equality_delete_path(field.children[index], field_id, path, | 620 | 26 | child_indexes)) { | 621 | 19 | return true; | 622 | 19 | } | 623 | 7 | child_indexes->pop_back(); | 624 | 7 | } | 625 | 13 | path->pop_back(); | 626 | 13 | return false; | 627 | 32 | } |
Unexecuted instantiation: _ZN5doris18IcebergReaderMixinINS_9OrcReaderEE34_find_parquet_equality_delete_pathERKNS_11FieldSchemaEiPSt6vectorIPS4_SaIS7_EEPS6_ImSaImEE |
628 | | |
629 | | template <typename BaseReader> |
630 | | bool IcebergReaderMixin<BaseReader>::_find_orc_equality_delete_path( |
631 | | const orc::Type* field, const std::string& field_name, int32_t field_id, |
632 | | std::vector<const orc::Type*>* path, std::vector<std::string>* names, |
633 | 40 | std::vector<size_t>* child_indexes) { |
634 | 40 | DORIS_CHECK(field != nullptr); |
635 | 40 | DORIS_CHECK(path != nullptr); |
636 | 40 | DORIS_CHECK(names != nullptr); |
637 | 40 | DORIS_CHECK(child_indexes != nullptr); |
638 | 40 | path->push_back(field); |
639 | 40 | names->push_back(field_name); |
640 | 40 | if (field->hasAttributeKey("iceberg.id") && |
641 | 40 | std::stoi(field->getAttributeValue("iceberg.id")) == field_id) { |
642 | 28 | return true; |
643 | 28 | } |
644 | 12 | for (size_t index = 0; index < field->getSubtypeCount(); ++index) { |
645 | 6 | child_indexes->push_back(index); |
646 | 6 | if (_find_orc_equality_delete_path(field->getSubtype(index), field->getFieldName(index), |
647 | 6 | field_id, path, names, child_indexes)) { |
648 | 6 | return true; |
649 | 6 | } |
650 | 0 | child_indexes->pop_back(); |
651 | 0 | } |
652 | 6 | path->pop_back(); |
653 | 6 | names->pop_back(); |
654 | 6 | return false; |
655 | 12 | } Unexecuted instantiation: _ZN5doris18IcebergReaderMixinINS_13ParquetReaderEE30_find_orc_equality_delete_pathEPKN3orc4TypeERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEiPSt6vectorIS6_SaIS6_EEPSF_ISC_SaISC_EEPSF_ImSaImEE _ZN5doris18IcebergReaderMixinINS_9OrcReaderEE30_find_orc_equality_delete_pathEPKN3orc4TypeERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEiPSt6vectorIS6_SaIS6_EEPSF_ISC_SaISC_EEPSF_ImSaImEE Line | Count | Source | 633 | 40 | std::vector<size_t>* child_indexes) { | 634 | 40 | DORIS_CHECK(field != nullptr); | 635 | 40 | DORIS_CHECK(path != nullptr); | 636 | 40 | DORIS_CHECK(names != nullptr); | 637 | 40 | DORIS_CHECK(child_indexes != nullptr); | 638 | 40 | path->push_back(field); | 639 | 40 | names->push_back(field_name); | 640 | 40 | if (field->hasAttributeKey("iceberg.id") && | 641 | 40 | std::stoi(field->getAttributeValue("iceberg.id")) == field_id) { | 642 | 28 | return true; | 643 | 28 | } | 644 | 12 | for (size_t index = 0; index < field->getSubtypeCount(); ++index) { | 645 | 6 | child_indexes->push_back(index); | 646 | 6 | if (_find_orc_equality_delete_path(field->getSubtype(index), field->getFieldName(index), | 647 | 6 | field_id, path, names, child_indexes)) { | 648 | 6 | return true; | 649 | 6 | } | 650 | 0 | child_indexes->pop_back(); | 651 | 0 | } | 652 | 6 | path->pop_back(); | 653 | 6 | names->pop_back(); | 654 | 6 | return false; | 655 | 12 | } |
|
656 | | |
657 | | template <typename BaseReader> |
658 | | Status IcebergReaderMixin<BaseReader>::_build_parquet_equality_delete_read_specs( |
659 | | ParquetReader* reader, const TIcebergDeleteFileDesc& delete_file, |
660 | 35 | std::vector<EqualityDeleteReadSpec>* read_specs) const { |
661 | 35 | DORIS_CHECK(reader != nullptr); |
662 | 35 | DORIS_CHECK(read_specs != nullptr); |
663 | 35 | const FieldDescriptor* delete_field_desc = nullptr; |
664 | 35 | RETURN_IF_ERROR(reader->get_file_metadata_schema(&delete_field_desc)); |
665 | 35 | DORIS_CHECK(delete_field_desc != nullptr); |
666 | 43 | for (const auto field_id : delete_file.field_ids) { |
667 | 43 | std::vector<const FieldSchema*> path; |
668 | 43 | std::vector<size_t> child_indexes; |
669 | 49 | for (const auto& root : delete_field_desc->get_fields_schema()) { |
670 | 49 | if (_find_parquet_equality_delete_path(root, field_id, &path, &child_indexes)) { |
671 | 43 | break; |
672 | 43 | } |
673 | 49 | } |
674 | 43 | if (path.empty()) { |
675 | 0 | return Status::DataQualityError( |
676 | 0 | "missing field id {} when reading equality delete file {}", field_id, |
677 | 0 | delete_file.path); |
678 | 0 | } |
679 | 43 | const auto* root = path.front(); |
680 | 43 | const auto* leaf = path.back(); |
681 | 43 | if (!leaf->children.empty()) { |
682 | 0 | return Status::NotSupported( |
683 | 0 | "Iceberg equality delete does not support complex column {}", leaf->name); |
684 | 0 | } |
685 | 43 | const auto delete_key_type = make_nullable(leaf->data_type); |
686 | 43 | read_specs->push_back({ |
687 | 43 | .nested_field = |
688 | 43 | { |
689 | 43 | .field_id = field_id, |
690 | 43 | .block_name = leaf->name, |
691 | 43 | .leaf_type = equality_delete_key_type(_find_schema_field(field_id), |
692 | 43 | delete_key_type), |
693 | 43 | .source_leaf_type = delete_key_type, |
694 | 43 | .child_indexes = std::move(child_indexes), |
695 | 43 | .missing_value = nullptr, |
696 | 43 | }, |
697 | 43 | .leaf_name = leaf->name, |
698 | 43 | .root_name = root->name, |
699 | 43 | .root_type = make_nullable(root->data_type), |
700 | 43 | }); |
701 | 43 | } |
702 | 35 | return Status::OK(); |
703 | 35 | } _ZNK5doris18IcebergReaderMixinINS_13ParquetReaderEE41_build_parquet_equality_delete_read_specsEPS1_RKNS_22TIcebergDeleteFileDescEPSt6vectorINS2_22EqualityDeleteReadSpecESaIS8_EE Line | Count | Source | 660 | 35 | std::vector<EqualityDeleteReadSpec>* read_specs) const { | 661 | 35 | DORIS_CHECK(reader != nullptr); | 662 | 35 | DORIS_CHECK(read_specs != nullptr); | 663 | 35 | const FieldDescriptor* delete_field_desc = nullptr; | 664 | 35 | RETURN_IF_ERROR(reader->get_file_metadata_schema(&delete_field_desc)); | 665 | 35 | DORIS_CHECK(delete_field_desc != nullptr); | 666 | 43 | for (const auto field_id : delete_file.field_ids) { | 667 | 43 | std::vector<const FieldSchema*> path; | 668 | 43 | std::vector<size_t> child_indexes; | 669 | 49 | for (const auto& root : delete_field_desc->get_fields_schema()) { | 670 | 49 | if (_find_parquet_equality_delete_path(root, field_id, &path, &child_indexes)) { | 671 | 43 | break; | 672 | 43 | } | 673 | 49 | } | 674 | 43 | if (path.empty()) { | 675 | 0 | return Status::DataQualityError( | 676 | 0 | "missing field id {} when reading equality delete file {}", field_id, | 677 | 0 | delete_file.path); | 678 | 0 | } | 679 | 43 | const auto* root = path.front(); | 680 | 43 | const auto* leaf = path.back(); | 681 | 43 | if (!leaf->children.empty()) { | 682 | 0 | return Status::NotSupported( | 683 | 0 | "Iceberg equality delete does not support complex column {}", leaf->name); | 684 | 0 | } | 685 | 43 | const auto delete_key_type = make_nullable(leaf->data_type); | 686 | 43 | read_specs->push_back({ | 687 | 43 | .nested_field = | 688 | 43 | { | 689 | 43 | .field_id = field_id, | 690 | 43 | .block_name = leaf->name, | 691 | 43 | .leaf_type = equality_delete_key_type(_find_schema_field(field_id), | 692 | 43 | delete_key_type), | 693 | 43 | .source_leaf_type = delete_key_type, | 694 | 43 | .child_indexes = std::move(child_indexes), | 695 | 43 | .missing_value = nullptr, | 696 | 43 | }, | 697 | 43 | .leaf_name = leaf->name, | 698 | 43 | .root_name = root->name, | 699 | 43 | .root_type = make_nullable(root->data_type), | 700 | 43 | }); | 701 | 43 | } | 702 | 35 | return Status::OK(); | 703 | 35 | } |
Unexecuted instantiation: _ZNK5doris18IcebergReaderMixinINS_9OrcReaderEE41_build_parquet_equality_delete_read_specsEPNS_13ParquetReaderERKNS_22TIcebergDeleteFileDescEPSt6vectorINS2_22EqualityDeleteReadSpecESaIS9_EE |
704 | | |
705 | | template <typename BaseReader> |
706 | | Status IcebergReaderMixin<BaseReader>::_build_orc_equality_delete_read_specs( |
707 | | OrcReader* reader, const TIcebergDeleteFileDesc& delete_file, |
708 | 24 | std::vector<EqualityDeleteReadSpec>* read_specs) const { |
709 | 24 | DORIS_CHECK(reader != nullptr); |
710 | 24 | DORIS_CHECK(read_specs != nullptr); |
711 | 24 | const auto* delete_root = reader->get_file_root_type(); |
712 | 24 | DORIS_CHECK(delete_root != nullptr); |
713 | 28 | for (const auto field_id : delete_file.field_ids) { |
714 | 28 | std::vector<const orc::Type*> path; |
715 | 28 | std::vector<std::string> names; |
716 | 28 | std::vector<size_t> child_indexes; |
717 | 34 | for (size_t root_index = 0; root_index < delete_root->getSubtypeCount(); ++root_index) { |
718 | 34 | if (_find_orc_equality_delete_path(delete_root->getSubtype(root_index), |
719 | 34 | delete_root->getFieldName(root_index), field_id, |
720 | 34 | &path, &names, &child_indexes)) { |
721 | 28 | break; |
722 | 28 | } |
723 | 34 | } |
724 | 28 | if (path.empty()) { |
725 | 0 | return Status::DataQualityError( |
726 | 0 | "missing field id {} when reading equality delete file {}", field_id, |
727 | 0 | delete_file.path); |
728 | 0 | } |
729 | 28 | const auto* root = path.front(); |
730 | 28 | const auto* leaf = path.back(); |
731 | 28 | if (leaf->getSubtypeCount() > 0) { |
732 | 0 | return Status::NotSupported( |
733 | 0 | "Iceberg equality delete does not support complex column {}", names.back()); |
734 | 0 | } |
735 | 28 | const auto delete_key_type = make_nullable(reader->convert_to_doris_type(leaf)); |
736 | 28 | read_specs->push_back({ |
737 | 28 | .nested_field = |
738 | 28 | { |
739 | 28 | .field_id = field_id, |
740 | 28 | .block_name = names.back(), |
741 | 28 | .leaf_type = equality_delete_key_type(_find_schema_field(field_id), |
742 | 28 | delete_key_type), |
743 | 28 | .source_leaf_type = delete_key_type, |
744 | 28 | .child_indexes = std::move(child_indexes), |
745 | 28 | .missing_value = nullptr, |
746 | 28 | }, |
747 | 28 | .leaf_name = names.back(), |
748 | 28 | .root_name = names.front(), |
749 | 28 | .root_type = make_nullable(reader->convert_to_doris_type(root)), |
750 | 28 | }); |
751 | 28 | } |
752 | 24 | return Status::OK(); |
753 | 24 | } Unexecuted instantiation: _ZNK5doris18IcebergReaderMixinINS_13ParquetReaderEE37_build_orc_equality_delete_read_specsEPNS_9OrcReaderERKNS_22TIcebergDeleteFileDescEPSt6vectorINS2_22EqualityDeleteReadSpecESaIS9_EE _ZNK5doris18IcebergReaderMixinINS_9OrcReaderEE37_build_orc_equality_delete_read_specsEPS1_RKNS_22TIcebergDeleteFileDescEPSt6vectorINS2_22EqualityDeleteReadSpecESaIS8_EE Line | Count | Source | 708 | 24 | std::vector<EqualityDeleteReadSpec>* read_specs) const { | 709 | 24 | DORIS_CHECK(reader != nullptr); | 710 | 24 | DORIS_CHECK(read_specs != nullptr); | 711 | 24 | const auto* delete_root = reader->get_file_root_type(); | 712 | 24 | DORIS_CHECK(delete_root != nullptr); | 713 | 28 | for (const auto field_id : delete_file.field_ids) { | 714 | 28 | std::vector<const orc::Type*> path; | 715 | 28 | std::vector<std::string> names; | 716 | 28 | std::vector<size_t> child_indexes; | 717 | 34 | for (size_t root_index = 0; root_index < delete_root->getSubtypeCount(); ++root_index) { | 718 | 34 | if (_find_orc_equality_delete_path(delete_root->getSubtype(root_index), | 719 | 34 | delete_root->getFieldName(root_index), field_id, | 720 | 34 | &path, &names, &child_indexes)) { | 721 | 28 | break; | 722 | 28 | } | 723 | 34 | } | 724 | 28 | if (path.empty()) { | 725 | 0 | return Status::DataQualityError( | 726 | 0 | "missing field id {} when reading equality delete file {}", field_id, | 727 | 0 | delete_file.path); | 728 | 0 | } | 729 | 28 | const auto* root = path.front(); | 730 | 28 | const auto* leaf = path.back(); | 731 | 28 | if (leaf->getSubtypeCount() > 0) { | 732 | 0 | return Status::NotSupported( | 733 | 0 | "Iceberg equality delete does not support complex column {}", names.back()); | 734 | 0 | } | 735 | 28 | const auto delete_key_type = make_nullable(reader->convert_to_doris_type(leaf)); | 736 | 28 | read_specs->push_back({ | 737 | 28 | .nested_field = | 738 | 28 | { | 739 | 28 | .field_id = field_id, | 740 | 28 | .block_name = names.back(), | 741 | 28 | .leaf_type = equality_delete_key_type(_find_schema_field(field_id), | 742 | 28 | delete_key_type), | 743 | 28 | .source_leaf_type = delete_key_type, | 744 | 28 | .child_indexes = std::move(child_indexes), | 745 | 28 | .missing_value = nullptr, | 746 | 28 | }, | 747 | 28 | .leaf_name = names.back(), | 748 | 28 | .root_name = names.front(), | 749 | 28 | .root_type = make_nullable(reader->convert_to_doris_type(root)), | 750 | 28 | }); | 751 | 28 | } | 752 | 24 | return Status::OK(); | 753 | 24 | } |
|
754 | | |
755 | | template <typename BaseReader> |
756 | | Status IcebergReaderMixin<BaseReader>::_build_equality_delete_read_specs( |
757 | | GenericReader* reader, const TIcebergDeleteFileDesc& delete_file, |
758 | 59 | std::vector<EqualityDeleteReadSpec>* read_specs) const { |
759 | 59 | DORIS_CHECK(reader != nullptr); |
760 | 59 | DORIS_CHECK(read_specs != nullptr); |
761 | 59 | if (auto* parquet_reader = typeid_cast<ParquetReader*>(reader)) { |
762 | 35 | return _build_parquet_equality_delete_read_specs(parquet_reader, delete_file, read_specs); |
763 | 35 | } |
764 | 24 | if (auto* orc_reader = typeid_cast<OrcReader*>(reader)) { |
765 | 24 | return _build_orc_equality_delete_read_specs(orc_reader, delete_file, read_specs); |
766 | 24 | } |
767 | 0 | return Status::InternalError("Unsupported format of delete file"); |
768 | 24 | } _ZNK5doris18IcebergReaderMixinINS_13ParquetReaderEE33_build_equality_delete_read_specsEPNS_13GenericReaderERKNS_22TIcebergDeleteFileDescEPSt6vectorINS2_22EqualityDeleteReadSpecESaIS9_EE Line | Count | Source | 758 | 35 | std::vector<EqualityDeleteReadSpec>* read_specs) const { | 759 | 35 | DORIS_CHECK(reader != nullptr); | 760 | 35 | DORIS_CHECK(read_specs != nullptr); | 761 | 35 | if (auto* parquet_reader = typeid_cast<ParquetReader*>(reader)) { | 762 | 35 | return _build_parquet_equality_delete_read_specs(parquet_reader, delete_file, read_specs); | 763 | 35 | } | 764 | 0 | if (auto* orc_reader = typeid_cast<OrcReader*>(reader)) { | 765 | 0 | return _build_orc_equality_delete_read_specs(orc_reader, delete_file, read_specs); | 766 | 0 | } | 767 | 0 | return Status::InternalError("Unsupported format of delete file"); | 768 | 0 | } |
_ZNK5doris18IcebergReaderMixinINS_9OrcReaderEE33_build_equality_delete_read_specsEPNS_13GenericReaderERKNS_22TIcebergDeleteFileDescEPSt6vectorINS2_22EqualityDeleteReadSpecESaIS9_EE Line | Count | Source | 758 | 24 | std::vector<EqualityDeleteReadSpec>* read_specs) const { | 759 | 24 | DORIS_CHECK(reader != nullptr); | 760 | 24 | DORIS_CHECK(read_specs != nullptr); | 761 | 24 | if (auto* parquet_reader = typeid_cast<ParquetReader*>(reader)) { | 762 | 0 | return _build_parquet_equality_delete_read_specs(parquet_reader, delete_file, read_specs); | 763 | 0 | } | 764 | 24 | if (auto* orc_reader = typeid_cast<OrcReader*>(reader)) { | 765 | 24 | return _build_orc_equality_delete_read_specs(orc_reader, delete_file, read_specs); | 766 | 24 | } | 767 | 0 | return Status::InternalError("Unsupported format of delete file"); | 768 | 24 | } |
|
769 | | |
770 | | template <typename BaseReader> |
771 | | void IcebergReaderMixin<BaseReader>::_register_equality_delete_read_specs( |
772 | | const std::vector<EqualityDeleteReadSpec>& read_specs, |
773 | | std::vector<std::string>* delete_col_names, std::vector<DataTypePtr>* delete_col_types, |
774 | | std::vector<int>* delete_col_ids, std::vector<std::string>* read_root_names, |
775 | | std::vector<DataTypePtr>* read_root_types, |
776 | 59 | std::unordered_map<std::string, uint32_t>* read_root_positions) { |
777 | 59 | DORIS_CHECK(delete_col_names != nullptr); |
778 | 59 | DORIS_CHECK(delete_col_types != nullptr); |
779 | 59 | DORIS_CHECK(delete_col_ids != nullptr); |
780 | 59 | DORIS_CHECK(read_root_names != nullptr); |
781 | 59 | DORIS_CHECK(read_root_types != nullptr); |
782 | 59 | DORIS_CHECK(read_root_positions != nullptr); |
783 | 71 | for (const auto& spec : read_specs) { |
784 | 71 | delete_col_ids->push_back(spec.nested_field.field_id); |
785 | 71 | delete_col_names->push_back(spec.leaf_name); |
786 | 71 | delete_col_types->push_back(spec.nested_field.leaf_type); |
787 | 71 | if (!_id_to_block_column_name.contains(spec.nested_field.field_id)) { |
788 | 54 | _id_to_block_column_name.emplace(spec.nested_field.field_id, spec.leaf_name); |
789 | 54 | _expand_col_names.push_back(spec.leaf_name); |
790 | 54 | _expand_col_field_ids.push_back(spec.nested_field.field_id); |
791 | 54 | _expand_columns.emplace_back(spec.nested_field.leaf_type->create_column(), |
792 | 54 | spec.nested_field.leaf_type, spec.leaf_name); |
793 | 54 | } |
794 | 71 | if (!read_root_positions->contains(spec.root_name)) { |
795 | 67 | read_root_positions->emplace(spec.root_name, read_root_names->size()); |
796 | 67 | read_root_names->push_back(spec.root_name); |
797 | 67 | read_root_types->push_back(spec.root_type); |
798 | 67 | } |
799 | 71 | } |
800 | 59 | } _ZN5doris18IcebergReaderMixinINS_13ParquetReaderEE36_register_equality_delete_read_specsERKSt6vectorINS2_22EqualityDeleteReadSpecESaIS4_EEPS3_INSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaISE_EEPS3_ISt10shared_ptrIKNS_9IDataTypeEESaISL_EEPS3_IiSaIiEESH_SO_PSt13unordered_mapISE_jSt4hashISE_ESt8equal_toISE_ESaISt4pairIKSE_jEEE Line | Count | Source | 776 | 35 | std::unordered_map<std::string, uint32_t>* read_root_positions) { | 777 | 35 | DORIS_CHECK(delete_col_names != nullptr); | 778 | 35 | DORIS_CHECK(delete_col_types != nullptr); | 779 | 35 | DORIS_CHECK(delete_col_ids != nullptr); | 780 | 35 | DORIS_CHECK(read_root_names != nullptr); | 781 | 35 | DORIS_CHECK(read_root_types != nullptr); | 782 | 35 | DORIS_CHECK(read_root_positions != nullptr); | 783 | 43 | for (const auto& spec : read_specs) { | 784 | 43 | delete_col_ids->push_back(spec.nested_field.field_id); | 785 | 43 | delete_col_names->push_back(spec.leaf_name); | 786 | 43 | delete_col_types->push_back(spec.nested_field.leaf_type); | 787 | 43 | if (!_id_to_block_column_name.contains(spec.nested_field.field_id)) { | 788 | 34 | _id_to_block_column_name.emplace(spec.nested_field.field_id, spec.leaf_name); | 789 | 34 | _expand_col_names.push_back(spec.leaf_name); | 790 | 34 | _expand_col_field_ids.push_back(spec.nested_field.field_id); | 791 | 34 | _expand_columns.emplace_back(spec.nested_field.leaf_type->create_column(), | 792 | 34 | spec.nested_field.leaf_type, spec.leaf_name); | 793 | 34 | } | 794 | 43 | if (!read_root_positions->contains(spec.root_name)) { | 795 | 39 | read_root_positions->emplace(spec.root_name, read_root_names->size()); | 796 | 39 | read_root_names->push_back(spec.root_name); | 797 | 39 | read_root_types->push_back(spec.root_type); | 798 | 39 | } | 799 | 43 | } | 800 | 35 | } |
_ZN5doris18IcebergReaderMixinINS_9OrcReaderEE36_register_equality_delete_read_specsERKSt6vectorINS2_22EqualityDeleteReadSpecESaIS4_EEPS3_INSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaISE_EEPS3_ISt10shared_ptrIKNS_9IDataTypeEESaISL_EEPS3_IiSaIiEESH_SO_PSt13unordered_mapISE_jSt4hashISE_ESt8equal_toISE_ESaISt4pairIKSE_jEEE Line | Count | Source | 776 | 24 | std::unordered_map<std::string, uint32_t>* read_root_positions) { | 777 | 24 | DORIS_CHECK(delete_col_names != nullptr); | 778 | 24 | DORIS_CHECK(delete_col_types != nullptr); | 779 | 24 | DORIS_CHECK(delete_col_ids != nullptr); | 780 | 24 | DORIS_CHECK(read_root_names != nullptr); | 781 | 24 | DORIS_CHECK(read_root_types != nullptr); | 782 | 24 | DORIS_CHECK(read_root_positions != nullptr); | 783 | 28 | for (const auto& spec : read_specs) { | 784 | 28 | delete_col_ids->push_back(spec.nested_field.field_id); | 785 | 28 | delete_col_names->push_back(spec.leaf_name); | 786 | 28 | delete_col_types->push_back(spec.nested_field.leaf_type); | 787 | 28 | if (!_id_to_block_column_name.contains(spec.nested_field.field_id)) { | 788 | 20 | _id_to_block_column_name.emplace(spec.nested_field.field_id, spec.leaf_name); | 789 | 20 | _expand_col_names.push_back(spec.leaf_name); | 790 | 20 | _expand_col_field_ids.push_back(spec.nested_field.field_id); | 791 | 20 | _expand_columns.emplace_back(spec.nested_field.leaf_type->create_column(), | 792 | 20 | spec.nested_field.leaf_type, spec.leaf_name); | 793 | 20 | } | 794 | 28 | if (!read_root_positions->contains(spec.root_name)) { | 795 | 28 | read_root_positions->emplace(spec.root_name, read_root_names->size()); | 796 | 28 | read_root_names->push_back(spec.root_name); | 797 | 28 | read_root_types->push_back(spec.root_type); | 798 | 28 | } | 799 | 28 | } | 800 | 24 | } |
|
801 | | |
802 | | template <typename BaseReader> |
803 | | Status IcebergReaderMixin<BaseReader>::_initialize_equality_delete_reader( |
804 | | GenericReader* reader, const std::vector<std::string>& read_root_names, |
805 | 59 | std::unordered_map<std::string, uint32_t>* read_root_positions) { |
806 | 59 | DORIS_CHECK(reader != nullptr); |
807 | 59 | DORIS_CHECK(read_root_positions != nullptr); |
808 | 59 | if (auto* parquet_reader = typeid_cast<ParquetReader*>(reader)) { |
809 | | // Delete files have TFileRangeDesc.size=-1, which would cause |
810 | | // set_fill_columns to return EndOfFile("No row group to read") when filtering is enabled. |
811 | 35 | ParquetInitContext context; |
812 | 35 | context.filter_groups = false; |
813 | 35 | context.column_names = read_root_names; |
814 | 35 | context.col_name_to_block_idx = read_root_positions; |
815 | 35 | return parquet_reader->init_reader(&context); |
816 | 35 | } |
817 | 24 | auto* orc_reader = typeid_cast<OrcReader*>(reader); |
818 | 24 | DORIS_CHECK(orc_reader != nullptr); |
819 | 24 | OrcInitContext context; |
820 | 24 | context.column_names = read_root_names; |
821 | 24 | context.col_name_to_block_idx = read_root_positions; |
822 | 24 | return orc_reader->init_reader(&context); |
823 | 59 | } _ZN5doris18IcebergReaderMixinINS_13ParquetReaderEE34_initialize_equality_delete_readerEPNS_13GenericReaderERKSt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaISB_EEPSt13unordered_mapISB_jSt4hashISB_ESt8equal_toISB_ESaISt4pairIKSB_jEEE Line | Count | Source | 805 | 35 | std::unordered_map<std::string, uint32_t>* read_root_positions) { | 806 | 35 | DORIS_CHECK(reader != nullptr); | 807 | 35 | DORIS_CHECK(read_root_positions != nullptr); | 808 | 35 | if (auto* parquet_reader = typeid_cast<ParquetReader*>(reader)) { | 809 | | // Delete files have TFileRangeDesc.size=-1, which would cause | 810 | | // set_fill_columns to return EndOfFile("No row group to read") when filtering is enabled. | 811 | 35 | ParquetInitContext context; | 812 | 35 | context.filter_groups = false; | 813 | 35 | context.column_names = read_root_names; | 814 | 35 | context.col_name_to_block_idx = read_root_positions; | 815 | 35 | return parquet_reader->init_reader(&context); | 816 | 35 | } | 817 | 0 | auto* orc_reader = typeid_cast<OrcReader*>(reader); | 818 | 0 | DORIS_CHECK(orc_reader != nullptr); | 819 | 0 | OrcInitContext context; | 820 | 0 | context.column_names = read_root_names; | 821 | 0 | context.col_name_to_block_idx = read_root_positions; | 822 | 0 | return orc_reader->init_reader(&context); | 823 | 35 | } |
_ZN5doris18IcebergReaderMixinINS_9OrcReaderEE34_initialize_equality_delete_readerEPNS_13GenericReaderERKSt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaISB_EEPSt13unordered_mapISB_jSt4hashISB_ESt8equal_toISB_ESaISt4pairIKSB_jEEE Line | Count | Source | 805 | 24 | std::unordered_map<std::string, uint32_t>* read_root_positions) { | 806 | 24 | DORIS_CHECK(reader != nullptr); | 807 | 24 | DORIS_CHECK(read_root_positions != nullptr); | 808 | 24 | if (auto* parquet_reader = typeid_cast<ParquetReader*>(reader)) { | 809 | | // Delete files have TFileRangeDesc.size=-1, which would cause | 810 | | // set_fill_columns to return EndOfFile("No row group to read") when filtering is enabled. | 811 | 0 | ParquetInitContext context; | 812 | 0 | context.filter_groups = false; | 813 | 0 | context.column_names = read_root_names; | 814 | 0 | context.col_name_to_block_idx = read_root_positions; | 815 | 0 | return parquet_reader->init_reader(&context); | 816 | 0 | } | 817 | 24 | auto* orc_reader = typeid_cast<OrcReader*>(reader); | 818 | 24 | DORIS_CHECK(orc_reader != nullptr); | 819 | 24 | OrcInitContext context; | 820 | 24 | context.column_names = read_root_names; | 821 | 24 | context.col_name_to_block_idx = read_root_positions; | 822 | 24 | return orc_reader->init_reader(&context); | 823 | 24 | } |
|
824 | | |
825 | | template <typename BaseReader> |
826 | | Status IcebergReaderMixin<BaseReader>::_merge_equality_delete_rows( |
827 | | GenericReader* reader, const std::vector<EqualityDeleteReadSpec>& read_specs, |
828 | | const std::vector<std::string>& read_root_names, |
829 | | const std::vector<DataTypePtr>& read_root_types, |
830 | | const std::unordered_map<std::string, uint32_t>& read_root_positions, |
831 | 59 | Block* eq_file_block) const { |
832 | 59 | DORIS_CHECK(reader != nullptr); |
833 | 59 | DORIS_CHECK(eq_file_block != nullptr); |
834 | 59 | bool eof = false; |
835 | 142 | while (!eof) { |
836 | 83 | Block raw_block; |
837 | 178 | for (size_t index = 0; index < read_root_names.size(); ++index) { |
838 | 95 | raw_block.insert({read_root_types[index]->create_column(), read_root_types[index], |
839 | 95 | read_root_names[index]}); |
840 | 95 | } |
841 | 83 | size_t read_rows = 0; |
842 | 83 | RETURN_IF_ERROR(reader->get_next_block(&raw_block, &read_rows, &eof)); |
843 | 83 | if (read_rows == 0) { |
844 | 24 | continue; |
845 | 24 | } |
846 | 59 | Block key_block; |
847 | 71 | for (const auto& spec : read_specs) { |
848 | 71 | ColumnPtr key_column; |
849 | 71 | RETURN_IF_ERROR(_extract_nested_equality_delete_column( |
850 | 71 | raw_block.get_by_position(read_root_positions.at(spec.root_name)).column, |
851 | 71 | spec.nested_field, &key_column)); |
852 | 71 | key_block.insert({std::move(key_column), spec.nested_field.leaf_type, spec.leaf_name}); |
853 | 71 | } |
854 | 59 | ScopedMutableBlock scoped_mutable_block(eq_file_block); |
855 | 59 | RETURN_IF_ERROR(scoped_mutable_block.mutable_block().merge(key_block)); |
856 | 59 | } |
857 | 59 | return Status::OK(); |
858 | 59 | } _ZNK5doris18IcebergReaderMixinINS_13ParquetReaderEE27_merge_equality_delete_rowsEPNS_13GenericReaderERKSt6vectorINS2_22EqualityDeleteReadSpecESaIS6_EERKS5_INSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaISG_EERKS5_ISt10shared_ptrIKNS_9IDataTypeEESaISO_EERKSt13unordered_mapISG_jSt4hashISG_ESt8equal_toISG_ESaISt4pairIKSG_jEEEPNS_5BlockE Line | Count | Source | 831 | 35 | Block* eq_file_block) const { | 832 | 35 | DORIS_CHECK(reader != nullptr); | 833 | 35 | DORIS_CHECK(eq_file_block != nullptr); | 834 | 35 | bool eof = false; | 835 | 70 | while (!eof) { | 836 | 35 | Block raw_block; | 837 | 74 | for (size_t index = 0; index < read_root_names.size(); ++index) { | 838 | 39 | raw_block.insert({read_root_types[index]->create_column(), read_root_types[index], | 839 | 39 | read_root_names[index]}); | 840 | 39 | } | 841 | 35 | size_t read_rows = 0; | 842 | 35 | RETURN_IF_ERROR(reader->get_next_block(&raw_block, &read_rows, &eof)); | 843 | 35 | if (read_rows == 0) { | 844 | 0 | continue; | 845 | 0 | } | 846 | 35 | Block key_block; | 847 | 43 | for (const auto& spec : read_specs) { | 848 | 43 | ColumnPtr key_column; | 849 | 43 | RETURN_IF_ERROR(_extract_nested_equality_delete_column( | 850 | 43 | raw_block.get_by_position(read_root_positions.at(spec.root_name)).column, | 851 | 43 | spec.nested_field, &key_column)); | 852 | 43 | key_block.insert({std::move(key_column), spec.nested_field.leaf_type, spec.leaf_name}); | 853 | 43 | } | 854 | 35 | ScopedMutableBlock scoped_mutable_block(eq_file_block); | 855 | 35 | RETURN_IF_ERROR(scoped_mutable_block.mutable_block().merge(key_block)); | 856 | 35 | } | 857 | 35 | return Status::OK(); | 858 | 35 | } |
_ZNK5doris18IcebergReaderMixinINS_9OrcReaderEE27_merge_equality_delete_rowsEPNS_13GenericReaderERKSt6vectorINS2_22EqualityDeleteReadSpecESaIS6_EERKS5_INSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaISG_EERKS5_ISt10shared_ptrIKNS_9IDataTypeEESaISO_EERKSt13unordered_mapISG_jSt4hashISG_ESt8equal_toISG_ESaISt4pairIKSG_jEEEPNS_5BlockE Line | Count | Source | 831 | 24 | Block* eq_file_block) const { | 832 | 24 | DORIS_CHECK(reader != nullptr); | 833 | 24 | DORIS_CHECK(eq_file_block != nullptr); | 834 | 24 | bool eof = false; | 835 | 72 | while (!eof) { | 836 | 48 | Block raw_block; | 837 | 104 | for (size_t index = 0; index < read_root_names.size(); ++index) { | 838 | 56 | raw_block.insert({read_root_types[index]->create_column(), read_root_types[index], | 839 | 56 | read_root_names[index]}); | 840 | 56 | } | 841 | 48 | size_t read_rows = 0; | 842 | 48 | RETURN_IF_ERROR(reader->get_next_block(&raw_block, &read_rows, &eof)); | 843 | 48 | if (read_rows == 0) { | 844 | 24 | continue; | 845 | 24 | } | 846 | 24 | Block key_block; | 847 | 28 | for (const auto& spec : read_specs) { | 848 | 28 | ColumnPtr key_column; | 849 | 28 | RETURN_IF_ERROR(_extract_nested_equality_delete_column( | 850 | 28 | raw_block.get_by_position(read_root_positions.at(spec.root_name)).column, | 851 | 28 | spec.nested_field, &key_column)); | 852 | 28 | key_block.insert({std::move(key_column), spec.nested_field.leaf_type, spec.leaf_name}); | 853 | 28 | } | 854 | 24 | ScopedMutableBlock scoped_mutable_block(eq_file_block); | 855 | 24 | RETURN_IF_ERROR(scoped_mutable_block.mutable_block().merge(key_block)); | 856 | 24 | } | 857 | 24 | return Status::OK(); | 858 | 24 | } |
|
859 | | |
860 | | template <typename BaseReader> |
861 | | Status IcebergReaderMixin<BaseReader>::_read_equality_delete_file( |
862 | 60 | const TIcebergDeleteFileDesc& delete_file) { |
863 | 60 | if (!delete_file.__isset.field_ids) [[unlikely]] { |
864 | 0 | return Status::InternalError("missing delete field ids when reading equality delete file"); |
865 | 0 | } |
866 | 60 | TFileRangeDesc delete_desc; |
867 | 60 | delete_desc.__set_fs_name(this->get_scan_range().fs_name); |
868 | 60 | delete_desc.path = delete_file.path; |
869 | 60 | delete_desc.start_offset = 0; |
870 | 60 | delete_desc.size = -1; |
871 | 60 | delete_desc.file_size = delete_file.__isset.file_size ? delete_file.file_size : -1; |
872 | | |
873 | 60 | std::unique_ptr<GenericReader> reader = _create_equality_reader(delete_desc); |
874 | 60 | RETURN_IF_ERROR(reader->init_schema_reader()); |
875 | 59 | std::vector<EqualityDeleteReadSpec> read_specs; |
876 | 59 | RETURN_IF_ERROR(_build_equality_delete_read_specs(reader.get(), delete_file, &read_specs)); |
877 | | |
878 | 59 | std::vector<std::string> delete_col_names; |
879 | 59 | std::vector<DataTypePtr> delete_col_types; |
880 | 59 | std::vector<int> delete_col_ids; |
881 | 59 | std::vector<std::string> read_root_names; |
882 | 59 | std::vector<DataTypePtr> read_root_types; |
883 | 59 | std::unordered_map<std::string, uint32_t> read_root_positions; |
884 | 59 | _register_equality_delete_read_specs(read_specs, &delete_col_names, &delete_col_types, |
885 | 59 | &delete_col_ids, &read_root_names, &read_root_types, |
886 | 59 | &read_root_positions); |
887 | 59 | RETURN_IF_ERROR(_initialize_equality_delete_reader(reader.get(), read_root_names, |
888 | 59 | &read_root_positions)); |
889 | | |
890 | 59 | if (!_equality_delete_block_map.contains(delete_col_ids)) { |
891 | 55 | _equality_delete_block_map.emplace(delete_col_ids, _equality_delete_blocks.size()); |
892 | 55 | Block block; |
893 | 55 | _generate_equality_delete_block(&block, delete_col_names, delete_col_types); |
894 | 55 | _equality_delete_blocks.emplace_back(std::move(block)); |
895 | 55 | } |
896 | 59 | Block& eq_file_block = _equality_delete_blocks[_equality_delete_block_map[delete_col_ids]]; |
897 | 59 | return _merge_equality_delete_rows(reader.get(), read_specs, read_root_names, read_root_types, |
898 | 59 | read_root_positions, &eq_file_block); |
899 | 59 | } _ZN5doris18IcebergReaderMixinINS_13ParquetReaderEE26_read_equality_delete_fileERKNS_22TIcebergDeleteFileDescE Line | Count | Source | 862 | 36 | const TIcebergDeleteFileDesc& delete_file) { | 863 | 36 | if (!delete_file.__isset.field_ids) [[unlikely]] { | 864 | 0 | return Status::InternalError("missing delete field ids when reading equality delete file"); | 865 | 0 | } | 866 | 36 | TFileRangeDesc delete_desc; | 867 | 36 | delete_desc.__set_fs_name(this->get_scan_range().fs_name); | 868 | 36 | delete_desc.path = delete_file.path; | 869 | 36 | delete_desc.start_offset = 0; | 870 | 36 | delete_desc.size = -1; | 871 | 36 | delete_desc.file_size = delete_file.__isset.file_size ? delete_file.file_size : -1; | 872 | | | 873 | 36 | std::unique_ptr<GenericReader> reader = _create_equality_reader(delete_desc); | 874 | 36 | RETURN_IF_ERROR(reader->init_schema_reader()); | 875 | 35 | std::vector<EqualityDeleteReadSpec> read_specs; | 876 | 35 | RETURN_IF_ERROR(_build_equality_delete_read_specs(reader.get(), delete_file, &read_specs)); | 877 | | | 878 | 35 | std::vector<std::string> delete_col_names; | 879 | 35 | std::vector<DataTypePtr> delete_col_types; | 880 | 35 | std::vector<int> delete_col_ids; | 881 | 35 | std::vector<std::string> read_root_names; | 882 | 35 | std::vector<DataTypePtr> read_root_types; | 883 | 35 | std::unordered_map<std::string, uint32_t> read_root_positions; | 884 | 35 | _register_equality_delete_read_specs(read_specs, &delete_col_names, &delete_col_types, | 885 | 35 | &delete_col_ids, &read_root_names, &read_root_types, | 886 | 35 | &read_root_positions); | 887 | 35 | RETURN_IF_ERROR(_initialize_equality_delete_reader(reader.get(), read_root_names, | 888 | 35 | &read_root_positions)); | 889 | | | 890 | 35 | if (!_equality_delete_block_map.contains(delete_col_ids)) { | 891 | 33 | _equality_delete_block_map.emplace(delete_col_ids, _equality_delete_blocks.size()); | 892 | 33 | Block block; | 893 | 33 | _generate_equality_delete_block(&block, delete_col_names, delete_col_types); | 894 | 33 | _equality_delete_blocks.emplace_back(std::move(block)); | 895 | 33 | } | 896 | 35 | Block& eq_file_block = _equality_delete_blocks[_equality_delete_block_map[delete_col_ids]]; | 897 | 35 | return _merge_equality_delete_rows(reader.get(), read_specs, read_root_names, read_root_types, | 898 | 35 | read_root_positions, &eq_file_block); | 899 | 35 | } |
_ZN5doris18IcebergReaderMixinINS_9OrcReaderEE26_read_equality_delete_fileERKNS_22TIcebergDeleteFileDescE Line | Count | Source | 862 | 24 | const TIcebergDeleteFileDesc& delete_file) { | 863 | 24 | if (!delete_file.__isset.field_ids) [[unlikely]] { | 864 | 0 | return Status::InternalError("missing delete field ids when reading equality delete file"); | 865 | 0 | } | 866 | 24 | TFileRangeDesc delete_desc; | 867 | 24 | delete_desc.__set_fs_name(this->get_scan_range().fs_name); | 868 | 24 | delete_desc.path = delete_file.path; | 869 | 24 | delete_desc.start_offset = 0; | 870 | 24 | delete_desc.size = -1; | 871 | 24 | delete_desc.file_size = delete_file.__isset.file_size ? delete_file.file_size : -1; | 872 | | | 873 | 24 | std::unique_ptr<GenericReader> reader = _create_equality_reader(delete_desc); | 874 | 24 | RETURN_IF_ERROR(reader->init_schema_reader()); | 875 | 24 | std::vector<EqualityDeleteReadSpec> read_specs; | 876 | 24 | RETURN_IF_ERROR(_build_equality_delete_read_specs(reader.get(), delete_file, &read_specs)); | 877 | | | 878 | 24 | std::vector<std::string> delete_col_names; | 879 | 24 | std::vector<DataTypePtr> delete_col_types; | 880 | 24 | std::vector<int> delete_col_ids; | 881 | 24 | std::vector<std::string> read_root_names; | 882 | 24 | std::vector<DataTypePtr> read_root_types; | 883 | 24 | std::unordered_map<std::string, uint32_t> read_root_positions; | 884 | 24 | _register_equality_delete_read_specs(read_specs, &delete_col_names, &delete_col_types, | 885 | 24 | &delete_col_ids, &read_root_names, &read_root_types, | 886 | 24 | &read_root_positions); | 887 | 24 | RETURN_IF_ERROR(_initialize_equality_delete_reader(reader.get(), read_root_names, | 888 | 24 | &read_root_positions)); | 889 | | | 890 | 24 | if (!_equality_delete_block_map.contains(delete_col_ids)) { | 891 | 22 | _equality_delete_block_map.emplace(delete_col_ids, _equality_delete_blocks.size()); | 892 | 22 | Block block; | 893 | 22 | _generate_equality_delete_block(&block, delete_col_names, delete_col_types); | 894 | 22 | _equality_delete_blocks.emplace_back(std::move(block)); | 895 | 22 | } | 896 | 24 | Block& eq_file_block = _equality_delete_blocks[_equality_delete_block_map[delete_col_ids]]; | 897 | 24 | return _merge_equality_delete_rows(reader.get(), read_specs, read_root_names, read_root_types, | 898 | 24 | read_root_positions, &eq_file_block); | 899 | 24 | } |
|
900 | | |
901 | | template <typename BaseReader> |
902 | | Status IcebergReaderMixin<BaseReader>::_equality_delete_base( |
903 | 53 | const std::vector<TIcebergDeleteFileDesc>& delete_files) { |
904 | 59 | for (const auto& delete_file : delete_files) { |
905 | 59 | RETURN_IF_ERROR(_read_equality_delete_file(delete_file)); |
906 | 71 | for (const auto field_id : delete_file.field_ids) { |
907 | 71 | _equality_delete_col_ids.insert(field_id); |
908 | 71 | } |
909 | 59 | } |
910 | 55 | for (const auto& [delete_col_ids, block_idx] : _equality_delete_block_map) { |
911 | 55 | auto& eq_file_block = _equality_delete_blocks[block_idx]; |
912 | 55 | auto equality_delete_impl = |
913 | 55 | EqualityDeleteBase::get_delete_impl(&eq_file_block, delete_col_ids); |
914 | 55 | RETURN_IF_ERROR(equality_delete_impl->init(this->get_profile())); |
915 | 55 | _equality_delete_impls.emplace_back(std::move(equality_delete_impl)); |
916 | 55 | } |
917 | 53 | return Status::OK(); |
918 | 53 | } _ZN5doris18IcebergReaderMixinINS_13ParquetReaderEE21_equality_delete_baseERKSt6vectorINS_22TIcebergDeleteFileDescESaIS4_EE Line | Count | Source | 903 | 32 | const std::vector<TIcebergDeleteFileDesc>& delete_files) { | 904 | 35 | for (const auto& delete_file : delete_files) { | 905 | 35 | RETURN_IF_ERROR(_read_equality_delete_file(delete_file)); | 906 | 43 | for (const auto field_id : delete_file.field_ids) { | 907 | 43 | _equality_delete_col_ids.insert(field_id); | 908 | 43 | } | 909 | 35 | } | 910 | 33 | for (const auto& [delete_col_ids, block_idx] : _equality_delete_block_map) { | 911 | 33 | auto& eq_file_block = _equality_delete_blocks[block_idx]; | 912 | 33 | auto equality_delete_impl = | 913 | 33 | EqualityDeleteBase::get_delete_impl(&eq_file_block, delete_col_ids); | 914 | 33 | RETURN_IF_ERROR(equality_delete_impl->init(this->get_profile())); | 915 | 33 | _equality_delete_impls.emplace_back(std::move(equality_delete_impl)); | 916 | 33 | } | 917 | 32 | return Status::OK(); | 918 | 32 | } |
_ZN5doris18IcebergReaderMixinINS_9OrcReaderEE21_equality_delete_baseERKSt6vectorINS_22TIcebergDeleteFileDescESaIS4_EE Line | Count | Source | 903 | 21 | const std::vector<TIcebergDeleteFileDesc>& delete_files) { | 904 | 24 | for (const auto& delete_file : delete_files) { | 905 | 24 | RETURN_IF_ERROR(_read_equality_delete_file(delete_file)); | 906 | 28 | for (const auto field_id : delete_file.field_ids) { | 907 | 28 | _equality_delete_col_ids.insert(field_id); | 908 | 28 | } | 909 | 24 | } | 910 | 22 | for (const auto& [delete_col_ids, block_idx] : _equality_delete_block_map) { | 911 | 22 | auto& eq_file_block = _equality_delete_blocks[block_idx]; | 912 | 22 | auto equality_delete_impl = | 913 | 22 | EqualityDeleteBase::get_delete_impl(&eq_file_block, delete_col_ids); | 914 | 22 | RETURN_IF_ERROR(equality_delete_impl->init(this->get_profile())); | 915 | 22 | _equality_delete_impls.emplace_back(std::move(equality_delete_impl)); | 916 | 22 | } | 917 | 21 | return Status::OK(); | 918 | 21 | } |
|
919 | | |
920 | | template <typename BaseReader> |
921 | | void IcebergReaderMixin<BaseReader>::_generate_equality_delete_block( |
922 | | Block* block, const std::vector<std::string>& equality_delete_col_names, |
923 | 55 | const std::vector<DataTypePtr>& equality_delete_col_types) { |
924 | 122 | for (int i = 0; i < equality_delete_col_names.size(); ++i) { |
925 | 67 | DataTypePtr data_type = make_nullable(equality_delete_col_types[i]); |
926 | 67 | MutableColumnPtr data_column = data_type->create_column(); |
927 | 67 | block->insert(ColumnWithTypeAndName(std::move(data_column), data_type, |
928 | 67 | equality_delete_col_names[i])); |
929 | 67 | } |
930 | 55 | } _ZN5doris18IcebergReaderMixinINS_13ParquetReaderEE31_generate_equality_delete_blockEPNS_5BlockERKSt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaISB_EERKS5_ISt10shared_ptrIKNS_9IDataTypeEESaISJ_EE Line | Count | Source | 923 | 33 | const std::vector<DataTypePtr>& equality_delete_col_types) { | 924 | 74 | for (int i = 0; i < equality_delete_col_names.size(); ++i) { | 925 | 41 | DataTypePtr data_type = make_nullable(equality_delete_col_types[i]); | 926 | 41 | MutableColumnPtr data_column = data_type->create_column(); | 927 | 41 | block->insert(ColumnWithTypeAndName(std::move(data_column), data_type, | 928 | 41 | equality_delete_col_names[i])); | 929 | 41 | } | 930 | 33 | } |
_ZN5doris18IcebergReaderMixinINS_9OrcReaderEE31_generate_equality_delete_blockEPNS_5BlockERKSt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaISB_EERKS5_ISt10shared_ptrIKNS_9IDataTypeEESaISJ_EE Line | Count | Source | 923 | 22 | const std::vector<DataTypePtr>& equality_delete_col_types) { | 924 | 48 | for (int i = 0; i < equality_delete_col_names.size(); ++i) { | 925 | 26 | DataTypePtr data_type = make_nullable(equality_delete_col_types[i]); | 926 | 26 | MutableColumnPtr data_column = data_type->create_column(); | 927 | 26 | block->insert(ColumnWithTypeAndName(std::move(data_column), data_type, | 928 | 26 | equality_delete_col_names[i])); | 929 | 26 | } | 930 | 22 | } |
|
931 | | |
932 | | template <typename BaseReader> |
933 | 61 | Status IcebergReaderMixin<BaseReader>::_expand_block_if_need(Block* block) { |
934 | 61 | std::set<std::string> names; |
935 | 61 | auto block_names = block->get_names(); |
936 | 61 | names.insert(block_names.begin(), block_names.end()); |
937 | 61 | for (auto& col : _expand_columns) { |
938 | 54 | if (_missing_equality_delete_values.contains(col.name) || |
939 | 54 | _is_derived_equality_delete_column(col.name)) { |
940 | | // The reader has no column for a key that is missing from the file or extracted from |
941 | | // another column; on_after_read_block appends it at the batch's final row count. |
942 | 24 | continue; |
943 | 24 | } |
944 | 30 | if (names.contains(col.name)) { |
945 | 0 | return Status::InternalError("Wrong expand column '{}'", col.name); |
946 | 0 | } |
947 | 30 | names.insert(col.name); |
948 | 30 | (*this->col_name_to_block_idx_ref())[col.name] = block->columns(); |
949 | 30 | block->insert({col.type->create_column(), col.type, col.name}); |
950 | 30 | } |
951 | 61 | return Status::OK(); |
952 | 61 | } _ZN5doris18IcebergReaderMixinINS_13ParquetReaderEE21_expand_block_if_needEPNS_5BlockE Line | Count | Source | 933 | 37 | Status IcebergReaderMixin<BaseReader>::_expand_block_if_need(Block* block) { | 934 | 37 | std::set<std::string> names; | 935 | 37 | auto block_names = block->get_names(); | 936 | 37 | names.insert(block_names.begin(), block_names.end()); | 937 | 37 | for (auto& col : _expand_columns) { | 938 | 34 | if (_missing_equality_delete_values.contains(col.name) || | 939 | 34 | _is_derived_equality_delete_column(col.name)) { | 940 | | // The reader has no column for a key that is missing from the file or extracted from | 941 | | // another column; on_after_read_block appends it at the batch's final row count. | 942 | 17 | continue; | 943 | 17 | } | 944 | 17 | if (names.contains(col.name)) { | 945 | 0 | return Status::InternalError("Wrong expand column '{}'", col.name); | 946 | 0 | } | 947 | 17 | names.insert(col.name); | 948 | 17 | (*this->col_name_to_block_idx_ref())[col.name] = block->columns(); | 949 | 17 | block->insert({col.type->create_column(), col.type, col.name}); | 950 | 17 | } | 951 | 37 | return Status::OK(); | 952 | 37 | } |
_ZN5doris18IcebergReaderMixinINS_9OrcReaderEE21_expand_block_if_needEPNS_5BlockE Line | Count | Source | 933 | 24 | Status IcebergReaderMixin<BaseReader>::_expand_block_if_need(Block* block) { | 934 | 24 | std::set<std::string> names; | 935 | 24 | auto block_names = block->get_names(); | 936 | 24 | names.insert(block_names.begin(), block_names.end()); | 937 | 24 | for (auto& col : _expand_columns) { | 938 | 20 | if (_missing_equality_delete_values.contains(col.name) || | 939 | 20 | _is_derived_equality_delete_column(col.name)) { | 940 | | // The reader has no column for a key that is missing from the file or extracted from | 941 | | // another column; on_after_read_block appends it at the batch's final row count. | 942 | 7 | continue; | 943 | 7 | } | 944 | 13 | if (names.contains(col.name)) { | 945 | 0 | return Status::InternalError("Wrong expand column '{}'", col.name); | 946 | 0 | } | 947 | 13 | names.insert(col.name); | 948 | 13 | (*this->col_name_to_block_idx_ref())[col.name] = block->columns(); | 949 | 13 | block->insert({col.type->create_column(), col.type, col.name}); | 950 | 13 | } | 951 | 24 | return Status::OK(); | 952 | 24 | } |
|
953 | | |
954 | | template <typename BaseReader> |
955 | 156 | const schema::external::TStructField* IcebergReaderMixin<BaseReader>::_current_schema_root() const { |
956 | 156 | const auto& scan_params = this->get_scan_params(); |
957 | 156 | if (!scan_params.__isset.history_schema_info || scan_params.history_schema_info.empty()) { |
958 | 0 | return nullptr; |
959 | 0 | } |
960 | 156 | const schema::external::TSchema* current_schema = &scan_params.history_schema_info.front(); |
961 | 156 | if (scan_params.__isset.current_schema_id) { |
962 | 156 | const auto schema_it = std::ranges::find_if( |
963 | 156 | scan_params.history_schema_info, [&](const schema::external::TSchema& schema) { |
964 | 156 | return schema.__isset.schema_id && |
965 | 156 | schema.schema_id == scan_params.current_schema_id; |
966 | 156 | }); _ZZNK5doris18IcebergReaderMixinINS_13ParquetReaderEE20_current_schema_rootEvENKUlRKNS_6schema8external7TSchemaEE_clES7_ Line | Count | Source | 963 | 107 | scan_params.history_schema_info, [&](const schema::external::TSchema& schema) { | 964 | 107 | return schema.__isset.schema_id && | 965 | 107 | schema.schema_id == scan_params.current_schema_id; | 966 | 107 | }); |
_ZZNK5doris18IcebergReaderMixinINS_9OrcReaderEE20_current_schema_rootEvENKUlRKNS_6schema8external7TSchemaEE_clES7_ Line | Count | Source | 963 | 49 | scan_params.history_schema_info, [&](const schema::external::TSchema& schema) { | 964 | 49 | return schema.__isset.schema_id && | 965 | 49 | schema.schema_id == scan_params.current_schema_id; | 966 | 49 | }); |
|
967 | 156 | if (schema_it == scan_params.history_schema_info.end()) { |
968 | 0 | return nullptr; |
969 | 0 | } |
970 | 156 | current_schema = &*schema_it; |
971 | 156 | } |
972 | 156 | return current_schema->__isset.root_field ? ¤t_schema->root_field : nullptr; |
973 | 156 | } _ZNK5doris18IcebergReaderMixinINS_13ParquetReaderEE20_current_schema_rootEv Line | Count | Source | 955 | 107 | const schema::external::TStructField* IcebergReaderMixin<BaseReader>::_current_schema_root() const { | 956 | 107 | const auto& scan_params = this->get_scan_params(); | 957 | 107 | if (!scan_params.__isset.history_schema_info || scan_params.history_schema_info.empty()) { | 958 | 0 | return nullptr; | 959 | 0 | } | 960 | 107 | const schema::external::TSchema* current_schema = &scan_params.history_schema_info.front(); | 961 | 107 | if (scan_params.__isset.current_schema_id) { | 962 | 107 | const auto schema_it = std::ranges::find_if( | 963 | 107 | scan_params.history_schema_info, [&](const schema::external::TSchema& schema) { | 964 | 107 | return schema.__isset.schema_id && | 965 | 107 | schema.schema_id == scan_params.current_schema_id; | 966 | 107 | }); | 967 | 107 | if (schema_it == scan_params.history_schema_info.end()) { | 968 | 0 | return nullptr; | 969 | 0 | } | 970 | 107 | current_schema = &*schema_it; | 971 | 107 | } | 972 | 107 | return current_schema->__isset.root_field ? ¤t_schema->root_field : nullptr; | 973 | 107 | } |
_ZNK5doris18IcebergReaderMixinINS_9OrcReaderEE20_current_schema_rootEv Line | Count | Source | 955 | 49 | const schema::external::TStructField* IcebergReaderMixin<BaseReader>::_current_schema_root() const { | 956 | 49 | const auto& scan_params = this->get_scan_params(); | 957 | 49 | if (!scan_params.__isset.history_schema_info || scan_params.history_schema_info.empty()) { | 958 | 0 | return nullptr; | 959 | 0 | } | 960 | 49 | const schema::external::TSchema* current_schema = &scan_params.history_schema_info.front(); | 961 | 49 | if (scan_params.__isset.current_schema_id) { | 962 | 49 | const auto schema_it = std::ranges::find_if( | 963 | 49 | scan_params.history_schema_info, [&](const schema::external::TSchema& schema) { | 964 | 49 | return schema.__isset.schema_id && | 965 | 49 | schema.schema_id == scan_params.current_schema_id; | 966 | 49 | }); | 967 | 49 | if (schema_it == scan_params.history_schema_info.end()) { | 968 | 0 | return nullptr; | 969 | 0 | } | 970 | 49 | current_schema = &*schema_it; | 971 | 49 | } | 972 | 49 | return current_schema->__isset.root_field ? ¤t_schema->root_field : nullptr; | 973 | 49 | } |
|
974 | | |
975 | | template <typename BaseReader> |
976 | | const schema::external::TField* IcebergReaderMixin<BaseReader>::_find_current_schema_field( |
977 | 5 | const std::string& name) const { |
978 | 5 | const auto* root = _current_schema_root(); |
979 | 5 | if (root == nullptr) { |
980 | 0 | return nullptr; |
981 | 0 | } |
982 | 10 | const auto field = std::ranges::find_if(root->fields, [&](const auto& field_ptr) { |
983 | 10 | return field_ptr.__isset.field_ptr && field_ptr.field_ptr != nullptr && |
984 | 10 | field_ptr.field_ptr->__isset.name && iequal(field_ptr.field_ptr->name, name); |
985 | 10 | }); _ZZNK5doris18IcebergReaderMixinINS_13ParquetReaderEE26_find_current_schema_fieldERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEENKUlRKT_E_clINS_6schema8external9TFieldPtrEEEDaSD_ Line | Count | Source | 982 | 8 | const auto field = std::ranges::find_if(root->fields, [&](const auto& field_ptr) { | 983 | 8 | return field_ptr.__isset.field_ptr && field_ptr.field_ptr != nullptr && | 984 | 8 | field_ptr.field_ptr->__isset.name && iequal(field_ptr.field_ptr->name, name); | 985 | 8 | }); |
_ZZNK5doris18IcebergReaderMixinINS_9OrcReaderEE26_find_current_schema_fieldERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEENKUlRKT_E_clINS_6schema8external9TFieldPtrEEEDaSD_ Line | Count | Source | 982 | 2 | const auto field = std::ranges::find_if(root->fields, [&](const auto& field_ptr) { | 983 | 2 | return field_ptr.__isset.field_ptr && field_ptr.field_ptr != nullptr && | 984 | 2 | field_ptr.field_ptr->__isset.name && iequal(field_ptr.field_ptr->name, name); | 985 | 2 | }); |
|
986 | 5 | return field == root->fields.end() ? nullptr : field->field_ptr.get(); |
987 | 5 | } _ZNK5doris18IcebergReaderMixinINS_13ParquetReaderEE26_find_current_schema_fieldERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE Line | Count | Source | 977 | 4 | const std::string& name) const { | 978 | 4 | const auto* root = _current_schema_root(); | 979 | 4 | if (root == nullptr) { | 980 | 0 | return nullptr; | 981 | 0 | } | 982 | 4 | const auto field = std::ranges::find_if(root->fields, [&](const auto& field_ptr) { | 983 | 4 | return field_ptr.__isset.field_ptr && field_ptr.field_ptr != nullptr && | 984 | 4 | field_ptr.field_ptr->__isset.name && iequal(field_ptr.field_ptr->name, name); | 985 | 4 | }); | 986 | 4 | return field == root->fields.end() ? nullptr : field->field_ptr.get(); | 987 | 4 | } |
_ZNK5doris18IcebergReaderMixinINS_9OrcReaderEE26_find_current_schema_fieldERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE Line | Count | Source | 977 | 1 | const std::string& name) const { | 978 | 1 | const auto* root = _current_schema_root(); | 979 | 1 | if (root == nullptr) { | 980 | 0 | return nullptr; | 981 | 0 | } | 982 | 1 | const auto field = std::ranges::find_if(root->fields, [&](const auto& field_ptr) { | 983 | 1 | return field_ptr.__isset.field_ptr && field_ptr.field_ptr != nullptr && | 984 | 1 | field_ptr.field_ptr->__isset.name && iequal(field_ptr.field_ptr->name, name); | 985 | 1 | }); | 986 | 1 | return field == root->fields.end() ? nullptr : field->field_ptr.get(); | 987 | 1 | } |
|
988 | | |
989 | | template <typename BaseReader> |
990 | | const schema::external::TField* IcebergReaderMixin<BaseReader>::_find_schema_field( |
991 | 71 | int32_t field_id) const { |
992 | 71 | auto path = _find_schema_field_path(field_id); |
993 | 71 | return path.empty() ? nullptr : path.back(); |
994 | 71 | } _ZNK5doris18IcebergReaderMixinINS_13ParquetReaderEE18_find_schema_fieldEi Line | Count | Source | 991 | 43 | int32_t field_id) const { | 992 | 43 | auto path = _find_schema_field_path(field_id); | 993 | 43 | return path.empty() ? nullptr : path.back(); | 994 | 43 | } |
_ZNK5doris18IcebergReaderMixinINS_9OrcReaderEE18_find_schema_fieldEi Line | Count | Source | 991 | 28 | int32_t field_id) const { | 992 | 28 | auto path = _find_schema_field_path(field_id); | 993 | 28 | return path.empty() ? nullptr : path.back(); | 994 | 28 | } |
|
995 | | |
996 | | template <typename BaseReader> |
997 | | bool IcebergReaderMixin<BaseReader>::_find_schema_field_path_in_field( |
998 | | const schema::external::TField* field, int32_t field_id, |
999 | 466 | std::vector<const schema::external::TField*>* path) { |
1000 | 466 | DORIS_CHECK(path != nullptr); |
1001 | 466 | if (field == nullptr) { |
1002 | 0 | return false; |
1003 | 0 | } |
1004 | 466 | path->push_back(field); |
1005 | 466 | if (field->__isset.id && field->id == field_id) { |
1006 | 150 | return true; |
1007 | 150 | } |
1008 | 316 | if (field->__isset.nestedField) { |
1009 | 89 | if (field->nestedField.__isset.struct_field && |
1010 | 89 | field->nestedField.struct_field.__isset.fields) { |
1011 | 89 | for (const auto& child_ptr : field->nestedField.struct_field.fields) { |
1012 | 89 | if (child_ptr.__isset.field_ptr && child_ptr.field_ptr != nullptr && |
1013 | 89 | _find_schema_field_path_in_field(child_ptr.field_ptr.get(), field_id, path)) { |
1014 | 69 | return true; |
1015 | 69 | } |
1016 | 89 | } |
1017 | 89 | } else if (field->nestedField.__isset.array_field && |
1018 | 0 | field->nestedField.array_field.__isset.item_field) { |
1019 | 0 | const auto& child_ptr = field->nestedField.array_field.item_field; |
1020 | 0 | if (child_ptr.__isset.field_ptr && child_ptr.field_ptr != nullptr && |
1021 | 0 | _find_schema_field_path_in_field(child_ptr.field_ptr.get(), field_id, path)) { |
1022 | 0 | return true; |
1023 | 0 | } |
1024 | 0 | } else if (field->nestedField.__isset.map_field) { |
1025 | 0 | const auto& map = field->nestedField.map_field; |
1026 | 0 | if (map.__isset.key_field && map.key_field.__isset.field_ptr && |
1027 | 0 | map.key_field.field_ptr != nullptr && |
1028 | 0 | _find_schema_field_path_in_field(map.key_field.field_ptr.get(), field_id, path)) { |
1029 | 0 | return true; |
1030 | 0 | } |
1031 | 0 | if (map.__isset.value_field && map.value_field.__isset.field_ptr && |
1032 | 0 | map.value_field.field_ptr != nullptr && |
1033 | 0 | _find_schema_field_path_in_field(map.value_field.field_ptr.get(), field_id, path)) { |
1034 | 0 | return true; |
1035 | 0 | } |
1036 | 0 | } |
1037 | 89 | } |
1038 | 247 | path->pop_back(); |
1039 | 247 | return false; |
1040 | 316 | } _ZN5doris18IcebergReaderMixinINS_13ParquetReaderEE32_find_schema_field_path_in_fieldEPKNS_6schema8external6TFieldEiPSt6vectorIS7_SaIS7_EE Line | Count | Source | 999 | 319 | std::vector<const schema::external::TField*>* path) { | 1000 | 319 | DORIS_CHECK(path != nullptr); | 1001 | 319 | if (field == nullptr) { | 1002 | 0 | return false; | 1003 | 0 | } | 1004 | 319 | path->push_back(field); | 1005 | 319 | if (field->__isset.id && field->id == field_id) { | 1006 | 102 | return true; | 1007 | 102 | } | 1008 | 217 | if (field->__isset.nestedField) { | 1009 | 65 | if (field->nestedField.__isset.struct_field && | 1010 | 65 | field->nestedField.struct_field.__isset.fields) { | 1011 | 70 | for (const auto& child_ptr : field->nestedField.struct_field.fields) { | 1012 | 70 | if (child_ptr.__isset.field_ptr && child_ptr.field_ptr != nullptr && | 1013 | 70 | _find_schema_field_path_in_field(child_ptr.field_ptr.get(), field_id, path)) { | 1014 | 53 | return true; | 1015 | 53 | } | 1016 | 70 | } | 1017 | 65 | } else if (field->nestedField.__isset.array_field && | 1018 | 0 | field->nestedField.array_field.__isset.item_field) { | 1019 | 0 | const auto& child_ptr = field->nestedField.array_field.item_field; | 1020 | 0 | if (child_ptr.__isset.field_ptr && child_ptr.field_ptr != nullptr && | 1021 | 0 | _find_schema_field_path_in_field(child_ptr.field_ptr.get(), field_id, path)) { | 1022 | 0 | return true; | 1023 | 0 | } | 1024 | 0 | } else if (field->nestedField.__isset.map_field) { | 1025 | 0 | const auto& map = field->nestedField.map_field; | 1026 | 0 | if (map.__isset.key_field && map.key_field.__isset.field_ptr && | 1027 | 0 | map.key_field.field_ptr != nullptr && | 1028 | 0 | _find_schema_field_path_in_field(map.key_field.field_ptr.get(), field_id, path)) { | 1029 | 0 | return true; | 1030 | 0 | } | 1031 | 0 | if (map.__isset.value_field && map.value_field.__isset.field_ptr && | 1032 | 0 | map.value_field.field_ptr != nullptr && | 1033 | 0 | _find_schema_field_path_in_field(map.value_field.field_ptr.get(), field_id, path)) { | 1034 | 0 | return true; | 1035 | 0 | } | 1036 | 0 | } | 1037 | 65 | } | 1038 | 164 | path->pop_back(); | 1039 | 164 | return false; | 1040 | 217 | } |
_ZN5doris18IcebergReaderMixinINS_9OrcReaderEE32_find_schema_field_path_in_fieldEPKNS_6schema8external6TFieldEiPSt6vectorIS7_SaIS7_EE Line | Count | Source | 999 | 147 | std::vector<const schema::external::TField*>* path) { | 1000 | 147 | DORIS_CHECK(path != nullptr); | 1001 | 147 | if (field == nullptr) { | 1002 | 0 | return false; | 1003 | 0 | } | 1004 | 147 | path->push_back(field); | 1005 | 147 | if (field->__isset.id && field->id == field_id) { | 1006 | 48 | return true; | 1007 | 48 | } | 1008 | 99 | if (field->__isset.nestedField) { | 1009 | 24 | if (field->nestedField.__isset.struct_field && | 1010 | 24 | field->nestedField.struct_field.__isset.fields) { | 1011 | 24 | for (const auto& child_ptr : field->nestedField.struct_field.fields) { | 1012 | 19 | if (child_ptr.__isset.field_ptr && child_ptr.field_ptr != nullptr && | 1013 | 19 | _find_schema_field_path_in_field(child_ptr.field_ptr.get(), field_id, path)) { | 1014 | 16 | return true; | 1015 | 16 | } | 1016 | 19 | } | 1017 | 24 | } else if (field->nestedField.__isset.array_field && | 1018 | 0 | field->nestedField.array_field.__isset.item_field) { | 1019 | 0 | const auto& child_ptr = field->nestedField.array_field.item_field; | 1020 | 0 | if (child_ptr.__isset.field_ptr && child_ptr.field_ptr != nullptr && | 1021 | 0 | _find_schema_field_path_in_field(child_ptr.field_ptr.get(), field_id, path)) { | 1022 | 0 | return true; | 1023 | 0 | } | 1024 | 0 | } else if (field->nestedField.__isset.map_field) { | 1025 | 0 | const auto& map = field->nestedField.map_field; | 1026 | 0 | if (map.__isset.key_field && map.key_field.__isset.field_ptr && | 1027 | 0 | map.key_field.field_ptr != nullptr && | 1028 | 0 | _find_schema_field_path_in_field(map.key_field.field_ptr.get(), field_id, path)) { | 1029 | 0 | return true; | 1030 | 0 | } | 1031 | 0 | if (map.__isset.value_field && map.value_field.__isset.field_ptr && | 1032 | 0 | map.value_field.field_ptr != nullptr && | 1033 | 0 | _find_schema_field_path_in_field(map.value_field.field_ptr.get(), field_id, path)) { | 1034 | 0 | return true; | 1035 | 0 | } | 1036 | 0 | } | 1037 | 24 | } | 1038 | 83 | path->pop_back(); | 1039 | 83 | return false; | 1040 | 99 | } |
|
1041 | | |
1042 | | template <typename BaseReader> |
1043 | | bool IcebergReaderMixin<BaseReader>::_find_schema_field_path_in_root( |
1044 | | const schema::external::TStructField* root, int32_t field_id, |
1045 | 180 | std::vector<const schema::external::TField*>* path) { |
1046 | 180 | DORIS_CHECK(path != nullptr); |
1047 | 180 | if (root == nullptr || !root->__isset.fields) { |
1048 | 0 | return false; |
1049 | 0 | } |
1050 | 377 | return std::ranges::any_of(root->fields, [&](const auto& field_ptr) { |
1051 | 377 | return field_ptr.__isset.field_ptr && field_ptr.field_ptr != nullptr && |
1052 | 377 | _find_schema_field_path_in_field(field_ptr.field_ptr.get(), field_id, path); |
1053 | 377 | }); _ZZN5doris18IcebergReaderMixinINS_13ParquetReaderEE31_find_schema_field_path_in_rootEPKNS_6schema8external12TStructFieldEiPSt6vectorIPKNS4_6TFieldESaISB_EEENKUlRKT_E_clINS4_9TFieldPtrEEEDaSH_ Line | Count | Source | 1050 | 249 | return std::ranges::any_of(root->fields, [&](const auto& field_ptr) { | 1051 | 249 | return field_ptr.__isset.field_ptr && field_ptr.field_ptr != nullptr && | 1052 | 249 | _find_schema_field_path_in_field(field_ptr.field_ptr.get(), field_id, path); | 1053 | 249 | }); |
_ZZN5doris18IcebergReaderMixinINS_9OrcReaderEE31_find_schema_field_path_in_rootEPKNS_6schema8external12TStructFieldEiPSt6vectorIPKNS4_6TFieldESaISB_EEENKUlRKT_E_clINS4_9TFieldPtrEEEDaSH_ Line | Count | Source | 1050 | 128 | return std::ranges::any_of(root->fields, [&](const auto& field_ptr) { | 1051 | 128 | return field_ptr.__isset.field_ptr && field_ptr.field_ptr != nullptr && | 1052 | 128 | _find_schema_field_path_in_field(field_ptr.field_ptr.get(), field_id, path); | 1053 | 128 | }); |
|
1054 | 180 | } _ZN5doris18IcebergReaderMixinINS_13ParquetReaderEE31_find_schema_field_path_in_rootEPKNS_6schema8external12TStructFieldEiPSt6vectorIPKNS4_6TFieldESaISB_EE Line | Count | Source | 1045 | 122 | std::vector<const schema::external::TField*>* path) { | 1046 | 122 | DORIS_CHECK(path != nullptr); | 1047 | 122 | if (root == nullptr || !root->__isset.fields) { | 1048 | 0 | return false; | 1049 | 0 | } | 1050 | 122 | return std::ranges::any_of(root->fields, [&](const auto& field_ptr) { | 1051 | 122 | return field_ptr.__isset.field_ptr && field_ptr.field_ptr != nullptr && | 1052 | 122 | _find_schema_field_path_in_field(field_ptr.field_ptr.get(), field_id, path); | 1053 | 122 | }); | 1054 | 122 | } |
_ZN5doris18IcebergReaderMixinINS_9OrcReaderEE31_find_schema_field_path_in_rootEPKNS_6schema8external12TStructFieldEiPSt6vectorIPKNS4_6TFieldESaISB_EE Line | Count | Source | 1045 | 58 | std::vector<const schema::external::TField*>* path) { | 1046 | 58 | DORIS_CHECK(path != nullptr); | 1047 | 58 | if (root == nullptr || !root->__isset.fields) { | 1048 | 0 | return false; | 1049 | 0 | } | 1050 | 58 | return std::ranges::any_of(root->fields, [&](const auto& field_ptr) { | 1051 | 58 | return field_ptr.__isset.field_ptr && field_ptr.field_ptr != nullptr && | 1052 | 58 | _find_schema_field_path_in_field(field_ptr.field_ptr.get(), field_id, path); | 1053 | 58 | }); | 1054 | 58 | } |
|
1055 | | |
1056 | | template <typename BaseReader> |
1057 | | std::vector<const schema::external::TField*> |
1058 | 140 | IcebergReaderMixin<BaseReader>::_find_schema_field_path(int32_t field_id) const { |
1059 | 140 | std::vector<const schema::external::TField*> path; |
1060 | 140 | if (_find_schema_field_path_in_root(_current_schema_root(), field_id, &path)) { |
1061 | 125 | return path; |
1062 | 125 | } |
1063 | | |
1064 | | // Equality deletes remain applicable after their key is dropped from the current schema. |
1065 | | // FE can retain that field's metadata in history_schema_info; field IDs are stable, so recover |
1066 | | // the original initial-default/required semantics from any historical schema that contains it. |
1067 | 15 | const auto& scan_params = this->get_scan_params(); |
1068 | 15 | if (!scan_params.__isset.history_schema_info) { |
1069 | 0 | return {}; |
1070 | 0 | } |
1071 | 29 | for (const auto& schema : scan_params.history_schema_info) { |
1072 | 29 | if (!schema.__isset.root_field) { |
1073 | 0 | continue; |
1074 | 0 | } |
1075 | 29 | path.clear(); |
1076 | 29 | if (_find_schema_field_path_in_root(&schema.root_field, field_id, &path)) { |
1077 | 14 | return path; |
1078 | 14 | } |
1079 | 29 | } |
1080 | 1 | return {}; |
1081 | 15 | } _ZNK5doris18IcebergReaderMixinINS_13ParquetReaderEE23_find_schema_field_pathEi Line | Count | Source | 1058 | 92 | IcebergReaderMixin<BaseReader>::_find_schema_field_path(int32_t field_id) const { | 1059 | 92 | std::vector<const schema::external::TField*> path; | 1060 | 92 | if (_find_schema_field_path_in_root(_current_schema_root(), field_id, &path)) { | 1061 | 82 | return path; | 1062 | 82 | } | 1063 | | | 1064 | | // Equality deletes remain applicable after their key is dropped from the current schema. | 1065 | | // FE can retain that field's metadata in history_schema_info; field IDs are stable, so recover | 1066 | | // the original initial-default/required semantics from any historical schema that contains it. | 1067 | 10 | const auto& scan_params = this->get_scan_params(); | 1068 | 10 | if (!scan_params.__isset.history_schema_info) { | 1069 | 0 | return {}; | 1070 | 0 | } | 1071 | 19 | for (const auto& schema : scan_params.history_schema_info) { | 1072 | 19 | if (!schema.__isset.root_field) { | 1073 | 0 | continue; | 1074 | 0 | } | 1075 | 19 | path.clear(); | 1076 | 19 | if (_find_schema_field_path_in_root(&schema.root_field, field_id, &path)) { | 1077 | 9 | return path; | 1078 | 9 | } | 1079 | 19 | } | 1080 | 1 | return {}; | 1081 | 10 | } |
_ZNK5doris18IcebergReaderMixinINS_9OrcReaderEE23_find_schema_field_pathEi Line | Count | Source | 1058 | 48 | IcebergReaderMixin<BaseReader>::_find_schema_field_path(int32_t field_id) const { | 1059 | 48 | std::vector<const schema::external::TField*> path; | 1060 | 48 | if (_find_schema_field_path_in_root(_current_schema_root(), field_id, &path)) { | 1061 | 43 | return path; | 1062 | 43 | } | 1063 | | | 1064 | | // Equality deletes remain applicable after their key is dropped from the current schema. | 1065 | | // FE can retain that field's metadata in history_schema_info; field IDs are stable, so recover | 1066 | | // the original initial-default/required semantics from any historical schema that contains it. | 1067 | 5 | const auto& scan_params = this->get_scan_params(); | 1068 | 5 | if (!scan_params.__isset.history_schema_info) { | 1069 | 0 | return {}; | 1070 | 0 | } | 1071 | 10 | for (const auto& schema : scan_params.history_schema_info) { | 1072 | 10 | if (!schema.__isset.root_field) { | 1073 | 0 | continue; | 1074 | 0 | } | 1075 | 10 | path.clear(); | 1076 | 10 | if (_find_schema_field_path_in_root(&schema.root_field, field_id, &path)) { | 1077 | 5 | return path; | 1078 | 5 | } | 1079 | 10 | } | 1080 | 0 | return {}; | 1081 | 5 | } |
|
1082 | | |
1083 | | template <typename BaseReader> |
1084 | | Status IcebergReaderMixin<BaseReader>::_extract_nested_equality_delete_column( |
1085 | | const ColumnPtr& root_column, const NestedEqualityDeleteColumn& nested_field, |
1086 | 105 | ColumnPtr* leaf_column) const { |
1087 | 105 | DORIS_CHECK(static_cast<bool>(root_column)); |
1088 | 105 | DORIS_CHECK(nested_field.leaf_type != nullptr); |
1089 | 105 | DORIS_CHECK(leaf_column != nullptr); |
1090 | 105 | const IColumn* current = root_column.get(); |
1091 | 105 | std::vector<const NullMap*> ancestor_null_maps; |
1092 | 105 | for (size_t child_index : nested_field.child_indexes) { |
1093 | 57 | if (const auto* nullable = check_and_get_column<ColumnNullable>(*current); |
1094 | 57 | nullable != nullptr) { |
1095 | 57 | ancestor_null_maps.push_back(&nullable->get_null_map_data()); |
1096 | 57 | current = &nullable->get_nested_column(); |
1097 | 57 | } |
1098 | 57 | const auto* struct_column = check_and_get_column<ColumnStruct>(*current); |
1099 | 57 | if (struct_column == nullptr || child_index >= struct_column->tuple_size()) { |
1100 | 0 | return Status::InternalError( |
1101 | 0 | "Iceberg equality delete path for field id {} is absent from column {}", |
1102 | 0 | nested_field.field_id, root_column->get_name()); |
1103 | 0 | } |
1104 | 57 | current = &struct_column->get_column(child_index); |
1105 | 57 | } |
1106 | 105 | if (const auto* nullable = check_and_get_column<ColumnNullable>(*current); |
1107 | 105 | nullable != nullptr) { |
1108 | 105 | ancestor_null_maps.push_back(&nullable->get_null_map_data()); |
1109 | 105 | current = &nullable->get_nested_column(); |
1110 | 105 | } |
1111 | 105 | ColumnPtr repeated_missing_value; |
1112 | 105 | if (static_cast<bool>(nested_field.missing_value)) { |
1113 | 2 | repeated_missing_value = iceberg::repeat_initial_default_column(nested_field.missing_value, |
1114 | 2 | root_column->size()); |
1115 | 2 | current = repeated_missing_value.get(); |
1116 | 2 | if (const auto* nullable = check_and_get_column<ColumnNullable>(*current); |
1117 | 2 | nullable != nullptr) { |
1118 | 2 | ancestor_null_maps.push_back(&nullable->get_null_map_data()); |
1119 | 2 | current = &nullable->get_nested_column(); |
1120 | 2 | } |
1121 | 2 | } |
1122 | | |
1123 | 105 | DORIS_CHECK(nested_field.source_leaf_type != nullptr); |
1124 | 105 | auto result = ColumnNullable::create( |
1125 | 105 | remove_nullable(nested_field.source_leaf_type)->create_column(), ColumnUInt8::create()); |
1126 | 105 | auto& result_data = result->get_nested_column(); |
1127 | 105 | auto& result_null_map = result->get_null_map_data(); |
1128 | 105 | result_data.reserve(root_column->size()); |
1129 | 105 | result_null_map.reserve(root_column->size()); |
1130 | 272 | for (size_t row = 0; row < root_column->size(); ++row) { |
1131 | 167 | bool is_null = false; |
1132 | 278 | for (const auto* null_map : ancestor_null_maps) { |
1133 | 278 | if ((*null_map)[row] != 0) { |
1134 | 11 | is_null = true; |
1135 | 11 | break; |
1136 | 11 | } |
1137 | 278 | } |
1138 | 167 | if (is_null) { |
1139 | 11 | result_data.insert_default(); |
1140 | 11 | result_null_map.push_back(1); |
1141 | 156 | } else { |
1142 | 156 | result_data.insert_from(*current, row); |
1143 | 156 | result_null_map.push_back(0); |
1144 | 156 | } |
1145 | 167 | } |
1146 | 105 | return widen_equality_delete_key(std::move(result), |
1147 | 105 | make_nullable(nested_field.source_leaf_type), |
1148 | 105 | make_nullable(nested_field.leaf_type), leaf_column); |
1149 | 105 | } _ZNK5doris18IcebergReaderMixinINS_13ParquetReaderEE38_extract_nested_equality_delete_columnERKNS_3COWINS_7IColumnEE13immutable_ptrIS4_EERKNS2_26NestedEqualityDeleteColumnEPS7_ Line | Count | Source | 1086 | 67 | ColumnPtr* leaf_column) const { | 1087 | 67 | DORIS_CHECK(static_cast<bool>(root_column)); | 1088 | 67 | DORIS_CHECK(nested_field.leaf_type != nullptr); | 1089 | 67 | DORIS_CHECK(leaf_column != nullptr); | 1090 | 67 | const IColumn* current = root_column.get(); | 1091 | 67 | std::vector<const NullMap*> ancestor_null_maps; | 1092 | 67 | for (size_t child_index : nested_field.child_indexes) { | 1093 | 42 | if (const auto* nullable = check_and_get_column<ColumnNullable>(*current); | 1094 | 42 | nullable != nullptr) { | 1095 | 42 | ancestor_null_maps.push_back(&nullable->get_null_map_data()); | 1096 | 42 | current = &nullable->get_nested_column(); | 1097 | 42 | } | 1098 | 42 | const auto* struct_column = check_and_get_column<ColumnStruct>(*current); | 1099 | 42 | if (struct_column == nullptr || child_index >= struct_column->tuple_size()) { | 1100 | 0 | return Status::InternalError( | 1101 | 0 | "Iceberg equality delete path for field id {} is absent from column {}", | 1102 | 0 | nested_field.field_id, root_column->get_name()); | 1103 | 0 | } | 1104 | 42 | current = &struct_column->get_column(child_index); | 1105 | 42 | } | 1106 | 67 | if (const auto* nullable = check_and_get_column<ColumnNullable>(*current); | 1107 | 67 | nullable != nullptr) { | 1108 | 67 | ancestor_null_maps.push_back(&nullable->get_null_map_data()); | 1109 | 67 | current = &nullable->get_nested_column(); | 1110 | 67 | } | 1111 | 67 | ColumnPtr repeated_missing_value; | 1112 | 67 | if (static_cast<bool>(nested_field.missing_value)) { | 1113 | 1 | repeated_missing_value = iceberg::repeat_initial_default_column(nested_field.missing_value, | 1114 | 1 | root_column->size()); | 1115 | 1 | current = repeated_missing_value.get(); | 1116 | 1 | if (const auto* nullable = check_and_get_column<ColumnNullable>(*current); | 1117 | 1 | nullable != nullptr) { | 1118 | 1 | ancestor_null_maps.push_back(&nullable->get_null_map_data()); | 1119 | 1 | current = &nullable->get_nested_column(); | 1120 | 1 | } | 1121 | 1 | } | 1122 | | | 1123 | 67 | DORIS_CHECK(nested_field.source_leaf_type != nullptr); | 1124 | 67 | auto result = ColumnNullable::create( | 1125 | 67 | remove_nullable(nested_field.source_leaf_type)->create_column(), ColumnUInt8::create()); | 1126 | 67 | auto& result_data = result->get_nested_column(); | 1127 | 67 | auto& result_null_map = result->get_null_map_data(); | 1128 | 67 | result_data.reserve(root_column->size()); | 1129 | 67 | result_null_map.reserve(root_column->size()); | 1130 | 176 | for (size_t row = 0; row < root_column->size(); ++row) { | 1131 | 109 | bool is_null = false; | 1132 | 189 | for (const auto* null_map : ancestor_null_maps) { | 1133 | 189 | if ((*null_map)[row] != 0) { | 1134 | 6 | is_null = true; | 1135 | 6 | break; | 1136 | 6 | } | 1137 | 189 | } | 1138 | 109 | if (is_null) { | 1139 | 6 | result_data.insert_default(); | 1140 | 6 | result_null_map.push_back(1); | 1141 | 103 | } else { | 1142 | 103 | result_data.insert_from(*current, row); | 1143 | 103 | result_null_map.push_back(0); | 1144 | 103 | } | 1145 | 109 | } | 1146 | 67 | return widen_equality_delete_key(std::move(result), | 1147 | 67 | make_nullable(nested_field.source_leaf_type), | 1148 | 67 | make_nullable(nested_field.leaf_type), leaf_column); | 1149 | 67 | } |
_ZNK5doris18IcebergReaderMixinINS_9OrcReaderEE38_extract_nested_equality_delete_columnERKNS_3COWINS_7IColumnEE13immutable_ptrIS4_EERKNS2_26NestedEqualityDeleteColumnEPS7_ Line | Count | Source | 1086 | 38 | ColumnPtr* leaf_column) const { | 1087 | 38 | DORIS_CHECK(static_cast<bool>(root_column)); | 1088 | 38 | DORIS_CHECK(nested_field.leaf_type != nullptr); | 1089 | 38 | DORIS_CHECK(leaf_column != nullptr); | 1090 | 38 | const IColumn* current = root_column.get(); | 1091 | 38 | std::vector<const NullMap*> ancestor_null_maps; | 1092 | 38 | for (size_t child_index : nested_field.child_indexes) { | 1093 | 15 | if (const auto* nullable = check_and_get_column<ColumnNullable>(*current); | 1094 | 15 | nullable != nullptr) { | 1095 | 15 | ancestor_null_maps.push_back(&nullable->get_null_map_data()); | 1096 | 15 | current = &nullable->get_nested_column(); | 1097 | 15 | } | 1098 | 15 | const auto* struct_column = check_and_get_column<ColumnStruct>(*current); | 1099 | 15 | if (struct_column == nullptr || child_index >= struct_column->tuple_size()) { | 1100 | 0 | return Status::InternalError( | 1101 | 0 | "Iceberg equality delete path for field id {} is absent from column {}", | 1102 | 0 | nested_field.field_id, root_column->get_name()); | 1103 | 0 | } | 1104 | 15 | current = &struct_column->get_column(child_index); | 1105 | 15 | } | 1106 | 38 | if (const auto* nullable = check_and_get_column<ColumnNullable>(*current); | 1107 | 38 | nullable != nullptr) { | 1108 | 38 | ancestor_null_maps.push_back(&nullable->get_null_map_data()); | 1109 | 38 | current = &nullable->get_nested_column(); | 1110 | 38 | } | 1111 | 38 | ColumnPtr repeated_missing_value; | 1112 | 38 | if (static_cast<bool>(nested_field.missing_value)) { | 1113 | 1 | repeated_missing_value = iceberg::repeat_initial_default_column(nested_field.missing_value, | 1114 | 1 | root_column->size()); | 1115 | 1 | current = repeated_missing_value.get(); | 1116 | 1 | if (const auto* nullable = check_and_get_column<ColumnNullable>(*current); | 1117 | 1 | nullable != nullptr) { | 1118 | 1 | ancestor_null_maps.push_back(&nullable->get_null_map_data()); | 1119 | 1 | current = &nullable->get_nested_column(); | 1120 | 1 | } | 1121 | 1 | } | 1122 | | | 1123 | 38 | DORIS_CHECK(nested_field.source_leaf_type != nullptr); | 1124 | 38 | auto result = ColumnNullable::create( | 1125 | 38 | remove_nullable(nested_field.source_leaf_type)->create_column(), ColumnUInt8::create()); | 1126 | 38 | auto& result_data = result->get_nested_column(); | 1127 | 38 | auto& result_null_map = result->get_null_map_data(); | 1128 | 38 | result_data.reserve(root_column->size()); | 1129 | 38 | result_null_map.reserve(root_column->size()); | 1130 | 96 | for (size_t row = 0; row < root_column->size(); ++row) { | 1131 | 58 | bool is_null = false; | 1132 | 89 | for (const auto* null_map : ancestor_null_maps) { | 1133 | 89 | if ((*null_map)[row] != 0) { | 1134 | 5 | is_null = true; | 1135 | 5 | break; | 1136 | 5 | } | 1137 | 89 | } | 1138 | 58 | if (is_null) { | 1139 | 5 | result_data.insert_default(); | 1140 | 5 | result_null_map.push_back(1); | 1141 | 53 | } else { | 1142 | 53 | result_data.insert_from(*current, row); | 1143 | 53 | result_null_map.push_back(0); | 1144 | 53 | } | 1145 | 58 | } | 1146 | 38 | return widen_equality_delete_key(std::move(result), | 1147 | 38 | make_nullable(nested_field.source_leaf_type), | 1148 | 38 | make_nullable(nested_field.leaf_type), leaf_column); | 1149 | 38 | } |
|
1150 | | |
1151 | | template <typename BaseReader> |
1152 | 61 | Status IcebergReaderMixin<BaseReader>::_materialize_nested_equality_delete_columns(Block* block) { |
1153 | 61 | DORIS_CHECK(block != nullptr); |
1154 | | // A carrier may be the source of other keys under the same physical root, so extract every |
1155 | | // leaf before replacing any carrier column with its own leaf. |
1156 | 61 | std::vector<ColumnPtr> leaves; |
1157 | 61 | leaves.reserve(_nested_equality_delete_columns.size()); |
1158 | 61 | for (const auto& nested_field : _nested_equality_delete_columns) { |
1159 | 34 | const auto& source_name = nested_field.source_block_name.empty() |
1160 | 34 | ? nested_field.block_name |
1161 | 34 | : nested_field.source_block_name; |
1162 | 34 | const auto source = this->col_name_to_block_idx_ref()->find(source_name); |
1163 | 34 | DORIS_CHECK(source != this->col_name_to_block_idx_ref()->end()); |
1164 | 34 | DORIS_CHECK(source->second < block->columns()); |
1165 | 34 | ColumnPtr leaf; |
1166 | 34 | RETURN_IF_ERROR(_extract_nested_equality_delete_column( |
1167 | 34 | block->get_by_position(source->second).column, nested_field, &leaf)); |
1168 | 34 | leaves.push_back(std::move(leaf)); |
1169 | 34 | } |
1170 | 95 | for (size_t index = 0; index < leaves.size(); ++index) { |
1171 | 34 | const auto& nested_field = _nested_equality_delete_columns[index]; |
1172 | 34 | const auto type = make_nullable(nested_field.leaf_type); |
1173 | 34 | auto& positions = *this->col_name_to_block_idx_ref(); |
1174 | 34 | if (!nested_field.source_block_name.empty()) { |
1175 | | // A key extracted from a projected root or another key's carrier is not read, so the |
1176 | | // block gets its column only now. |
1177 | 11 | DORIS_CHECK(!positions.contains(nested_field.block_name)); |
1178 | 11 | positions[nested_field.block_name] = block->columns(); |
1179 | 11 | block->insert({std::move(leaves[index]), type, nested_field.block_name}); |
1180 | 11 | continue; |
1181 | 11 | } |
1182 | 23 | const auto target = positions.find(nested_field.block_name); |
1183 | 23 | DORIS_CHECK(target != positions.end()); |
1184 | 23 | DORIS_CHECK(target->second < block->columns()); |
1185 | 23 | auto& column = block->get_by_position(target->second); |
1186 | 23 | column.column = std::move(leaves[index]); |
1187 | 23 | column.type = type; |
1188 | 23 | } |
1189 | 61 | return Status::OK(); |
1190 | 61 | } _ZN5doris18IcebergReaderMixinINS_13ParquetReaderEE43_materialize_nested_equality_delete_columnsEPNS_5BlockE Line | Count | Source | 1152 | 37 | Status IcebergReaderMixin<BaseReader>::_materialize_nested_equality_delete_columns(Block* block) { | 1153 | 37 | DORIS_CHECK(block != nullptr); | 1154 | | // A carrier may be the source of other keys under the same physical root, so extract every | 1155 | | // leaf before replacing any carrier column with its own leaf. | 1156 | 37 | std::vector<ColumnPtr> leaves; | 1157 | 37 | leaves.reserve(_nested_equality_delete_columns.size()); | 1158 | 37 | for (const auto& nested_field : _nested_equality_delete_columns) { | 1159 | 24 | const auto& source_name = nested_field.source_block_name.empty() | 1160 | 24 | ? nested_field.block_name | 1161 | 24 | : nested_field.source_block_name; | 1162 | 24 | const auto source = this->col_name_to_block_idx_ref()->find(source_name); | 1163 | 24 | DORIS_CHECK(source != this->col_name_to_block_idx_ref()->end()); | 1164 | 24 | DORIS_CHECK(source->second < block->columns()); | 1165 | 24 | ColumnPtr leaf; | 1166 | 24 | RETURN_IF_ERROR(_extract_nested_equality_delete_column( | 1167 | 24 | block->get_by_position(source->second).column, nested_field, &leaf)); | 1168 | 24 | leaves.push_back(std::move(leaf)); | 1169 | 24 | } | 1170 | 61 | for (size_t index = 0; index < leaves.size(); ++index) { | 1171 | 24 | const auto& nested_field = _nested_equality_delete_columns[index]; | 1172 | 24 | const auto type = make_nullable(nested_field.leaf_type); | 1173 | 24 | auto& positions = *this->col_name_to_block_idx_ref(); | 1174 | 24 | if (!nested_field.source_block_name.empty()) { | 1175 | | // A key extracted from a projected root or another key's carrier is not read, so the | 1176 | | // block gets its column only now. | 1177 | 11 | DORIS_CHECK(!positions.contains(nested_field.block_name)); | 1178 | 11 | positions[nested_field.block_name] = block->columns(); | 1179 | 11 | block->insert({std::move(leaves[index]), type, nested_field.block_name}); | 1180 | 11 | continue; | 1181 | 11 | } | 1182 | 13 | const auto target = positions.find(nested_field.block_name); | 1183 | 13 | DORIS_CHECK(target != positions.end()); | 1184 | 13 | DORIS_CHECK(target->second < block->columns()); | 1185 | 13 | auto& column = block->get_by_position(target->second); | 1186 | 13 | column.column = std::move(leaves[index]); | 1187 | 13 | column.type = type; | 1188 | 13 | } | 1189 | 37 | return Status::OK(); | 1190 | 37 | } |
_ZN5doris18IcebergReaderMixinINS_9OrcReaderEE43_materialize_nested_equality_delete_columnsEPNS_5BlockE Line | Count | Source | 1152 | 24 | Status IcebergReaderMixin<BaseReader>::_materialize_nested_equality_delete_columns(Block* block) { | 1153 | 24 | DORIS_CHECK(block != nullptr); | 1154 | | // A carrier may be the source of other keys under the same physical root, so extract every | 1155 | | // leaf before replacing any carrier column with its own leaf. | 1156 | 24 | std::vector<ColumnPtr> leaves; | 1157 | 24 | leaves.reserve(_nested_equality_delete_columns.size()); | 1158 | 24 | for (const auto& nested_field : _nested_equality_delete_columns) { | 1159 | 10 | const auto& source_name = nested_field.source_block_name.empty() | 1160 | 10 | ? nested_field.block_name | 1161 | 10 | : nested_field.source_block_name; | 1162 | 10 | const auto source = this->col_name_to_block_idx_ref()->find(source_name); | 1163 | 10 | DORIS_CHECK(source != this->col_name_to_block_idx_ref()->end()); | 1164 | 10 | DORIS_CHECK(source->second < block->columns()); | 1165 | 10 | ColumnPtr leaf; | 1166 | 10 | RETURN_IF_ERROR(_extract_nested_equality_delete_column( | 1167 | 10 | block->get_by_position(source->second).column, nested_field, &leaf)); | 1168 | 10 | leaves.push_back(std::move(leaf)); | 1169 | 10 | } | 1170 | 34 | for (size_t index = 0; index < leaves.size(); ++index) { | 1171 | 10 | const auto& nested_field = _nested_equality_delete_columns[index]; | 1172 | 10 | const auto type = make_nullable(nested_field.leaf_type); | 1173 | 10 | auto& positions = *this->col_name_to_block_idx_ref(); | 1174 | 10 | if (!nested_field.source_block_name.empty()) { | 1175 | | // A key extracted from a projected root or another key's carrier is not read, so the | 1176 | | // block gets its column only now. | 1177 | 0 | DORIS_CHECK(!positions.contains(nested_field.block_name)); | 1178 | 0 | positions[nested_field.block_name] = block->columns(); | 1179 | 0 | block->insert({std::move(leaves[index]), type, nested_field.block_name}); | 1180 | 0 | continue; | 1181 | 0 | } | 1182 | 10 | const auto target = positions.find(nested_field.block_name); | 1183 | 10 | DORIS_CHECK(target != positions.end()); | 1184 | 10 | DORIS_CHECK(target->second < block->columns()); | 1185 | 10 | auto& column = block->get_by_position(target->second); | 1186 | 10 | column.column = std::move(leaves[index]); | 1187 | 10 | column.type = type; | 1188 | 10 | } | 1189 | 24 | return Status::OK(); | 1190 | 24 | } |
|
1191 | | |
1192 | | template <typename BaseReader> |
1193 | | Status IcebergReaderMixin<BaseReader>::_create_missing_equality_delete_value( |
1194 | | int32_t field_id, const DataTypePtr& delete_key_type, size_t physical_path_size, |
1195 | 21 | ColumnPtr* const value) const { |
1196 | 21 | DORIS_CHECK(delete_key_type != nullptr); |
1197 | 21 | DORIS_CHECK(value != nullptr); |
1198 | 21 | const auto table_path = _find_schema_field_path(field_id); |
1199 | 21 | if (table_path.empty()) { |
1200 | | // Without field-id-bound current or historical metadata BE cannot distinguish a true NULL |
1201 | | // initial default from a non-NULL default, so continuing would risk silently keeping or |
1202 | | // deleting wrong rows. |
1203 | 1 | return Status::InternalError( |
1204 | 1 | "Missing Iceberg schema metadata for equality-delete field id {}", field_id); |
1205 | 1 | } |
1206 | 20 | const size_t missing_index = |
1207 | 20 | physical_path_size < table_path.size() ? physical_path_size : table_path.size() - 1; |
1208 | 20 | const auto* missing_field = table_path[missing_index]; |
1209 | 20 | DORIS_CHECK(missing_field != nullptr); |
1210 | | |
1211 | 20 | if (!supports_iceberg_scan_semantics_v2(&this->get_scan_params()) && |
1212 | 20 | !missing_field->__isset.initial_default_value) { |
1213 | 0 | *value = delete_key_type->create_column_const(1, Field()); |
1214 | 0 | return Status::OK(); |
1215 | 0 | } |
1216 | | |
1217 | 20 | DataTypePtr missing_type = delete_key_type; |
1218 | 20 | for (size_t index = table_path.size(); index > missing_index + 1; --index) { |
1219 | 0 | const auto* parent = table_path[index - 2]; |
1220 | 0 | const auto* child = table_path[index - 1]; |
1221 | 0 | DORIS_CHECK(parent != nullptr); |
1222 | 0 | DORIS_CHECK(child != nullptr); |
1223 | 0 | DORIS_CHECK(child->__isset.name); |
1224 | 0 | if (!parent->__isset.nestedField || !parent->nestedField.__isset.struct_field) { |
1225 | 0 | return Status::NotSupported( |
1226 | 0 | "Iceberg equality delete field id {} has a non-struct missing ancestor", |
1227 | 0 | field_id); |
1228 | 0 | } |
1229 | 0 | missing_type = std::make_shared<DataTypeStruct>(DataTypes {std::move(missing_type)}, |
1230 | 0 | Strings {child->name}); |
1231 | 0 | if (parent->__isset.is_optional && parent->is_optional) { |
1232 | 0 | missing_type = make_nullable(missing_type); |
1233 | 0 | } |
1234 | 0 | } |
1235 | | |
1236 | 20 | ColumnPtr missing_root_value; |
1237 | 20 | RETURN_IF_ERROR(iceberg::create_initial_default_column(*missing_field, missing_type, |
1238 | 20 | &missing_root_value)); |
1239 | 20 | if (missing_index + 1 == table_path.size()) { |
1240 | 20 | *value = std::move(missing_root_value); |
1241 | 20 | return Status::OK(); |
1242 | 20 | } |
1243 | | |
1244 | 0 | NestedEqualityDeleteColumn missing_path { |
1245 | 0 | .field_id = field_id, |
1246 | 0 | .block_name = "", |
1247 | 0 | .leaf_type = delete_key_type, |
1248 | 0 | .source_leaf_type = delete_key_type, |
1249 | 0 | .child_indexes = std::vector<size_t>(table_path.size() - missing_index - 1, 0), |
1250 | 0 | .missing_value = nullptr, |
1251 | 0 | }; |
1252 | 0 | return _extract_nested_equality_delete_column(missing_root_value, missing_path, value); |
1253 | 20 | } _ZNK5doris18IcebergReaderMixinINS_13ParquetReaderEE37_create_missing_equality_delete_valueEiRKSt10shared_ptrIKNS_9IDataTypeEEmPNS_3COWINS_7IColumnEE13immutable_ptrISA_EE Line | Count | Source | 1195 | 13 | ColumnPtr* const value) const { | 1196 | 13 | DORIS_CHECK(delete_key_type != nullptr); | 1197 | 13 | DORIS_CHECK(value != nullptr); | 1198 | 13 | const auto table_path = _find_schema_field_path(field_id); | 1199 | 13 | if (table_path.empty()) { | 1200 | | // Without field-id-bound current or historical metadata BE cannot distinguish a true NULL | 1201 | | // initial default from a non-NULL default, so continuing would risk silently keeping or | 1202 | | // deleting wrong rows. | 1203 | 1 | return Status::InternalError( | 1204 | 1 | "Missing Iceberg schema metadata for equality-delete field id {}", field_id); | 1205 | 1 | } | 1206 | 12 | const size_t missing_index = | 1207 | 12 | physical_path_size < table_path.size() ? physical_path_size : table_path.size() - 1; | 1208 | 12 | const auto* missing_field = table_path[missing_index]; | 1209 | 12 | DORIS_CHECK(missing_field != nullptr); | 1210 | | | 1211 | 12 | if (!supports_iceberg_scan_semantics_v2(&this->get_scan_params()) && | 1212 | 12 | !missing_field->__isset.initial_default_value) { | 1213 | 0 | *value = delete_key_type->create_column_const(1, Field()); | 1214 | 0 | return Status::OK(); | 1215 | 0 | } | 1216 | | | 1217 | 12 | DataTypePtr missing_type = delete_key_type; | 1218 | 12 | for (size_t index = table_path.size(); index > missing_index + 1; --index) { | 1219 | 0 | const auto* parent = table_path[index - 2]; | 1220 | 0 | const auto* child = table_path[index - 1]; | 1221 | 0 | DORIS_CHECK(parent != nullptr); | 1222 | 0 | DORIS_CHECK(child != nullptr); | 1223 | 0 | DORIS_CHECK(child->__isset.name); | 1224 | 0 | if (!parent->__isset.nestedField || !parent->nestedField.__isset.struct_field) { | 1225 | 0 | return Status::NotSupported( | 1226 | 0 | "Iceberg equality delete field id {} has a non-struct missing ancestor", | 1227 | 0 | field_id); | 1228 | 0 | } | 1229 | 0 | missing_type = std::make_shared<DataTypeStruct>(DataTypes {std::move(missing_type)}, | 1230 | 0 | Strings {child->name}); | 1231 | 0 | if (parent->__isset.is_optional && parent->is_optional) { | 1232 | 0 | missing_type = make_nullable(missing_type); | 1233 | 0 | } | 1234 | 0 | } | 1235 | | | 1236 | 12 | ColumnPtr missing_root_value; | 1237 | 12 | RETURN_IF_ERROR(iceberg::create_initial_default_column(*missing_field, missing_type, | 1238 | 12 | &missing_root_value)); | 1239 | 12 | if (missing_index + 1 == table_path.size()) { | 1240 | 12 | *value = std::move(missing_root_value); | 1241 | 12 | return Status::OK(); | 1242 | 12 | } | 1243 | | | 1244 | 0 | NestedEqualityDeleteColumn missing_path { | 1245 | 0 | .field_id = field_id, | 1246 | 0 | .block_name = "", | 1247 | 0 | .leaf_type = delete_key_type, | 1248 | 0 | .source_leaf_type = delete_key_type, | 1249 | 0 | .child_indexes = std::vector<size_t>(table_path.size() - missing_index - 1, 0), | 1250 | 0 | .missing_value = nullptr, | 1251 | 0 | }; | 1252 | 0 | return _extract_nested_equality_delete_column(missing_root_value, missing_path, value); | 1253 | 12 | } |
_ZNK5doris18IcebergReaderMixinINS_9OrcReaderEE37_create_missing_equality_delete_valueEiRKSt10shared_ptrIKNS_9IDataTypeEEmPNS_3COWINS_7IColumnEE13immutable_ptrISA_EE Line | Count | Source | 1195 | 8 | ColumnPtr* const value) const { | 1196 | 8 | DORIS_CHECK(delete_key_type != nullptr); | 1197 | 8 | DORIS_CHECK(value != nullptr); | 1198 | 8 | const auto table_path = _find_schema_field_path(field_id); | 1199 | 8 | if (table_path.empty()) { | 1200 | | // Without field-id-bound current or historical metadata BE cannot distinguish a true NULL | 1201 | | // initial default from a non-NULL default, so continuing would risk silently keeping or | 1202 | | // deleting wrong rows. | 1203 | 0 | return Status::InternalError( | 1204 | 0 | "Missing Iceberg schema metadata for equality-delete field id {}", field_id); | 1205 | 0 | } | 1206 | 8 | const size_t missing_index = | 1207 | 8 | physical_path_size < table_path.size() ? physical_path_size : table_path.size() - 1; | 1208 | 8 | const auto* missing_field = table_path[missing_index]; | 1209 | 8 | DORIS_CHECK(missing_field != nullptr); | 1210 | | | 1211 | 8 | if (!supports_iceberg_scan_semantics_v2(&this->get_scan_params()) && | 1212 | 8 | !missing_field->__isset.initial_default_value) { | 1213 | 0 | *value = delete_key_type->create_column_const(1, Field()); | 1214 | 0 | return Status::OK(); | 1215 | 0 | } | 1216 | | | 1217 | 8 | DataTypePtr missing_type = delete_key_type; | 1218 | 8 | for (size_t index = table_path.size(); index > missing_index + 1; --index) { | 1219 | 0 | const auto* parent = table_path[index - 2]; | 1220 | 0 | const auto* child = table_path[index - 1]; | 1221 | 0 | DORIS_CHECK(parent != nullptr); | 1222 | 0 | DORIS_CHECK(child != nullptr); | 1223 | 0 | DORIS_CHECK(child->__isset.name); | 1224 | 0 | if (!parent->__isset.nestedField || !parent->nestedField.__isset.struct_field) { | 1225 | 0 | return Status::NotSupported( | 1226 | 0 | "Iceberg equality delete field id {} has a non-struct missing ancestor", | 1227 | 0 | field_id); | 1228 | 0 | } | 1229 | 0 | missing_type = std::make_shared<DataTypeStruct>(DataTypes {std::move(missing_type)}, | 1230 | 0 | Strings {child->name}); | 1231 | 0 | if (parent->__isset.is_optional && parent->is_optional) { | 1232 | 0 | missing_type = make_nullable(missing_type); | 1233 | 0 | } | 1234 | 0 | } | 1235 | | | 1236 | 8 | ColumnPtr missing_root_value; | 1237 | 8 | RETURN_IF_ERROR(iceberg::create_initial_default_column(*missing_field, missing_type, | 1238 | 8 | &missing_root_value)); | 1239 | 8 | if (missing_index + 1 == table_path.size()) { | 1240 | 8 | *value = std::move(missing_root_value); | 1241 | 8 | return Status::OK(); | 1242 | 8 | } | 1243 | | | 1244 | 0 | NestedEqualityDeleteColumn missing_path { | 1245 | 0 | .field_id = field_id, | 1246 | 0 | .block_name = "", | 1247 | 0 | .leaf_type = delete_key_type, | 1248 | 0 | .source_leaf_type = delete_key_type, | 1249 | 0 | .child_indexes = std::vector<size_t>(table_path.size() - missing_index - 1, 0), | 1250 | 0 | .missing_value = nullptr, | 1251 | 0 | }; | 1252 | 0 | return _extract_nested_equality_delete_column(missing_root_value, missing_path, value); | 1253 | 8 | } |
|
1254 | | |
1255 | | template <typename BaseReader> |
1256 | | Status IcebergReaderMixin<BaseReader>::_register_missing_equality_delete_column( |
1257 | 19 | int32_t field_id, const std::string& name, const DataTypePtr& delete_key_type) { |
1258 | 19 | DORIS_CHECK(delete_key_type != nullptr); |
1259 | 19 | ColumnPtr default_column; |
1260 | 19 | RETURN_IF_ERROR( |
1261 | 19 | _create_missing_equality_delete_value(field_id, delete_key_type, 0, &default_column)); |
1262 | | // The key is appended after the read (on_after_read_block), not by a synthesized-column |
1263 | | // handler: the reader filters only the columns its block had before the read, and Parquet's |
1264 | | // lazy read also looks up a tuple slot for every synthesized column, which this hidden key |
1265 | | // does not have. |
1266 | 18 | const bool inserted = |
1267 | 18 | _missing_equality_delete_values.emplace(name, std::move(default_column)).second; |
1268 | 18 | DORIS_CHECK(inserted); |
1269 | 18 | return Status::OK(); |
1270 | 19 | } _ZN5doris18IcebergReaderMixinINS_13ParquetReaderEE40_register_missing_equality_delete_columnEiRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKSt10shared_ptrIKNS_9IDataTypeEE Line | Count | Source | 1257 | 12 | int32_t field_id, const std::string& name, const DataTypePtr& delete_key_type) { | 1258 | 12 | DORIS_CHECK(delete_key_type != nullptr); | 1259 | 12 | ColumnPtr default_column; | 1260 | 12 | RETURN_IF_ERROR( | 1261 | 12 | _create_missing_equality_delete_value(field_id, delete_key_type, 0, &default_column)); | 1262 | | // The key is appended after the read (on_after_read_block), not by a synthesized-column | 1263 | | // handler: the reader filters only the columns its block had before the read, and Parquet's | 1264 | | // lazy read also looks up a tuple slot for every synthesized column, which this hidden key | 1265 | | // does not have. | 1266 | 11 | const bool inserted = | 1267 | 11 | _missing_equality_delete_values.emplace(name, std::move(default_column)).second; | 1268 | 11 | DORIS_CHECK(inserted); | 1269 | 11 | return Status::OK(); | 1270 | 12 | } |
_ZN5doris18IcebergReaderMixinINS_9OrcReaderEE40_register_missing_equality_delete_columnEiRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKSt10shared_ptrIKNS_9IDataTypeEE Line | Count | Source | 1257 | 7 | int32_t field_id, const std::string& name, const DataTypePtr& delete_key_type) { | 1258 | 7 | DORIS_CHECK(delete_key_type != nullptr); | 1259 | 7 | ColumnPtr default_column; | 1260 | 7 | RETURN_IF_ERROR( | 1261 | 7 | _create_missing_equality_delete_value(field_id, delete_key_type, 0, &default_column)); | 1262 | | // The key is appended after the read (on_after_read_block), not by a synthesized-column | 1263 | | // handler: the reader filters only the columns its block had before the read, and Parquet's | 1264 | | // lazy read also looks up a tuple slot for every synthesized column, which this hidden key | 1265 | | // does not have. | 1266 | 7 | const bool inserted = | 1267 | 7 | _missing_equality_delete_values.emplace(name, std::move(default_column)).second; | 1268 | 7 | DORIS_CHECK(inserted); | 1269 | 7 | return Status::OK(); | 1270 | 7 | } |
|
1271 | | |
1272 | | template <typename BaseReader> |
1273 | | bool IcebergReaderMixin<BaseReader>::_is_derived_equality_delete_column( |
1274 | 41 | const std::string& name) const { |
1275 | 41 | return std::ranges::any_of(_nested_equality_delete_columns, [&](const auto& nested_field) { |
1276 | 40 | return nested_field.block_name == name && !nested_field.source_block_name.empty(); |
1277 | 40 | }); _ZZNK5doris18IcebergReaderMixinINS_13ParquetReaderEE34_is_derived_equality_delete_columnERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEENKUlRKT_E_clINS2_26NestedEqualityDeleteColumnEEEDaSD_ Line | Count | Source | 1275 | 30 | return std::ranges::any_of(_nested_equality_delete_columns, [&](const auto& nested_field) { | 1276 | 30 | return nested_field.block_name == name && !nested_field.source_block_name.empty(); | 1277 | 30 | }); |
_ZZNK5doris18IcebergReaderMixinINS_9OrcReaderEE34_is_derived_equality_delete_columnERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEENKUlRKT_E_clINS2_26NestedEqualityDeleteColumnEEEDaSD_ Line | Count | Source | 1275 | 10 | return std::ranges::any_of(_nested_equality_delete_columns, [&](const auto& nested_field) { | 1276 | 10 | return nested_field.block_name == name && !nested_field.source_block_name.empty(); | 1277 | 10 | }); |
|
1278 | 41 | } _ZNK5doris18IcebergReaderMixinINS_13ParquetReaderEE34_is_derived_equality_delete_columnERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE Line | Count | Source | 1274 | 28 | const std::string& name) const { | 1275 | 28 | return std::ranges::any_of(_nested_equality_delete_columns, [&](const auto& nested_field) { | 1276 | 28 | return nested_field.block_name == name && !nested_field.source_block_name.empty(); | 1277 | 28 | }); | 1278 | 28 | } |
_ZNK5doris18IcebergReaderMixinINS_9OrcReaderEE34_is_derived_equality_delete_columnERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE Line | Count | Source | 1274 | 13 | const std::string& name) const { | 1275 | 13 | return std::ranges::any_of(_nested_equality_delete_columns, [&](const auto& nested_field) { | 1276 | 13 | return nested_field.block_name == name && !nested_field.source_block_name.empty(); | 1277 | 13 | }); | 1278 | 13 | } |
|
1279 | | |
1280 | | template <typename BaseReader> |
1281 | | Status IcebergReaderMixin<BaseReader>::_materialize_missing_equality_delete_column( |
1282 | 18 | Block* block, const std::string& name, const ColumnPtr& value, size_t rows) { |
1283 | 18 | if (!this->col_name_to_block_idx_ref()->contains(name)) { |
1284 | | // A key that is absent from the file is not a physical child of the reader, so the block |
1285 | | // has no column for it: append one before equality-delete filtering. MultiEqualityDelete |
1286 | | // requires a full, batch-sized column. |
1287 | 13 | const auto expand_col = std::ranges::find_if( |
1288 | 13 | _expand_columns, |
1289 | 15 | [&](const ColumnWithTypeAndName& col) { return col.name == name; });_ZZN5doris18IcebergReaderMixinINS_13ParquetReaderEE43_materialize_missing_equality_delete_columnEPNS_5BlockERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKNS_3COWINS_7IColumnEE13immutable_ptrISE_EEmENKUlRKNS_21ColumnWithTypeAndNameEE_clESM_ Line | Count | Source | 1289 | 7 | [&](const ColumnWithTypeAndName& col) { return col.name == name; }); |
_ZZN5doris18IcebergReaderMixinINS_9OrcReaderEE43_materialize_missing_equality_delete_columnEPNS_5BlockERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKNS_3COWINS_7IColumnEE13immutable_ptrISE_EEmENKUlRKNS_21ColumnWithTypeAndNameEE_clESM_ Line | Count | Source | 1289 | 8 | [&](const ColumnWithTypeAndName& col) { return col.name == name; }); |
|
1290 | 13 | DORIS_CHECK(expand_col != _expand_columns.end()); |
1291 | 13 | (*this->col_name_to_block_idx_ref())[name] = block->columns(); |
1292 | 13 | block->insert( |
1293 | 13 | {iceberg::repeat_initial_default_column(value, rows), expand_col->type, name}); |
1294 | 13 | return Status::OK(); |
1295 | 13 | } |
1296 | 5 | const auto position = this->col_name_to_block_idx_ref()->at(name); |
1297 | 5 | DORIS_CHECK(position < block->columns()); |
1298 | 5 | DORIS_CHECK(block->get_by_position(position).column->empty()); |
1299 | | // MultiEqualityDelete hashes each key column directly. Materialize the repeated default so |
1300 | | // every key has the batch row count; a ColumnConst keeps only one nested value and therefore |
1301 | | // cannot participate in the row-wise multi-column hash contract. |
1302 | 5 | block->get_by_position(position).column = iceberg::repeat_initial_default_column(value, rows); |
1303 | 5 | return Status::OK(); |
1304 | 18 | } _ZN5doris18IcebergReaderMixinINS_13ParquetReaderEE43_materialize_missing_equality_delete_columnEPNS_5BlockERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKNS_3COWINS_7IColumnEE13immutable_ptrISE_EEm Line | Count | Source | 1282 | 11 | Block* block, const std::string& name, const ColumnPtr& value, size_t rows) { | 1283 | 11 | if (!this->col_name_to_block_idx_ref()->contains(name)) { | 1284 | | // A key that is absent from the file is not a physical child of the reader, so the block | 1285 | | // has no column for it: append one before equality-delete filtering. MultiEqualityDelete | 1286 | | // requires a full, batch-sized column. | 1287 | 6 | const auto expand_col = std::ranges::find_if( | 1288 | 6 | _expand_columns, | 1289 | 6 | [&](const ColumnWithTypeAndName& col) { return col.name == name; }); | 1290 | 6 | DORIS_CHECK(expand_col != _expand_columns.end()); | 1291 | 6 | (*this->col_name_to_block_idx_ref())[name] = block->columns(); | 1292 | 6 | block->insert( | 1293 | 6 | {iceberg::repeat_initial_default_column(value, rows), expand_col->type, name}); | 1294 | 6 | return Status::OK(); | 1295 | 6 | } | 1296 | 5 | const auto position = this->col_name_to_block_idx_ref()->at(name); | 1297 | 5 | DORIS_CHECK(position < block->columns()); | 1298 | 5 | DORIS_CHECK(block->get_by_position(position).column->empty()); | 1299 | | // MultiEqualityDelete hashes each key column directly. Materialize the repeated default so | 1300 | | // every key has the batch row count; a ColumnConst keeps only one nested value and therefore | 1301 | | // cannot participate in the row-wise multi-column hash contract. | 1302 | 5 | block->get_by_position(position).column = iceberg::repeat_initial_default_column(value, rows); | 1303 | 5 | return Status::OK(); | 1304 | 11 | } |
_ZN5doris18IcebergReaderMixinINS_9OrcReaderEE43_materialize_missing_equality_delete_columnEPNS_5BlockERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKNS_3COWINS_7IColumnEE13immutable_ptrISE_EEm Line | Count | Source | 1282 | 7 | Block* block, const std::string& name, const ColumnPtr& value, size_t rows) { | 1283 | 7 | if (!this->col_name_to_block_idx_ref()->contains(name)) { | 1284 | | // A key that is absent from the file is not a physical child of the reader, so the block | 1285 | | // has no column for it: append one before equality-delete filtering. MultiEqualityDelete | 1286 | | // requires a full, batch-sized column. | 1287 | 7 | const auto expand_col = std::ranges::find_if( | 1288 | 7 | _expand_columns, | 1289 | 7 | [&](const ColumnWithTypeAndName& col) { return col.name == name; }); | 1290 | 7 | DORIS_CHECK(expand_col != _expand_columns.end()); | 1291 | 7 | (*this->col_name_to_block_idx_ref())[name] = block->columns(); | 1292 | 7 | block->insert( | 1293 | 7 | {iceberg::repeat_initial_default_column(value, rows), expand_col->type, name}); | 1294 | 7 | return Status::OK(); | 1295 | 7 | } | 1296 | 0 | const auto position = this->col_name_to_block_idx_ref()->at(name); | 1297 | 0 | DORIS_CHECK(position < block->columns()); | 1298 | 0 | DORIS_CHECK(block->get_by_position(position).column->empty()); | 1299 | | // MultiEqualityDelete hashes each key column directly. Materialize the repeated default so | 1300 | | // every key has the batch row count; a ColumnConst keeps only one nested value and therefore | 1301 | | // cannot participate in the row-wise multi-column hash contract. | 1302 | 0 | block->get_by_position(position).column = iceberg::repeat_initial_default_column(value, rows); | 1303 | 0 | return Status::OK(); | 1304 | 7 | } |
|
1305 | | |
1306 | | template <typename BaseReader> |
1307 | | Status IcebergReaderMixin<BaseReader>::_materialize_missing_equality_delete_columns(Block* block, |
1308 | 64 | size_t rows) { |
1309 | 64 | for (const auto& [name, value] : _missing_equality_delete_values) { |
1310 | 18 | RETURN_IF_ERROR(_materialize_missing_equality_delete_column(block, name, value, rows)); |
1311 | 18 | } |
1312 | 64 | return Status::OK(); |
1313 | 64 | } _ZN5doris18IcebergReaderMixinINS_13ParquetReaderEE44_materialize_missing_equality_delete_columnsEPNS_5BlockEm Line | Count | Source | 1308 | 40 | size_t rows) { | 1309 | 40 | for (const auto& [name, value] : _missing_equality_delete_values) { | 1310 | 11 | RETURN_IF_ERROR(_materialize_missing_equality_delete_column(block, name, value, rows)); | 1311 | 11 | } | 1312 | 40 | return Status::OK(); | 1313 | 40 | } |
_ZN5doris18IcebergReaderMixinINS_9OrcReaderEE44_materialize_missing_equality_delete_columnsEPNS_5BlockEm Line | Count | Source | 1308 | 24 | size_t rows) { | 1309 | 24 | for (const auto& [name, value] : _missing_equality_delete_values) { | 1310 | 7 | RETURN_IF_ERROR(_materialize_missing_equality_delete_column(block, name, value, rows)); | 1311 | 7 | } | 1312 | 24 | return Status::OK(); | 1313 | 24 | } |
|
1314 | | |
1315 | | template <typename BaseReader> |
1316 | 61 | Status IcebergReaderMixin<BaseReader>::_shrink_block_if_need(Block* block) { |
1317 | 61 | std::set<size_t> positions_to_erase; |
1318 | 61 | for (const std::string& expand_col : _expand_col_names) { |
1319 | 54 | if (!this->col_name_to_block_idx_ref()->contains(expand_col)) { |
1320 | 0 | return Status::InternalError("Wrong erase column '{}', block: {}", expand_col, |
1321 | 0 | block->dump_names()); |
1322 | 0 | } |
1323 | 54 | positions_to_erase.emplace((*this->col_name_to_block_idx_ref())[expand_col]); |
1324 | 54 | } |
1325 | 61 | block->erase(positions_to_erase); |
1326 | 61 | for (const std::string& expand_col : _expand_col_names) { |
1327 | 54 | this->col_name_to_block_idx_ref()->erase(expand_col); |
1328 | 54 | } |
1329 | 61 | return Status::OK(); |
1330 | 61 | } _ZN5doris18IcebergReaderMixinINS_13ParquetReaderEE21_shrink_block_if_needEPNS_5BlockE Line | Count | Source | 1316 | 37 | Status IcebergReaderMixin<BaseReader>::_shrink_block_if_need(Block* block) { | 1317 | 37 | std::set<size_t> positions_to_erase; | 1318 | 37 | for (const std::string& expand_col : _expand_col_names) { | 1319 | 34 | if (!this->col_name_to_block_idx_ref()->contains(expand_col)) { | 1320 | 0 | return Status::InternalError("Wrong erase column '{}', block: {}", expand_col, | 1321 | 0 | block->dump_names()); | 1322 | 0 | } | 1323 | 34 | positions_to_erase.emplace((*this->col_name_to_block_idx_ref())[expand_col]); | 1324 | 34 | } | 1325 | 37 | block->erase(positions_to_erase); | 1326 | 37 | for (const std::string& expand_col : _expand_col_names) { | 1327 | 34 | this->col_name_to_block_idx_ref()->erase(expand_col); | 1328 | 34 | } | 1329 | 37 | return Status::OK(); | 1330 | 37 | } |
_ZN5doris18IcebergReaderMixinINS_9OrcReaderEE21_shrink_block_if_needEPNS_5BlockE Line | Count | Source | 1316 | 24 | Status IcebergReaderMixin<BaseReader>::_shrink_block_if_need(Block* block) { | 1317 | 24 | std::set<size_t> positions_to_erase; | 1318 | 24 | for (const std::string& expand_col : _expand_col_names) { | 1319 | 20 | if (!this->col_name_to_block_idx_ref()->contains(expand_col)) { | 1320 | 0 | return Status::InternalError("Wrong erase column '{}', block: {}", expand_col, | 1321 | 0 | block->dump_names()); | 1322 | 0 | } | 1323 | 20 | positions_to_erase.emplace((*this->col_name_to_block_idx_ref())[expand_col]); | 1324 | 20 | } | 1325 | 24 | block->erase(positions_to_erase); | 1326 | 24 | for (const std::string& expand_col : _expand_col_names) { | 1327 | 20 | this->col_name_to_block_idx_ref()->erase(expand_col); | 1328 | 20 | } | 1329 | 24 | return Status::OK(); | 1330 | 24 | } |
|
1331 | | |
1332 | | template <typename BaseReader> |
1333 | | Status IcebergReaderMixin<BaseReader>::_position_delete_base( |
1334 | 2 | const std::string data_file_path, const std::vector<TIcebergDeleteFileDesc>& delete_files) { |
1335 | 2 | std::vector<DeleteRows*> delete_rows_array; |
1336 | 2 | int64_t num_delete_rows = 0; |
1337 | 2 | for (const auto& delete_file : delete_files) { |
1338 | 2 | SCOPED_TIMER(_iceberg_profile.delete_files_read_time); |
1339 | 2 | Status create_status = Status::OK(); |
1340 | 2 | auto* delete_file_cache = _kv_cache->template get<DeleteFile>( |
1341 | 2 | _delet_file_cache_key(delete_file.path), [&]() -> DeleteFile* { |
1342 | 2 | auto position_delete = std::make_unique<DeleteFile>(); |
1343 | 2 | TFileRangeDesc delete_file_range; |
1344 | 2 | delete_file_range.__set_fs_name(this->get_scan_range().fs_name); |
1345 | 2 | delete_file_range.path = delete_file.path; |
1346 | 2 | delete_file_range.start_offset = 0; |
1347 | 2 | delete_file_range.size = -1; |
1348 | 2 | delete_file_range.file_size = |
1349 | 2 | delete_file.__isset.file_size ? delete_file.file_size : -1; |
1350 | 2 | create_status = |
1351 | 2 | _read_position_delete_file(&delete_file_range, position_delete.get()); |
1352 | 2 | if (!create_status) { |
1353 | 2 | return nullptr; |
1354 | 2 | } |
1355 | 0 | return position_delete.release(); |
1356 | 2 | }); _ZZN5doris18IcebergReaderMixinINS_13ParquetReaderEE21_position_delete_baseENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKSt6vectorINS_22TIcebergDeleteFileDescESaISA_EEENKUlvE_clB5cxx11Ev Line | Count | Source | 1341 | 2 | _delet_file_cache_key(delete_file.path), [&]() -> DeleteFile* { | 1342 | 2 | auto position_delete = std::make_unique<DeleteFile>(); | 1343 | 2 | TFileRangeDesc delete_file_range; | 1344 | 2 | delete_file_range.__set_fs_name(this->get_scan_range().fs_name); | 1345 | 2 | delete_file_range.path = delete_file.path; | 1346 | 2 | delete_file_range.start_offset = 0; | 1347 | 2 | delete_file_range.size = -1; | 1348 | 2 | delete_file_range.file_size = | 1349 | 2 | delete_file.__isset.file_size ? delete_file.file_size : -1; | 1350 | 2 | create_status = | 1351 | 2 | _read_position_delete_file(&delete_file_range, position_delete.get()); | 1352 | 2 | if (!create_status) { | 1353 | 2 | return nullptr; | 1354 | 2 | } | 1355 | 0 | return position_delete.release(); | 1356 | 2 | }); |
Unexecuted instantiation: _ZZN5doris18IcebergReaderMixinINS_9OrcReaderEE21_position_delete_baseENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKSt6vectorINS_22TIcebergDeleteFileDescESaISA_EEENKUlvE_clB5cxx11Ev |
1357 | 2 | if (create_status.is<ErrorCode::END_OF_FILE>()) { |
1358 | 0 | continue; |
1359 | 2 | } else if (!create_status.ok()) { |
1360 | 2 | return create_status; |
1361 | 2 | } |
1362 | | |
1363 | 0 | DeleteFile& delete_file_map = *((DeleteFile*)delete_file_cache); |
1364 | 0 | auto get_value = [&](const auto& v) { |
1365 | 0 | DeleteRows* row_ids = v.second.get(); |
1366 | 0 | if (!row_ids->empty()) { |
1367 | 0 | delete_rows_array.emplace_back(row_ids); |
1368 | 0 | num_delete_rows += row_ids->size(); |
1369 | 0 | } |
1370 | 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_ |
1371 | 0 | delete_file_map.if_contains(data_file_path, get_value); |
1372 | 0 | } |
1373 | 0 | if (num_delete_rows > 0) { |
1374 | 0 | SCOPED_TIMER(_iceberg_profile.delete_rows_sort_time); |
1375 | 0 | _iceberg_delete_rows = |
1376 | 0 | _kv_cache->template get<DeleteRows>(data_file_path, [&]() -> DeleteRows* { |
1377 | 0 | auto data_file_position_delete = std::make_unique<DeleteRows>(); |
1378 | 0 | _sort_delete_rows(delete_rows_array, num_delete_rows, |
1379 | 0 | *data_file_position_delete); |
1380 | 0 | return data_file_position_delete.release(); |
1381 | 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 |
1382 | 0 | set_delete_rows(); |
1383 | 0 | COUNTER_UPDATE(_iceberg_profile.num_delete_rows, num_delete_rows); |
1384 | 0 | } |
1385 | 0 | return Status::OK(); |
1386 | 2 | } _ZN5doris18IcebergReaderMixinINS_13ParquetReaderEE21_position_delete_baseENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKSt6vectorINS_22TIcebergDeleteFileDescESaISA_EE Line | Count | Source | 1334 | 2 | const std::string data_file_path, const std::vector<TIcebergDeleteFileDesc>& delete_files) { | 1335 | 2 | std::vector<DeleteRows*> delete_rows_array; | 1336 | 2 | int64_t num_delete_rows = 0; | 1337 | 2 | for (const auto& delete_file : delete_files) { | 1338 | 2 | SCOPED_TIMER(_iceberg_profile.delete_files_read_time); | 1339 | 2 | Status create_status = Status::OK(); | 1340 | 2 | auto* delete_file_cache = _kv_cache->template get<DeleteFile>( | 1341 | 2 | _delet_file_cache_key(delete_file.path), [&]() -> DeleteFile* { | 1342 | 2 | auto position_delete = std::make_unique<DeleteFile>(); | 1343 | 2 | TFileRangeDesc delete_file_range; | 1344 | 2 | delete_file_range.__set_fs_name(this->get_scan_range().fs_name); | 1345 | 2 | delete_file_range.path = delete_file.path; | 1346 | 2 | delete_file_range.start_offset = 0; | 1347 | 2 | delete_file_range.size = -1; | 1348 | 2 | delete_file_range.file_size = | 1349 | 2 | delete_file.__isset.file_size ? delete_file.file_size : -1; | 1350 | 2 | create_status = | 1351 | 2 | _read_position_delete_file(&delete_file_range, position_delete.get()); | 1352 | 2 | if (!create_status) { | 1353 | 2 | return nullptr; | 1354 | 2 | } | 1355 | 2 | return position_delete.release(); | 1356 | 2 | }); | 1357 | 2 | if (create_status.is<ErrorCode::END_OF_FILE>()) { | 1358 | 0 | continue; | 1359 | 2 | } else if (!create_status.ok()) { | 1360 | 2 | return create_status; | 1361 | 2 | } | 1362 | | | 1363 | 0 | DeleteFile& delete_file_map = *((DeleteFile*)delete_file_cache); | 1364 | 0 | auto get_value = [&](const auto& v) { | 1365 | 0 | DeleteRows* row_ids = v.second.get(); | 1366 | 0 | if (!row_ids->empty()) { | 1367 | 0 | delete_rows_array.emplace_back(row_ids); | 1368 | 0 | num_delete_rows += row_ids->size(); | 1369 | 0 | } | 1370 | 0 | }; | 1371 | 0 | delete_file_map.if_contains(data_file_path, get_value); | 1372 | 0 | } | 1373 | 0 | if (num_delete_rows > 0) { | 1374 | 0 | SCOPED_TIMER(_iceberg_profile.delete_rows_sort_time); | 1375 | 0 | _iceberg_delete_rows = | 1376 | 0 | _kv_cache->template get<DeleteRows>(data_file_path, [&]() -> DeleteRows* { | 1377 | 0 | auto data_file_position_delete = std::make_unique<DeleteRows>(); | 1378 | 0 | _sort_delete_rows(delete_rows_array, num_delete_rows, | 1379 | 0 | *data_file_position_delete); | 1380 | 0 | return data_file_position_delete.release(); | 1381 | 0 | }); | 1382 | 0 | set_delete_rows(); | 1383 | 0 | COUNTER_UPDATE(_iceberg_profile.num_delete_rows, num_delete_rows); | 1384 | 0 | } | 1385 | 0 | return Status::OK(); | 1386 | 2 | } |
Unexecuted instantiation: _ZN5doris18IcebergReaderMixinINS_9OrcReaderEE21_position_delete_baseENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKSt6vectorINS_22TIcebergDeleteFileDescESaISA_EE |
1387 | | |
1388 | | template <typename BaseReader> |
1389 | | typename IcebergReaderMixin<BaseReader>::PositionDeleteRange |
1390 | 0 | IcebergReaderMixin<BaseReader>::_get_range(const ColumnDictI32& file_path_column) { |
1391 | 0 | PositionDeleteRange range; |
1392 | 0 | size_t read_rows = file_path_column.get_data().size(); |
1393 | 0 | const int* code_path = file_path_column.get_data().data(); |
1394 | 0 | const int* code_path_start = code_path; |
1395 | 0 | const int* code_path_end = code_path + read_rows; |
1396 | 0 | while (code_path < code_path_end) { |
1397 | 0 | int code = code_path[0]; |
1398 | 0 | const int* code_end = std::upper_bound(code_path, code_path_end, code); |
1399 | 0 | range.data_file_path.emplace_back(file_path_column.get_value(code).to_string()); |
1400 | 0 | range.range.emplace_back(code_path - code_path_start, code_end - code_path_start); |
1401 | 0 | code_path = code_end; |
1402 | 0 | } |
1403 | 0 | return range; |
1404 | 0 | } Unexecuted instantiation: _ZN5doris18IcebergReaderMixinINS_13ParquetReaderEE10_get_rangeERKNS_13ColumnDictI32E Unexecuted instantiation: _ZN5doris18IcebergReaderMixinINS_9OrcReaderEE10_get_rangeERKNS_13ColumnDictI32E |
1405 | | |
1406 | | template <typename BaseReader> |
1407 | | typename IcebergReaderMixin<BaseReader>::PositionDeleteRange |
1408 | 0 | IcebergReaderMixin<BaseReader>::_get_range(const ColumnString& file_path_column) { |
1409 | 0 | PositionDeleteRange range; |
1410 | 0 | size_t read_rows = file_path_column.size(); |
1411 | 0 | size_t index = 0; |
1412 | 0 | while (index < read_rows) { |
1413 | 0 | StringRef data_path = file_path_column.get_data_at(index); |
1414 | 0 | size_t left = index - 1; |
1415 | 0 | size_t right = read_rows; |
1416 | 0 | while (left + 1 != right) { |
1417 | 0 | size_t mid = left + (right - left) / 2; |
1418 | 0 | if (file_path_column.get_data_at(mid) > data_path) { |
1419 | 0 | right = mid; |
1420 | 0 | } else { |
1421 | 0 | left = mid; |
1422 | 0 | } |
1423 | 0 | } |
1424 | 0 | range.data_file_path.emplace_back(data_path.to_string()); |
1425 | 0 | range.range.emplace_back(index, left + 1); |
1426 | 0 | index = left + 1; |
1427 | 0 | } |
1428 | 0 | return range; |
1429 | 0 | } Unexecuted instantiation: _ZN5doris18IcebergReaderMixinINS_13ParquetReaderEE10_get_rangeERKNS_9ColumnStrIjEE Unexecuted instantiation: _ZN5doris18IcebergReaderMixinINS_9OrcReaderEE10_get_rangeERKNS_9ColumnStrIjEE |
1430 | | |
1431 | | template <typename BaseReader> |
1432 | | void IcebergReaderMixin<BaseReader>::_sort_delete_rows( |
1433 | | const std::vector<std::vector<int64_t>*>& delete_rows_array, int64_t num_delete_rows, |
1434 | 0 | std::vector<int64_t>& result) { |
1435 | 0 | if (delete_rows_array.empty()) { |
1436 | 0 | return; |
1437 | 0 | } |
1438 | 0 | if (delete_rows_array.size() == 1) { |
1439 | 0 | result.resize(num_delete_rows); |
1440 | 0 | memcpy(result.data(), delete_rows_array.front()->data(), sizeof(int64_t) * num_delete_rows); |
1441 | 0 | return; |
1442 | 0 | } |
1443 | 0 | if (delete_rows_array.size() == 2) { |
1444 | 0 | result.resize(num_delete_rows); |
1445 | 0 | std::merge(delete_rows_array.front()->begin(), delete_rows_array.front()->end(), |
1446 | 0 | delete_rows_array.back()->begin(), delete_rows_array.back()->end(), |
1447 | 0 | result.begin()); |
1448 | 0 | return; |
1449 | 0 | } |
1450 | | |
1451 | 0 | using vec_pair = std::pair<std::vector<int64_t>::iterator, std::vector<int64_t>::iterator>; |
1452 | 0 | result.resize(num_delete_rows); |
1453 | 0 | auto row_id_iter = result.begin(); |
1454 | 0 | auto iter_end = result.end(); |
1455 | 0 | std::vector<vec_pair> rows_array; |
1456 | 0 | for (auto* rows : delete_rows_array) { |
1457 | 0 | if (!rows->empty()) { |
1458 | 0 | rows_array.emplace_back(rows->begin(), rows->end()); |
1459 | 0 | } |
1460 | 0 | } |
1461 | 0 | size_t array_size = rows_array.size(); |
1462 | 0 | while (row_id_iter != iter_end) { |
1463 | 0 | int64_t min_index = 0; |
1464 | 0 | int64_t min = *rows_array[0].first; |
1465 | 0 | for (size_t i = 0; i < array_size; ++i) { |
1466 | 0 | if (*rows_array[i].first < min) { |
1467 | 0 | min_index = i; |
1468 | 0 | min = *rows_array[i].first; |
1469 | 0 | } |
1470 | 0 | } |
1471 | 0 | *row_id_iter++ = min; |
1472 | 0 | rows_array[min_index].first++; |
1473 | 0 | if (UNLIKELY(rows_array[min_index].first == rows_array[min_index].second)) { |
1474 | 0 | rows_array.erase(rows_array.begin() + min_index); |
1475 | 0 | array_size--; |
1476 | 0 | } |
1477 | 0 | } |
1478 | 0 | } Unexecuted instantiation: _ZN5doris18IcebergReaderMixinINS_13ParquetReaderEE17_sort_delete_rowsERKSt6vectorIPS3_IlSaIlEESaIS6_EElRS5_ Unexecuted instantiation: _ZN5doris18IcebergReaderMixinINS_9OrcReaderEE17_sort_delete_rowsERKSt6vectorIPS3_IlSaIlEESaIS6_EElRS5_ |
1479 | | |
1480 | | template <typename BaseReader> |
1481 | | Status IcebergReaderMixin<BaseReader>::_gen_position_delete_file_range( |
1482 | | Block& block, DeleteFile* position_delete, size_t read_rows, |
1483 | 0 | bool file_path_column_dictionary_coded) { |
1484 | 0 | SCOPED_TIMER(_iceberg_profile.parse_delete_file_time); |
1485 | 0 | auto name_to_pos_map = block.get_name_to_pos_map(); |
1486 | 0 | ColumnPtr path_column = block.get_by_position(name_to_pos_map[ICEBERG_FILE_PATH]).column; |
1487 | 0 | DCHECK_EQ(path_column->size(), read_rows); |
1488 | 0 | ColumnPtr pos_column = block.get_by_position(name_to_pos_map[ICEBERG_ROW_POS]).column; |
1489 | 0 | if (const auto* nullable_col = check_and_get_column<ColumnNullable>(*path_column); |
1490 | 0 | nullable_col != nullptr) { |
1491 | 0 | if (nullable_col->has_null(0, read_rows)) { |
1492 | 0 | return Status::Corruption( |
1493 | 0 | "Iceberg position delete column file_path contains null values"); |
1494 | 0 | } |
1495 | 0 | path_column = remove_nullable(path_column); |
1496 | 0 | } |
1497 | 0 | if (const auto* nullable_col = check_and_get_column<ColumnNullable>(*pos_column); |
1498 | 0 | nullable_col != nullptr) { |
1499 | 0 | if (nullable_col->has_null(0, read_rows)) { |
1500 | 0 | return Status::Corruption("Iceberg position delete column pos contains null values"); |
1501 | 0 | } |
1502 | 0 | pos_column = remove_nullable(pos_column); |
1503 | 0 | } |
1504 | 0 | using ColumnType = typename PrimitiveTypeTraits<TYPE_BIGINT>::ColumnType; |
1505 | 0 | const int64_t* src_data = assert_cast<const ColumnType&>(*pos_column).get_data().data(); |
1506 | 0 | PositionDeleteRange range; |
1507 | 0 | if (file_path_column_dictionary_coded) { |
1508 | 0 | range = _get_range(assert_cast<const ColumnDictI32&>(*path_column)); |
1509 | 0 | } else { |
1510 | 0 | range = _get_range(assert_cast<const ColumnString&>(*path_column)); |
1511 | 0 | } |
1512 | 0 | for (int i = 0; i < range.range.size(); ++i) { |
1513 | 0 | std::string key = range.data_file_path[i]; |
1514 | 0 | auto iter = position_delete->find(key); |
1515 | 0 | DeleteRows* delete_rows; |
1516 | 0 | if (iter == position_delete->end()) { |
1517 | 0 | delete_rows = new DeleteRows; |
1518 | 0 | std::unique_ptr<DeleteRows> delete_rows_ptr(delete_rows); |
1519 | 0 | (*position_delete)[key] = std::move(delete_rows_ptr); |
1520 | 0 | } else { |
1521 | 0 | delete_rows = iter->second.get(); |
1522 | 0 | } |
1523 | 0 | const int64_t* cpy_start = src_data + range.range[i].first; |
1524 | 0 | const int64_t cpy_count = range.range[i].second - range.range[i].first; |
1525 | 0 | int64_t origin_size = delete_rows->size(); |
1526 | 0 | delete_rows->resize(origin_size + cpy_count); |
1527 | 0 | int64_t* dest_position = &(*delete_rows)[origin_size]; |
1528 | 0 | memcpy(dest_position, cpy_start, cpy_count * sizeof(int64_t)); |
1529 | 0 | } |
1530 | 0 | return Status::OK(); |
1531 | 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 |
1532 | | |
1533 | | template <typename BaseReader> |
1534 | | Status IcebergReaderMixin<BaseReader>::read_deletion_vector( |
1535 | 1 | const std::string& data_file_path, const TIcebergDeleteFileDesc& delete_file_desc) { |
1536 | 1 | size_t bytes_read = 0; |
1537 | 1 | RETURN_IF_ERROR(validate_iceberg_deletion_vector_descriptor(delete_file_desc, bytes_read)); |
1538 | | |
1539 | 1 | Status create_status = Status::OK(); |
1540 | 1 | SCOPED_TIMER(_iceberg_profile.delete_files_read_time); |
1541 | 1 | bool decoded_cache_hit = false; |
1542 | 1 | _iceberg_deletion_vector = _kv_cache->template get<DeletionVector>( |
1543 | 1 | build_iceberg_deletion_vector_cache_key(data_file_path, delete_file_desc), |
1544 | 1 | [&]() -> DeletionVector* { |
1545 | 1 | auto deletion_vector = std::make_unique<DeletionVector>(); |
1546 | | |
1547 | 1 | io::FileCacheStatistics file_cache_stats; |
1548 | 1 | IcebergDeleteFileReaderOptions options; |
1549 | 1 | options.state = this->get_state(); |
1550 | 1 | options.profile = this->get_profile(); |
1551 | 1 | options.scan_params = &this->get_scan_params(); |
1552 | 1 | options.io_ctx = this->get_io_ctx(); |
1553 | 1 | options.fs_name = &this->get_scan_range().fs_name; |
1554 | 1 | options.deletion_vector_file_cache_stats = &file_cache_stats; |
1555 | 1 | create_status = read_iceberg_deletion_vector(delete_file_desc, options, |
1556 | 1 | deletion_vector.get()); |
1557 | 1 | COUNTER_UPDATE(_iceberg_profile.file_cache_hit_count, |
1558 | 1 | file_cache_stats.num_local_io_total); |
1559 | 1 | COUNTER_UPDATE(_iceberg_profile.file_cache_miss_count, |
1560 | 1 | file_cache_stats.num_remote_io_total); |
1561 | 1 | COUNTER_UPDATE(_iceberg_profile.file_cache_peer_read_count, |
1562 | 1 | file_cache_stats.num_peer_io_total); |
1563 | 1 | if (!create_status.ok()) [[unlikely]] { |
1564 | 1 | return nullptr; |
1565 | 1 | } |
1566 | | |
1567 | 0 | SCOPED_TIMER(_iceberg_profile.parse_delete_file_time); |
1568 | 0 | COUNTER_UPDATE(_iceberg_profile.num_delete_rows, deletion_vector->cardinality()); |
1569 | 0 | return deletion_vector.release(); |
1570 | 1 | }, _ZZN5doris18IcebergReaderMixinINS_13ParquetReaderEE20read_deletion_vectorERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKNS_22TIcebergDeleteFileDescEENKUlvE_clEv Line | Count | Source | 1544 | 1 | [&]() -> DeletionVector* { | 1545 | 1 | auto deletion_vector = std::make_unique<DeletionVector>(); | 1546 | | | 1547 | 1 | io::FileCacheStatistics file_cache_stats; | 1548 | 1 | IcebergDeleteFileReaderOptions options; | 1549 | 1 | options.state = this->get_state(); | 1550 | 1 | options.profile = this->get_profile(); | 1551 | 1 | options.scan_params = &this->get_scan_params(); | 1552 | 1 | options.io_ctx = this->get_io_ctx(); | 1553 | 1 | options.fs_name = &this->get_scan_range().fs_name; | 1554 | 1 | options.deletion_vector_file_cache_stats = &file_cache_stats; | 1555 | 1 | create_status = read_iceberg_deletion_vector(delete_file_desc, options, | 1556 | 1 | deletion_vector.get()); | 1557 | 1 | COUNTER_UPDATE(_iceberg_profile.file_cache_hit_count, | 1558 | 1 | file_cache_stats.num_local_io_total); | 1559 | 1 | COUNTER_UPDATE(_iceberg_profile.file_cache_miss_count, | 1560 | 1 | file_cache_stats.num_remote_io_total); | 1561 | 1 | COUNTER_UPDATE(_iceberg_profile.file_cache_peer_read_count, | 1562 | 1 | file_cache_stats.num_peer_io_total); | 1563 | 1 | if (!create_status.ok()) [[unlikely]] { | 1564 | 1 | return nullptr; | 1565 | 1 | } | 1566 | | | 1567 | 0 | SCOPED_TIMER(_iceberg_profile.parse_delete_file_time); | 1568 | 0 | COUNTER_UPDATE(_iceberg_profile.num_delete_rows, deletion_vector->cardinality()); | 1569 | 0 | return deletion_vector.release(); | 1570 | 1 | }, |
Unexecuted instantiation: _ZZN5doris18IcebergReaderMixinINS_9OrcReaderEE20read_deletion_vectorERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKNS_22TIcebergDeleteFileDescEENKUlvE_clEv |
1571 | 1 | &decoded_cache_hit); |
1572 | | |
1573 | 1 | RETURN_IF_ERROR(create_status); |
1574 | 0 | COUNTER_UPDATE(decoded_cache_hit ? _iceberg_profile.decoded_cache_hit_count |
1575 | 0 | : _iceberg_profile.decoded_cache_miss_count, |
1576 | 0 | 1); |
1577 | 0 | if (!_iceberg_deletion_vector->isEmpty()) [[likely]] { |
1578 | 0 | set_deletion_vector(); |
1579 | 0 | } |
1580 | 0 | return Status::OK(); |
1581 | 1 | } _ZN5doris18IcebergReaderMixinINS_13ParquetReaderEE20read_deletion_vectorERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKNS_22TIcebergDeleteFileDescE Line | Count | Source | 1535 | 1 | const std::string& data_file_path, const TIcebergDeleteFileDesc& delete_file_desc) { | 1536 | 1 | size_t bytes_read = 0; | 1537 | 1 | RETURN_IF_ERROR(validate_iceberg_deletion_vector_descriptor(delete_file_desc, bytes_read)); | 1538 | | | 1539 | 1 | Status create_status = Status::OK(); | 1540 | 1 | SCOPED_TIMER(_iceberg_profile.delete_files_read_time); | 1541 | 1 | bool decoded_cache_hit = false; | 1542 | 1 | _iceberg_deletion_vector = _kv_cache->template get<DeletionVector>( | 1543 | 1 | build_iceberg_deletion_vector_cache_key(data_file_path, delete_file_desc), | 1544 | 1 | [&]() -> DeletionVector* { | 1545 | 1 | auto deletion_vector = std::make_unique<DeletionVector>(); | 1546 | | | 1547 | 1 | io::FileCacheStatistics file_cache_stats; | 1548 | 1 | IcebergDeleteFileReaderOptions options; | 1549 | 1 | options.state = this->get_state(); | 1550 | 1 | options.profile = this->get_profile(); | 1551 | 1 | options.scan_params = &this->get_scan_params(); | 1552 | 1 | options.io_ctx = this->get_io_ctx(); | 1553 | 1 | options.fs_name = &this->get_scan_range().fs_name; | 1554 | 1 | options.deletion_vector_file_cache_stats = &file_cache_stats; | 1555 | 1 | create_status = read_iceberg_deletion_vector(delete_file_desc, options, | 1556 | 1 | deletion_vector.get()); | 1557 | 1 | COUNTER_UPDATE(_iceberg_profile.file_cache_hit_count, | 1558 | 1 | file_cache_stats.num_local_io_total); | 1559 | 1 | COUNTER_UPDATE(_iceberg_profile.file_cache_miss_count, | 1560 | 1 | file_cache_stats.num_remote_io_total); | 1561 | 1 | COUNTER_UPDATE(_iceberg_profile.file_cache_peer_read_count, | 1562 | 1 | file_cache_stats.num_peer_io_total); | 1563 | 1 | if (!create_status.ok()) [[unlikely]] { | 1564 | 1 | return nullptr; | 1565 | 1 | } | 1566 | | | 1567 | 1 | SCOPED_TIMER(_iceberg_profile.parse_delete_file_time); | 1568 | 1 | COUNTER_UPDATE(_iceberg_profile.num_delete_rows, deletion_vector->cardinality()); | 1569 | 1 | return deletion_vector.release(); | 1570 | 1 | }, | 1571 | 1 | &decoded_cache_hit); | 1572 | | | 1573 | 1 | RETURN_IF_ERROR(create_status); | 1574 | 0 | COUNTER_UPDATE(decoded_cache_hit ? _iceberg_profile.decoded_cache_hit_count | 1575 | 0 | : _iceberg_profile.decoded_cache_miss_count, | 1576 | 0 | 1); | 1577 | 0 | if (!_iceberg_deletion_vector->isEmpty()) [[likely]] { | 1578 | 0 | set_deletion_vector(); | 1579 | 0 | } | 1580 | 0 | return Status::OK(); | 1581 | 1 | } |
Unexecuted instantiation: _ZN5doris18IcebergReaderMixinINS_9OrcReaderEE20read_deletion_vectorERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKNS_22TIcebergDeleteFileDescE |
1582 | | |
1583 | | } // namespace doris |