core/vdbe: Short-circuit index seek on NULL keys in LEFT JOIN#6268
Open
friskypriyanshu wants to merge 4 commits intotursodatabase:mainfrom
Open
core/vdbe: Short-circuit index seek on NULL keys in LEFT JOIN#6268friskypriyanshu wants to merge 4 commits intotursodatabase:mainfrom
friskypriyanshu wants to merge 4 commits intotursodatabase:mainfrom
Conversation
Contributor
Fossier: Manual Review Requested
Score BreakdownTotal Score: 69.3/100 | Confidence: 100% | Outcome: REVIEW
|
Collaborator
|
/fossier approve |
Author
|
Hi @penberg @jussisaurio, just a gentle ping on this one. All checks are green, including the fix for the fuzzer regression. Ready for review whenever you have a moment. Thanks! |
jussisaurio
reviewed
Apr 9, 2026
| }; | ||
|
|
||
| if is_eq_only { | ||
| // We only care about Unpacked record sources for this short-circuit |
Collaborator
There was a problem hiding this comment.
isn't it invariant that this is RecordSource::Unpacked, since it's constructed above? Let's do let ... else instead of if let for that reason.
| if is_eq_only { | ||
| // We only care about Unpacked record sources for this short-circuit | ||
| if let RecordSource::Unpacked { start_reg, .. } = record_source { | ||
| // Check only the primary register (no need for a loop 'i' here) |
Collaborator
There was a problem hiding this comment.
Why is there no need? This should be part of the comment.
| if let RecordSource::Unpacked { start_reg, .. } = record_source { | ||
| // Check only the primary register (no need for a loop 'i' here) | ||
| if state.registers[start_reg].is_null() { | ||
| let offset = match target_pc { |
Collaborator
There was a problem hiding this comment.
You can use target_pc.as_offset_int() here which has equivalent behavior
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.
Fixes: #6077
Description
Fixes a query optimizer bug where chained LEFT JOINs producing virtual NULL keys were incorrectly matching literal NULLs in downstream indexed tables.
Root Cause & Fix
The VDBE op_seek instruction was evaluating NULL keys against the index instead of short-circuiting (violating NULL = NULL is false).
In core/vdbe/execute.rs (op_seek):
Intercepted RecordSource::Unpacked registers before calling seek_internal.
If any search register evaluates to Null, the seek instantly aborts.
Extracted target_pc to update state.pc directly and returned InsnFunctionStepResult::Step to correctly trigger the "not found" branch.
Testing
Added left_join_null_index_bug.sqltest using the exact schema/query from the issue.
Suite now passes cleanly with correct empty columns for unmatched rows.