iceberg-cpp
Loading...
Searching...
No Matches
merging_snapshot_update.h
Go to the documentation of this file.
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19
20#pragma once
21
23
24#include <cstdint>
25#include <memory>
26#include <optional>
27#include <string>
28#include <unordered_map>
29#include <unordered_set>
30#include <vector>
31
33#include "iceberg/iceberg_export.h"
36#include "iceberg/result.h"
37#include "iceberg/type_fwd.h"
38#include "iceberg/update/snapshot_update.h"
40
41namespace iceberg {
42
69class ICEBERG_EXPORT MergingSnapshotUpdate : public SnapshotUpdate {
70 public:
71 ~MergingSnapshotUpdate() override = default;
72
73 // SnapshotUpdate overrides
74 Result<std::vector<ManifestFile>> Apply(
75 const TableMetadata& metadata_to_update,
76 const std::shared_ptr<Snapshot>& snapshot) override;
77
78 Status CleanUncommitted(const std::unordered_set<std::string>& committed) override;
79
80 std::unordered_map<std::string, std::string> Summary() override;
81
82 protected:
84 explicit MergingSnapshotUpdate(std::string table_name,
85 std::shared_ptr<TransactionContext> ctx);
86
88 Status AddDataFile(std::shared_ptr<DataFile> file);
89
91 Status AddDeleteFile(std::shared_ptr<DataFile> file);
92
98 Status ValidateNewDeleteFile(const TableMetadata& metadata, const DataFile& file);
99
102 Status AddDeleteFile(std::shared_ptr<DataFile> file, int64_t data_sequence_number);
103
109 Status AddManifest(ManifestFile manifest);
110
112 Status DeleteDataFile(std::shared_ptr<DataFile> file);
113
115 Status DeleteDeleteFile(std::shared_ptr<DataFile> file);
116
120 Status DeleteByPath(std::string_view path);
121
127 Status DeleteByRowFilter(std::shared_ptr<Expression> expr);
128
133 Status DropPartition(int32_t spec_id, PartitionValues partition);
134
136 void FailMissingDeletePaths();
137
139 void FailAnyDelete();
140
142 void SetNewDataFilesDataSequenceNumber(int64_t sequence_number);
143
146 return new_data_files_data_seq_number_.has_value();
147 }
148
150 void CaseSensitive(bool case_sensitive);
151
153 bool IsCaseSensitive() const { return case_sensitive_; }
154
156 bool AddsDataFiles() const;
157
159 bool AddsDeleteFiles() const;
160
162 bool DeletesDataFiles() const;
163
165 bool DeletesDeleteFiles() const;
166
168 const std::shared_ptr<Expression>& RowFilter() const { return delete_expression_; }
169
174 Result<std::shared_ptr<PartitionSpec>> DataSpec() const;
175
177 std::vector<std::shared_ptr<DataFile>> AddedDataFiles() const;
178
181 static Status ValidateAddedDataFiles(const TableMetadata& metadata,
182 std::optional<int64_t> starting_snapshot_id,
183 std::shared_ptr<Expression> filter,
184 const std::shared_ptr<Snapshot>& parent,
185 std::shared_ptr<FileIO> io,
186 bool case_sensitive = true);
187
191 static Status ValidateAddedDataFiles(const TableMetadata& metadata,
192 std::optional<int64_t> starting_snapshot_id,
193 const PartitionSet& partition_set,
194 const std::shared_ptr<Snapshot>& parent,
195 std::shared_ptr<FileIO> io);
196
200 static Status ValidateDataFilesExist(
201 const TableMetadata& metadata, std::optional<int64_t> starting_snapshot_id,
202 const std::unordered_set<std::string>& file_paths, bool skip_deletes,
203 std::shared_ptr<Expression> filter, const std::shared_ptr<Snapshot>& parent,
204 std::shared_ptr<FileIO> io, bool case_sensitive = true);
205
216 std::optional<int64_t> starting_snapshot_id,
217 const DataFileSet& replaced_files,
218 const std::shared_ptr<Snapshot>& parent,
219 std::shared_ptr<FileIO> io) const {
220 const bool ignore_equality_deletes = new_data_files_data_seq_number_.has_value();
221 return ValidateNoNewDeletesForDataFiles(metadata, starting_snapshot_id,
222 replaced_files, parent, io,
223 ignore_equality_deletes);
224 }
225
233 static Status ValidateNoNewDeletesForDataFiles(
234 const TableMetadata& metadata, std::optional<int64_t> starting_snapshot_id,
235 const DataFileSet& replaced_files, const std::shared_ptr<Snapshot>& parent,
236 std::shared_ptr<FileIO> io, bool ignore_equality_deletes = false);
237
241 static Status ValidateNoNewDeletesForDataFiles(
242 const TableMetadata& metadata, std::optional<int64_t> starting_snapshot_id,
243 std::shared_ptr<Expression> data_filter, const DataFileSet& replaced_files,
244 const std::shared_ptr<Snapshot>& parent, std::shared_ptr<FileIO> io,
245 bool case_sensitive = true);
246
250 static Status ValidateNoNewDeleteFiles(const TableMetadata& metadata,
251 std::optional<int64_t> starting_snapshot_id,
252 std::shared_ptr<Expression> data_filter,
253 const std::shared_ptr<Snapshot>& parent,
254 std::shared_ptr<FileIO> io,
255 bool case_sensitive = true);
256
260 static Status ValidateNoNewDeleteFiles(const TableMetadata& metadata,
261 std::optional<int64_t> starting_snapshot_id,
262 const PartitionSet& partition_set,
263 const std::shared_ptr<Snapshot>& parent,
264 std::shared_ptr<FileIO> io);
265
268 static Status ValidateDeletedDataFiles(const TableMetadata& metadata,
269 std::optional<int64_t> starting_snapshot_id,
270 std::shared_ptr<Expression> data_filter,
271 const std::shared_ptr<Snapshot>& parent,
272 std::shared_ptr<FileIO> io,
273 bool case_sensitive = true);
274
278 static Status ValidateDeletedDataFiles(const TableMetadata& metadata,
279 std::optional<int64_t> starting_snapshot_id,
280 const PartitionSet& partition_set,
281 const std::shared_ptr<Snapshot>& parent,
282 std::shared_ptr<FileIO> io);
283
285 static Result<std::unique_ptr<DeleteFileIndex>> AddedDeleteFiles(
286 const TableMetadata& metadata, std::optional<int64_t> starting_snapshot_id,
287 std::shared_ptr<Expression> data_filter,
288 std::shared_ptr<PartitionSet> partition_set,
289 const std::shared_ptr<Snapshot>& parent, std::shared_ptr<FileIO> io,
290 bool case_sensitive = true);
291
295 static Status ValidateAddedDVs(
296 const TableMetadata& metadata, std::optional<int64_t> starting_snapshot_id,
297 std::shared_ptr<Expression> conflict_filter,
298 const std::unordered_set<std::string>& referenced_data_files,
299 const std::shared_ptr<Snapshot>& parent, std::shared_ptr<FileIO> io,
300 bool case_sensitive = true);
301
304 Status ValidateAddedDVs(const TableMetadata& metadata,
305 std::optional<int64_t> starting_snapshot_id,
306 std::shared_ptr<Expression> conflict_filter,
307 const std::shared_ptr<Snapshot>& parent,
308 std::shared_ptr<FileIO> io) const;
309
310 private:
311 struct PendingDeleteFile {
312 std::shared_ptr<DataFile> file;
313 std::optional<int64_t> data_sequence_number;
314 };
315
320 struct PendingDeleteFilesByReferencedFile {
321 struct Entry {
322 std::string referenced_file;
323 std::vector<PendingDeleteFile> files;
324 };
325
326 void Add(std::string referenced_file, PendingDeleteFile file);
327 bool empty() const { return entries_.empty(); }
328 size_t size() const { return entries_.size(); }
329 const std::vector<Entry>& entries() const { return entries_; }
330
331 private:
332 std::vector<Entry> entries_;
333 std::unordered_map<std::string, size_t> index_by_referenced_file_;
334 };
335
336 ManifestWriterFactory MakeWriterFactory(const std::shared_ptr<Schema>& schema);
337
341 Result<ManifestFile> CopyManifest(const ManifestFile& manifest, bool update_summary);
342
343 Status AddDeleteFile(std::shared_ptr<DataFile> file,
344 std::optional<int64_t> data_sequence_number);
345
346 Status ManagersReady() const;
347
348 void SetSummaryProperty(const std::string& property, const std::string& value) override;
349
350 Result<std::vector<PendingDeleteFile>> MergeDVs() const;
351
353 Result<std::vector<ManifestFile>> WriteNewDataManifests();
354
356 Result<std::vector<ManifestFile>> WriteNewDeleteManifests();
357
358 Status CleanUncommittedAppends(const std::unordered_set<std::string>& committed);
359
360 Status DeleteUncommitted(std::vector<ManifestFile>& manifests,
361 const std::unordered_set<std::string>& committed, bool clear);
362
363 // Used for commit event notifications and diagnostic log messages.
364 std::string table_name_;
365 std::shared_ptr<Expression> delete_expression_;
366 bool case_sensitive_ = true;
367
368 // Stable sub-builders for added files — accumulated across retries and merged
369 // into summary_builder_ at the start of each Apply() call.
370 SnapshotSummaryBuilder added_data_files_summary_;
371 SnapshotSummaryBuilder added_delete_files_summary_;
372 SnapshotSummaryBuilder appended_manifests_summary_;
373 std::unordered_map<std::string, std::string> custom_summary_properties_;
374
375 std::unique_ptr<ManifestFilterManager> data_filter_manager_;
376 std::unique_ptr<ManifestFilterManager> delete_filter_manager_;
377 std::unique_ptr<ManifestMergeManager> data_merge_manager_;
378 std::unique_ptr<ManifestMergeManager> delete_merge_manager_;
379
380 std::unordered_map<int32_t, DataFileSet> new_data_files_by_spec_;
381 std::vector<PendingDeleteFile> v2_deletes_;
382 PendingDeleteFilesByReferencedFile dvs_by_referenced_file_;
383 std::optional<int64_t> new_data_files_data_seq_number_;
384
385 // Manifests passed via AddManifest(): inherit path (no copy needed) and
386 // rewrite path (must be copied with the current snapshot ID).
387 std::vector<ManifestFile> append_manifests_;
388 // Original manifests kept to recreate copied manifests after retry cleanup.
389 std::vector<ManifestFile> append_manifests_to_copy_;
390 std::vector<ManifestFile> rewritten_append_manifests_;
391
392 // Set to true when new files are staged after the cache was populated, so the
393 // cache is invalidated and re-written on the next Apply() call (commit retry).
394 bool has_new_data_files_ = false;
395 bool has_new_delete_files_ = false;
396
397 std::vector<ManifestFile> cached_new_data_manifests_;
398 std::vector<ManifestFile> cached_new_delete_manifests_;
399};
400
401} // namespace iceberg
A set of DataFile pointers with insertion order preserved and deduplicated by file path.
Definition data_file_set.h:44
Abstract base class for merge-based snapshot write operations.
Definition merging_snapshot_update.h:69
const std::shared_ptr< Expression > & RowFilter() const
Returns the row-filter expression set via DeleteByRowFilter, or nullptr.
Definition merging_snapshot_update.h:168
bool IsCaseSensitive() const
Returns true if case-sensitive matching is enabled (default: true).
Definition merging_snapshot_update.h:153
Status ValidateNoNewDeletesForDataFiles(const TableMetadata &metadata, std::optional< int64_t > starting_snapshot_id, const DataFileSet &replaced_files, const std::shared_ptr< Snapshot > &parent, std::shared_ptr< FileIO > io) const
Return an error if any snapshot after starting_snapshot_id, or from the beginning if unset,...
Definition merging_snapshot_update.h:215
bool HasDataSequenceNumber() const
Returns true if SetNewDataFilesDataSequenceNumber was called.
Definition merging_snapshot_update.h:145
A set that uses a pair of spec ID and partition tuple as elements.
Definition partition_value_util.h:204
StructLike wrapper for a vector of literals that represent partition values.
Definition partition_values.h:36
API for table changes that produce snapshots.
Definition snapshot_update.h:46
std::function< Result< std::unique_ptr< ManifestWriter > >(int32_t spec_id, ManifestContent content)> ManifestWriterFactory
Factory type for creating ManifestWriter instances.
Definition manifest_writer.h:169
DataFile carries data file path, partition tuple, metrics, ...
Definition manifest_entry.h:62
Entry in a manifest list.
Definition manifest_list.h:85
Represents the metadata for an Iceberg table.
Definition table_metadata.h:73