Skip to content

feature(physical-plan): add NullAwareMode to SortMergeJoinExec - #26090

Draft
TinyMurky wants to merge 18 commits into
apache:mainfrom
TinyMurky:support-null-aware-SortMergeJoinExec
Draft

TinyMurky wants to merge 18 commits into
apache:mainfrom
TinyMurky:support-null-aware-SortMergeJoinExec

Conversation

@TinyMurky

Copy link
Copy Markdown
Contributor

This is a draft PR, I'm still working on the issue

Which issue does this PR close?

Rationale for this change

What changes are included in this PR?

What is the testing strategy for this PR?

Are there any user-facing changes?

@codecov-commenter

codecov-commenter commented Oct 6, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 84.91620% with 27 lines in your changes missing coverage. Please review.
✅ Project coverage is 82.91%. Comparing base (d38c545) to head (8f3e360).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
...on/physical-plan/src/joins/sort_merge_join/exec.rs 83.33% 7 Missing and 6 partials ⚠️
...l-plan/src/joins/sort_merge_join/bitwise_stream.rs 87.09% 5 Missing and 3 partials ⚠️
...er/src/ensure_requirements/enforce_distribution.rs 81.81% 4 Missing ⚠️
datafusion/core/src/physical_planner.rs 88.23% 1 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #26090      +/-   ##
==========================================
- Coverage   82.91%   82.91%   -0.01%     
==========================================
  Files        1155     1155              
  Lines      458091   458243     +152     
  Branches   458091   458243     +152     
==========================================
+ Hits       379830   379945     +115     
- Misses      55220    55247      +27     
- Partials    23041    23051      +10     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@TinyMurky
TinyMurky force-pushed the support-null-aware-SortMergeJoinExec branch from bd3306c to 1b3711b Compare October 9, 2026 15:54
@github-actions github-actions Bot added auto detected api change Auto detected API change core Core DataFusion crate and removed auto detected api change Auto detected API change labels Oct 9, 2026
@TinyMurky
TinyMurky force-pushed the support-null-aware-SortMergeJoinExec branch 2 times, most recently from 6048d8c to 2b3d2c5 Compare October 14, 2026 03:17
@github-actions github-actions Bot added optimizer Optimizer rules sqllogictest SQL Logic Tests (.slt) labels Oct 14, 2026
@TinyMurky
TinyMurky force-pushed the support-null-aware-SortMergeJoinExec branch 2 times, most recently from b76ba05 to 541942f Compare October 19, 2026 07:33
…distribution_requirements when null_aware is true
Pass the validated null-aware mode to the bitwise stream and initialize the subquery state. Validate single-partition inputs at execution time.
Restore the seven-argument SortMergeJoinExec::try_new constructor and enable null-aware semantics through the validated with_null_aware builder. Preserve the flag when rebuilding plans.

Restore the original protobuf schema and generated types. Reject serialization of null-aware sort-merge joins rather than silently losing their semantics.

Restore ordinary join test configuration and update direct stream callers to pass no null-aware mode.
Classify the inner input as empty, containing NULL keys, or nonempty without NULL keys before the merge scan. Retain the first nonempty batch at offset zero for matching.

Finish null-aware LeftAnti streams without emitting rows when the inner input contains a NULL key.
Choose null-aware SortMergeJoinExec for single-key LeftAnti joins without a filter when hash joins are not preferred. Require NullEqualsNothing and request ASC NULLS FIRST ordering.

Apply an outer-key validity mask to unmatched rows when the inner input is nonempty without NULL keys. Use logical_nulls to account for dictionary values that are NULL. Preserve unmatched rows when the inner input is empty.
Distinguish CollectLeft null-aware hash joins from the supported single-partition LeftAnti sort-merge path. Clarify that remaining null-aware joins retain CollectLeft mode.
Document the supported null-aware LeftAnti routing and HashJoin fallback. Use a match guard for the RHS NULL early exit without changing its behavior.
Carry the original null-aware flag through both sort-merge join key reordering constructors so rebuilt joins retain NOT IN semantics.
Expect SortMergeJoinExec for eligible NOT IN queries when hash join is not preferred. Update the regression comments to reflect null-aware sort-merge join support.
Display the null_aware marker in default, verbose, and tree plan formats when enabled.

Update the existing EXPLAIN expectation and add a tree-format SQLLogicTest case for null-aware LeftAnti joins.
Add SQL regression coverage for null-aware sort-merge joins when
prefer_hash_join is false. Verify that an empty RHS preserves NULL outer
keys and duplicate rows, an RHS containing NULL suppresses all rows, and
a nonempty RHS without NULL excludes NULL and matched outer keys.

Use a four-partition RHS to verify that NULL detection covers the entire
input. Assert null-aware SMJ plans with target_partitions set to 1 or 4
and with join repartitioning enabled or disabled.

Verify that unsupported correlated anti joins retain the CollectLeft
HashJoin fallback and that null-aware mark joins preserve UNKNOWN results
when hash joins are not preferred. Update the related test comments.

Refs apache#25546
Add five executor tests for null-aware LeftAnti sort-merge joins. Cover
empty inputs, empty batches before RHS NULLs, startup prefetch across key
groups, draining remaining left batches, and dictionary value NULLs.

Use row IDs to verify that NULL and duplicate rows are retained or removed
according to NOT IN semantics. Exercise batch sizes 1 and 2 at key-group
boundaries and check dictionaries with valid indices pointing to NULL
values and different index mappings on each side.

Reuse the existing join and input helpers, with small fixture helpers
modeled on the null-aware HashJoin tests. Execute plans directly so the
optimizer cannot simplify away empty-input cases.

Refs apache#25546
@TinyMurky
TinyMurky force-pushed the support-null-aware-SortMergeJoinExec branch from 541942f to 8f3e360 Compare October 19, 2026 08:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

core Core DataFusion crate optimizer Optimizer rules physical-plan Changes to the physical-plan crate sqllogictest SQL Logic Tests (.slt)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support null-aware (NOT IN) anti / mark joins in SortMergeJoinExec

2 participants