@@ -276,9 +276,11 @@ impl Unparser<'_> {
276
276
) -> Result < ( ) > {
277
277
match plan {
278
278
LogicalPlan :: TableScan ( scan) => {
279
- if let Some ( unparsed_table_scan) =
280
- Self :: unparse_table_scan_pushdown ( plan, None ) ?
281
- {
279
+ if let Some ( unparsed_table_scan) = Self :: unparse_table_scan_pushdown (
280
+ plan,
281
+ None ,
282
+ select. already_projected ( ) ,
283
+ ) ? {
282
284
return self . select_to_sql_recursively (
283
285
& unparsed_table_scan,
284
286
query,
@@ -585,6 +587,7 @@ impl Unparser<'_> {
585
587
let unparsed_table_scan = Self :: unparse_table_scan_pushdown (
586
588
plan,
587
589
Some ( plan_alias. alias . clone ( ) ) ,
590
+ select. already_projected ( ) ,
588
591
) ?;
589
592
// if the child plan is a TableScan with pushdown operations, we don't need to
590
593
// create an additional subquery for it
@@ -714,6 +717,7 @@ impl Unparser<'_> {
714
717
fn unparse_table_scan_pushdown (
715
718
plan : & LogicalPlan ,
716
719
alias : Option < TableReference > ,
720
+ already_projected : bool ,
717
721
) -> Result < Option < LogicalPlan > > {
718
722
match plan {
719
723
LogicalPlan :: TableScan ( table_scan) => {
@@ -743,24 +747,29 @@ impl Unparser<'_> {
743
747
}
744
748
}
745
749
746
- if let Some ( project_vec) = & table_scan. projection {
747
- let project_columns = project_vec
748
- . iter ( )
749
- . cloned ( )
750
- . map ( |i| {
751
- let schema = table_scan. source . schema ( ) ;
752
- let field = schema. field ( i) ;
753
- if alias. is_some ( ) {
754
- Column :: new ( alias. clone ( ) , field. name ( ) . clone ( ) )
755
- } else {
756
- Column :: new (
757
- Some ( table_scan. table_name . clone ( ) ) ,
758
- field. name ( ) . clone ( ) ,
759
- )
760
- }
761
- } )
762
- . collect :: < Vec < _ > > ( ) ;
763
- builder = builder. project ( project_columns) ?;
750
+ // Avoid creating a duplicate Projection node, which would result in an additional subquery if a projection already exists.
751
+ // For example, if the `optimize_projection` rule is applied, there will be a Projection node, and duplicate projection
752
+ // information included in the TableScan node.
753
+ if !already_projected {
754
+ if let Some ( project_vec) = & table_scan. projection {
755
+ let project_columns = project_vec
756
+ . iter ( )
757
+ . cloned ( )
758
+ . map ( |i| {
759
+ let schema = table_scan. source . schema ( ) ;
760
+ let field = schema. field ( i) ;
761
+ if alias. is_some ( ) {
762
+ Column :: new ( alias. clone ( ) , field. name ( ) . clone ( ) )
763
+ } else {
764
+ Column :: new (
765
+ Some ( table_scan. table_name . clone ( ) ) ,
766
+ field. name ( ) . clone ( ) ,
767
+ )
768
+ }
769
+ } )
770
+ . collect :: < Vec < _ > > ( ) ;
771
+ builder = builder. project ( project_columns) ?;
772
+ }
764
773
}
765
774
766
775
let filter_expr: Result < Option < Expr > > = table_scan
@@ -805,14 +814,17 @@ impl Unparser<'_> {
805
814
Self :: unparse_table_scan_pushdown (
806
815
& subquery_alias. input ,
807
816
Some ( subquery_alias. alias . clone ( ) ) ,
817
+ already_projected,
808
818
)
809
819
}
810
820
// SubqueryAlias could be rewritten to a plan with a projection as the top node by [rewrite::subquery_alias_inner_query_and_columns].
811
821
// The inner table scan could be a scan with pushdown operations.
812
822
LogicalPlan :: Projection ( projection) => {
813
- if let Some ( plan) =
814
- Self :: unparse_table_scan_pushdown ( & projection. input , alias. clone ( ) ) ?
815
- {
823
+ if let Some ( plan) = Self :: unparse_table_scan_pushdown (
824
+ & projection. input ,
825
+ alias. clone ( ) ,
826
+ already_projected,
827
+ ) ? {
816
828
let exprs = if alias. is_some ( ) {
817
829
let mut alias_rewriter =
818
830
alias. as_ref ( ) . map ( |alias_name| TableAliasRewriter {
0 commit comments