Repository navigation
feat: make the materialized CTE nodes a first-class LogicalPlan variant - #26269
Conversation
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #26269 +/- ##
==========================================
- Coverage 82.89% 82.88% -0.02%
==========================================
Files 1154 1154
Lines 457630 457707 +77
Branches 457630 457707 +77
==========================================
+ Hits 379370 379378 +8
- Misses 55256 55308 +52
- Partials 23004 23021 +17 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
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 |
1ca8c39 to
e408875
Compare
0356f37 to
37c5b98
Compare
Replace the `MaterializedCte` and `MaterializedCteScan` extension nodes with the variants `LogicalPlan::MaterializedCte` and `LogicalPlan::MaterializedCteScan`. Each rule now states what it does with the nodes in its `match`, and the downcasts are removed from `PushDownFilter`, `PullUpCorrelatedExpr`, `head_output_expr` and the physical planner. `MaterializedCte::try_new` checks that the scans have the schema of the body, and `MaterializedCteScan::find_in` finds the scans of one CTE, also in subquery expressions. The unparser, the Substrait producer and the protobuf serializer return a "not implemented" error for the two variants. Plans and results do not change. Closes apache#26238. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
37c5b98 to
14c4e73
Compare
| pub cte: LogicalPlan, | ||
| pub continuation: LogicalPlan, | ||
| /// The body of the CTE | ||
| pub cte: Arc<LogicalPlan>, |
There was a problem hiding this comment.
nit: the field is cte but the accessor is body(), so call sites end up reading cte.cte (e.g. in decorrelate.rs and optimize_projections). Since #25580 hasn't shipped in a release yet, renaming the field to body now would be free:
- pub cte: Arc<LogicalPlan>,
+ pub body: Arc<LogicalPlan>,|
Thanks @adriangb! This is ready to go once the conflicts are resolved. |
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
# Conflicts: # datafusion/expr/src/logical_plan/display.rs
|
I merged up to resolve conflicts |
Which issue does this PR close?
LogicalPlanvariants #26238.Rationale for this change
#25580 plans
WITH x AS MATERIALIZED (...)with two built-inUserDefinedLogicalNodes insideLogicalPlan::Extension. Rules that must know about the nodes find them with a downcast, and code outside DataFusion sees an unknown extension node.For users of SQL nothing changes. Plans and results are the same. For library users, the nodes are now visible in a
match:It is easier to do this before more rules are written against the extension nodes.
What changes are included in this PR?
LogicalPlan::MaterializedCte(MaterializedCtePlan).MaterializedCtePlanhas two cases:Cte, which computes the body once and evaluates the continuation, andScan, a leaf that reads the buffered output. This keeps the number of top-level variants low, in the same way asLogicalPlan::StatementandLogicalPlan::Ddl. Amatcharm that treats both cases the same way isLogicalPlan::MaterializedCte(_).Scancase and not aTableScanover aTableSource. ATableScanwould need a downcast of the source to read the CTE id, andOptimizeProjectionswould write a projection into it, which changes the plans.MaterializedCte::try_newchecks that each scan of the CTE in the continuation has the column names and types of the body.with_new_exprsand theTreeNoderewrites do not run this check again.MaterializedCteScan::find_inreturns the scans of one CTE in a plan, also in subquery expressions.PushDownFilter,PullUpCorrelatedExpr,LogicalPlan::head_output_exprand the physical planner. Eachmatchnow states the behaviour, and the behaviour is the same as before.Comparison with PostgreSQL and DuckDB. PostgreSQL plans a CTE as a separate subplan that
CteScannodes read. DuckDB uses aLOGICAL_MATERIALIZED_CTEnode andLOGICAL_CTE_REFleaves. This PR uses the same two-part shape.Are these changes tested?
Yes.
cte_materialized.sltpasses without changes, so no plan changed. There are new unit tests for the constructor check and forfind_in. The "not implemented" arms have no tests.Are there any user-facing changes?
Yes, this is a public API change. An exhaustive
matchonLogicalPlanin downstream code needs one new arm.MaterializedCte::cteandMaterializedCte::continuationare nowArc<LogicalPlan>. There is an entry in the 56.0.0 upgrade guide.