Skip to content

Add RewriteFiles support to iceberg-rust #1607

Open
2 of 4 issues completed
Open

Description

@CTTY

Is your feature request related to a problem or challenge?

Currently, iceberg-rust does not support committing operations that both add and delete files. This feature, known as RewriteFiles in iceberg-java, is crucial for our use case, particularly for compaction.

Describe the solution you'd like

Based on my initial investigation in #1606, I believe the following three components are necessary to implement RewriteFiles in iceberg-rust:

  • Process delete files: We need to add logic to handle delete files when generating snapshots.
  • Implement RewriteFilesAction: This will require creating a new transaction action, RewriteFilesAction, and related classes like RewriteFilesOperation.
  • Support validation: We need to add validation for rewrite operations to prevent conflicts. Currently we don't have any validation mechnism in the codebase, so a new trait SnapshotValidator would be needed.

Willingness to contribute

I would be willing to contribute to this feature with guidance from the Iceberg Rust community

Activity

  1. debugmiller commented on Dec 4, 2025

    @debugmiller

    I was just looking to do compaction. This would be great!

  2. added a commit that references this issue on Dec 26, 2025
    8ea1deb
  3. jdockerty commented on Jan 13, 2026

    @jdockerty
    Contributor

    I believe introducing this RewriteFiles action also means exposing the ability to mark data files as DELETED too? It doesn't seem like that is currently possible within iceberg-rust, as the only changes are additive via FastAppend.

    Being able to mark data files as deleted/replaced would be very helpful for our use case too. I think doing that is part of the RewriteFile action, it is something our use case would be greatly helped by.

    Is there anyway that we can help move this along?

  4. jdockerty commented on Jan 20, 2026

    @jdockerty
    Contributor

    @Xuanwo Are you able to provide any insight/guidance on ☝️?

  5. CTTY commented on Jan 20, 2026

    @CTTY
    CollaboratorAuthor

    Hey @jdockerty , sorry I thought I had replied but obviously I didn't.

    I believe introducing this RewriteFiles action also means exposing the ability to mark data files as DELETED too?

    In this issue, I meant to support RewriteFiles as long as we can process delete files. Delete file support can be added separately

  6. drbothen commented on Feb 15, 2026

    @drbothen

    Hi @CTTY, I've been working on a RewriteFiles implementation for our compaction use case and have a working version I'd like to contribute. Before opening a PR, I wanted to check with you since you own this issue:

    1. Are you actively working on feat(transaction): RewriteFilesAction + Validation Support + Process Delete Manifests #1606?
    2. Would you be open to reviewing a PR that implements the core RewriteFilesAction + SnapshotProducer delete file support?

    The implementation covers:

    • SnapshotProducer changes to support deleted_data_files (write deleted manifest, validate files exist, summary tracking)
    • RewriteFilesAction that uses Operation::Replace per the spec
    • Validation that files to delete exist in the current snapshot
    • 6 unit tests including round-trip with catalog

    Happy to coordinate however works best!

  7. CTTY commented on Mar 16, 2026

    @CTTY
    CollaboratorAuthor

    Hey @drbothen sorry for the late reply, as the storage trait work is about to be wrapped up, I'm picking this back up! We want to get transaction API to a good state to enable compaction use cases

  8. self-assigned this
    on Mar 16, 2026
  9. mattefunnel commented on Mar 24, 2026

    @mattefunnel

    @CTTY (and others), we’re interested in this as well. Feel free to reach out if there’s anything I can do to help drive this forward.

  10. brgr-s commented on May 21, 2026

    @brgr-s

    @CTTY Currently working on getting #2242 and #1606 and test it stand-alone to bin pack an unpartioned table without branching. Will get with feedback as soon as I have some, or if you have a different order in mind.

  11. hotcache commented on Aug 21, 2026

    @hotcache

    Hi @CTTY, @blackmwk, @dannycjones, @rexminnis,

    I've been following the discussion across #1607, #2620, and #2367, and I'd
    like to help move this forward. I have a working implementation that I'd like
    to propose as a PR.

    Approach

    Based on the discussion, there were two open design questions:

    1. MergingSnapshotProducer as a new struct vs extending existing actions —
      I went with a composition-based MergingSnapshotProducer struct
      (aligning with @blackmwk's suggestion), but using Rust composition
      instead of Java-style inheritance (aligning with @dannycjones's preference
      for idiomatic Rust).

    2. Cross-retry cache — I intentionally deferred this to a follow-up PR.
      As @rexminnis noted, "always-rewrite-per-attempt is correct, just not
      optimal." This unblocks the feature without requiring the cache design
      to be settled first.

    Architecture

    The key design choice is that MergingSnapshotProducer is a shared engine
    owned by each action via composition
    , not a trait or base class:

    MergingSnapshotProducer (struct — shared engine)
    │ - add/delete file tracking
    │ - ManifestFilterManager (filters deleted files from manifests)
    │ - manifest writing + summary computation
    │ - delegates snapshot creation to SnapshotProducer
    │
    │ Owned by each action:
    │
    ├── RewriteFilesAction (this PR)
    │ operation: Replace
    │ validate: fail_missing_delete_paths
    │
    ├── OverwriteFilesAction (future)
    │ operation: Overwrite
    │ validate: conflict_detection_filter
    │
    └── RowDeltaAction (future)
    operation: Overwrite
    validate: no_new_deletes_on_target_files

    This structure keeps future operations simple. Adding a new operation
    means writing a thin struct that:

    1. Owns a MergingSnapshotProducer
    2. Implements its own validate() rules
    3. Calls producer.commit_snapshot()

    No shared manifest filtering, caching, or summary logic needs to be
    duplicated — it's all in MergingSnapshotProducer. For example,
    RewriteFilesAction is ~50 lines (excluding tests), similar to how
    Java's BaseRewriteFiles is trivially thin on top of
    MergingSnapshotProducer.

    The existing FastAppendAction and SnapshotProducer are completely
    unchanged.

    Planned follow-up PRs

    • PR2: Manifest cache for retry optimization
      (Mutex<Option<Vec<ManifestFile>>> in MergingSnapshotProducer)
    • PR3: SnapshotValidator trait for conflict detection
      (applies to both RewriteFiles and FastAppend)
    • PR4: OverwriteFilesAction — demonstrates extensibility of the
      MergingSnapshotProducer pattern

    I'd love to hear your thoughts before I open the PR. @CTTY, I want to
    make sure this doesn't conflict with your plans — happy to coordinate.

  12. added a commit that references this issue on Aug 21, 2026
    9583743
  13. added a commit that references this issue on Oct 20, 2026
    d63b83f
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions