MCPcopy Create free account
hub / github.com/apache/datafusion / extract_from_plan

Function extract_from_plan

datafusion/optimizer/src/extract_leaf_expressions.rs:171–265  ·  view source on GitHub ↗

Extracts `MoveTowardsLeafNodes` sub-expressions from a plan node. Works for any number of inputs (0, 1, 2, …N). For multi-input nodes like Join, each extracted sub-expression is routed to the correct input by checking which input's schema contains all of the expression's column references.

(
    plan: LogicalPlan,
    alias_generator: &Arc<AliasGenerator>,
)

Source from the content-addressed store, hash-verified

169/// by checking which input's schema contains all of the expression's column
170/// references.
171fn extract_from_plan(
172 plan: LogicalPlan,
173 alias_generator: &Arc<AliasGenerator>,
174) -> Result<Transformed<LogicalPlan>> {
175 // Only extract from plan types whose output schema is predictable after
176 // expression rewriting. Nodes like Window derive column names from
177 // their expressions, so rewriting `get_field` inside a window function
178 // changes the output schema and breaks the recovery projection.
179 if !matches!(
180 &plan,
181 LogicalPlan::Aggregate(_)
182 | LogicalPlan::Filter(_)
183 | LogicalPlan::Sort(_)
184 | LogicalPlan::Limit(_)
185 | LogicalPlan::Join(_)
186 ) {
187 return Ok(Transformed::no(plan));
188 }
189
190 let inputs = plan.inputs();
191 if inputs.is_empty() {
192 return Ok(Transformed::no(plan));
193 }
194
195 // Fast pre-check: skip all allocations if no extractable expressions exist
196 if !has_extractable_expr(&plan.expressions()) {
197 return Ok(Transformed::no(plan));
198 }
199
200 // Save original output schema before any transformation
201 let original_schema = Arc::clone(plan.schema());
202
203 // Build per-input schemas from borrowed inputs (before plan is consumed
204 // by map_expressions). We only need schemas and column sets for routing;
205 // the actual inputs are cloned later only if extraction succeeds.
206 let input_schemas: Vec<Arc<DFSchema>> =
207 inputs.iter().map(|i| Arc::clone(i.schema())).collect();
208
209 // Build per-input extractors
210 let mut extractors: Vec<LeafExpressionExtractor> = input_schemas
211 .iter()
212 .map(|schema| LeafExpressionExtractor::new(schema.as_ref(), alias_generator))
213 .collect();
214
215 // Build per-input column sets for routing expressions to the correct input
216 let input_column_sets: Vec<std::collections::HashSet<ColumnReference>> =
217 input_schemas
218 .iter()
219 .map(|schema| schema_columns(schema.as_ref()))
220 .collect();
221
222 // Transform expressions via map_expressions with routing
223 let transformed = plan.map_expressions(|expr| {
224 routing_extract(expr, &mut extractors, &input_column_sets)
225 })?;
226
227 // If no expressions were rewritten, nothing was extracted
228 if !transformed.transformed {

Callers 1

rewriteMethod · 0.85

Calls 15

has_extractable_exprFunction · 0.85
newFunction · 0.85
schema_columnsFunction · 0.85
routing_extractFunction · 0.85
collectMethod · 0.80
map_expressionsMethod · 0.80
with_new_exprsMethod · 0.80
inputsMethod · 0.45
is_emptyMethod · 0.45
expressionsMethod · 0.45

Tested by

no test coverage detected

Used in the wild real call sites across dependent graphs

searching dependent graphs…