Skip to content

fix(physical-plan): report Final emission for LeftSemi hash and neste… - #24976

Open
TinyMurky wants to merge 2 commits into
apache:mainfrom
TinyMurky:EmissionType-Incremental-emit-fix
Open

fix(physical-plan): report Final emission for LeftSemi hash and neste…#24976
TinyMurky wants to merge 2 commits into
apache:mainfrom
TinyMurky:EmissionType-Incremental-emit-fix

Conversation

@TinyMurky

@TinyMurky TinyMurky commented Sep 6, 2026

Copy link
Copy Markdown

Which issue does this PR close?

Rationale for this change

HashJoinExec and NestedLoopJoinExec report LeftSemi joins as emitting incrementally, but they only emit matched build-side rows after the probe
side is exhausted.

Reporting EmissionType::Final reflects their actual behavior and allows SanityCheckPlan to reject pipelines with an unbounded probe side that cannot produce output.

What changes are included in this PR?

  • Classify LeftSemi joins as EmissionType::Final in both operators, regardless of the probe input's emission type.
  • Added unit tests verifying the emission type of LeftSemi joins in both HashJoinExec and NestedLoopJoinExec.
  • Add an integration test covering input swapping for an unbounded left
    input, rejection of an unbounded probe input, and successful planning when
    both inputs are bounded.

Are these changes tested?

Added unit tests verifying the emission type of LeftSemi joins in both HashJoinExec and NestedLoopJoinExec.

Added an integration test covering:

  • Unbounded left and bounded right: planning succeeds after swapping to
    RightSemi.
  • Bounded left and unbounded right: planning is rejected.
  • Both inputs bounded: planning succeeds.

Following test commands have been executed and passed

  • cargo test -p datafusion
  • cargo test --profile=ci --test sqllogictests
  • cargo test -p datafusion
  • cargo test -p datafusion-cli

Are there any user-facing changes?

Yes.

LeftSemi hash and nested loop joins now report Final emission.

Plans with a bounded build side and an unbounded probe side are rejected instead of being accepted despite being unable to produce output.

Results for bounded inputs are unchanged.

…d loop joins

## Which issue does this PR close?

-  apache#24962(apache#24962)

## Rationale for this change

`HashJoinExec` and `NestedLoopJoinExec` report `LeftSemi` joins as
emitting incrementally, but they only emit matched build-side rows after
the probeside is exhausted.

Reporting `EmissionType::Final` reflects their actual behavior and
allows `SanityCheckPlan` to reject pipelines with an unbounded probe
side that cannot produce output.

## What changes are included in this PR?

- Classify `LeftSemi` joins as `EmissionType::Final` in both operators,
regardless of the probe input's emission type.
- Added unit tests verifying the emission type of LeftSemi joins in both
`HashJoinExec` and `NestedLoopJoinExec`.
- Add an integration test covering input swapping for an unbounded left
input, rejection of an unbounded probe input, and successful planning
when  both inputs are bounded.

## Are these changes tested?

- Added unit tests verifying the emission type of LeftSemi joins in both
`HashJoinExec` and `NestedLoopJoinExec`.

- Added an integration test covering:
  - Unbounded left and bounded right: planning succeeds after swapping
to RightSemi.

  - Bounded left and unbounded right: planning is rejected.
  - Both inputs bounded: planning succeeds.

Following test commands have been executed and passed
- `cargo test -p datafusion`
- `cargo test --profile=ci --test sqllogictests`
- `cargo test -p datafusion`
- `cargo test -p datafusion-cli`

## Are there any user-facing changes?

Yes. `LeftSemi` hash and nested loop joins now report Final
emission.Plans with a bounded build side and an unbounded probe side are
rejected instead of being accepted despite being unable to produce
output.Results for bounded inputs are unchanged.

@jayzhan211 jayzhan211 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @TinyMurky , LGTM!

@codecov-commenter

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 87.80488% with 5 lines in your changes missing coverage. Please review.
✅ Project coverage is 81.67%. Comparing base (722cbf2) to head (db05bba).

Files with missing lines Patch % Lines
...tafusion/physical-plan/src/joins/hash_join/exec.rs 84.00% 1 Missing and 3 partials ⚠️
...fusion/physical-plan/src/joins/nested_loop_join.rs 93.75% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #24976      +/-   ##
==========================================
- Coverage   81.67%   81.67%   -0.01%     
==========================================
  Files        1126     1126              
  Lines      414533   414560      +27     
  Branches   414533   414560      +27     
==========================================
+ Hits       338562   338581      +19     
+ Misses      56058    56057       -1     
- Partials    19913    19922       +9     

☔ 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 commented Sep 6, 2026

Copy link
Copy Markdown
Author

Thanks for the review!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

core Core DataFusion crate physical-plan Changes to the physical-plan crate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants