@@ -551,15 +551,9 @@ impl LogicalPlan {
551551 Projection :: try_new ( projection. expr . to_vec ( ) , Arc :: new ( inputs[ 0 ] . clone ( ) ) )
552552 . map ( LogicalPlan :: Projection )
553553 }
554- LogicalPlan :: Window ( Window {
555- window_expr,
556- schema,
557- ..
558- } ) => Ok ( LogicalPlan :: Window ( Window {
559- input : Arc :: new ( inputs[ 0 ] . clone ( ) ) ,
560- window_expr : window_expr. to_vec ( ) ,
561- schema : schema. clone ( ) ,
562- } ) ) ,
554+ LogicalPlan :: Window ( Window { window_expr, .. } ) => Ok ( LogicalPlan :: Window (
555+ Window :: try_new ( window_expr. to_vec ( ) , Arc :: new ( inputs[ 0 ] . clone ( ) ) ) ?,
556+ ) ) ,
563557 LogicalPlan :: Aggregate ( Aggregate {
564558 group_expr,
565559 aggr_expr,
@@ -837,10 +831,19 @@ impl LogicalPlan {
837831 LogicalPlan :: Extension ( e) => Ok ( LogicalPlan :: Extension ( Extension {
838832 node : e. node . from_template ( & expr, inputs) ,
839833 } ) ) ,
840- LogicalPlan :: Union ( Union { schema, .. } ) => Ok ( LogicalPlan :: Union ( Union {
841- inputs : inputs. iter ( ) . cloned ( ) . map ( Arc :: new) . collect ( ) ,
842- schema : schema. clone ( ) ,
843- } ) ) ,
834+ LogicalPlan :: Union ( Union { schema, .. } ) => {
835+ let input_schema = inputs[ 0 ] . schema ( ) ;
836+ // If inputs are not pruned do not change schema.
837+ let schema = if schema. fields ( ) . len ( ) == input_schema. fields ( ) . len ( ) {
838+ schema
839+ } else {
840+ input_schema
841+ } ;
842+ Ok ( LogicalPlan :: Union ( Union {
843+ inputs : inputs. iter ( ) . cloned ( ) . map ( Arc :: new) . collect ( ) ,
844+ schema : schema. clone ( ) ,
845+ } ) )
846+ }
844847 LogicalPlan :: Distinct ( distinct) => {
845848 let distinct = match distinct {
846849 Distinct :: All ( _) => Distinct :: All ( Arc :: new ( inputs[ 0 ] . clone ( ) ) ) ,
@@ -1792,11 +1795,8 @@ pub struct Projection {
17921795impl Projection {
17931796 /// Create a new Projection
17941797 pub fn try_new ( expr : Vec < Expr > , input : Arc < LogicalPlan > ) -> Result < Self > {
1795- let schema = Arc :: new ( DFSchema :: new_with_metadata (
1796- exprlist_to_fields ( & expr, & input) ?,
1797- input. schema ( ) . metadata ( ) . clone ( ) ,
1798- ) ?) ;
1799- Self :: try_new_with_schema ( expr, input, schema)
1798+ let projection_schema = projection_schema ( & input, & expr) ?;
1799+ Self :: try_new_with_schema ( expr, input, projection_schema)
18001800 }
18011801
18021802 /// Create a new Projection using the specified output schema
@@ -1808,11 +1808,6 @@ impl Projection {
18081808 if expr. len ( ) != schema. fields ( ) . len ( ) {
18091809 return plan_err ! ( "Projection has mismatch between number of expressions ({}) and number of fields in schema ({})" , expr. len( ) , schema. fields( ) . len( ) ) ;
18101810 }
1811- // Update functional dependencies of `input` according to projection
1812- // expressions:
1813- let id_key_groups = calc_func_dependencies_for_project ( & expr, & input) ?;
1814- let schema = schema. as_ref ( ) . clone ( ) ;
1815- let schema = Arc :: new ( schema. with_functional_dependencies ( id_key_groups) ) ;
18161811 Ok ( Self {
18171812 expr,
18181813 input,
@@ -1836,6 +1831,29 @@ impl Projection {
18361831 }
18371832}
18381833
1834+ /// Computes the schema of the result produced by applying a projection to the input logical plan.
1835+ ///
1836+ /// # Arguments
1837+ ///
1838+ /// * `input`: A reference to the input `LogicalPlan` for which the projection schema
1839+ /// will be computed.
1840+ /// * `exprs`: A slice of `Expr` expressions representing the projection operation to apply.
1841+ ///
1842+ /// # Returns
1843+ ///
1844+ /// A `Result` containing an `Arc<DFSchema>` representing the schema of the result
1845+ /// produced by the projection operation. If the schema computation is successful,
1846+ /// the `Result` will contain the schema; otherwise, it will contain an error.
1847+ pub fn projection_schema ( input : & LogicalPlan , exprs : & [ Expr ] ) -> Result < Arc < DFSchema > > {
1848+ let mut schema = DFSchema :: new_with_metadata (
1849+ exprlist_to_fields ( exprs, input) ?,
1850+ input. schema ( ) . metadata ( ) . clone ( ) ,
1851+ ) ?;
1852+ schema = schema
1853+ . with_functional_dependencies ( calc_func_dependencies_for_project ( exprs, input) ?) ;
1854+ Ok ( Arc :: new ( schema) )
1855+ }
1856+
18391857/// Aliased subquery
18401858#[ derive( Clone , PartialEq , Eq , Hash ) ]
18411859// mark non_exhaustive to encourage use of try_new/new()
@@ -1934,8 +1952,7 @@ impl Window {
19341952 /// Create a new window operator.
19351953 pub fn try_new ( window_expr : Vec < Expr > , input : Arc < LogicalPlan > ) -> Result < Self > {
19361954 let mut window_fields: Vec < DFField > = input. schema ( ) . fields ( ) . clone ( ) ;
1937- window_fields
1938- . extend_from_slice ( & exprlist_to_fields ( window_expr. iter ( ) , input. as_ref ( ) ) ?) ;
1955+ window_fields. extend_from_slice ( & exprlist_to_fields ( window_expr. iter ( ) , & input) ?) ;
19391956 let metadata = input. schema ( ) . metadata ( ) . clone ( ) ;
19401957
19411958 // Update functional dependencies for window:
@@ -2357,6 +2374,13 @@ impl Aggregate {
23572374 schema,
23582375 } )
23592376 }
2377+
2378+ /// Get the length of the group by expression in the output schema
2379+ /// This is not simply group by expression length. Expression may be
2380+ /// GroupingSet, etc. In these case we need to get inner expression lengths.
2381+ pub fn group_expr_len ( & self ) -> Result < usize > {
2382+ grouping_set_expr_count ( & self . group_expr )
2383+ }
23602384}
23612385
23622386/// Checks whether any expression in `group_expr` contains `Expr::GroupingSet`.
0 commit comments