Skip to content

fix(ffi): don't discard downcast-delegating wrappers of foreign plans - #25749

Merged
alamb merged 2 commits into
apache:mainfrom
timsaucer:fix-ffi-plan-downcast-delegate
Sep 28, 2026
Merged

alamb merged 2 commits into
apache:mainfrom
timsaucer:fix-ffi-plan-downcast-delegate

Conversation

@timsaucer

Copy link
Copy Markdown
Member

Which issue does this PR close?

Rationale for this change

A transparent wrapper ExecutionPlan (one that implements downcast_delegate, such as datafusion-tracing's InstrumentedExec) around a ForeignExecutionPlan is silently dropped when it is passed back across the FFI boundary. For example, installing the tracing instrumentation rule via FFI leaves the plan un-instrumented. Also, when such a wrapper is the child of a foreign plan, it does not receive the runtime handle.

What changes are included in this PR?

  • FFI_ExecutionPlan::new: the "already foreign" shortcut now checks the concrete type via Any instead of the delegate-aware downcast_ref, so it only fires for a real ForeignExecutionPlan.
  • pass_runtime_to_children: the child check also uses Any, so a local wrapper child of a foreign parent is re-wrapped with the runtime.
  • plan_is_foreign intentionally stays delegate-aware, since a delegating wrapper typically forwards replace_children to the foreign plan and its children still need the runtime. A comment explains this.

What is the testing strategy for this PR?

  • Added an optional downcast_delegate mode to the existing EmptyExec test plan (with_downcast_delegate).
  • Added test_ffi_execution_plan_delegating_wrapper, which checks that the wrapper survives FFI_ExecutionPlan::new and that a wrapper child of a foreign parent gets the runtime. Reverting either fix on its own makes the test fail.

Are there any user-facing changes?

No API changes. Wrapper plans that implement downcast_delegate are now kept when they cross the FFI boundary instead of being discarded.

🤖 Generated with Claude Code

`FFI_ExecutionPlan::new` and `pass_runtime_to_children` used the
delegate-aware `downcast_ref`/`is` to detect `ForeignExecutionPlan`.
A wrapper whose `downcast_delegate` is a foreign plan (e.g.
datafusion-tracing's `InstrumentedExec`) was treated as the foreign plan
itself: `new` returned the pre-wrapper FFI plan, dropping the wrapper,
and a wrapper child of a foreign parent was not given the runtime.

Check the concrete type via `Any` at those sites. `plan_is_foreign`
stays delegate-aware since a delegating wrapper typically forwards
`replace_children` to the foreign plan.

Closes apache#25717

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added the ffi Changes to the ffi crate label Sep 25, 2026
@timsaucer
timsaucer marked this pull request as ready for review September 25, 2026 11:58
@codecov-commenter

codecov-commenter commented Sep 25, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 89.74359% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 82.55%. Comparing base (991fd23) to head (cf21434).

Files with missing lines Patch % Lines
datafusion/ffi/src/execution_plan.rs 89.74% 1 Missing and 3 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #25749      +/-   ##
==========================================
- Coverage   82.55%   82.55%   -0.01%     
==========================================
  Files        1141     1141              
  Lines      440209   440246      +37     
  Branches   440209   440246      +37     
==========================================
+ Hits       363409   363426      +17     
- Misses      54829    54842      +13     
- Partials    21971    21978       +7     

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

@namanjain24-sudo

Copy link
Copy Markdown
Contributor

FYI, closed #25645 in favor of this one — it covers the same fix plus pass_runtime_to_children.

…-downcast-delegate

# Conflicts:
#	datafusion/ffi/src/execution_plan.rs
@alamb

alamb commented Sep 28, 2026

Copy link
Copy Markdown
Contributor

I merged up from main to resolve a conflict

@alamb
alamb enabled auto-merge September 28, 2026 15:23
@alamb
alamb added this pull request to the merge queue Sep 28, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Sep 28, 2026
@alamb
alamb added this pull request to the merge queue Sep 28, 2026
Merged via the queue into apache:main with commit c1786f7 Sep 28, 2026
42 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ffi Changes to the ffi crate v56.0.0

Projects

None yet

Development

Successfully merging this pull request may close these issues.

FFI_ExecutionPlan::new silently discards transparent wrapper nodes

4 participants