From acb7772f687267366696d62cef7ac9f01608c35f Mon Sep 17 00:00:00 2001
From: Yanxin Xiang <yanxinxiang0917@outlook.com>
Date: Wed, 7 Feb 2024 15:34:19 -0600
Subject: [PATCH 1/9] fix: issue #9130 substitute redundant columns when doing
 cross join

---
 datafusion-cli/src/exec.rs                  |  3 +-
 datafusion/core/src/datasource/memory.rs    |  4 +++
 datafusion/expr/src/logical_plan/builder.rs | 39 +++++++++++++++++++--
 datafusion/expr/src/logical_plan/plan.rs    | 11 +++++-
 datafusion/sql/src/select.rs                |  9 +++--
 5 files changed, 59 insertions(+), 7 deletions(-)

diff --git a/datafusion-cli/src/exec.rs b/datafusion-cli/src/exec.rs
index 6ca8dfe927a3..93f702a34df6 100644
--- a/datafusion-cli/src/exec.rs
+++ b/datafusion-cli/src/exec.rs
@@ -219,6 +219,7 @@ async fn exec_and_print(
 
     let statements = DFParser::parse_sql_with_dialect(&sql, dialect.as_ref())?;
     for statement in statements {
+        // println!("cur statement is {:?}", statement);
         let plan = create_plan(ctx, statement).await?;
 
         // For plans like `Explain` ignore `MaxRows` option and always display all rows
@@ -228,7 +229,7 @@ async fn exec_and_print(
                 | LogicalPlan::DescribeTable(_)
                 | LogicalPlan::Analyze(_)
         );
-
+        // println!("the final logical plan is {:?}", plan);
         let df = ctx.execute_logical_plan(plan).await?;
         let physical_plan = df.create_physical_plan().await?;
 
diff --git a/datafusion/core/src/datasource/memory.rs b/datafusion/core/src/datasource/memory.rs
index 901e74dfc218..3591ae884310 100644
--- a/datafusion/core/src/datasource/memory.rs
+++ b/datafusion/core/src/datasource/memory.rs
@@ -70,6 +70,10 @@ impl MemTable {
     pub fn try_new(schema: SchemaRef, partitions: Vec<Vec<RecordBatch>>) -> Result<Self> {
         for batches in partitions.iter().flatten() {
             let batches_schema = batches.schema();
+            println!(
+                "the new schema is {:?}, schema set is {:?}",
+                batches_schema, schema
+            );
             if !schema.contains(&batches_schema) {
                 debug!(
                     "mem table schema does not contain batches schema. \
diff --git a/datafusion/expr/src/logical_plan/builder.rs b/datafusion/expr/src/logical_plan/builder.rs
index 68499f09d22b..1d3452f79d96 100644
--- a/datafusion/expr/src/logical_plan/builder.rs
+++ b/datafusion/expr/src/logical_plan/builder.rs
@@ -47,7 +47,7 @@ use crate::{
     TableProviderFilterPushDown, TableSource, WriteOp,
 };
 
-use arrow::datatypes::{DataType, Schema, SchemaRef};
+use arrow::datatypes::{DataType, Field, Schema, SchemaRef};
 use datafusion_common::display::ToStringifiedPlan;
 use datafusion_common::{
     get_target_functional_dependencies, plan_datafusion_err, plan_err, Column, DFField,
@@ -890,6 +890,7 @@ impl LogicalPlanBuilder {
     pub fn cross_join(self, right: LogicalPlan) -> Result<Self> {
         let join_schema =
             build_join_schema(self.plan.schema(), right.schema(), &JoinType::Inner)?;
+        println!("left is {:?} \n right is {:?}", self.plan, right);
         Ok(Self::from(LogicalPlan::CrossJoin(CrossJoin {
             left: Arc::new(self.plan),
             right: Arc::new(right),
@@ -1124,7 +1125,28 @@ impl LogicalPlanBuilder {
         )?))
     }
 }
-
+pub fn change_redundant_column(fields: Vec<DFField>) -> Vec<DFField> {
+    let mut name_map = HashMap::new();
+    fields
+        .into_iter()
+        .map(|field| {
+            if !name_map.contains_key(field.name()) {
+                name_map.insert(field.name().to_string(), 0);
+                field
+            } else {
+                let cur_cnt = &name_map.get(field.name());
+                let name = field.name().to_string() + ":" + &cur_cnt.unwrap().to_string();
+                name_map.insert(field.name().to_string(), cur_cnt.unwrap() + 1);
+                DFField::new(
+                    field.qualifier().cloned(),
+                    &name,
+                    field.data_type().clone(),
+                    field.is_nullable(),
+                )
+            }
+        })
+        .collect()
+}
 /// Creates a schema for a join operation.
 /// The fields from the left side are first
 pub fn build_join_schema(
@@ -1184,13 +1206,16 @@ pub fn build_join_schema(
             right_fields.clone()
         }
     };
+    //println!("total fields is {:?}", fields);
     let func_dependencies = left.functional_dependencies().join(
         right.functional_dependencies(),
         join_type,
         left_fields.len(),
     );
+    // println!("func_dependencies is {:?}", func_dependencies);
     let mut metadata = left.metadata().clone();
     metadata.extend(right.metadata().clone());
+    // let schema = DFSchema::new_with_metadata(change_redundant_column(fields), metadata)?;
     let schema = DFSchema::new_with_metadata(fields, metadata)?;
     schema.with_functional_dependencies(func_dependencies)
 }
@@ -1231,12 +1256,16 @@ fn add_group_by_exprs_from_dependencies(
     }
     Ok(group_expr)
 }
+pub(crate) fn validate_unique_names_with_table<'a>() {
+    unimplemented!()
+}
 /// Errors if one or more expressions have equal names.
 pub(crate) fn validate_unique_names<'a>(
     node_name: &str,
     expressions: impl IntoIterator<Item = &'a Expr>,
 ) -> Result<()> {
     let mut unique_names = HashMap::new();
+
     expressions.into_iter().enumerate().try_for_each(|(position, expr)| {
         let name = expr.display_name()?;
         match unique_names.get(&name) {
@@ -1245,6 +1274,7 @@ pub(crate) fn validate_unique_names<'a>(
                 Ok(())
             },
             Some((existing_position, existing_expr)) => {
+                //println!("node_name is {}, existing expr is {:?}", node_name, existing_expr);
                 plan_err!("{node_name} require unique expression names \
                              but the expression \"{existing_expr}\" at position {existing_position} and \"{expr}\" \
                              at position {position} have the same name. Consider aliasing (\"AS\") one of them."
@@ -1360,6 +1390,7 @@ pub fn project(
     let mut projected_expr = vec![];
     for e in expr {
         let e = e.into();
+        //println!("cur_expression is {:?}", e);
         match e {
             Expr::Wildcard { qualifier: None } => {
                 projected_expr.extend(expand_wildcard(input_schema, &plan, None)?)
@@ -1375,6 +1406,10 @@ pub fn project(
                 .push(columnize_expr(normalize_col(e, &plan)?, input_schema)),
         }
     }
+    // println!(
+    //     "before validation the projection name is {:?} \n and the expression is {:?}",
+    //     plan, projected_expr
+    // );
     validate_unique_names("Projections", projected_expr.iter())?;
 
     Projection::try_new(projected_expr, Arc::new(plan)).map(LogicalPlan::Projection)
diff --git a/datafusion/expr/src/logical_plan/plan.rs b/datafusion/expr/src/logical_plan/plan.rs
index b7d75dc0ae80..d80bef1df7f3 100644
--- a/datafusion/expr/src/logical_plan/plan.rs
+++ b/datafusion/expr/src/logical_plan/plan.rs
@@ -24,6 +24,7 @@ use std::sync::Arc;
 
 use super::dml::CopyTo;
 use super::DdlStatement;
+use crate::builder::change_redundant_column;
 use crate::dml::CopyOptions;
 use crate::expr::{
     Alias, Exists, InSubquery, Placeholder, Sort as SortExpr, WindowFunction,
@@ -1891,7 +1892,11 @@ impl SubqueryAlias {
         alias: impl Into<OwnedTableReference>,
     ) -> Result<Self> {
         let alias = alias.into();
-        let schema: Schema = plan.schema().as_ref().clone().into();
+        let fields = change_redundant_column(plan.schema().fields().clone());
+        let meta_data = plan.schema().as_ref().metadata().clone();
+        let schema: Schema = DFSchema::new_with_metadata(fields, meta_data)
+            .unwrap()
+            .into();
         // Since schema is the same, other than qualifier, we can use existing
         // functional dependencies:
         let func_dependencies = plan.schema().functional_dependencies().clone();
@@ -2181,6 +2186,10 @@ impl TableScan {
                 df_schema.with_functional_dependencies(func_dependencies)
             })?;
         let projected_schema = Arc::new(projected_schema);
+        // println!(
+        //     "projected_schema is {:?} \n and projection is {:?}",
+        //     projected_schema, projection,
+        // );
         Ok(Self {
             table_name,
             source: table_source,
diff --git a/datafusion/sql/src/select.rs b/datafusion/sql/src/select.rs
index f47720d4674a..585bebe657e5 100644
--- a/datafusion/sql/src/select.rs
+++ b/datafusion/sql/src/select.rs
@@ -66,7 +66,8 @@ impl<'a, S: ContextProvider> SqlToRel<'a, S> {
         if !select.sort_by.is_empty() {
             return not_impl_err!("SORT BY");
         }
-
+        // println!("select from is {:?}", select.from);
+        // println!("current planner_context is {:?}", planner_context);
         // process `from` clause
         let plan = self.plan_from_tables(select.from, planner_context)?;
         let empty_from = matches!(plan, LogicalPlan::EmptyRelation(_));
@@ -77,7 +78,6 @@ impl<'a, S: ContextProvider> SqlToRel<'a, S> {
         // handle named windows before processing the projection expression
         check_conflicting_windows(&select.named_window)?;
         match_window_definitions(&mut select.projection, &select.named_window)?;
-
         // process the SELECT expressions, with wildcards expanded.
         let select_exprs = self.prepare_select_exprs(
             &base_plan,
@@ -85,7 +85,10 @@ impl<'a, S: ContextProvider> SqlToRel<'a, S> {
             empty_from,
             planner_context,
         )?;
-
+        // println!(
+        //     "base plan is {:?} \n select expression is {:?} \n planner_context is {:?}",
+        //     base_plan, select_exprs, planner_context
+        // );
         // having and group by clause may reference aliases defined in select projection
         let projected_plan = self.project(base_plan.clone(), select_exprs.clone())?;
         // Place the fields of the base plan at the front so that when there are references

From 1c0830d4663c7064a1a714e49cf981d29446d841 Mon Sep 17 00:00:00 2001
From: Yanxin Xiang <yanxinxiang0917@outlook.com>
Date: Wed, 7 Feb 2024 16:35:17 -0600
Subject: [PATCH 2/9] add test

---
 datafusion-cli/src/exec.rs                    |  2 -
 datafusion/expr/src/logical_plan/builder.rs   | 29 +++++++--
 datafusion/expr/src/logical_plan/plan.rs      |  5 +-
 datafusion/sql/src/select.rs                  |  8 +--
 .../same_column_name_cross_join.slt           | 61 +++++++++++++++++++
 5 files changed, 87 insertions(+), 18 deletions(-)
 create mode 100644 datafusion/sqllogictest/test_files/same_column_name_cross_join.slt

diff --git a/datafusion-cli/src/exec.rs b/datafusion-cli/src/exec.rs
index 93f702a34df6..d1e4a5b3638e 100644
--- a/datafusion-cli/src/exec.rs
+++ b/datafusion-cli/src/exec.rs
@@ -219,7 +219,6 @@ async fn exec_and_print(
 
     let statements = DFParser::parse_sql_with_dialect(&sql, dialect.as_ref())?;
     for statement in statements {
-        // println!("cur statement is {:?}", statement);
         let plan = create_plan(ctx, statement).await?;
 
         // For plans like `Explain` ignore `MaxRows` option and always display all rows
@@ -229,7 +228,6 @@ async fn exec_and_print(
                 | LogicalPlan::DescribeTable(_)
                 | LogicalPlan::Analyze(_)
         );
-        // println!("the final logical plan is {:?}", plan);
         let df = ctx.execute_logical_plan(plan).await?;
         let physical_plan = df.create_physical_plan().await?;
 
diff --git a/datafusion/expr/src/logical_plan/builder.rs b/datafusion/expr/src/logical_plan/builder.rs
index 1d3452f79d96..3e11a5ded32c 100644
--- a/datafusion/expr/src/logical_plan/builder.rs
+++ b/datafusion/expr/src/logical_plan/builder.rs
@@ -890,7 +890,6 @@ impl LogicalPlanBuilder {
     pub fn cross_join(self, right: LogicalPlan) -> Result<Self> {
         let join_schema =
             build_join_schema(self.plan.schema(), right.schema(), &JoinType::Inner)?;
-        println!("left is {:?} \n right is {:?}", self.plan, right);
         Ok(Self::from(LogicalPlan::CrossJoin(CrossJoin {
             left: Arc::new(self.plan),
             right: Arc::new(right),
@@ -1212,7 +1211,6 @@ pub fn build_join_schema(
         join_type,
         left_fields.len(),
     );
-    // println!("func_dependencies is {:?}", func_dependencies);
     let mut metadata = left.metadata().clone();
     metadata.extend(right.metadata().clone());
     // let schema = DFSchema::new_with_metadata(change_redundant_column(fields), metadata)?;
@@ -1406,10 +1404,7 @@ pub fn project(
                 .push(columnize_expr(normalize_col(e, &plan)?, input_schema)),
         }
     }
-    // println!(
-    //     "before validation the projection name is {:?} \n and the expression is {:?}",
-    //     plan, projected_expr
-    // );
+
     validate_unique_names("Projections", projected_expr.iter())?;
 
     Projection::try_new(projected_expr, Arc::new(plan)).map(LogicalPlan::Projection)
@@ -1604,6 +1599,7 @@ mod tests {
     use crate::{col, expr, expr_fn::exists, in_subquery, lit, scalar_subquery, sum};
 
     use arrow::datatypes::{DataType, Field};
+    use arrow::ipc::Int;
     use datafusion_common::{OwnedTableReference, SchemaError, TableReference};
 
     #[test]
@@ -2111,4 +2107,25 @@ mod tests {
 
         Ok(())
     }
+    #[test]
+    fn test_change_redundant_column() -> Result<()> {
+        let t1_field_1 = DFField::new_unqualified("a", DataType::Int32, false);
+        let t2_field_1 = DFField::new_unqualified("a", DataType::Int32, false);
+        let t1_field_2 = DFField::new_unqualified("b", DataType::Int32, false);
+        let t2_field_2 = DFField::new_unqualified("b", DataType::Int32, false);
+
+        let field_vec = vec![t1_field_1, t2_field_1, t1_field_2, t2_field_2];
+        let remove_redundant = change_redundant_column(field_vec);
+
+        assert_eq!(
+            remove_redundant,
+            vec![
+                DFField::new_unqualified("a", DataType::Int32, false),
+                DFField::new_unqualified("a:0", DataType::Int32, false),
+                DFField::new_unqualified("b", DataType::Int32, false),
+                DFField::new_unqualified("b:0", DataType::Int32, false)
+            ]
+        );
+        Ok(())
+    }
 }
diff --git a/datafusion/expr/src/logical_plan/plan.rs b/datafusion/expr/src/logical_plan/plan.rs
index d80bef1df7f3..8e6b015f74d1 100644
--- a/datafusion/expr/src/logical_plan/plan.rs
+++ b/datafusion/expr/src/logical_plan/plan.rs
@@ -2186,10 +2186,7 @@ impl TableScan {
                 df_schema.with_functional_dependencies(func_dependencies)
             })?;
         let projected_schema = Arc::new(projected_schema);
-        // println!(
-        //     "projected_schema is {:?} \n and projection is {:?}",
-        //     projected_schema, projection,
-        // );
+
         Ok(Self {
             table_name,
             source: table_source,
diff --git a/datafusion/sql/src/select.rs b/datafusion/sql/src/select.rs
index 585bebe657e5..b5b6ada48fb0 100644
--- a/datafusion/sql/src/select.rs
+++ b/datafusion/sql/src/select.rs
@@ -66,8 +66,7 @@ impl<'a, S: ContextProvider> SqlToRel<'a, S> {
         if !select.sort_by.is_empty() {
             return not_impl_err!("SORT BY");
         }
-        // println!("select from is {:?}", select.from);
-        // println!("current planner_context is {:?}", planner_context);
+
         // process `from` clause
         let plan = self.plan_from_tables(select.from, planner_context)?;
         let empty_from = matches!(plan, LogicalPlan::EmptyRelation(_));
@@ -85,10 +84,7 @@ impl<'a, S: ContextProvider> SqlToRel<'a, S> {
             empty_from,
             planner_context,
         )?;
-        // println!(
-        //     "base plan is {:?} \n select expression is {:?} \n planner_context is {:?}",
-        //     base_plan, select_exprs, planner_context
-        // );
+
         // having and group by clause may reference aliases defined in select projection
         let projected_plan = self.project(base_plan.clone(), select_exprs.clone())?;
         // Place the fields of the base plan at the front so that when there are references
diff --git a/datafusion/sqllogictest/test_files/same_column_name_cross_join.slt b/datafusion/sqllogictest/test_files/same_column_name_cross_join.slt
new file mode 100644
index 000000000000..b47b8b7eef9f
--- /dev/null
+++ b/datafusion/sqllogictest/test_files/same_column_name_cross_join.slt
@@ -0,0 +1,61 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+
+#   http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+
+# prepare the tables
+
+statement ok
+create table t1 (a int, b int);
+
+statement ok
+create table t2 (a int, b int);
+
+statement ok
+create table t3 (a int, b int);
+
+statement ok
+insert into t1 values (1, 2);
+
+statement ok
+insert into t2 values (3, 4);
+
+statement ok
+insert into t3 values (5, 6);
+
+query IIIIII
+select * from (t1 cross join t2) as t cross join t3;
+-------
+----
+5 6 1 2 3 4
+
+query IIIIIIII
+select * from (t1 cross join t2) as t cross join (t2 cross join t3)
+-------
+----
+1 2 3 4 3 4 5 6
+
+query IIIIIIIIIIII
+select * from (t1 cross join t2) as t cross join (t2 cross join t3) cross join (t1 cross join t3) as tt
+--------
+----
+1 2 5 6 1 2 3 4 3 4 5 6
+
+query IIIIIIIIIIIIIIII
+select * from (t1 cross join t2) as t cross join (t2 cross join t3) cross join (t1 cross join t3) as tt cross join (t2 cross join t3) as ttt;
+--------
+----
+1 2 5 6 1 2 3 4 3 4 5 6 3 4 5 6

From 40e1276290542b4e4389886f4a583e306e346871 Mon Sep 17 00:00:00 2001
From: Yanxin Xiang <yanxinxiang0917@outlook.com>
Date: Wed, 7 Feb 2024 16:46:55 -0600
Subject: [PATCH 3/9] fix:bugs

---
 datafusion/expr/src/logical_plan/builder.rs | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/datafusion/expr/src/logical_plan/builder.rs b/datafusion/expr/src/logical_plan/builder.rs
index 3e11a5ded32c..7c0fa55ca981 100644
--- a/datafusion/expr/src/logical_plan/builder.rs
+++ b/datafusion/expr/src/logical_plan/builder.rs
@@ -47,7 +47,7 @@ use crate::{
     TableProviderFilterPushDown, TableSource, WriteOp,
 };
 
-use arrow::datatypes::{DataType, Field, Schema, SchemaRef};
+use arrow::datatypes::{DataType, Schema, SchemaRef};
 use datafusion_common::display::ToStringifiedPlan;
 use datafusion_common::{
     get_target_functional_dependencies, plan_datafusion_err, plan_err, Column, DFField,
@@ -1254,9 +1254,6 @@ fn add_group_by_exprs_from_dependencies(
     }
     Ok(group_expr)
 }
-pub(crate) fn validate_unique_names_with_table<'a>() {
-    unimplemented!()
-}
 /// Errors if one or more expressions have equal names.
 pub(crate) fn validate_unique_names<'a>(
     node_name: &str,
@@ -1599,7 +1596,6 @@ mod tests {
     use crate::{col, expr, expr_fn::exists, in_subquery, lit, scalar_subquery, sum};
 
     use arrow::datatypes::{DataType, Field};
-    use arrow::ipc::Int;
     use datafusion_common::{OwnedTableReference, SchemaError, TableReference};
 
     #[test]

From aad32fcf5a6e54e0fd309be73e203db2e6c9f292 Mon Sep 17 00:00:00 2001
From: Yanxin Xiang <yanxinxiang0917@outlook.com>
Date: Sun, 11 Feb 2024 19:58:47 -0600
Subject: [PATCH 4/9] optimize code

---
 datafusion/expr/src/logical_plan/builder.rs | 16 +++++++---------
 1 file changed, 7 insertions(+), 9 deletions(-)

diff --git a/datafusion/expr/src/logical_plan/builder.rs b/datafusion/expr/src/logical_plan/builder.rs
index 7c0fa55ca981..4c3ff54d06eb 100644
--- a/datafusion/expr/src/logical_plan/builder.rs
+++ b/datafusion/expr/src/logical_plan/builder.rs
@@ -1129,19 +1129,18 @@ pub fn change_redundant_column(fields: Vec<DFField>) -> Vec<DFField> {
     fields
         .into_iter()
         .map(|field| {
-            if !name_map.contains_key(field.name()) {
-                name_map.insert(field.name().to_string(), 0);
-                field
-            } else {
-                let cur_cnt = &name_map.get(field.name());
-                let name = field.name().to_string() + ":" + &cur_cnt.unwrap().to_string();
-                name_map.insert(field.name().to_string(), cur_cnt.unwrap() + 1);
+            let counter = name_map.entry(field.name().to_string()).or_insert(0);
+            *counter += 1;
+            if *counter > 1 {
+                let new_name = format!("{}:{}", field.name(), counter);
                 DFField::new(
                     field.qualifier().cloned(),
-                    &name,
+                    &new_name,
                     field.data_type().clone(),
                     field.is_nullable(),
                 )
+            } else {
+                field
             }
         })
         .collect()
@@ -1385,7 +1384,6 @@ pub fn project(
     let mut projected_expr = vec![];
     for e in expr {
         let e = e.into();
-        //println!("cur_expression is {:?}", e);
         match e {
             Expr::Wildcard { qualifier: None } => {
                 projected_expr.extend(expand_wildcard(input_schema, &plan, None)?)

From 0ec41bd5132b8f08bb33b1438ff08618efaaf2a0 Mon Sep 17 00:00:00 2001
From: Yanxin Xiang <yanxinxiang0917@outlook.com>
Date: Sun, 11 Feb 2024 20:28:53 -0600
Subject: [PATCH 5/9] optimize code

---
 datafusion/expr/src/logical_plan/builder.rs | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/datafusion/expr/src/logical_plan/builder.rs b/datafusion/expr/src/logical_plan/builder.rs
index 4c3ff54d06eb..2efe45471ca9 100644
--- a/datafusion/expr/src/logical_plan/builder.rs
+++ b/datafusion/expr/src/logical_plan/builder.rs
@@ -1132,7 +1132,7 @@ pub fn change_redundant_column(fields: Vec<DFField>) -> Vec<DFField> {
             let counter = name_map.entry(field.name().to_string()).or_insert(0);
             *counter += 1;
             if *counter > 1 {
-                let new_name = format!("{}:{}", field.name(), counter);
+                let new_name = format!("{}:{}", field.name(), *counter - 1);
                 DFField::new(
                     field.qualifier().cloned(),
                     &new_name,
@@ -2115,9 +2115,9 @@ mod tests {
             remove_redundant,
             vec![
                 DFField::new_unqualified("a", DataType::Int32, false),
-                DFField::new_unqualified("a:0", DataType::Int32, false),
+                DFField::new_unqualified("a:1", DataType::Int32, false),
                 DFField::new_unqualified("b", DataType::Int32, false),
-                DFField::new_unqualified("b:0", DataType::Int32, false)
+                DFField::new_unqualified("b:1", DataType::Int32, false)
             ]
         );
         Ok(())

From c7b65f310b754ceca3720296e2d8901283b43f99 Mon Sep 17 00:00:00 2001
From: Yanxin Xiang <yanxinxiang0917@outlook.com>
Date: Mon, 12 Feb 2024 09:55:32 -0600
Subject: [PATCH 6/9] deleting extra debug info

---
 datafusion/core/src/datasource/memory.rs    | 4 ----
 datafusion/expr/src/logical_plan/builder.rs | 3 ---
 2 files changed, 7 deletions(-)

diff --git a/datafusion/core/src/datasource/memory.rs b/datafusion/core/src/datasource/memory.rs
index 3591ae884310..901e74dfc218 100644
--- a/datafusion/core/src/datasource/memory.rs
+++ b/datafusion/core/src/datasource/memory.rs
@@ -70,10 +70,6 @@ impl MemTable {
     pub fn try_new(schema: SchemaRef, partitions: Vec<Vec<RecordBatch>>) -> Result<Self> {
         for batches in partitions.iter().flatten() {
             let batches_schema = batches.schema();
-            println!(
-                "the new schema is {:?}, schema set is {:?}",
-                batches_schema, schema
-            );
             if !schema.contains(&batches_schema) {
                 debug!(
                     "mem table schema does not contain batches schema. \
diff --git a/datafusion/expr/src/logical_plan/builder.rs b/datafusion/expr/src/logical_plan/builder.rs
index 2efe45471ca9..7c85842cd9d9 100644
--- a/datafusion/expr/src/logical_plan/builder.rs
+++ b/datafusion/expr/src/logical_plan/builder.rs
@@ -1204,7 +1204,6 @@ pub fn build_join_schema(
             right_fields.clone()
         }
     };
-    //println!("total fields is {:?}", fields);
     let func_dependencies = left.functional_dependencies().join(
         right.functional_dependencies(),
         join_type,
@@ -1212,7 +1211,6 @@ pub fn build_join_schema(
     );
     let mut metadata = left.metadata().clone();
     metadata.extend(right.metadata().clone());
-    // let schema = DFSchema::new_with_metadata(change_redundant_column(fields), metadata)?;
     let schema = DFSchema::new_with_metadata(fields, metadata)?;
     schema.with_functional_dependencies(func_dependencies)
 }
@@ -1268,7 +1266,6 @@ pub(crate) fn validate_unique_names<'a>(
                 Ok(())
             },
             Some((existing_position, existing_expr)) => {
-                //println!("node_name is {}, existing expr is {:?}", node_name, existing_expr);
                 plan_err!("{node_name} require unique expression names \
                              but the expression \"{existing_expr}\" at position {existing_position} and \"{expr}\" \
                              at position {position} have the same name. Consider aliasing (\"AS\") one of them."

From fe621994043620044b0bb4e02f15d5ac881e81b1 Mon Sep 17 00:00:00 2001
From: Yanxin Xiang <yanxinxiang0917@outlook.com>
Date: Fri, 16 Feb 2024 15:19:34 -0600
Subject: [PATCH 7/9] adding test and optimized code

---
 datafusion/expr/src/logical_plan/builder.rs | 6 ++++--
 datafusion/expr/src/logical_plan/plan.rs    | 4 +---
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/datafusion/expr/src/logical_plan/builder.rs b/datafusion/expr/src/logical_plan/builder.rs
index 7c85842cd9d9..39df96d61f45 100644
--- a/datafusion/expr/src/logical_plan/builder.rs
+++ b/datafusion/expr/src/logical_plan/builder.rs
@@ -2102,10 +2102,11 @@ mod tests {
     fn test_change_redundant_column() -> Result<()> {
         let t1_field_1 = DFField::new_unqualified("a", DataType::Int32, false);
         let t2_field_1 = DFField::new_unqualified("a", DataType::Int32, false);
+        let t2_field_3 = DFField::new_unqualified("a", DataType::Int32, false);
         let t1_field_2 = DFField::new_unqualified("b", DataType::Int32, false);
         let t2_field_2 = DFField::new_unqualified("b", DataType::Int32, false);
 
-        let field_vec = vec![t1_field_1, t2_field_1, t1_field_2, t2_field_2];
+        let field_vec = vec![t1_field_1, t2_field_1, t1_field_2, t2_field_2, t2_field_3];
         let remove_redundant = change_redundant_column(field_vec);
 
         assert_eq!(
@@ -2114,7 +2115,8 @@ mod tests {
                 DFField::new_unqualified("a", DataType::Int32, false),
                 DFField::new_unqualified("a:1", DataType::Int32, false),
                 DFField::new_unqualified("b", DataType::Int32, false),
-                DFField::new_unqualified("b:1", DataType::Int32, false)
+                DFField::new_unqualified("b:1", DataType::Int32, false),
+                DFField::new_unqualified("a:2", DataType::Int32, false),
             ]
         );
         Ok(())
diff --git a/datafusion/expr/src/logical_plan/plan.rs b/datafusion/expr/src/logical_plan/plan.rs
index 8e6b015f74d1..ba768cf3c6d6 100644
--- a/datafusion/expr/src/logical_plan/plan.rs
+++ b/datafusion/expr/src/logical_plan/plan.rs
@@ -1894,9 +1894,7 @@ impl SubqueryAlias {
         let alias = alias.into();
         let fields = change_redundant_column(plan.schema().fields().clone());
         let meta_data = plan.schema().as_ref().metadata().clone();
-        let schema: Schema = DFSchema::new_with_metadata(fields, meta_data)
-            .unwrap()
-            .into();
+        let schema: Schema = DFSchema::new_with_metadata(fields, meta_data)?.into();
         // Since schema is the same, other than qualifier, we can use existing
         // functional dependencies:
         let func_dependencies = plan.schema().functional_dependencies().clone();

From 2829f99a22496d513321e653c3a449041ffbb9a6 Mon Sep 17 00:00:00 2001
From: Yanxin Xiang <yanxinxiang0917@outlook.com>
Date: Fri, 16 Feb 2024 21:47:04 -0600
Subject: [PATCH 8/9] fix test

---
 .../sqllogictest/test_files/same_column_name_cross_join.slt     | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/datafusion/sqllogictest/test_files/same_column_name_cross_join.slt b/datafusion/sqllogictest/test_files/same_column_name_cross_join.slt
index b47b8b7eef9f..97209d3e38e5 100644
--- a/datafusion/sqllogictest/test_files/same_column_name_cross_join.slt
+++ b/datafusion/sqllogictest/test_files/same_column_name_cross_join.slt
@@ -42,12 +42,14 @@ select * from (t1 cross join t2) as t cross join t3;
 ----
 5 6 1 2 3 4
 
+
 query IIIIIIII
 select * from (t1 cross join t2) as t cross join (t2 cross join t3)
 -------
 ----
 1 2 3 4 3 4 5 6
 
+
 query IIIIIIIIIIII
 select * from (t1 cross join t2) as t cross join (t2 cross join t3) cross join (t1 cross join t3) as tt
 --------

From 3276fda9a3e6fe840eb74aa389d41e6927fddadc Mon Sep 17 00:00:00 2001
From: Yanxin Xiang <yanxinxiang0917@outlook.com>
Date: Fri, 16 Feb 2024 21:55:21 -0600
Subject: [PATCH 9/9] fix test

---
 .../test_files/same_column_name_cross_join.slt             | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/datafusion/sqllogictest/test_files/same_column_name_cross_join.slt b/datafusion/sqllogictest/test_files/same_column_name_cross_join.slt
index 97209d3e38e5..de004267c938 100644
--- a/datafusion/sqllogictest/test_files/same_column_name_cross_join.slt
+++ b/datafusion/sqllogictest/test_files/same_column_name_cross_join.slt
@@ -40,7 +40,8 @@ query IIIIII
 select * from (t1 cross join t2) as t cross join t3;
 -------
 ----
-5 6 1 2 3 4
+1 2 3 4 5 6
+
 
 
 query IIIIIIII
@@ -54,10 +55,10 @@ query IIIIIIIIIIII
 select * from (t1 cross join t2) as t cross join (t2 cross join t3) cross join (t1 cross join t3) as tt
 --------
 ----
-1 2 5 6 1 2 3 4 3 4 5 6
+1 2 3 4 3 4 5 6 1 2 5 6
 
 query IIIIIIIIIIIIIIII
 select * from (t1 cross join t2) as t cross join (t2 cross join t3) cross join (t1 cross join t3) as tt cross join (t2 cross join t3) as ttt;
 --------
 ----
-1 2 5 6 1 2 3 4 3 4 5 6 3 4 5 6
+1 2 3 4 3 4 5 6 1 2 5 6 3 4 5 6
