Skip to content

Commit cdce3f1

Browse files
committed
Stop copying plans in LogicalPlan::with_param_values
1 parent 03d8ba1 commit cdce3f1

File tree

1 file changed

+28
-51
lines changed
  • datafusion/expr/src/logical_plan

1 file changed

+28
-51
lines changed

datafusion/expr/src/logical_plan/plan.rs

Lines changed: 28 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1226,14 +1226,19 @@ impl LogicalPlan {
12261226
param_values: impl Into<ParamValues>,
12271227
) -> Result<LogicalPlan> {
12281228
let param_values = param_values.into();
1229-
match self {
1230-
LogicalPlan::Prepare(prepare_lp) => {
1231-
param_values.verify(&prepare_lp.data_types)?;
1232-
let input_plan = prepare_lp.input;
1233-
input_plan.replace_params_with_values(&param_values)
1229+
let plan_with_values = self.replace_params_with_values(&param_values)?;
1230+
1231+
// unwrap Prepare
1232+
Ok(if let LogicalPlan::Prepare(prepare_lp) = plan_with_values {
1233+
param_values.verify(&prepare_lp.data_types)?;
1234+
// try and take ownership of the input if is not shared, clone otherwise
1235+
match Arc::try_unwrap(prepare_lp.input) {
1236+
Ok(input) => input,
1237+
Err(arc_input) => arc_input.as_ref().clone(),
12341238
}
1235-
_ => self.replace_params_with_values(&param_values),
1236-
}
1239+
} else {
1240+
plan_with_values
1241+
})
12371242
}
12381243

12391244
/// Returns the maximum number of rows that this plan can output, if known.
@@ -1544,27 +1549,26 @@ impl LogicalPlan {
15441549
/// ...) replaced with corresponding values provided in
15451550
/// `params_values`
15461551
///
1547-
/// See [`Self::with_param_values`] for examples and usage
1552+
/// See [`Self::with_param_values`] for examples and usage with an owned
1553+
/// `ParamValues`
15481554
pub fn replace_params_with_values(
1549-
&self,
1555+
self,
15501556
param_values: &ParamValues,
15511557
) -> Result<LogicalPlan> {
1552-
let new_exprs = self
1553-
.expressions()
1554-
.into_iter()
1555-
.map(|e| {
1556-
let e = e.infer_placeholder_types(self.schema())?;
1557-
Self::replace_placeholders_with_values(e, param_values)
1558+
self.transform_up_with_subqueries(&|plan| {
1559+
let schema = plan.schema().clone();
1560+
plan.map_expressions(|e| {
1561+
e.infer_placeholder_types(&schema)?.transform_up(&|e| {
1562+
if let Expr::Placeholder(Placeholder { id, .. }) = e {
1563+
let value = param_values.get_placeholders_with_values(&id)?;
1564+
Ok(Transformed::yes(Expr::Literal(value)))
1565+
} else {
1566+
Ok(Transformed::no(e))
1567+
}
1568+
})
15581569
})
1559-
.collect::<Result<Vec<_>>>()?;
1560-
1561-
let new_inputs_with_values = self
1562-
.inputs()
1563-
.into_iter()
1564-
.map(|inp| inp.replace_params_with_values(param_values))
1565-
.collect::<Result<Vec<_>>>()?;
1566-
1567-
self.with_new_exprs(new_exprs, new_inputs_with_values)
1570+
})
1571+
.map(|res| res.data)
15681572
}
15691573

15701574
/// Walk the logical plan, find any `Placeholder` tokens, and return a map of their IDs and DataTypes
@@ -1596,33 +1600,6 @@ impl LogicalPlan {
15961600
})
15971601
.map(|_| param_types)
15981602
}
1599-
1600-
/// Return an Expr with all placeholders replaced with their
1601-
/// corresponding values provided in the params_values
1602-
fn replace_placeholders_with_values(
1603-
expr: Expr,
1604-
param_values: &ParamValues,
1605-
) -> Result<Expr> {
1606-
expr.transform(&|expr| {
1607-
match &expr {
1608-
Expr::Placeholder(Placeholder { id, .. }) => {
1609-
let value = param_values.get_placeholders_with_values(id)?;
1610-
// Replace the placeholder with the value
1611-
Ok(Transformed::yes(Expr::Literal(value)))
1612-
}
1613-
Expr::ScalarSubquery(qry) => {
1614-
let subquery =
1615-
Arc::new(qry.subquery.replace_params_with_values(param_values)?);
1616-
Ok(Transformed::yes(Expr::ScalarSubquery(Subquery {
1617-
subquery,
1618-
outer_ref_columns: qry.outer_ref_columns.clone(),
1619-
})))
1620-
}
1621-
_ => Ok(Transformed::no(expr)),
1622-
}
1623-
})
1624-
.data()
1625-
}
16261603
}
16271604

16281605
// Various implementations for printing out LogicalPlans

0 commit comments

Comments
 (0)