Skip to content

feat(scan): plan changelog tasks from deletion vectors - #958

Draft
manuzhang wants to merge 1 commit into
apache:mainfrom
manuzhang:agent/changelog-dv
Draft

manuzhang wants to merge 1 commit into
apache:mainfrom
manuzhang:agent/changelog-dv

Conversation

@manuzhang

@manuzhang manuzhang commented Sep 23, 2026

Copy link
Copy Markdown
Member

What

Plan changelog tasks for format version 3 tables that use deletion vectors:

  • Add DeletedRowsScanTask, a ChangelogScanTask with added_deletes() and
    existing_deletes(), for rows deleted by a deletion vector committed against a
    data file that already existed.
  • Add DeletionVectorChangelogPlanner (changelog_dv_planner_internal.{h,cc}),
    which reads the delete manifests of the changelog snapshots, indexes the
    deletion vectors each snapshot added and removed, and plans the delete side: a
    vector committed together with its data file is attached to that file's
    AddedRowsScanTask; a vector removed together with its data file becomes the
    existing delete of the DeletedDataFileScanTask; a vector for an existing data
    file locates the file in the committing snapshot's data manifests and produces a
    DeletedRowsScanTask carrying the added vector and the vector it replaced.
  • IncrementalChangelogScan uses the planner only when the table format version
    is 3 or higher. Format version 1 and 2 tables keep rejecting delete manifests
    with NotSupported.
  • The planner checks every delete manifest of every changelog snapshot, not only
    the manifests written in the range, and rejects position delete files and
    equality delete files with NotSupported. A delete file removed before the
    range no longer applies to any row, so it is the one case that is ignored.

This is planning only, matching the existing changelog tasks: a consumer of
DeletedRowsScanTask reads the data file and emits the positions set in the added
vector that are not set in the existing vector.

Why

IncrementalChangelogScan failed on any snapshot that carried a delete manifest,
so a table with row-level deletes could not produce a changelog at all. Format
version 3 makes this tractable: each data file has at most one live deletion
vector and a new vector replaces the previous one, so the rows a snapshot deleted
are exactly the difference between the vector it added and the vector it removed,
without reading any earlier delete files.

Position and equality delete files accumulate instead, so their rows cannot be
attributed to a snapshot without reading every earlier delete file. A format
version 3 table can still carry them, for example after an upgrade from version
2, in manifests that no snapshot in the range rewrote. Checking every delete
manifest makes that case an explicit error instead of a changelog that silently
omits the rows those files delete.

Behavior change

  • Changelog scans of format version 3 tables with deletion vectors now succeed and
    may return DeletedRowsScanTask, which callers that switch on task type must
    handle.
  • The error for delete files on format version 1 and 2 tables is now
    "Delete files are only supported in changelog scans of format version 3 tables".
  • For every changelog snapshot that adds deletion vectors to existing data files,
    planning reads that snapshot's data manifests to find the referenced files.
  • Planning reads every delete manifest of every changelog snapshot, each manifest
    once, and fails with NotSupported when one holds a position delete file or an
    equality delete file that is live or that a changelog snapshot removed. Delete
    files removed before the range are ignored.

Testing

New cases in incremental_changelog_scan_test.cc cover a deletion vector added to
an existing file, a vector replacing an earlier one (single snapshot and across
two snapshots), a vector committed with its data file, a vector removed with its
data file, partition pruning of vectors by the data filter, vectors outside the
scan range, the NotSupported errors for format version 2 delete files, position
delete files and equality delete files written in the range or carried in a
manifest untouched during the range, and a position delete file removed before
the range being ignored. scan_test passes locally.

🤖 Generated with Claude Code

Copilot AI lite review requested due to automatic review settings September 23, 2026 03:00

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Copilot AI review requested due to automatic review settings September 23, 2026 03:16

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

IncrementalChangelogScan rejected every snapshot that carried a delete
manifest, so tables using row-level deletes could not be scanned for
changes. Format version 3 stores row-level deletes as deletion vectors,
where each data file has at most one live vector and a new vector
replaces the previous one. That makes the rows a snapshot deleted the
difference between the vector it added and the vector it removed.

Add DeletionVectorChangelogPlanner, which reads the deletion vectors
added and removed by each changelog snapshot and plans the delete side:
a vector committed with its data file joins the AddedRowsScanTask, a
vector removed with its data file becomes the existing delete of the
DeletedDataFileScanTask, and a vector for a data file that already
existed produces the new DeletedRowsScanTask with the added vector and
the replaced vector. IncrementalChangelogScan uses the planner only for
format version 3 tables.

Delete files on format version 1 and 2 tables, position delete files and
equality delete files remain unsupported and are rejected with
NotSupported. The planner reads every delete manifest of the changelog
snapshots, not only those written in the range, so a position or
equality delete file carried in an older manifest is rejected as well
unless it was removed before the range and can no longer apply to any
row.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings September 23, 2026 03:51

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants