Skip to content

fix: flush FilterExec output for unbounded inputs - #24353

Open
goutamadwant wants to merge 1 commit into
apache:mainfrom
goutamadwant:fix-unbounded-filter-flush
Open

fix: flush FilterExec output for unbounded inputs#24353
goutamadwant wants to merge 1 commit into
apache:mainfrom
goutamadwant:fix-unbounded-filter-flush

Conversation

@goutamadwant

Copy link
Copy Markdown
Contributor

Which issue does this PR close?

Rationale for this change

While prototyping the minimal push-based streaming example proposed in #9016, I found that FilterExec could buffer small filtered results indefinitely when its input was unbounded. Because an unbounded source may never finish, consumers could not observe those results while continuing to push input batches.

This PR extracts the smallest prerequisite fix so the streaming example and user-guide documentation can follow as separate, focused PRs.

This is complementary to #23856: that PR changes how filtered batches are supplied to the coalescer, while this PR controls when buffered rows become observable for an unbounded input.

What changes are included in this PR?

  • Add a non-final LimitedBatchCoalescer flush operation that emits buffered rows while still allowing subsequent input.
  • Preserve idempotent coalescer finalization.
  • Flush FilterExec output after each input batch when its input is unbounded.
  • Preserve the existing coalescing behavior for bounded inputs.
  • Preserve existing fetch-limit behavior.
  • Add regression coverage for:
    • emitting results while an unbounded input remains open;
    • multiple input pushes;
    • a fully filtered batch followed by a matching batch;
    • bounded-input coalescing;
    • flushing without preventing subsequent input.

Planned follow-up PRs:

  1. Add the simplest possible push-based streaming example under datafusion-examples, showing how to feed batches into a running query and consume results incrementally.
  2. Add a “Using DataFusion for streaming” section to the library user guide, based on that example and documenting relevant boundedness and execution considerations.

Are these changes tested?

Yes.

  • Verified that the new unbounded-input regression test fails before the implementation and passes afterward.
  • cargo test -p datafusion-physical-plan
  • cargo test -p datafusion
  • cargo test -p datafusion-cli
  • cargo test --profile=ci --test sqllogictests
  • Contributor-guide extended workspace test suite with avro,json,backtrace,extended_tests,recursive_protection,parquet_encryption
  • cargo clippy --all-targets --all-features -- -D warnings
  • cargo fmt --all -- --check
  • Rust documentation, license-header, and typo checks

Are there any user-facing changes?

Yes. FilterExec now emits filtered results incrementally for unbounded inputs instead of waiting for the target batch size or input completion.

Bounded-input coalescing remains unchanged. There are no public API or breaking changes.

@github-actions github-actions Bot added the physical-plan Changes to the physical-plan crate label Aug 14, 2026
@2010YOUY01

Copy link
Copy Markdown
Contributor

I found that FilterExec could buffer small filtered results indefinitely when its input was unbounded

Was that only to buffer up to batch_size from the configuration? I think this is still intended for streaming input. It's a convention for each operator to produce reasonably large output batches, which helps downstream operators vectorize.

@codecov-commenter

codecov-commenter commented Aug 14, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 78.52349% with 32 lines in your changes missing coverage. Please review.
✅ Project coverage is 81.18%. Comparing base (b9399dc) to head (3289f3f).

Files with missing lines Patch % Lines
datafusion/physical-plan/src/filter.rs 74.78% 7 Missing and 23 partials ⚠️
datafusion/physical-plan/src/coalesce/mod.rs 93.33% 0 Missing and 2 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #24353      +/-   ##
==========================================
- Coverage   81.19%   81.18%   -0.01%     
==========================================
  Files        1110     1110              
  Lines      388750   388891     +141     
  Branches   388750   388891     +141     
==========================================
+ Hits       315657   315740      +83     
- Misses      54506    54537      +31     
- Partials    18587    18614      +27     

☔ 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.

@goutamadwant
goutamadwant force-pushed the fix-unbounded-filter-flush branch from de069c7 to 3289f3f Compare August 15, 2026 07:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

physical-plan Changes to the physical-plan crate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants