Skip to content

Native DataFrame + builders: CTEs / shared subplans (ReferenceRel) with in-band subtrees #211

Description

@nielspardon

Summary

Add support for CTEs / shared subplansReferenceRel + subtree_ordinal — to both the substrait.builders.plan layer and the substrait.dataframe native DataFrame API (as DataFrame.cache()).

This was prototyped in #204 but pulled out to keep that PR focused, and because the first cut used a contextvars-based mechanism that circumvented the builder layer. This issue tracks doing it properly at both layers. See discussion: #204 (comment)

Design (agreed in review)

Carry the shared subtrees in-band inside the Plan — in Plan.relations (the leading rel entries), exactly the way a Plan already carries its extension declarations — rather than out-of-band via a contextvar.

Concretely:

  • type_inference: thread the subtree list through infer_rel_schema / infer_plan_schema as a parameter (extracted from plan.relations), and add a reference case that resolves a ReferenceRel's schema against subtrees[subtree_ordinal]. No contextvar.
  • builders (substrait.builders.plan):
    • a reference(...) builder that emits a ReferenceRel-rooted plan;
    • every builder propagates its input plans' shared subtrees into its output plan (mirroring how _merge_extensions already carries extensions upward);
    • multi-input builders (join, set, …) rebase subtree_ordinals when merging inputs that each carry their own subtrees, so ordinals stay unique and correct.
  • dataframe (substrait.dataframe): DataFrame.cache() on top of the builder support — dedupe repeated uses of a cached frame and reference the shared subtree; to_plan() emits the subtrees as the plan's leading relations.

Because the subtrees then live inside the resolved Plan, the builder-internal infer_plan_schema(bound_plan) calls have the subtree list available directly — which is what makes the contextvar unnecessary.

Notes

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions