Skip to content

fix: preserve Arrow field metadata on scalar subquery expressions - #24939

Open
M-Tesla wants to merge 1 commit into
apache:mainfrom
M-Tesla:fix-24933-scalar-subquery-metadata
Open

fix: preserve Arrow field metadata on scalar subquery expressions#24939
M-Tesla wants to merge 1 commit into
apache:mainfrom
M-Tesla:fix-24933-scalar-subquery-metadata

Conversation

@M-Tesla

@M-Tesla M-Tesla commented Sep 4, 2026

Copy link
Copy Markdown

Which issue does this PR close?

Related: apache/sedona-db#1231, apache/sedona-db#1226. This is the uncorrelated physical-plan counterpart of the earlier outer-reference metadata fix in #17524 / #17422.

Rationale for this change

UDFs that distinguish Arrow extension types from their storage types (for example spatial predicates such as ST_Intersects) need ARROW:extension:name on every argument. Uncorrelated scalar subqueries kept that metadata in the logical plan, but physical planning built a ScalarSubqueryExpr from only the data type and nullability. The synthesized physical field had empty metadata, so queries like WHERE udf(col, (SELECT geometry FROM t WHERE id = 1)) failed even though the equivalent join form worked.

What changes are included in this PR?

  • ScalarSubqueryExpr now stores the output FieldRef (name scalar_subquery, original type/nullability, and metadata) via new_with_metadata. The existing new constructor is unchanged and still produces a field with empty metadata.
  • Physical lowering copies metadata from the logical subquery output field while still using Expr::nullable so zero-row subqueries remain nullable.
  • Protobuf encoding adds an additive metadata map on PhysicalScalarSubqueryExprNode so plan round-trips keep extension metadata.

What is the testing strategy for this PR?

  • Unit test scalar_subquery_preserves_output_field_metadata in planner.rs reproduces the drop during physical lowering.
  • Unit test return_field_preserves_extension_metadata and an updated proto round-trip in scalar_subquery.rs.
  • End-to-end regression test_extension_metadata_preserve_in_uncorrelated_scalar_subquery in user_defined_scalar_functions.rs, based on the issue reproducer. The existing EXISTS-subquery metadata test still passes.

Are there any user-facing changes?

Additive only: ScalarSubqueryExpr::new_with_metadata and an optional protobuf metadata map (older payloads decode as empty metadata). Existing new(data_type, nullable, ...) keeps working. Queries whose UDFs inspect argument field metadata now see the subquery's original extension metadata in the physical plan.

Uncorrelated scalar subqueries copied only data type and nullability into
the physical expression, so UDFs that rely on Arrow extension metadata
saw a bare storage type. Keep the subquery output metadata through
physical planning and protobuf round-trips.
@github-actions github-actions Bot added physical-expr Changes to the physical-expr crates core Core DataFusion crate labels Sep 4, 2026

@paleolimbot paleolimbot left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thank you for fixing! This seems reasonable but I have also not spent much time in this part of the code. I wonder if @neilconway has any opinions / is aware of implications of this I haven't thought of.

This needs CI to run (I can't help with that since I'm not a committer here) which may highlight some issues, and I wonder if the metadata.slt file can help add another layer to prevent a regression.

Comment on lines +2341 to +2346
SELECT id
FROM l
WHERE metadata_required(
l.geometry,
(SELECT r.geometry FROM r WHERE r.id = 1)
)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Is there a good way to get a query that exercises this into a .slt file as well? Maybe datafusion/sqllogictest/test_files/metadata.slt?

@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown

Thank you for opening this pull request!

Reviewer note: cargo-semver-checks reported the current version number is not SemVer-compatible with the changes in this pull request (compared against the base branch).

Details
     Cloning apache/main
    Building datafusion v55.0.0 (current)
       Built [  63.377s] (current)
     Parsing datafusion v55.0.0 (current)
      Parsed [   0.034s] (current)
    Building datafusion v55.0.0 (baseline)
       Built [  59.260s] (baseline)
     Parsing datafusion v55.0.0 (baseline)
      Parsed [   0.037s] (baseline)
    Checking datafusion v55.0.0 -> v55.0.0 (no change; assume patch)
     Checked [   0.659s] 223 checks: 223 pass, 31 skip
     Summary no semver update required
    Finished [ 125.045s] datafusion
    Building datafusion-physical-expr v55.0.0 (current)
       Built [  29.486s] (current)
     Parsing datafusion-physical-expr v55.0.0 (current)
      Parsed [   0.048s] (current)
    Building datafusion-physical-expr v55.0.0 (baseline)
       Built [  29.592s] (baseline)
     Parsing datafusion-physical-expr v55.0.0 (baseline)
      Parsed [   0.051s] (baseline)
    Checking datafusion-physical-expr v55.0.0 -> v55.0.0 (no change; assume patch)
     Checked [   0.337s] 223 checks: 223 pass, 31 skip
     Summary no semver update required
    Finished [  60.459s] datafusion-physical-expr
    Building datafusion-proto-models v55.0.0 (current)
       Built [  25.559s] (current)
     Parsing datafusion-proto-models v55.0.0 (current)
      Parsed [   0.131s] (current)
    Building datafusion-proto-models v55.0.0 (baseline)
       Built [  25.783s] (baseline)
     Parsing datafusion-proto-models v55.0.0 (baseline)
      Parsed [   0.141s] (baseline)
    Checking datafusion-proto-models v55.0.0 -> v55.0.0 (no change; assume patch)
     Checked [   1.759s] 223 checks: 222 pass, 1 fail, 0 warn, 31 skip

--- failure constructible_struct_adds_field: struct exhaustively constructible through public API adds field ---

Description:
A pub struct that could be exhaustively constructed with a literal using only public API has a new pub field, breaking existing exhaustive literals.
        ref: https://doc.rust-lang.org/reference/expressions/struct-expr.html
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.50.0/src/lints/constructible_struct_adds_field.ron

Failed in:
  field PhysicalScalarSubqueryExprNode.metadata in /home/runner/work/datafusion/datafusion/datafusion/proto-models/src/generated/prost.rs:2645
  field PhysicalScalarSubqueryExprNode.metadata in /home/runner/work/datafusion/datafusion/datafusion/proto-models/src/generated/prost.rs:2645

     Summary semver requires new major version: 1 major and 0 minor checks failed
    Finished [  54.728s] datafusion-proto-models

@github-actions github-actions Bot added the auto detected api change Auto detected API change label Sep 4, 2026
@codecov-commenter

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 76.53061% with 23 lines in your changes missing coverage. Please review.
✅ Project coverage is 81.63%. Comparing base (20d1c56) to head (6e68c94).
⚠️ Report is 7 commits behind head on main.

Files with missing lines Patch % Lines
datafusion/proto-models/src/generated/pbjson.rs 0.00% 14 Missing ⚠️
datafusion/physical-expr/src/planner.rs 82.75% 3 Missing and 2 partials ⚠️
datafusion/physical-expr/src/scalar_subquery.rs 92.72% 2 Missing and 2 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #24939      +/-   ##
==========================================
- Coverage   81.64%   81.63%   -0.01%     
==========================================
  Files        1123     1123              
  Lines      410248   410383     +135     
  Branches   410248   410383     +135     
==========================================
+ Hits       334940   335026      +86     
- Misses      55617    55660      +43     
- Partials    19691    19697       +6     

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

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

Labels

auto detected api change Auto detected API change core Core DataFusion crate physical-expr Changes to the physical-expr crates

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Scalar subqueries drop extension metadata from their result

3 participants