Conversation
ddd8fc9 to
7045282
Compare
5d8f215 to
c43b75f
Compare
|
Important Format specification voteThis PR modifies the Lance format specification, so it requires 3 binding +1 votes from PMC members (excluding the proposer) and a minimum 72-hour voting period, weekends excluded, before it can merge. Vote by approving this PR (+1) or requesting changes (−1, a veto). See the voting process. Status: ❌ Blocked — 0 of 3 required approvals
Updated automatically by the format-spec vote gate, which re-checks every 15 minutes — just voted? Re-check now (press Run workflow; leave the input blank to re-check every open format PR). A PMC member may apply the |
FRI keeps existing indices usable after fragment rewrites by translating old physical row addresses to new ones. Today it supports order-preserving compaction. This proposal extends the same system index to support stable partitioning, with both mapping types sharing one fragment-lineage history. Following [the unified FRI proposal](#8972 (comment)), source/destination lineage stays in FRI details, while large mapping payloads remain in separate immutable files. ### One history, multiple mappings Continue storing FRI information in a single `__lance_frag_reuse` system-index entry. Keep the existing `InlineContent` / `ExternalFile` envelope and the original field number for legacy versions. Add tagged transitions alongside them: ```text FragmentReuseIndexDetails └── InlineContent, stored inline or in external details.binpb ├── legacy_versions[] └── transitions[] ├── ordered sources[] ├── ordered destinations[] └── mapping ├── OrderedCompaction: surviving-row bitmap └── StablePartition: immutable row-map reference ``` Sources and destinations define the common rewrite graph. Each mapping defines how to translate row offsets. Legacy groups can be read as ordered-compaction transitions; mixed histories follow fragment lineage, not the order of records or dataset version numbers. ### Lightweight metadata, external row maps Ordered compaction retains its compact bitmap representation. Stable partition assigns each physical source row a nullable `uint16` destination label, preserving source order within each destination. A null label means the row was deleted. A counts matrix lets readers reconstruct destination offsets without reading all preceding labels. Stable-partition metadata records `map_id`, `map_size_bytes`, and optional `base_id`. The labels and counts are stored in `_fri/<map_id>/stable_partition.lance`. Mapping identity is independent of the FRI index UUID: updating the history rewrites its metadata, but does not rewrite existing row-map files. The history can be opened without loading labels; address translation reads the required blocks. ### Publication and compatibility `AppendFragmentReuseTransitions` expresses a transition delta. Combined atomically with a fragment rewrite, it lets the commit apply the delta to the current history and publish destination fragments and their mappings together. The persisted FRI details remain a snapshot of that history. - **Index version 0:** existing compaction format and read/write behavior remain unchanged. - **Index version 1:** supports legacy groups and tagged transitions in one history. - The first commit publishing index version 1 sets reader and writer flag **512**. The reader flag prevents old clients from partially interpreting the history; the writer flag prevents them from dropping mappings during metadata maintenance. Subsequent manifests retain both bits. ### Scope and validation This PR contains protobuf definitions, the corresponding format documentation, the proposed flag constant, and minimal compile adapters. It does not enable tagged-history reads or writes. Mapping implementations and reader integration follow in #9106 → #9064 → #9067 → #9068 → #9107. Replaces #9065 as the standalone spec at the bottom of native stack #9137, based on main `31d78d170`. `cargo fmt --all` and whitespace checks pass. Clippy and tests are blocked by dependency resolution: main requires `object_store_opendal 0.60.1`, while the crates.io index currently offers only up to 0.60.0. --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
d490d84 to
a3800c3
Compare
A metadata-only ledger that decodes FRI lineage and validates envelopes, fragment digests, row conservation, mapping payloads, and acyclic producer/consumer lineage on top of the finalized tagged FRI proto in main. Pure decode/validation over lance-core and the existing generated proto; no format-spec changes. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DgAshYD7wVzPVdjXRuWPPs
a3800c3 to
d63b7a2
Compare
There was a problem hiding this comment.
✅ Gate recommendation: approve.
The stale prerequisite stack is gone: this revision keeps the finalized FRI contract and merged mapping layer, and adds only the metadata ledger. The decoder preserves version 0 behavior, validates inline and external version 1 histories, mapping payloads, row conservation, and acyclic lineage, and leaves stable-partition row maps lazy.
What this adds
This PR implements one decoder for version-1 FRI history while preserving the existing version-0 representation.
Legacy
Version.groupsare lifted in memory into ordered-compaction transitions. Version-1 transitions decode their explicit mapping type:RowAddrRemap.The outer inline/external envelope is decoded through the same entry point, including external offset and size validation. Unsupported FRI index versions return an upgrade error.
Lineage validation
The decoder validates fragment digests and mapping-specific row-count invariants, then builds producer and consumer lookups for fragment IDs. It rejects duplicate producers, duplicate consumers, and cycles before returning transitions in deterministic topological order.
A transition with an unknown mapping is excluded from the readable lineage and marks the history as partially unsupported. This lets readers fall back to scanning affected paths while allowing writers and maintenance operations to reject a history they cannot preserve safely.
Mapping reuse
Each supported transition receives an in-memory content fingerprint derived from its ordered source and destination digests plus its mapping contents. The fingerprint is not persisted. It allows later reader layers to reuse an unchanged mapping reader when the FRI entry UUID changes because another transition was appended or removed.
This PR only decodes and validates history. It performs no stable-partition row-map IO, dataset lineage traversal, coverage planning, or index loading. The legacy version-0 reader and writer remain unchanged.
Validation
Tests cover inline and external histories, legacy lifting, mixed ordered-compaction and stable-partition transitions, multi-step lineage, deterministic ordering, invalid digests and row counts, duplicate producers and consumers, cycles, malformed protobuf input, unsupported mappings and index versions, external-size validation, and mapping fingerprint stability.
Validated with workspace Clippy and
cargo fmt --all.