Skip to content

fix: LazyMemoryExec should produce independent streams per execute()#21565

Open
viirya wants to merge 1 commit intoapache:mainfrom
viirya:fix-lazy-memory-exec-shared-state
Open

fix: LazyMemoryExec should produce independent streams per execute()#21565
viirya wants to merge 1 commit intoapache:mainfrom
viirya:fix-lazy-memory-exec-shared-state

Conversation

@viirya
Copy link
Copy Markdown
Member

@viirya viirya commented Apr 12, 2026

Which issue does this PR close?

  • Closes #.

Rationale for this change

LazyMemoryExec::execute() shares the same generator instance across multiple calls via Arc::clone, so a second call to execute(0) continues from where the first left off instead of starting from the beginning. This is inconsistent with how other ExecutionPlan implementations behave, where each execute() call produces an independent stream. This was discovered while writing e2e tests for NestedLoopJoinExec memory-limited execution (#21448), where the OOM fallback path re-executes the left child plan and got incomplete results.

What changes are included in this PR?

LazyMemoryExec::execute() was sharing the same generator instance (via Arc::clone) across multiple calls, causing streams to share mutable state. This meant a second call to execute(0) would continue from where the first call left off, instead of starting from the beginning.

Fix by calling reset_state() on the generator to create a fresh instance for each execute() call, matching the expected ExecutionPlan semantics that each execute() produces an independent stream.

Are these changes tested?

Unit test

Are there any user-facing changes?

No

LazyMemoryExec::execute() was sharing the same generator instance
(via Arc::clone) across multiple calls, causing streams to share
mutable state. This meant a second call to execute(0) would continue
from where the first call left off, instead of starting from the
beginning.

Fix by calling reset_state() on the generator to create a fresh
instance for each execute() call, matching the expected ExecutionPlan
semantics that each execute() produces an independent stream.

Co-authored-by: Isaac
@github-actions github-actions bot added the physical-plan Changes to the physical-plan crate label Apr 12, 2026
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.

1 participant