18
18
//! Expression utilities
19
19
20
20
use std:: cmp:: Ordering ;
21
- use std:: collections:: HashSet ;
21
+ use std:: collections:: { HashMap , HashSet } ;
22
22
use std:: sync:: Arc ;
23
23
24
24
use crate :: expr:: { Alias , Sort , WindowFunction } ;
25
25
use crate :: expr_rewriter:: strip_outer_reference;
26
26
use crate :: signature:: { Signature , TypeSignature } ;
27
27
use crate :: {
28
- and, BinaryExpr , Cast , Expr , ExprSchemable , Filter , GroupingSet , LogicalPlan ,
29
- Operator , TryCast ,
28
+ and, BinaryExpr , Expr , ExprSchemable , Filter , GroupingSet , LogicalPlan , Operator ,
30
29
} ;
31
30
32
31
use arrow:: datatypes:: { DataType , Field , Schema , TimeUnit } ;
33
- use datafusion_common:: tree_node:: { TreeNode , TreeNodeRecursion } ;
32
+ use datafusion_common:: tree_node:: {
33
+ Transformed , TransformedResult , TreeNode , TreeNodeRecursion ,
34
+ } ;
34
35
use datafusion_common:: utils:: get_at_indices;
35
36
use datafusion_common:: {
36
37
internal_err, plan_datafusion_err, plan_err, Column , DFSchema , DFSchemaRef , Result ,
@@ -247,7 +248,7 @@ pub fn enumerate_grouping_sets(group_expr: Vec<Expr>) -> Result<Vec<Expr>> {
247
248
248
249
/// Find all distinct exprs in a list of group by expressions. If the
249
250
/// first element is a `GroupingSet` expression then it must be the only expr.
250
- pub fn grouping_set_to_exprlist ( group_expr : & [ Expr ] ) -> Result < Vec < Expr > > {
251
+ pub fn grouping_set_to_exprlist ( group_expr : & [ Expr ] ) -> Result < Vec < & Expr > > {
251
252
if let Some ( Expr :: GroupingSet ( grouping_set) ) = group_expr. first ( ) {
252
253
if group_expr. len ( ) > 1 {
253
254
return plan_err ! (
@@ -256,7 +257,7 @@ pub fn grouping_set_to_exprlist(group_expr: &[Expr]) -> Result<Vec<Expr>> {
256
257
}
257
258
Ok ( grouping_set. distinct_expr ( ) )
258
259
} else {
259
- Ok ( group_expr. to_vec ( ) )
260
+ Ok ( group_expr. iter ( ) . collect ( ) )
260
261
}
261
262
}
262
263
@@ -725,13 +726,16 @@ pub fn from_plan(
725
726
}
726
727
727
728
/// Create field meta-data from an expression, for use in a result set schema
728
- pub fn exprlist_to_fields (
729
- exprs : & [ Expr ] ,
729
+ pub fn exprlist_to_fields < ' a > (
730
+ exprs : impl IntoIterator < Item = & ' a Expr > ,
730
731
plan : & LogicalPlan ,
731
732
) -> Result < Vec < ( Option < TableReference > , Arc < Field > ) > > {
732
733
// look for exact match in plan's output schema
733
734
let input_schema = & plan. schema ( ) ;
734
- exprs. iter ( ) . map ( |e| e. to_field ( input_schema) ) . collect ( )
735
+ exprs
736
+ . into_iter ( )
737
+ . map ( |e| e. to_field ( input_schema) )
738
+ . collect ( )
735
739
}
736
740
737
741
/// Convert an expression into Column expression if it's already provided as input plan.
@@ -749,37 +753,21 @@ pub fn exprlist_to_fields(
749
753
/// .aggregate(vec![col("c1")], vec![sum(col("c2"))])?
750
754
/// .project(vec![col("c1"), col("SUM(c2)")?
751
755
/// ```
752
- pub fn columnize_expr ( e : Expr , input_schema : & DFSchema ) -> Expr {
753
- match e {
754
- Expr :: Column ( _) => e,
755
- Expr :: OuterReferenceColumn ( _, _) => e,
756
- Expr :: Alias ( Alias {
757
- expr,
758
- relation,
759
- name,
760
- } ) => columnize_expr ( * expr, input_schema) . alias_qualified ( relation, name) ,
761
- Expr :: Cast ( Cast { expr, data_type } ) => Expr :: Cast ( Cast {
762
- expr : Box :: new ( columnize_expr ( * expr, input_schema) ) ,
763
- data_type,
764
- } ) ,
765
- Expr :: TryCast ( TryCast { expr, data_type } ) => Expr :: TryCast ( TryCast :: new (
766
- Box :: new ( columnize_expr ( * expr, input_schema) ) ,
767
- data_type,
756
+ pub fn columnize_expr ( e : Expr , input : & LogicalPlan ) -> Result < Expr > {
757
+ let output_exprs = match input. columnized_output_exprs ( ) {
758
+ Ok ( exprs) if !exprs. is_empty ( ) => exprs,
759
+ _ => return Ok ( e) ,
760
+ } ;
761
+ let exprs_map: HashMap < & Expr , Column > = output_exprs. into_iter ( ) . collect ( ) ;
762
+ e. transform_down ( |node : Expr | match exprs_map. get ( & node) {
763
+ Some ( column) => Ok ( Transformed :: new (
764
+ Expr :: Column ( column. clone ( ) ) ,
765
+ true ,
766
+ TreeNodeRecursion :: Jump ,
768
767
) ) ,
769
- Expr :: ScalarSubquery ( _) => e. clone ( ) ,
770
- _ => match e. display_name ( ) {
771
- Ok ( name) => {
772
- match input_schema. qualified_field_with_unqualified_name ( & name) {
773
- Ok ( ( qualifier, field) ) => {
774
- Expr :: Column ( Column :: from ( ( qualifier, field) ) )
775
- }
776
- // expression not provided as input, do not convert to a column reference
777
- Err ( _) => e,
778
- }
779
- }
780
- Err ( _) => e,
781
- } ,
782
- }
768
+ None => Ok ( Transformed :: no ( node) ) ,
769
+ } )
770
+ . data ( )
783
771
}
784
772
785
773
/// Collect all deeply nested `Expr::Column`'s. They are returned in order of
@@ -1235,7 +1223,7 @@ mod tests {
1235
1223
use super :: * ;
1236
1224
use crate :: {
1237
1225
col, cube, expr, expr_vec_fmt, grouping_set, lit, rollup, AggregateFunction ,
1238
- WindowFrame , WindowFunctionDefinition ,
1226
+ Cast , WindowFrame , WindowFunctionDefinition ,
1239
1227
} ;
1240
1228
1241
1229
#[ test]
0 commit comments