iceberg · API

iceberg.commit

A snapshot that adds and removes files, with the manifest maintenance that implies.

iceberg.append only ever adds: its manifest list is the new manifest plus the parent's, carried by reference. Everything else — delete, overwrite, replace, compaction — has to rewrite the manifests that mention a file it is removing, and that is what this module does.

prepare_commit(io, metadata, operation, files, extra)

files says what the snapshot adds (data files, delete files) and what it removes (by path). The parent's manifest list is then walked once:

  • a manifest that mentions none of the removed paths is carried by reference — same path, same counts, same sequence_number, min_sequence_number and first_row_id. Nothing is rewritten that does not have to be, which is what keeps a delete from touching the whole table;
  • a manifest that mentions one is rewritten. Every live entry it keeps becomes EXISTING with its sequence_number, file_sequence_number, snapshot_id and (v3) first_row_id written out explicitly — sequence inheritance is ADDED-only, so an EXISTING entry that left them null would be silently re-dated. Every live entry it drops becomes DELETED, with the same numbers, so an expiry can still find the file. Entries that were already DELETED in the parent belong to an older snapshot and are dropped;
  • a rewritten manifest with nothing live left is dropped from the list entirely rather than written as an empty file.

The rewritten manifest's list entry is credited to the new snapshot (added_snapshot_id, sequence_number) while its min_sequence_number stays whatever its oldest surviving file says — which is what makes the delete scope rules keep working across a rewrite.

Totals. The total-* summary keys are carried forward from the parent snapshot and adjusted by what this commit added and removed, because the manifest list does not record file sizes and a scan of every manifest to recompute them would defeat the point of carrying most of them by reference.

Row lineage (v3). Added data files get the table's next-row-id through their manifest, exactly as an append does. A rewritten manifest keeps the first_row_id it was assigned, and its entries carry theirs explicitly, so no range moves and none overlap. Rows in a data file this commit rewrites (copy-on-write) do get new ids — see the README's gaps table.

Structs

FileChanges

struct FileChanges

What one snapshot adds and what it takes away.

Implements Copyable, Defaultable, Movable

Fields
added_data: List[DataFile]
added_deletes: List[DataFile]
removed: List[String]: Paths of files this snapshot removes — data or delete, either way the manifest entry that names them becomes DELETED.

__init__

def __init__(out self)

is_empty

def is_empty(self) -> Bool

removes

def removes(self, path: String) -> Bool

Functions

prepare_commit

def prepare_commit(io: FileIO, metadata: TableMetadata, operation: String, var files: FileChanges, var extra_summary: Dict[String, String]) -> AppendResult

Write the manifests and manifest list for a commit, and build the new table metadata. Nothing is persisted: the caller commits it.

Aliases

comptime OP_DELETE = String("delete")
comptime OP_OVERWRITE = String("overwrite")
comptime OP_REPLACE = String("replace")