@@ -928,8 +928,40 @@ impl LogicalPlan {
928
928
}
929
929
}
930
930
}
931
- /// Convert a prepared [`LogicalPlan`] into its inner logical plan
932
- /// with all params replaced with their corresponding values
931
+ /// Replaces placeholder param values (like `$1`, `$2`) in [`LogicalPlan`]
932
+ /// with the specified `param_values`.
933
+ ///
934
+ /// [`LogicalPlan::Prepare`] are
935
+ /// converted to their inner logical plan for execution.
936
+ ///
937
+ /// # Example
938
+ /// ```
939
+ /// # use arrow::datatypes::{Field, Schema, DataType};
940
+ /// use datafusion_common::ScalarValue;
941
+ /// # use datafusion_expr::{lit, col, LogicalPlanBuilder, logical_plan::table_scan, placeholder};
942
+ /// # let schema = Schema::new(vec![
943
+ /// # Field::new("id", DataType::Int32, false),
944
+ /// # ]);
945
+ /// // Build SELECT * FROM t1 WHRERE id = $1
946
+ /// let plan = table_scan(Some("t1"), &schema, None).unwrap()
947
+ /// .filter(col("id").eq(placeholder("$1"))).unwrap()
948
+ /// .build().unwrap();
949
+ ///
950
+ /// assert_eq!("Filter: t1.id = $1\
951
+ /// \n TableScan: t1",
952
+ /// plan.display_indent().to_string()
953
+ /// );
954
+ ///
955
+ /// // Fill in the parameter $1 with a literal 3
956
+ /// let plan = plan.with_param_values(vec![
957
+ /// ScalarValue::from(3i32) // value at index 0 --> $1
958
+ /// ]).unwrap();
959
+ ///
960
+ /// assert_eq!("Filter: t1.id = Int32(3)\
961
+ /// \n TableScan: t1",
962
+ /// plan.display_indent().to_string()
963
+ /// );
964
+ /// ```
933
965
pub fn with_param_values (
934
966
self ,
935
967
param_values : Vec < ScalarValue > ,
@@ -961,7 +993,7 @@ impl LogicalPlan {
961
993
let input_plan = prepare_lp. input ;
962
994
input_plan. replace_params_with_values ( & param_values)
963
995
}
964
- _ => Ok ( self ) ,
996
+ _ => self . replace_params_with_values ( & param_values ) ,
965
997
}
966
998
}
967
999
@@ -1060,7 +1092,7 @@ impl LogicalPlan {
1060
1092
}
1061
1093
1062
1094
impl LogicalPlan {
1063
- /// applies collect to any subqueries in the plan
1095
+ /// applies `op` to any subqueries in the plan
1064
1096
pub ( crate ) fn apply_subqueries < F > ( & self , op : & mut F ) -> datafusion_common:: Result < ( ) >
1065
1097
where
1066
1098
F : FnMut ( & Self ) -> datafusion_common:: Result < VisitRecursion > ,
@@ -1112,17 +1144,22 @@ impl LogicalPlan {
1112
1144
Ok ( ( ) )
1113
1145
}
1114
1146
1115
- /// Return a logical plan with all placeholders/params (e.g $1 $2,
1116
- /// ...) replaced with corresponding values provided in the
1117
- /// params_values
1147
+ /// Return a `LogicalPlan` with all placeholders (e.g $1 $2,
1148
+ /// ...) replaced with corresponding values provided in
1149
+ /// `params_values`
1150
+ ///
1151
+ /// See [`Self::with_param_values`] for examples and usage
1118
1152
pub fn replace_params_with_values (
1119
1153
& self ,
1120
1154
param_values : & [ ScalarValue ] ,
1121
1155
) -> Result < LogicalPlan > {
1122
1156
let new_exprs = self
1123
1157
. expressions ( )
1124
1158
. into_iter ( )
1125
- . map ( |e| Self :: replace_placeholders_with_values ( e, param_values) )
1159
+ . map ( |e| {
1160
+ let e = e. infer_placeholder_types ( self . schema ( ) ) ?;
1161
+ Self :: replace_placeholders_with_values ( e, param_values)
1162
+ } )
1126
1163
. collect :: < Result < Vec < _ > > > ( ) ?;
1127
1164
1128
1165
let new_inputs_with_values = self
@@ -1219,7 +1256,9 @@ impl LogicalPlan {
1219
1256
// Various implementations for printing out LogicalPlans
1220
1257
impl LogicalPlan {
1221
1258
/// Return a `format`able structure that produces a single line
1222
- /// per node. For example:
1259
+ /// per node.
1260
+ ///
1261
+ /// # Example
1223
1262
///
1224
1263
/// ```text
1225
1264
/// Projection: employee.id
@@ -2321,7 +2360,7 @@ pub struct Unnest {
2321
2360
mod tests {
2322
2361
use super :: * ;
2323
2362
use crate :: logical_plan:: table_scan;
2324
- use crate :: { col, exists, in_subquery, lit} ;
2363
+ use crate :: { col, exists, in_subquery, lit, placeholder } ;
2325
2364
use arrow:: datatypes:: { DataType , Field , Schema } ;
2326
2365
use datafusion_common:: tree_node:: TreeNodeVisitor ;
2327
2366
use datafusion_common:: { not_impl_err, DFSchema , TableReference } ;
@@ -2767,10 +2806,7 @@ digraph {
2767
2806
2768
2807
let plan = table_scan ( TableReference :: none ( ) , & schema, None )
2769
2808
. unwrap ( )
2770
- . filter ( col ( "id" ) . eq ( Expr :: Placeholder ( Placeholder :: new (
2771
- "" . into ( ) ,
2772
- Some ( DataType :: Int32 ) ,
2773
- ) ) ) )
2809
+ . filter ( col ( "id" ) . eq ( placeholder ( "" ) ) )
2774
2810
. unwrap ( )
2775
2811
. build ( )
2776
2812
. unwrap ( ) ;
@@ -2783,10 +2819,7 @@ digraph {
2783
2819
2784
2820
let plan = table_scan ( TableReference :: none ( ) , & schema, None )
2785
2821
. unwrap ( )
2786
- . filter ( col ( "id" ) . eq ( Expr :: Placeholder ( Placeholder :: new (
2787
- "$0" . into ( ) ,
2788
- Some ( DataType :: Int32 ) ,
2789
- ) ) ) )
2822
+ . filter ( col ( "id" ) . eq ( placeholder ( "$0" ) ) )
2790
2823
. unwrap ( )
2791
2824
. build ( )
2792
2825
. unwrap ( ) ;
0 commit comments