feat(table): align primary-key vector read to physical-coordinate model#544
Open
JunRuiLee wants to merge 5 commits into
Open
feat(table): align primary-key vector read to physical-coordinate model#544JunRuiLee wants to merge 5 commits into
JunRuiLee wants to merge 5 commits into
Conversation
…e tests for pk-vector read
JunRuiLee
force-pushed
the
feat/pk-vector-physical-coords
branch
from
July 19, 2026 05:25
4a4ed1f to
99663ee
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Purpose
Linked issue: part of #514
Rust's primary-key (PK) vector read assumed every PK-vector data file carries a
first_row_id, using it to turn physical(file, row position)coordinates into global row ids. But Java never assignsfirst_row_idto PK-table data files — row-tracking (the only thing that assigns it) is forbidden on PK tables. Java's PK vector search works entirely in physical coordinates and deliberately does not produce global row ids:PrimaryKeyScoredResult.results()throws, and the physical position reader selects rows by file-local positions viabatch.selection(rowPositions).As a result, on a real Java-written PK-vector table (no
first_row_id) both the scored path and the materialized read fail loud in Rust. The existing tests only passed because they pinnedfirst_row_id == 0, makingfirst_row_id + position == position.This PR aligns the Rust PK vector read to Java's physical-coordinate model.
Brief change log
execute_scored()now fails loud when the query targets a PK-vector column (mirrors JavaPrimaryKeyScoredResult.results()throwing): the PK path produces physical positions, not global row ids, so callers must useexecute_read(). Removed the global-id helper that computedfirst_row_id + position.batch.selection(rowPositions)) instead of round-tripping through a global_ROW_ID/first_row_id. Added a local-selection read entry onDataFileReaderthat feeds file-local ranges straight to the format reader's row-selection, bypassing the global→local conversion._PKEY_VECTOR_POSITION/_PKEY_VECTOR_SCOREare emitted from an explicit cursor over the DV-filtered local selection, advanced by each batch's actual returned row count. The predicate-free guard is preserved (a row-filtering predicate would desync the cursor), and the local-selection reader rejects predicate readers self-consistently.first_row_idrequirement from the residual-filter position collection; surviving rows' file-local positions are recovered from their ordinal in the unfiltered scan.The DE/append (global-index) vector path and the shared
SearchResult { row_ids, scores }shape are untouched — global row ids are legitimate there.Tests
ivf-flatindexer is committed as opaque binaries and read back viaexecute_read()(pk_vector_java_fixture_test.rs). Its data files have nofirst_row_id— exactly the condition that broke the old code. Provenance (Java commit, generator command, schema/config, query + analytic top-k, checksum) is recorded in the test header. This becomes a permanent regression guard.execute_readwithfirst_row_id = Noneselects the correct file-local positions; withfirst_row_id = Some(100)(non-position-aligned) still returns the correct rows — catches any accidental reuse of the global row-range semantics.execute_scored()now returns an error; DEexecute_scored/to_row_rangestests stay green.cargo test -p paimonpasses;cargo clippy -p paimon --lib --tests -- -D warningsandcargo fmt --checkclean.API and Format
No storage-format change. Behavior change: PK
execute_scored()/execute()now return a clear error instead of (incorrect) results computed under thefirst_row_id == 0assumption — a corrective change on a path that was already broken for real Java-written data. No public physical-coordinate result type is added.Documentation
No documentation changes.