fix: sync unenforced_primary_key_position when field metadata updates#6706
Conversation
UpdateConfig's field-metadata path mutates field.metadata but leaves the cached unenforced_primary_key_position stale. The protobuf encoder reads the cached option, so the next commit drops the PK marker even though the metadata HashMap correctly contains the position key. The same hole on the other direction silently keeps a stale PK marker after the keys are removed. Re-derive the cached option from the freshly-applied metadata after each field-metadata update so the two views stay in sync. Export LANCE_UNENFORCED_PRIMARY_KEY alongside the position constant from lance_core::datatypes for the legacy boolean-flag fallback.
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
| for (field_id, field_metadata_update) in field_metadata_updates { | ||
| if let Some(field) = manifest.schema.field_by_id_mut(*field_id) { | ||
| apply_update_map(&mut field.metadata, field_metadata_update); | ||
| // The unenforced primary key position lives in two |
There was a problem hiding this comment.
this should be much more concise, just something like "also set unenforced primary key based on updated field metadata" is sufficient.
There was a problem hiding this comment.
Done in 34a0be5 — trimmed the comment to a single line.
|
looks like CI failure: |
|
The failing test The same test passed on Linux CI in this run, and this PR's only changes are in Could you please re-run the failed |
… fallback The 50ms inter-put sleep in `test_wal_only_size_trigger_fires_repeatedly` was tight: on slower Windows CI runners the background flush task did not always drain the trigger queue between puts, allowing crossings to coalesce into a single drain and the assertion `next_position >= 3` to fire spuriously. Bump the sleep to 250ms so it keeps a comfortable margin without slowing the suite. Also extend the metadata-sync regression test to cover both the truthy spellings of the legacy `lance-schema:unenforced-primary-key` boolean flag (`true`, `1`, `yes`, plus mixed-case) and the falsy / non-numeric fallback paths so codecov is satisfied.
|
Pushed b32468f to address both:
PTAL. |
Per review feedback on lance-format#6706 — the inline rationale belongs in the commit message of the original fix, not duplicated as a comment block above the line.
Summary
UpdateConfig's field-metadata path inTransaction::apply_update_map(rust/lance/src/dataset/transaction.rs) mutatesfield.metadatabut does not refresh the cachedField::unenforced_primary_key_position. The protobuf encoder forFieldreads the cachedOption<u32>(not the metadata HashMap), so the next commit drops the PK marker even though the metadata HashMap correctly containslance-schema:unenforced-primary-key:position. The mirror image is also broken: removing the keys from metadata leaves a stale cachedSome(_)that gets re-encoded as a PK marker on the next commit.This makes it currently impossible to install or remove an unenforced primary key on an existing dataset via any public API —
update_field_metadataand the deprecatedreplace_field_metadataboth go through this path, and the round-trip via reopen returns no PK.Fix
After applying each
field_metadata_update, re-derivefield.unenforced_primary_key_positionfrom the freshly-updated metadata using the same parsing rules the Arrow → Field decoder uses (position key first, then the legacy boolean-flag fallback). This keeps the two views in sync so the next protobuf encoding reflects the user's intent.Also re-exports
LANCE_UNENFORCED_PRIMARY_KEYfromlance_core::datatypesalongside the existingLANCE_UNENFORCED_PRIMARY_KEY_POSITIONre-export, so callers (and the new test) can use both constants without reaching into the privatefieldmodule.Test
test_update_field_metadata_syncs_unenforced_primary_key_positioninrust/lance/src/dataset/metadata.rscovers:Some(0),Schema::unenforced_primary_key()must report it, and a freshDataset::openmust round-trip the marker.The test fails on
main(returnsNoneinstead ofSome(0)) and passes with the fix.