feat: stabilize field IDs across schema evolution - #8658
Conversation
|
Important This PR touches the Lance format specification. Substantive changes to the format specification — the If this is a meaningful format change:
|
|
Do you think this will cause transactions to conflict with each other that did not before? I don't think it does today since we treat any schema change as conflicting with any other schema change. Do we know why we reused field ids in the first place? |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
There was a problem hiding this comment.
✅ Gate recommendation: approve.
The final schema-only Project gap is fixed: Java now preserves explicit existing identities, retains the existing same-name/type binding for metadata-free drop and reorder operations, and rejects unmatched fields before commit. This keeps released legacy Project behavior while preventing stable identities without backing data.
Field IDs currently act as physical bindings throughout Lance, but their allocator is derived from fields still referenced by the current snapshot. Once a dropped identity disappears from both the schema and data files, that integer can be reused for a different logical field. This makes a bare field ID ambiguous across schema evolution and prevents durable metadata from safely following a field through rename, drop, replacement, and restore.
This PR defines stable field identity as a one-way, branch-ancestry-scoped format contract. Activated manifests persist a monotonically increasing field-ID high-water mark; rename and metadata-only changes preserve identity, while new fields, type replacements, and overwrite allocate fresh identities. New datasets activate the contract in their initial manifest with fail-closed reader and writer requirements. Existing legacy datasets retain their current behavior until explicitly migrated, including a controlled writer-only rollout mode for deployments that have already retired pre-gate writers.
The same contract is enforced at transaction, clone, restore, Arrow conversion, Java/Python binding, and Blob representation boundaries so external schema metadata and file-local synthetic fields cannot manufacture dataset identities or silently downgrade required writer capabilities.