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
36#include "iceberg/result.h"
37#include "iceberg/type_fwd.h"
40
41namespace iceberg {
42
63class ICEBERG_EXPORT MergingSnapshotUpdate : public SnapshotUpdate {
64 public:
65 ~MergingSnapshotUpdate() override = default;
66
67 protected:
68 // SnapshotUpdate overrides
70 const TableMetadata& metadata_to_update,
71 const std::shared_ptr<Snapshot>& snapshot) override;
72
73 Status CleanUncommitted(const std::unordered_set<std::string>& committed) override;
74
75 std::unordered_map<std::string, std::string> Summary() override;
76
78 explicit MergingSnapshotUpdate(std::string table_name,
79 std::shared_ptr<TransactionContext> ctx);
80
82 Status AddDataFile(std::shared_ptr<DataFile> file);
83
85 Status AddDeleteFile(std::shared_ptr<DataFile> file);
86
92 Status ValidateNewDeleteFile(const TableMetadata& metadata, const DataFile& file);
93
96 Status AddDeleteFile(std::shared_ptr<DataFile> file, int64_t data_sequence_number);
97
103 Status AddManifest(ManifestFile manifest);
104
106 Status DeleteDataFile(std::shared_ptr<DataFile> file);
107
109 Status DeleteDeleteFile(std::shared_ptr<DataFile> file);
110
114 Status DeleteByPath(std::string_view path);
115
121 Status DeleteByRowFilter(std::shared_ptr<Expression> expr);
122
127 Status DropPartition(int32_t spec_id, PartitionValues partition);
128
131
134
136 void SetNewDataFilesDataSequenceNumber(int64_t sequence_number);
137
140 return new_data_files_data_seq_number_.has_value();
141 }
142
144 void CaseSensitive(bool case_sensitive);
145
147 bool IsCaseSensitive() const { return case_sensitive_; }
148
150 bool AddsDataFiles() const;
151
153 bool AddsDeleteFiles() const;
154
156 bool DeletesDataFiles() const;
157
159 bool DeletesDeleteFiles() const;
160
162 const std::shared_ptr<Expression>& RowFilter() const { return delete_expression_; }
163
169
171 std::vector<std::shared_ptr<DataFile>> AddedDataFiles() const;
172
175 static Status ValidateAddedDataFiles(const TableMetadata& metadata,
176 std::optional<int64_t> starting_snapshot_id,
177 std::shared_ptr<Expression> filter,
178 const std::shared_ptr<Snapshot>& parent,
179 std::shared_ptr<FileIO> io,
180 bool case_sensitive = true);
181
185 static Status ValidateAddedDataFiles(const TableMetadata& metadata,
186 std::optional<int64_t> starting_snapshot_id,
187 const PartitionSet& partition_set,
188 const std::shared_ptr<Snapshot>& parent,
189 std::shared_ptr<FileIO> io);
190
195 const TableMetadata& metadata, std::optional<int64_t> starting_snapshot_id,
196 const std::unordered_set<std::string>& file_paths, bool skip_deletes,
197 std::shared_ptr<Expression> filter, const std::shared_ptr<Snapshot>& parent,
198 std::shared_ptr<FileIO> io, bool case_sensitive = true);
199
210 std::optional<int64_t> starting_snapshot_id,
211 const DataFileSet& replaced_files,
212 const std::shared_ptr<Snapshot>& parent,
213 std::shared_ptr<FileIO> io) const {
214 const bool ignore_equality_deletes = new_data_files_data_seq_number_.has_value();
215 return ValidateNoNewDeletesForDataFiles(metadata, starting_snapshot_id,
216 replaced_files, parent, io,
217 ignore_equality_deletes);
218 }
219
228 const TableMetadata& metadata, std::optional<int64_t> starting_snapshot_id,
229 const DataFileSet& replaced_files, const std::shared_ptr<Snapshot>& parent,
230 std::shared_ptr<FileIO> io, bool ignore_equality_deletes = false);
231
236 const TableMetadata& metadata, std::optional<int64_t> starting_snapshot_id,
237 std::shared_ptr<Expression> data_filter, const DataFileSet& replaced_files,
238 const std::shared_ptr<Snapshot>& parent, std::shared_ptr<FileIO> io,
239 bool case_sensitive = true);
240
244 static Status ValidateNoNewDeleteFiles(const TableMetadata& metadata,
245 std::optional<int64_t> starting_snapshot_id,
246 std::shared_ptr<Expression> data_filter,
247 const std::shared_ptr<Snapshot>& parent,
248 std::shared_ptr<FileIO> io,
249 bool case_sensitive = true);
250
254 static Status ValidateNoNewDeleteFiles(const TableMetadata& metadata,
255 std::optional<int64_t> starting_snapshot_id,
256 const PartitionSet& partition_set,
257 const std::shared_ptr<Snapshot>& parent,
258 std::shared_ptr<FileIO> io);
259
262 static Status ValidateDeletedDataFiles(const TableMetadata& metadata,
263 std::optional<int64_t> starting_snapshot_id,
264 std::shared_ptr<Expression> data_filter,
265 const std::shared_ptr<Snapshot>& parent,
266 std::shared_ptr<FileIO> io,
267 bool case_sensitive = true);
268
272 static Status ValidateDeletedDataFiles(const TableMetadata& metadata,
273 std::optional<int64_t> starting_snapshot_id,
274 const PartitionSet& partition_set,
275 const std::shared_ptr<Snapshot>& parent,
276 std::shared_ptr<FileIO> io);
277
280 const TableMetadata& metadata, std::optional<int64_t> starting_snapshot_id,
281 std::shared_ptr<Expression> data_filter,
282 std::shared_ptr<PartitionSet> partition_set,
283 const std::shared_ptr<Snapshot>& parent, std::shared_ptr<FileIO> io,
284 bool case_sensitive = true);
285
289 static Status ValidateAddedDVs(
290 const TableMetadata& metadata, std::optional<int64_t> starting_snapshot_id,
291 std::shared_ptr<Expression> conflict_filter,
292 const std::unordered_set<std::string>& referenced_data_files,
293 const std::shared_ptr<Snapshot>& parent, std::shared_ptr<FileIO> io,
294 bool case_sensitive = true);
295
298 Status ValidateAddedDVs(const TableMetadata& metadata,
299 std::optional<int64_t> starting_snapshot_id,
300 std::shared_ptr<Expression> conflict_filter,
301 const std::shared_ptr<Snapshot>& parent,
302 std::shared_ptr<FileIO> io) const;
303
304 private:
305 struct PendingDeleteFile {
306 std::shared_ptr<DataFile> file;
307 std::optional<int64_t> data_sequence_number;
308 };
309
314 struct PendingDeleteFilesByReferencedFile {
315 struct Entry {
316 std::string referenced_file;
317 std::vector<PendingDeleteFile> files;
318 };
319
320 void Add(std::string referenced_file, PendingDeleteFile file);
321 bool empty() const { return entries_.empty(); }
322 size_t size() const { return entries_.size(); }
323 const std::vector<Entry>& entries() const { return entries_; }
324
325 private:
326 std::vector<Entry> entries_;
327 std::unordered_map<std::string, size_t> index_by_referenced_file_;
328 };
329
330 ManifestWriterFactory MakeWriterFactory(const std::shared_ptr<Schema>& schema);
331
335 Result<ManifestFile> CopyManifest(const ManifestFile& manifest, bool update_summary);
336
337 Status AddDeleteFile(std::shared_ptr<DataFile> file,
338 std::optional<int64_t> data_sequence_number);
339
340 Status ManagersReady() const;
341
342 void SetSummaryProperty(const std::string& property, const std::string& value) override;
343
344 Result<std::vector<PendingDeleteFile>> MergeDVs();
345
347 Result<std::vector<ManifestFile>> WriteNewDataManifests();
348
350 Result<std::vector<ManifestFile>> WriteNewDeleteManifests();
351
352 Status CleanUncommittedAppends(const std::unordered_set<std::string>& committed);
353
354 Status DeleteUncommitted(std::vector<ManifestFile>& manifests,
355 const std::unordered_set<std::string>& committed, bool clear);
356
357 // Used for commit event notifications and diagnostic log messages.
358 std::string table_name_;
359 std::shared_ptr<Expression> delete_expression_;
360 bool case_sensitive_ = true;
361
362 // Stable sub-builders for added files — accumulated across retries and merged
363 // into summary_builder_ at the start of each Apply() call.
364 SnapshotSummaryBuilder added_data_files_summary_;
365 SnapshotSummaryBuilder added_delete_files_summary_;
366 SnapshotSummaryBuilder appended_manifests_summary_;
367 std::unordered_map<std::string, std::string> custom_summary_properties_;
368
369 std::unique_ptr<ManifestFilterManager> data_filter_manager_;
370 std::unique_ptr<ManifestFilterManager> delete_filter_manager_;
371 std::unique_ptr<ManifestMergeManager> data_merge_manager_;
372 std::unique_ptr<ManifestMergeManager> delete_merge_manager_;
373
374 std::unordered_map<int32_t, DataFileSet> new_data_files_by_spec_;
375 std::vector<PendingDeleteFile> v2_deletes_;
376 PendingDeleteFilesByReferencedFile dvs_by_referenced_file_;
377 std::optional<int64_t> new_data_files_data_seq_number_;
378
379 // Manifests passed via AddManifest(): inherit path (no copy needed) and
380 // rewrite path (must be copied with the current snapshot ID).
381 std::vector<ManifestFile> append_manifests_;
382 // Original manifests kept to recreate copied manifests after retry cleanup.
383 std::vector<ManifestFile> append_manifests_to_copy_;
384 std::vector<ManifestFile> rewritten_append_manifests_;
385
386 // Set to true when new files are staged after the cache was populated, so the
387 // cache is invalidated and re-written on the next Apply() call (commit retry).
388 bool has_new_data_files_ = false;
389 bool has_new_delete_files_ = false;
390
391 std::vector<ManifestFile> cached_new_data_manifests_;
392 std::vector<ManifestFile> cached_new_delete_manifests_;
393 std::vector<PendingDeleteFile> merged_dvs_;
394 int32_t dv_merge_attempt_ = 0;
395};
396
397} // 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:63
Status AddDataFile(std::shared_ptr< DataFile > file)
Stage a data file to be added to the table.
Status DeleteDeleteFile(std::shared_ptr< DataFile > file)
Register a delete file (by object) to be removed from the table.
std::unordered_map< std::string, std::string > Summary() override
Get the summary map for this operation.
Status DeleteByRowFilter(std::shared_ptr< Expression > expr)
Register an expression to delete matching rows.
static Status ValidateAddedDataFiles(const TableMetadata &metadata, std::optional< int64_t > starting_snapshot_id, std::shared_ptr< Expression > filter, const std::shared_ptr< Snapshot > &parent, std::shared_ptr< FileIO > io, bool case_sensitive=true)
Return an error if any snapshot after starting_snapshot_id, or from the beginning if unset,...
const std::shared_ptr< Expression > & RowFilter() const
Returns the row-filter expression set via DeleteByRowFilter, or nullptr.
Definition merging_snapshot_update.h:162
bool IsCaseSensitive() const
Returns true if case-sensitive matching is enabled (default: true).
Definition merging_snapshot_update.h:147
void FailAnyDelete()
Fail if any manifest entry matches a delete condition.
static Status ValidateDeletedDataFiles(const TableMetadata &metadata, std::optional< int64_t > starting_snapshot_id, const PartitionSet &partition_set, const std::shared_ptr< Snapshot > &parent, std::shared_ptr< FileIO > io)
Return an error if any snapshot after starting_snapshot_id, or from the beginning if unset,...
static Status ValidateDeletedDataFiles(const TableMetadata &metadata, std::optional< int64_t > starting_snapshot_id, std::shared_ptr< Expression > data_filter, const std::shared_ptr< Snapshot > &parent, std::shared_ptr< FileIO > io, bool case_sensitive=true)
Return an error if any snapshot after starting_snapshot_id, or from the beginning if unset,...
Status ValidateAddedDVs(const TableMetadata &metadata, std::optional< int64_t > starting_snapshot_id, std::shared_ptr< Expression > conflict_filter, const std::shared_ptr< Snapshot > &parent, std::shared_ptr< FileIO > io) const
Return an error if a staged deletion vector conflicts with a deletion vector added since starting_sna...
static Status ValidateNoNewDeleteFiles(const TableMetadata &metadata, std::optional< int64_t > starting_snapshot_id, std::shared_ptr< Expression > data_filter, const std::shared_ptr< Snapshot > &parent, std::shared_ptr< FileIO > io, bool case_sensitive=true)
Return an error if any snapshot after starting_snapshot_id, or from the beginning if unset,...
Result< std::shared_ptr< PartitionSpec > > DataSpec() const
Returns the single partition spec for all staged data files.
bool AddsDataFiles() const
Returns true if any data files have been staged for addition.
static Status ValidateDataFilesExist(const TableMetadata &metadata, std::optional< int64_t > starting_snapshot_id, const std::unordered_set< std::string > &file_paths, bool skip_deletes, std::shared_ptr< Expression > filter, const std::shared_ptr< Snapshot > &parent, std::shared_ptr< FileIO > io, bool case_sensitive=true)
Return an error if any snapshot after starting_snapshot_id, or from the beginning if unset,...
static Status ValidateNoNewDeletesForDataFiles(const TableMetadata &metadata, std::optional< int64_t > starting_snapshot_id, std::shared_ptr< Expression > data_filter, const DataFileSet &replaced_files, const std::shared_ptr< Snapshot > &parent, std::shared_ptr< FileIO > io, bool case_sensitive=true)
Return an error if any snapshot after starting_snapshot_id, or from the beginning if unset,...
static Status ValidateNoNewDeleteFiles(const TableMetadata &metadata, std::optional< int64_t > starting_snapshot_id, const PartitionSet &partition_set, const std::shared_ptr< Snapshot > &parent, std::shared_ptr< FileIO > io)
Return an error if any snapshot after starting_snapshot_id, or from the beginning if unset,...
Result< std::vector< ManifestFile > > Apply(const TableMetadata &metadata_to_update, const std::shared_ptr< Snapshot > &snapshot) override
Apply the update's changes to the given metadata and snapshot.
Status DeleteByPath(std::string_view path)
Register a data file path to be deleted from the table.
void SetNewDataFilesDataSequenceNumber(int64_t sequence_number)
Override the data sequence number assigned to all newly-added data files.
static Status ValidateAddedDataFiles(const TableMetadata &metadata, std::optional< int64_t > starting_snapshot_id, const PartitionSet &partition_set, const std::shared_ptr< Snapshot > &parent, std::shared_ptr< FileIO > io)
Return an error if any snapshot after starting_snapshot_id, or from the beginning if unset,...
void FailMissingDeletePaths()
Fail if any registered delete path is not found in any manifest.
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:209
Status CleanUncommitted(const std::unordered_set< std::string > &committed) override
Clean up any uncommitted manifests that were created.
Status AddManifest(ManifestFile manifest)
Add all files in a pre-existing data manifest to the new snapshot.
bool HasDataSequenceNumber() const
Returns true if SetNewDataFilesDataSequenceNumber was called.
Definition merging_snapshot_update.h:139
std::vector< std::shared_ptr< DataFile > > AddedDataFiles() const
Returns all data files staged for addition.
bool DeletesDataFiles() const
Returns true if any data files have been registered for deletion.
static Status ValidateAddedDVs(const TableMetadata &metadata, std::optional< int64_t > starting_snapshot_id, std::shared_ptr< Expression > conflict_filter, const std::unordered_set< std::string > &referenced_data_files, const std::shared_ptr< Snapshot > &parent, std::shared_ptr< FileIO > io, bool case_sensitive=true)
Return an error if any snapshot after starting_snapshot_id, or from the beginning if unset,...
Status ValidateNewDeleteFile(const TableMetadata &metadata, const DataFile &file)
Validate a delete file against the table format version rules.
void CaseSensitive(bool case_sensitive)
Set case sensitivity for row filter and expression evaluation.
bool DeletesDeleteFiles() const
Returns true if any delete files have been registered for removal.
Status DeleteDataFile(std::shared_ptr< DataFile > file)
Register a data file (by object) to be deleted from the table.
Status AddDeleteFile(std::shared_ptr< DataFile > file, int64_t data_sequence_number)
Stage a delete file with an explicit data sequence number.
Status DropPartition(int32_t spec_id, PartitionValues partition)
Register a partition to be dropped.
static 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, bool ignore_equality_deletes=false)
Return an error if any snapshot after starting_snapshot_id, or from the beginning if unset,...
Status AddDeleteFile(std::shared_ptr< DataFile > file)
Stage a delete file to be added to the table.
bool AddsDeleteFiles() const
Returns true if any delete files have been staged for addition.
MergingSnapshotUpdate(std::string table_name, std::shared_ptr< TransactionContext > ctx)
Constructor; reads merge configuration from table properties.
static Result< std::unique_ptr< DeleteFileIndex > > AddedDeleteFiles(const TableMetadata &metadata, std::optional< int64_t > starting_snapshot_id, std::shared_ptr< Expression > data_filter, std::shared_ptr< PartitionSet > partition_set, const std::shared_ptr< Snapshot > &parent, std::shared_ptr< FileIO > io, bool case_sensitive=true)
Build a DeleteFileIndex of delete files added since starting_snapshot_id.
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:49
Define symbol visibility macros for core Iceberg APIs.
Core Apache Iceberg C++ APIs.
Definition arrow_io_util.h:33
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
std::expected< T, E > Result
Result alias.
Definition result.h:88
Define Result, Status, and error helpers.
Define base APIs for snapshot updates.
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