fix(btree): include null pages in non-IsNull queries for correct thre…#6043
fix(btree): include null pages in non-IsNull queries for correct thre…#6043Xuanwo merged 1 commit intolance-format:mainfrom
Conversation
…e-valued logic BTree index search only consulted pages whose value range matched the query. When a queried value (e.g. 0) didn't exist in any page, no pages were searched and the null row set was empty. This caused `NOT(x = 0)` to produce a BlockList with no nulls tracked, incorrectly allowing NULL rows to pass the filter. The fix adds null pages (both partially-null and all-null) to every non-IsNull query's page list as Matches::Some, so FlatIndex::search() evaluates the predicate and correctly marks those rows as NULL. This preserves three-valued logic for compound expressions like `(x != 0) OR (x < 5)`. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
PR ReviewSolid bug fix with good analysis. The three-valued logic gap when queried values don't appear in any BTree page is a real correctness issue, and the fix is well-targeted. No blocking issues foundThe approach of adding null pages as Minor note (non-blocking)The project guidelines in CLAUDE.md recommend LGTM |
|
This PR appears to address the issue #5918. |
|
@fenfeng9 awesome! Thanks for the pointer. This bug was found with a generative testing framework I have been hacking on. |
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
Xuanwo
left a comment
There was a problem hiding this comment.
Thank you for working on this!
lance-format#6043) …e-valued logic BTree index search only consulted pages whose value range matched the query. When a queried value (e.g. 0) didn't exist in any page, no pages were searched and the null row set was empty. This caused `NOT(x = 0)` to produce a BlockList with no nulls tracked, incorrectly allowing NULL rows to pass the filter. The fix adds null pages (both partially-null and all-null) to every non-IsNull query's page list as Matches::Some, so FlatIndex::search() evaluates the predicate and correctly marks those rows as NULL. This preserves three-valued logic for compound expressions like `(x != 0) OR (x < 5)`. Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
…e-valued logic
BTree index search only consulted pages whose value range matched the query. When a queried value (e.g. 0) didn't exist in any page, no pages were searched and the null row set was empty. This caused
NOT(x = 0)to produce a BlockList with no nulls tracked, incorrectly allowing NULL rows to pass the filter.The fix adds null pages (both partially-null and all-null) to every non-IsNull query's page list as Matches::Some, so FlatIndex::search() evaluates the predicate and correctly marks those rows as NULL. This preserves three-valued logic for compound expressions like
(x != 0) OR (x < 5).