This is an automated email from the ASF dual-hosted git repository.

jayzhan pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/datafusion.git


The following commit(s) were added to refs/heads/main by this push:
     new 359735ae17 Expand wildcard to actual expressions in 
`prepare_select_exprs` (#15090)
359735ae17 is described below

commit 359735ae1796ad28dbaae451249f0ecd24f38d28
Author: Jay Zhan <[email protected]>
AuthorDate: Wed Mar 12 07:49:43 2025 +0800

    Expand wildcard to actual expressions in `prepare_select_exprs` (#15090)
    
    * first draft
    
    * fix tests
    
    * cleanup
    
    * assert
    
    * clippy
    
    * fix test
    
    * fix test
---
 .../optimizer/tests/optimizer_integration.rs       |  40 +-
 datafusion/sql/src/select.rs                       |  78 ++-
 datafusion/sql/tests/cases/plan_to_sql.rs          |  57 +--
 datafusion/sql/tests/sql_integration.rs            | 525 ---------------------
 datafusion/sqllogictest/test_files/alias.slt       |  59 +++
 datafusion/sqllogictest/test_files/copy.slt        |  17 +
 datafusion/sqllogictest/test_files/cte.slt         | 146 ++++++
 datafusion/sqllogictest/test_files/group_by.slt    |  29 ++
 datafusion/sqllogictest/test_files/joins.slt       | 266 +++++++++++
 datafusion/sqllogictest/test_files/prepare.slt     |  15 +
 datafusion/sqllogictest/test_files/select.slt      |  13 +
 datafusion/sqllogictest/test_files/subquery.slt    |  20 +
 datafusion/sqllogictest/test_files/wildcard.slt    |  15 +
 13 files changed, 673 insertions(+), 607 deletions(-)

diff --git a/datafusion/optimizer/tests/optimizer_integration.rs 
b/datafusion/optimizer/tests/optimizer_integration.rs
index 66bd6b7512..5e66c7ec03 100644
--- a/datafusion/optimizer/tests/optimizer_integration.rs
+++ b/datafusion/optimizer/tests/optimizer_integration.rs
@@ -22,16 +22,14 @@ use std::sync::Arc;
 use arrow::datatypes::{DataType, Field, Schema, SchemaRef, TimeUnit};
 
 use datafusion_common::config::ConfigOptions;
-use datafusion_common::{assert_contains, plan_err, Result, TableReference};
+use datafusion_common::{plan_err, Result, TableReference};
 use datafusion_expr::planner::ExprPlanner;
-use datafusion_expr::sqlparser::dialect::PostgreSqlDialect;
 use datafusion_expr::test::function_stub::sum_udaf;
 use datafusion_expr::{AggregateUDF, LogicalPlan, ScalarUDF, TableSource, 
WindowUDF};
 use datafusion_functions_aggregate::average::avg_udaf;
 use datafusion_functions_aggregate::count::count_udaf;
 use datafusion_functions_aggregate::planner::AggregateFunctionPlanner;
 use datafusion_functions_window::planner::WindowFunctionPlanner;
-use datafusion_optimizer::analyzer::type_coercion::TypeCoercionRewriter;
 use datafusion_optimizer::analyzer::Analyzer;
 use datafusion_optimizer::optimizer::Optimizer;
 use datafusion_optimizer::{OptimizerConfig, OptimizerContext, OptimizerRule};
@@ -344,16 +342,6 @@ fn test_propagate_empty_relation_inner_join_and_unions() {
     assert_eq!(expected, format!("{plan}"));
 }
 
-#[test]
-fn select_wildcard_with_repeated_column() {
-    let sql = "SELECT *, col_int32 FROM test";
-    let err = test_sql(sql).expect_err("query should have failed");
-    assert_eq!(
-        "Schema error: Schema contains duplicate qualified field name 
test.col_int32",
-        err.strip_backtrace()
-    );
-}
-
 #[test]
 fn select_wildcard_with_repeated_column_but_is_aliased() {
     let sql = "SELECT *, col_int32 as col_32 FROM test";
@@ -390,32 +378,6 @@ fn 
select_correlated_predicate_subquery_with_uppercase_ident() {
     assert_eq!(expected, format!("{plan}"));
 }
 
-// The test should return an error
-// because the wildcard didn't be expanded before type coercion
-#[test]
-fn test_union_coercion_with_wildcard() -> Result<()> {
-    let dialect = PostgreSqlDialect {};
-    let context_provider = MyContextProvider::default();
-    let sql = "select * from (SELECT col_int32, col_uint32 FROM test) union 
all select * from(SELECT col_uint32, col_int32 FROM test)";
-    let statements = Parser::parse_sql(&dialect, sql)?;
-    let sql_to_rel = SqlToRel::new(&context_provider);
-    let logical_plan = 
sql_to_rel.sql_statement_to_plan(statements[0].clone())?;
-
-    if let LogicalPlan::Union(union) = logical_plan {
-        let err = TypeCoercionRewriter::coerce_union(union)
-            .err()
-            .unwrap()
-            .to_string();
-        assert_contains!(
-            err,
-            "Error during planning: Wildcard should be expanded before type 
coercion"
-        );
-    } else {
-        panic!("Expected Union plan");
-    }
-    Ok(())
-}
-
 fn test_sql(sql: &str) -> Result<LogicalPlan> {
     // parse the SQL
     let dialect = GenericDialect {}; // or AnsiDialect, or your own dialect ...
diff --git a/datafusion/sql/src/select.rs b/datafusion/sql/src/select.rs
index e21def4c39..ce9c5d2f7c 100644
--- a/datafusion/sql/src/select.rs
+++ b/datafusion/sql/src/select.rs
@@ -27,19 +27,19 @@ use crate::utils::{
 
 use datafusion_common::error::DataFusionErrorBuilder;
 use datafusion_common::tree_node::{TreeNode, TreeNodeRecursion};
-use datafusion_common::{not_impl_err, plan_err, Result};
+use datafusion_common::{not_impl_err, plan_err, Column, Result};
 use datafusion_common::{RecursionUnnestOption, UnnestOptions};
 use datafusion_expr::expr::{Alias, PlannedReplaceSelectItem, WildcardOptions};
 use datafusion_expr::expr_rewriter::{
     normalize_col, normalize_col_with_schemas_and_ambiguity_check, 
normalize_sorts,
 };
 use datafusion_expr::utils::{
-    expr_as_column_expr, expr_to_columns, find_aggregate_exprs, 
find_window_exprs,
+    expand_qualified_wildcard, expand_wildcard, expr_as_column_expr, 
expr_to_columns,
+    find_aggregate_exprs, find_window_exprs,
 };
 use datafusion_expr::{
-    qualified_wildcard_with_options, wildcard_with_options, Aggregate, Expr, 
Filter,
-    GroupingSet, LogicalPlan, LogicalPlanBuilder, LogicalPlanBuilderOptions,
-    Partitioning,
+    Aggregate, Expr, Filter, GroupingSet, LogicalPlan, LogicalPlanBuilder,
+    LogicalPlanBuilderOptions, Partitioning,
 };
 
 use indexmap::IndexMap;
@@ -92,6 +92,12 @@ impl<S: ContextProvider> SqlToRel<'_, S> {
             planner_context,
         )?;
 
+        // TOOD: remove this after Expr::Wildcard is removed
+        #[allow(deprecated)]
+        for expr in &select_exprs {
+            debug_assert!(!matches!(expr, Expr::Wildcard { .. }));
+        }
+
         // Having and group by clause may reference aliases defined in select 
projection
         let projected_plan = self.project(base_plan.clone(), 
select_exprs.clone())?;
 
@@ -583,7 +589,7 @@ impl<S: ContextProvider> SqlToRel<'_, S> {
         let mut error_builder = DataFusionErrorBuilder::new();
         for expr in projection {
             match self.sql_select_to_rex(expr, plan, empty_from, 
planner_context) {
-                Ok(expr) => prepared_select_exprs.push(expr),
+                Ok(expr) => prepared_select_exprs.extend(expr),
                 Err(err) => error_builder.add_error(err),
             }
         }
@@ -597,7 +603,7 @@ impl<S: ContextProvider> SqlToRel<'_, S> {
         plan: &LogicalPlan,
         empty_from: bool,
         planner_context: &mut PlannerContext,
-    ) -> Result<Expr> {
+    ) -> Result<Vec<Expr>> {
         match sql {
             SelectItem::UnnamedExpr(expr) => {
                 let expr = self.sql_to_expr(expr, plan.schema(), 
planner_context)?;
@@ -606,7 +612,7 @@ impl<S: ContextProvider> SqlToRel<'_, S> {
                     &[&[plan.schema()]],
                     &plan.using_columns()?,
                 )?;
-                Ok(col)
+                Ok(vec![col])
             }
             SelectItem::ExprWithAlias { expr, alias } => {
                 let select_expr =
@@ -622,7 +628,7 @@ impl<S: ContextProvider> SqlToRel<'_, S> {
                     Expr::Column(column) if column.name.eq(&name) => col,
                     _ => col.alias(name),
                 };
-                Ok(expr)
+                Ok(vec![expr])
             }
             SelectItem::Wildcard(options) => {
                 Self::check_wildcard_options(&options)?;
@@ -635,7 +641,17 @@ impl<S: ContextProvider> SqlToRel<'_, S> {
                     planner_context,
                     options,
                 )?;
-                Ok(wildcard_with_options(planned_options))
+
+                let expanded =
+                    expand_wildcard(plan.schema(), plan, 
Some(&planned_options))?;
+
+                // If there is a REPLACE statement, replace that column with 
the given
+                // replace expression. Column name remains the same.
+                if let Some(replace) = planned_options.replace {
+                    replace_columns(expanded, &replace)
+                } else {
+                    Ok(expanded)
+                }
             }
             SelectItem::QualifiedWildcard(object_name, options) => {
                 Self::check_wildcard_options(&options)?;
@@ -646,7 +662,19 @@ impl<S: ContextProvider> SqlToRel<'_, S> {
                     planner_context,
                     options,
                 )?;
-                Ok(qualified_wildcard_with_options(qualifier, planned_options))
+
+                let expanded = expand_qualified_wildcard(
+                    &qualifier,
+                    plan.schema(),
+                    Some(&planned_options),
+                )?;
+                // If there is a REPLACE statement, replace that column with 
the given
+                // replace expression. Column name remains the same.
+                if let Some(replace) = planned_options.replace {
+                    replace_columns(expanded, &replace)
+                } else {
+                    Ok(expanded)
+                }
             }
         }
     }
@@ -698,7 +726,10 @@ impl<S: ContextProvider> SqlToRel<'_, S> {
                         planner_context,
                     )
                 })
-                .collect::<Result<Vec<_>>>()?;
+                .collect::<Result<Vec<_>>>()?
+                .into_iter()
+                .flatten()
+                .collect();
             let planned_replace = PlannedReplaceSelectItem {
                 items: replace.items.into_iter().map(|i| *i).collect(),
                 planned_expressions: replace_expr,
@@ -884,3 +915,26 @@ fn match_window_definitions(
     }
     Ok(())
 }
+
+/// If there is a REPLACE statement in the projected expression in the form of
+/// "REPLACE (some_column_within_an_expr AS some_column)", this function 
replaces
+/// that column with the given replace expression. Column name remains the 
same.
+/// Multiple REPLACEs are also possible with comma separations.
+fn replace_columns(
+    mut exprs: Vec<Expr>,
+    replace: &PlannedReplaceSelectItem,
+) -> Result<Vec<Expr>> {
+    for expr in exprs.iter_mut() {
+        if let Expr::Column(Column { name, .. }) = expr {
+            if let Some((_, new_expr)) = replace
+                .items()
+                .iter()
+                .zip(replace.expressions().iter())
+                .find(|(item, _)| item.column_name.value == *name)
+            {
+                *expr = new_expr.clone().alias(name.clone())
+            }
+        }
+    }
+    Ok(exprs)
+}
diff --git a/datafusion/sql/tests/cases/plan_to_sql.rs 
b/datafusion/sql/tests/cases/plan_to_sql.rs
index fc0b7a26ba..8599de8646 100644
--- a/datafusion/sql/tests/cases/plan_to_sql.rs
+++ b/datafusion/sql/tests/cases/plan_to_sql.rs
@@ -325,9 +325,9 @@ fn roundtrip_statement_with_dialect() -> Result<()> {
             unparser_dialect: Box::new(UnparserMySqlDialect {}),
         },
         TestStatementWithDialect {
-            sql: "select * from (select * from j1 limit 10);",
+            sql: "select j1_id from (select j1_id from j1 limit 10);",
             expected:
-                "SELECT * FROM (SELECT * FROM `j1` LIMIT 10) AS 
`derived_limit`",
+                "SELECT `j1`.`j1_id` FROM (SELECT `j1`.`j1_id` FROM `j1` LIMIT 
10) AS `derived_limit`",
             parser_dialect: Box::new(MySqlDialect {}),
             unparser_dialect: Box::new(UnparserMySqlDialect {}),
         },
@@ -527,85 +527,79 @@ fn roundtrip_statement_with_dialect() -> Result<()> {
         },
         TestStatementWithDialect {
             sql: "SELECT * FROM (SELECT j1_id + 1 FROM j1) AS temp_j(id2)",
-            expected: r#"SELECT * FROM (SELECT (`j1`.`j1_id` + 1) AS `id2` 
FROM `j1`) AS `temp_j`"#,
+            expected: r#"SELECT `temp_j`.`id2` FROM (SELECT (`j1`.`j1_id` + 1) 
AS `id2` FROM `j1`) AS `temp_j`"#,
             parser_dialect: Box::new(GenericDialect {}),
             unparser_dialect: Box::new(SqliteDialect {}),
         },
         TestStatementWithDialect {
             sql: "SELECT * FROM (SELECT j1_id FROM j1 LIMIT 1) AS temp_j(id2)",
-            expected: r#"SELECT * FROM (SELECT `j1`.`j1_id` AS `id2` FROM `j1` 
LIMIT 1) AS `temp_j`"#,
+            expected: r#"SELECT `temp_j`.`id2` FROM (SELECT `j1`.`j1_id` AS 
`id2` FROM `j1` LIMIT 1) AS `temp_j`"#,
             parser_dialect: Box::new(GenericDialect {}),
             unparser_dialect: Box::new(SqliteDialect {}),
         },
         TestStatementWithDialect {
             sql: "SELECT * FROM UNNEST([1,2,3])",
-            expected: r#"SELECT * FROM (SELECT UNNEST([1, 2, 3]) AS 
"UNNEST(make_array(Int64(1),Int64(2),Int64(3)))")"#,
+            expected: r#"SELECT 
"UNNEST(make_array(Int64(1),Int64(2),Int64(3)))" FROM (SELECT UNNEST([1, 2, 3]) 
AS "UNNEST(make_array(Int64(1),Int64(2),Int64(3)))")"#,
             parser_dialect: Box::new(GenericDialect {}),
             unparser_dialect: Box::new(UnparserDefaultDialect {}),
         },
         TestStatementWithDialect {
             sql: "SELECT * FROM UNNEST([1,2,3]) AS t1 (c1)",
-            expected: r#"SELECT * FROM (SELECT UNNEST([1, 2, 3]) AS 
"UNNEST(make_array(Int64(1),Int64(2),Int64(3)))") AS t1 (c1)"#,
-            parser_dialect: Box::new(GenericDialect {}),
-            unparser_dialect: Box::new(UnparserDefaultDialect {}),
-        },
-        TestStatementWithDialect {
-            sql: "SELECT * FROM UNNEST([1,2,3]) AS t1 (c1)",
-            expected: r#"SELECT * FROM (SELECT UNNEST([1, 2, 3]) AS 
"UNNEST(make_array(Int64(1),Int64(2),Int64(3)))") AS t1 (c1)"#,
+            expected: r#"SELECT t1.c1 FROM (SELECT UNNEST([1, 2, 3]) AS 
"UNNEST(make_array(Int64(1),Int64(2),Int64(3)))") AS t1 (c1)"#,
             parser_dialect: Box::new(GenericDialect {}),
             unparser_dialect: Box::new(UnparserDefaultDialect {}),
         },
         TestStatementWithDialect {
             sql: "SELECT * FROM UNNEST([1,2,3]), j1",
-            expected: r#"SELECT * FROM (SELECT UNNEST([1, 2, 3]) AS 
"UNNEST(make_array(Int64(1),Int64(2),Int64(3)))") CROSS JOIN j1"#,
+            expected: r#"SELECT 
"UNNEST(make_array(Int64(1),Int64(2),Int64(3)))", j1.j1_id, j1.j1_string FROM 
(SELECT UNNEST([1, 2, 3]) AS "UNNEST(make_array(Int64(1),Int64(2),Int64(3)))") 
CROSS JOIN j1"#,
             parser_dialect: Box::new(GenericDialect {}),
             unparser_dialect: Box::new(UnparserDefaultDialect {}),
         },
         TestStatementWithDialect {
             sql: "SELECT * FROM UNNEST([1,2,3]) u(c1) JOIN j1 ON u.c1 = 
j1.j1_id",
-            expected: r#"SELECT * FROM (SELECT UNNEST([1, 2, 3]) AS 
"UNNEST(make_array(Int64(1),Int64(2),Int64(3)))") AS u (c1) JOIN j1 ON (u.c1 = 
j1.j1_id)"#,
+            expected: r#"SELECT u.c1, j1.j1_id, j1.j1_string FROM (SELECT 
UNNEST([1, 2, 3]) AS "UNNEST(make_array(Int64(1),Int64(2),Int64(3)))") AS u 
(c1) JOIN j1 ON (u.c1 = j1.j1_id)"#,
             parser_dialect: Box::new(GenericDialect {}),
             unparser_dialect: Box::new(UnparserDefaultDialect {}),
         },
         TestStatementWithDialect {
             sql: "SELECT * FROM UNNEST([1,2,3]) u(c1) UNION ALL SELECT * FROM 
UNNEST([4,5,6]) u(c1)",
-            expected: r#"SELECT * FROM (SELECT UNNEST([1, 2, 3]) AS 
"UNNEST(make_array(Int64(1),Int64(2),Int64(3)))") AS u (c1) UNION ALL SELECT * 
FROM (SELECT UNNEST([4, 5, 6]) AS 
"UNNEST(make_array(Int64(4),Int64(5),Int64(6)))") AS u (c1)"#,
+            expected: r#"SELECT u.c1 FROM (SELECT UNNEST([1, 2, 3]) AS 
"UNNEST(make_array(Int64(1),Int64(2),Int64(3)))") AS u (c1) UNION ALL SELECT 
u.c1 FROM (SELECT UNNEST([4, 5, 6]) AS 
"UNNEST(make_array(Int64(4),Int64(5),Int64(6)))") AS u (c1)"#,
             parser_dialect: Box::new(GenericDialect {}),
             unparser_dialect: Box::new(UnparserDefaultDialect {}),
         },
         TestStatementWithDialect {
             sql: "SELECT * FROM UNNEST([1,2,3])",
-            expected: r#"SELECT * FROM UNNEST([1, 2, 3])"#,
+            expected: r#"SELECT UNNEST(make_array(Int64(1),Int64(2),Int64(3))) 
FROM UNNEST([1, 2, 3])"#,
             parser_dialect: Box::new(GenericDialect {}),
             unparser_dialect: 
Box::new(CustomDialectBuilder::default().with_unnest_as_table_factor(true).build()),
         },
         TestStatementWithDialect {
             sql: "SELECT * FROM UNNEST([1,2,3]) AS t1 (c1)",
-            expected: r#"SELECT * FROM UNNEST([1, 2, 3]) AS t1 (c1)"#,
+            expected: r#"SELECT t1.c1 FROM UNNEST([1, 2, 3]) AS t1 (c1)"#,
             parser_dialect: Box::new(GenericDialect {}),
             unparser_dialect: 
Box::new(CustomDialectBuilder::default().with_unnest_as_table_factor(true).build()),
         },
         TestStatementWithDialect {
             sql: "SELECT * FROM UNNEST([1,2,3]) AS t1 (c1)",
-            expected: r#"SELECT * FROM UNNEST([1, 2, 3]) AS t1 (c1)"#,
+            expected: r#"SELECT t1.c1 FROM UNNEST([1, 2, 3]) AS t1 (c1)"#,
             parser_dialect: Box::new(GenericDialect {}),
             unparser_dialect: 
Box::new(CustomDialectBuilder::default().with_unnest_as_table_factor(true).build()),
         },
         TestStatementWithDialect {
             sql: "SELECT * FROM UNNEST([1,2,3]), j1",
-            expected: r#"SELECT * FROM UNNEST([1, 2, 3]) CROSS JOIN j1"#,
+            expected: r#"SELECT 
UNNEST(make_array(Int64(1),Int64(2),Int64(3))), j1.j1_id, j1.j1_string FROM 
UNNEST([1, 2, 3]) CROSS JOIN j1"#,
             parser_dialect: Box::new(GenericDialect {}),
             unparser_dialect: 
Box::new(CustomDialectBuilder::default().with_unnest_as_table_factor(true).build()),
         },
         TestStatementWithDialect {
             sql: "SELECT * FROM UNNEST([1,2,3]) u(c1) JOIN j1 ON u.c1 = 
j1.j1_id",
-            expected: r#"SELECT * FROM UNNEST([1, 2, 3]) AS u (c1) JOIN j1 ON 
(u.c1 = j1.j1_id)"#,
+            expected: r#"SELECT u.c1, j1.j1_id, j1.j1_string FROM UNNEST([1, 
2, 3]) AS u (c1) JOIN j1 ON (u.c1 = j1.j1_id)"#,
             parser_dialect: Box::new(GenericDialect {}),
             unparser_dialect: 
Box::new(CustomDialectBuilder::default().with_unnest_as_table_factor(true).build()),
         },
         TestStatementWithDialect {
             sql: "SELECT * FROM UNNEST([1,2,3]) u(c1) UNION ALL SELECT * FROM 
UNNEST([4,5,6]) u(c1)",
-            expected: r#"SELECT * FROM UNNEST([1, 2, 3]) AS u (c1) UNION ALL 
SELECT * FROM UNNEST([4, 5, 6]) AS u (c1)"#,
+            expected: r#"SELECT u.c1 FROM UNNEST([1, 2, 3]) AS u (c1) UNION 
ALL SELECT u.c1 FROM UNNEST([4, 5, 6]) AS u (c1)"#,
             parser_dialect: Box::new(GenericDialect {}),
             unparser_dialect: 
Box::new(CustomDialectBuilder::default().with_unnest_as_table_factor(true).build()),
         },
@@ -629,25 +623,25 @@ fn roundtrip_statement_with_dialect() -> Result<()> {
         },
         TestStatementWithDialect {
             sql: "SELECT * FROM unnest_table u, UNNEST(u.array_col)",
-            expected: r#"SELECT * FROM unnest_table AS u CROSS JOIN 
UNNEST(u.array_col)"#,
+            expected: r#"SELECT u.array_col, u.struct_col, 
UNNEST(outer_ref(u.array_col)) FROM unnest_table AS u CROSS JOIN 
UNNEST(u.array_col)"#,
             parser_dialect: Box::new(GenericDialect {}),
             unparser_dialect: 
Box::new(CustomDialectBuilder::default().with_unnest_as_table_factor(true).build()),
         },
         TestStatementWithDialect {
             sql: "SELECT * FROM unnest_table u, UNNEST(u.array_col) AS t1 
(c1)",
-            expected: r#"SELECT * FROM unnest_table AS u CROSS JOIN 
UNNEST(u.array_col) AS t1 (c1)"#,
+            expected: r#"SELECT u.array_col, u.struct_col, t1.c1 FROM 
unnest_table AS u CROSS JOIN UNNEST(u.array_col) AS t1 (c1)"#,
             parser_dialect: Box::new(GenericDialect {}),
             unparser_dialect: 
Box::new(CustomDialectBuilder::default().with_unnest_as_table_factor(true).build()),
         },
         TestStatementWithDialect {
             sql: "SELECT * FROM unnest_table u, UNNEST(u.array_col)",
-            expected: r#"SELECT * FROM unnest_table AS u CROSS JOIN LATERAL 
(SELECT UNNEST(u.array_col) AS "UNNEST(outer_ref(u.array_col))")"#,
+            expected: r#"SELECT u.array_col, u.struct_col, 
"UNNEST(outer_ref(u.array_col))" FROM unnest_table AS u CROSS JOIN LATERAL 
(SELECT UNNEST(u.array_col) AS "UNNEST(outer_ref(u.array_col))")"#,
             parser_dialect: Box::new(GenericDialect {}),
             unparser_dialect: Box::new(UnparserDefaultDialect {}),
         },
         TestStatementWithDialect {
             sql: "SELECT * FROM unnest_table u, UNNEST(u.array_col) AS t1 
(c1)",
-            expected: r#"SELECT * FROM unnest_table AS u CROSS JOIN LATERAL 
(SELECT UNNEST(u.array_col) AS "UNNEST(outer_ref(u.array_col))") AS t1 (c1)"#,
+            expected: r#"SELECT u.array_col, u.struct_col, t1.c1 FROM 
unnest_table AS u CROSS JOIN LATERAL (SELECT UNNEST(u.array_col) AS 
"UNNEST(outer_ref(u.array_col))") AS t1 (c1)"#,
             parser_dialect: Box::new(GenericDialect {}),
             unparser_dialect: Box::new(UnparserDefaultDialect {}),
         },
@@ -1457,13 +1451,13 @@ fn test_unnest_to_sql() {
 fn test_join_with_no_conditions() {
     sql_round_trip(
         GenericDialect {},
-        "SELECT * FROM j1 JOIN j2",
-        "SELECT * FROM j1 CROSS JOIN j2",
+        "SELECT j1.j1_id, j1.j1_string FROM j1 JOIN j2",
+        "SELECT j1.j1_id, j1.j1_string FROM j1 CROSS JOIN j2",
     );
     sql_round_trip(
         GenericDialect {},
-        "SELECT * FROM j1 CROSS JOIN j2",
-        "SELECT * FROM j1 CROSS JOIN j2",
+        "SELECT j1.j1_id, j1.j1_string FROM j1 CROSS JOIN j2",
+        "SELECT j1.j1_id, j1.j1_string FROM j1 CROSS JOIN j2",
     );
 }
 
@@ -1564,7 +1558,7 @@ fn test_unparse_extension_to_statement() -> Result<()> {
         Arc::new(UnusedUnparser {}),
     ]);
     let sql = unparser.plan_to_sql(&extension)?;
-    let expected = "SELECT * FROM j1";
+    let expected = "SELECT j1.j1_id, j1.j1_string FROM j1";
     assert_eq!(sql.to_string(), expected);
 
     if let Some(err) = plan_to_sql(&extension).err() {
@@ -1627,7 +1621,8 @@ fn test_unparse_extension_to_sql() -> Result<()> {
         Arc::new(UnusedUnparser {}),
     ]);
     let sql = unparser.plan_to_sql(&plan)?;
-    let expected = "SELECT j1.j1_id AS user_id FROM (SELECT * FROM j1)";
+    let expected =
+        "SELECT j1.j1_id AS user_id FROM (SELECT j1.j1_id, j1.j1_string FROM 
j1)";
     assert_eq!(sql.to_string(), expected);
 
     if let Some(err) = plan_to_sql(&plan).err() {
diff --git a/datafusion/sql/tests/sql_integration.rs 
b/datafusion/sql/tests/sql_integration.rs
index 1df1830268..6877e78264 100644
--- a/datafusion/sql/tests/sql_integration.rs
+++ b/datafusion/sql/tests/sql_integration.rs
@@ -54,15 +54,6 @@ use sqlparser::dialect::{Dialect, GenericDialect, 
HiveDialect, MySqlDialect};
 mod cases;
 mod common;
 
-#[test]
-fn test_schema_support() {
-    quick_test(
-        "SELECT * FROM s1.test",
-        "Projection: *\
-             \n  TableScan: s1.test",
-    );
-}
-
 #[test]
 fn parse_decimals() {
     let test_data = [
@@ -449,19 +440,6 @@ Explain
     quick_test(sql, plan);
 }
 
-#[test]
-fn plan_copy_to_query() {
-    let sql = "COPY (select * from test_decimal limit 10) to 'output.csv'";
-    let plan = r#"
-CopyTo: format=csv output_url=output.csv options: ()
-  Limit: skip=0, fetch=10
-    Projection: *
-      TableScan: test_decimal
-    "#
-    .trim();
-    quick_test(sql, plan);
-}
-
 #[test]
 fn plan_insert() {
     let sql =
@@ -585,15 +563,6 @@ fn select_repeated_column() {
     );
 }
 
-#[test]
-fn select_wildcard_with_repeated_column_but_is_aliased() {
-    quick_test(
-        "SELECT *, first_name AS fn from person",
-        "Projection: *, person.first_name AS fn\
-            \n  TableScan: person",
-    );
-}
-
 #[test]
 fn select_scalar_func_with_literal_no_relation() {
     quick_test(
@@ -793,30 +762,6 @@ fn join_with_ambiguous_column() {
     quick_test(sql, expected);
 }
 
-#[test]
-fn where_selection_with_ambiguous_column() {
-    let sql = "SELECT * FROM person a, person b WHERE id = id + 1";
-    let err = logical_plan(sql)
-        .expect_err("query should have failed")
-        .strip_backtrace();
-    assert_eq!(
-        "\"Schema error: Ambiguous reference to unqualified field id\"",
-        format!("{err:?}")
-    );
-}
-
-#[test]
-fn natural_join() {
-    let sql = "SELECT * FROM lineitem a NATURAL JOIN lineitem b";
-    let expected = "Projection: *\
-                        \n  Inner Join: Using a.l_item_id = b.l_item_id, 
a.l_description = b.l_description, a.price = b.price\
-                        \n    SubqueryAlias: a\
-                        \n      TableScan: lineitem\
-                        \n    SubqueryAlias: b\
-                        \n      TableScan: lineitem";
-    quick_test(sql, expected);
-}
-
 #[test]
 fn natural_left_join() {
     let sql = "SELECT l_item_id FROM lineitem a NATURAL LEFT JOIN lineitem b";
@@ -841,83 +786,6 @@ fn natural_right_join() {
     quick_test(sql, expected);
 }
 
-#[test]
-fn natural_join_no_common_becomes_cross_join() {
-    let sql = "SELECT * FROM person a NATURAL JOIN lineitem b";
-    let expected = "Projection: *\
-                        \n  Cross Join: \
-                        \n    SubqueryAlias: a\
-                        \n      TableScan: person\
-                        \n    SubqueryAlias: b\
-                        \n      TableScan: lineitem";
-    quick_test(sql, expected);
-}
-
-#[test]
-fn using_join_multiple_keys() {
-    let sql = "SELECT * FROM person a join person b using (id, age)";
-    let expected = "Projection: *\
-                        \n  Inner Join: Using a.id = b.id, a.age = b.age\
-                        \n    SubqueryAlias: a\
-                        \n      TableScan: person\
-                        \n    SubqueryAlias: b\
-                        \n      TableScan: person";
-    quick_test(sql, expected);
-}
-
-#[test]
-fn using_join_multiple_keys_subquery() {
-    let sql =
-        "SELECT age FROM (SELECT * FROM person a join person b using (id, age, 
state))";
-    let expected = "Projection: a.age\
-                        \n  Projection: *\
-                        \n    Inner Join: Using a.id = b.id, a.age = b.age, 
a.state = b.state\
-                        \n      SubqueryAlias: a\
-                        \n        TableScan: person\
-                        \n      SubqueryAlias: b\
-                        \n        TableScan: person";
-    quick_test(sql, expected);
-}
-
-#[test]
-fn using_join_multiple_keys_qualified_wildcard_select() {
-    let sql = "SELECT a.* FROM person a join person b using (id, age)";
-    let expected = "Projection: a.*\
-                        \n  Inner Join: Using a.id = b.id, a.age = b.age\
-                        \n    SubqueryAlias: a\
-                        \n      TableScan: person\
-                        \n    SubqueryAlias: b\
-                        \n      TableScan: person";
-    quick_test(sql, expected);
-}
-
-#[test]
-fn using_join_multiple_keys_select_all_columns() {
-    let sql = "SELECT a.*, b.* FROM person a join person b using (id, age)";
-    let expected = "Projection: a.*, b.*\
-                        \n  Inner Join: Using a.id = b.id, a.age = b.age\
-                        \n    SubqueryAlias: a\
-                        \n      TableScan: person\
-                        \n    SubqueryAlias: b\
-                        \n      TableScan: person";
-    quick_test(sql, expected);
-}
-
-#[test]
-fn using_join_multiple_keys_multiple_joins() {
-    let sql = "SELECT * FROM person a join person b using (id, age, state) 
join person c using (id, age, state)";
-    let expected = "Projection: *\
-                        \n  Inner Join: Using a.id = c.id, a.age = c.age, 
a.state = c.state\
-                        \n    Inner Join: Using a.id = b.id, a.age = b.age, 
a.state = b.state\
-                        \n      SubqueryAlias: a\
-                        \n        TableScan: person\
-                        \n      SubqueryAlias: b\
-                        \n        TableScan: person\
-                        \n    SubqueryAlias: c\
-                        \n      TableScan: person";
-    quick_test(sql, expected);
-}
-
 #[test]
 fn select_with_having() {
     let sql = "SELECT id, age
@@ -1233,24 +1101,6 @@ fn select_binary_expr_nested() {
     quick_test(sql, expected);
 }
 
-#[test]
-fn select_wildcard_with_groupby() {
-    quick_test(
-            r#"SELECT * FROM person GROUP BY id, first_name, last_name, age, 
state, salary, birth_date, "😀""#,
-            "Projection: *\
-             \n  Aggregate: groupBy=[[person.id, person.first_name, 
person.last_name, person.age, person.state, person.salary, person.birth_date, 
person.😀]], aggr=[[]]\
-             \n    TableScan: person",
-        );
-    quick_test(
-            "SELECT * FROM (SELECT first_name, last_name FROM person) AS a 
GROUP BY first_name, last_name",
-            "Projection: *\
-            \n  Aggregate: groupBy=[[a.first_name, a.last_name]], aggr=[[]]\
-            \n    SubqueryAlias: a\
-            \n      Projection: person.first_name, person.last_name\
-            \n        TableScan: person",
-        );
-}
-
 #[test]
 fn select_simple_aggregate() {
     quick_test(
@@ -1397,56 +1247,6 @@ fn select_interval_out_of_range() {
     );
 }
 
-#[test]
-fn recursive_ctes() {
-    let sql = "
-        WITH RECURSIVE numbers AS (
-              select 1 as n
-            UNION ALL
-              select n + 1 FROM numbers WHERE N < 10
-        )
-        select * from numbers;";
-    quick_test(
-        sql,
-        "Projection: *\
-    \n  SubqueryAlias: numbers\
-    \n    RecursiveQuery: is_distinct=false\
-    \n      Projection: Int64(1) AS n\
-    \n        EmptyRelation\
-    \n      Projection: numbers.n + Int64(1)\
-    \n        Filter: numbers.n < Int64(10)\
-    \n          TableScan: numbers",
-    )
-}
-
-#[test]
-fn recursive_ctes_disabled() {
-    let sql = "
-        WITH RECURSIVE numbers AS (
-              select 1 as n
-            UNION ALL
-              select n + 1 FROM numbers WHERE N < 10
-        )
-        select * from numbers;";
-
-    // manually setting up test here so that we can disable recursive ctes
-    let mut state = MockSessionState::default();
-    state.config_options.execution.enable_recursive_ctes = false;
-    let context = MockContextProvider { state };
-
-    let planner = SqlToRel::new_with_options(&context, 
ParserOptions::default());
-    let result = DFParser::parse_sql_with_dialect(sql, &GenericDialect {});
-    let mut ast = result.unwrap();
-
-    let err = planner
-        .statement_to_plan(ast.pop_front().unwrap())
-        .expect_err("query should have failed");
-    assert_eq!(
-        "This feature is not implemented: Recursive CTEs are not enabled",
-        err.strip_backtrace()
-    );
-}
-
 #[test]
 fn 
select_simple_aggregate_with_groupby_and_column_is_in_aggregate_and_groupby() {
     quick_test(
@@ -1618,15 +1418,6 @@ fn 
select_aggregate_with_non_column_inner_expression_with_groupby() {
     );
 }
 
-#[test]
-fn test_wildcard() {
-    quick_test(
-        "SELECT * from person",
-        "Projection: *\
-            \n  TableScan: person",
-    );
-}
-
 #[test]
 fn select_count_one() {
     let sql = "SELECT count(1) FROM person";
@@ -2060,20 +1851,6 @@ fn join_with_using() {
     quick_test(sql, expected);
 }
 
-#[test]
-fn project_wildcard_on_join_with_using() {
-    let sql = "SELECT * \
-            FROM lineitem \
-            JOIN lineitem as lineitem2 \
-            USING (l_item_id)";
-    let expected = "Projection: *\
-        \n  Inner Join: Using lineitem.l_item_id = lineitem2.l_item_id\
-        \n    TableScan: lineitem\
-        \n    SubqueryAlias: lineitem2\
-        \n      TableScan: lineitem";
-    quick_test(sql, expected);
-}
-
 #[test]
 fn equijoin_explicit_syntax_3_tables() {
     let sql = "SELECT id, order_id, l_description \
@@ -2867,24 +2644,6 @@ fn exists_subquery_schema_outer_schema_overlap() {
     quick_test(sql, expected);
 }
 
-#[test]
-fn exists_subquery_wildcard() {
-    let sql = "SELECT id FROM person p WHERE EXISTS \
-            (SELECT * FROM person \
-            WHERE last_name = p.last_name \
-            AND state = p.state)";
-
-    let expected = "Projection: p.id\
-        \n  Filter: EXISTS (<subquery>)\
-        \n    Subquery:\
-        \n      Projection: *\
-        \n        Filter: person.last_name = outer_ref(p.last_name) AND 
person.state = outer_ref(p.state)\
-        \n          TableScan: person\
-        \n    SubqueryAlias: p\
-        \n      TableScan: person";
-    quick_test(sql, expected);
-}
-
 #[test]
 fn in_subquery_uncorrelated() {
     let sql = "SELECT id FROM person p WHERE id IN \
@@ -2958,88 +2717,6 @@ fn scalar_subquery_reference_outer_field() {
     quick_test(sql, expected);
 }
 
-#[test]
-fn subquery_references_cte() {
-    let sql = "WITH \
-        cte AS (SELECT * FROM person) \
-        SELECT * FROM person WHERE EXISTS (SELECT * FROM cte WHERE id = 
person.id)";
-
-    let expected = "Projection: *\
-        \n  Filter: EXISTS (<subquery>)\
-        \n    Subquery:\
-        \n      Projection: *\
-        \n        Filter: cte.id = outer_ref(person.id)\
-        \n          SubqueryAlias: cte\
-        \n            Projection: *\
-        \n              TableScan: person\
-        \n    TableScan: person";
-
-    quick_test(sql, expected)
-}
-
-#[test]
-fn cte_with_no_column_names() {
-    let sql = "WITH \
-        numbers AS ( \
-            SELECT 1 as a, 2 as b, 3 as c \
-        ) \
-        SELECT * FROM numbers;";
-
-    let expected = "Projection: *\
-        \n  SubqueryAlias: numbers\
-        \n    Projection: Int64(1) AS a, Int64(2) AS b, Int64(3) AS c\
-        \n      EmptyRelation";
-
-    quick_test(sql, expected)
-}
-
-#[test]
-fn cte_with_column_names() {
-    let sql = "WITH \
-        numbers(a, b, c) AS ( \
-            SELECT 1, 2, 3 \
-        ) \
-        SELECT * FROM numbers;";
-
-    let expected = "Projection: *\
-        \n  SubqueryAlias: numbers\
-        \n    Projection: Int64(1) AS a, Int64(2) AS b, Int64(3) AS c\
-        \n      Projection: Int64(1), Int64(2), Int64(3)\
-        \n        EmptyRelation";
-
-    quick_test(sql, expected)
-}
-
-#[test]
-fn cte_with_column_aliases_precedence() {
-    // The end result should always be what CTE specification says
-    let sql = "WITH \
-        numbers(a, b, c) AS ( \
-            SELECT 1 as x, 2 as y, 3 as z \
-        ) \
-        SELECT * FROM numbers;";
-
-    let expected = "Projection: *\
-        \n  SubqueryAlias: numbers\
-        \n    Projection: x AS a, y AS b, z AS c\
-        \n      Projection: Int64(1) AS x, Int64(2) AS y, Int64(3) AS z\
-        \n        EmptyRelation";
-    quick_test(sql, expected)
-}
-
-#[test]
-fn cte_unbalanced_number_of_columns() {
-    let sql = "WITH \
-        numbers(a) AS ( \
-            SELECT 1, 2, 3 \
-        ) \
-        SELECT * FROM numbers;";
-
-    let expected = "Error during planning: Source table contains 3 columns but 
only 1 names given as column alias";
-    let result = logical_plan(sql).err().unwrap();
-    assert_eq!(result.strip_backtrace(), expected);
-}
-
 #[test]
 fn aggregate_with_rollup() {
     let sql =
@@ -3133,128 +2810,6 @@ fn join_on_complex_condition() {
     quick_test(sql, expected);
 }
 
-#[test]
-fn lateral_constant() {
-    let sql = "SELECT * FROM j1, LATERAL (SELECT 1) AS j2";
-    let expected = "Projection: *\
-            \n  Cross Join: \
-            \n    TableScan: j1\
-            \n    SubqueryAlias: j2\
-            \n      Projection: Int64(1)\
-            \n        EmptyRelation";
-    quick_test(sql, expected);
-}
-
-#[test]
-fn lateral_comma_join() {
-    let sql = "SELECT j1_string, j2_string FROM
-            j1, \
-            LATERAL (SELECT * FROM j2 WHERE j1_id < j2_id) AS j2";
-    let expected = "Projection: j1.j1_string, j2.j2_string\
-            \n  Cross Join: \
-            \n    TableScan: j1\
-            \n    SubqueryAlias: j2\
-            \n      Subquery:\
-            \n        Projection: *\
-            \n          Filter: outer_ref(j1.j1_id) < j2.j2_id\
-            \n            TableScan: j2";
-    quick_test(sql, expected);
-}
-
-#[test]
-fn lateral_comma_join_referencing_join_rhs() {
-    let sql = "SELECT * FROM\
-            \n  j1 JOIN (j2 JOIN j3 ON(j2_id = j3_id - 2)) ON(j1_id = j2_id),\
-            \n  LATERAL (SELECT * FROM j3 WHERE j3_string = j2_string) as j4;";
-    let expected = "Projection: *\
-            \n  Cross Join: \
-            \n    Inner Join:  Filter: j1.j1_id = j2.j2_id\
-            \n      TableScan: j1\
-            \n      Inner Join:  Filter: j2.j2_id = j3.j3_id - Int64(2)\
-            \n        TableScan: j2\
-            \n        TableScan: j3\
-            \n    SubqueryAlias: j4\
-            \n      Subquery:\
-            \n        Projection: *\
-            \n          Filter: j3.j3_string = outer_ref(j2.j2_string)\
-            \n            TableScan: j3";
-    quick_test(sql, expected);
-}
-
-#[test]
-fn lateral_comma_join_with_shadowing() {
-    // The j1_id on line 3 references the (closest) j1 definition from line 2.
-    let sql = "\
-            SELECT * FROM j1, LATERAL (\
-              SELECT * FROM j1, LATERAL (\
-                SELECT * FROM j2 WHERE j1_id = j2_id\
-              ) as j2\
-            ) as j2;";
-    let expected = "Projection: *\
-            \n  Cross Join: \
-            \n    TableScan: j1\
-            \n    SubqueryAlias: j2\
-            \n      Subquery:\
-            \n        Projection: *\
-            \n          Cross Join: \
-            \n            TableScan: j1\
-            \n            SubqueryAlias: j2\
-            \n              Subquery:\
-            \n                Projection: *\
-            \n                  Filter: outer_ref(j1.j1_id) = j2.j2_id\
-            \n                    TableScan: j2";
-    quick_test(sql, expected);
-}
-
-#[test]
-fn lateral_left_join() {
-    let sql = "SELECT j1_string, j2_string FROM \
-            j1 \
-            LEFT JOIN LATERAL (SELECT * FROM j2 WHERE j1_id < j2_id) AS j2 
ON(true);";
-    let expected = "Projection: j1.j1_string, j2.j2_string\
-            \n  Left Join:  Filter: Boolean(true)\
-            \n    TableScan: j1\
-            \n    SubqueryAlias: j2\
-            \n      Subquery:\
-            \n        Projection: *\
-            \n          Filter: outer_ref(j1.j1_id) < j2.j2_id\
-            \n            TableScan: j2";
-    quick_test(sql, expected);
-}
-
-#[test]
-fn lateral_nested_left_join() {
-    let sql = "SELECT * FROM 
-            j1, \
-            (j2 LEFT JOIN LATERAL (SELECT * FROM j3 WHERE j1_id + j2_id = 
j3_id) AS j3 ON(true))";
-    let expected = "Projection: *\
-            \n  Cross Join: \
-            \n    TableScan: j1\
-            \n    Left Join:  Filter: Boolean(true)\
-            \n      TableScan: j2\
-            \n      SubqueryAlias: j3\
-            \n        Subquery:\
-            \n          Projection: *\
-            \n            Filter: outer_ref(j1.j1_id) + outer_ref(j2.j2_id) = 
j3.j3_id\
-            \n              TableScan: j3";
-    quick_test(sql, expected);
-}
-
-#[test]
-fn lateral_unnest() {
-    let sql = "SELECT * from unnest_table u, unnest(u.array_col)";
-    let expected = "Projection: *\
-            \n  Cross Join: \
-            \n    SubqueryAlias: u\
-            \n      TableScan: unnest_table\
-            \n    Subquery:\
-            \n      Projection: 
__unnest_placeholder(outer_ref(u.array_col),depth=1) AS 
UNNEST(outer_ref(u.array_col))\
-            \n        Unnest: 
lists[__unnest_placeholder(outer_ref(u.array_col))|depth=1] structs[]\
-            \n          Projection: outer_ref(u.array_col) AS 
__unnest_placeholder(outer_ref(u.array_col))\
-            \n            EmptyRelation";
-    quick_test(sql, expected);
-}
-
 #[test]
 fn hive_aggregate_with_filter() -> Result<()> {
     let dialect = &HiveDialect {};
@@ -3515,20 +3070,6 @@ fn test_one_side_constant_full_join() {
     quick_test(sql, expected);
 }
 
-#[test]
-fn test_select_all_inner_join() {
-    let sql = "SELECT *
-            FROM person \
-            INNER JOIN orders \
-            ON orders.customer_id * 2 = person.id + 10";
-
-    let expected = "Projection: *\
-            \n  Inner Join:  Filter: orders.customer_id * Int64(2) = person.id 
+ Int64(10)\
-            \n    TableScan: person\
-            \n    TableScan: orders";
-    quick_test(sql, expected);
-}
-
 #[test]
 fn test_select_join_key_inner_join() {
     let sql = "SELECT  orders.customer_id * 2,  person.id + 10
@@ -4258,34 +3799,6 @@ fn test_prepare_statement_to_plan_limit() {
     prepare_stmt_replace_params_quick_test(plan, param_values, expected_plan);
 }
 
-#[test]
-fn test_prepare_statement_to_plan_value_list() {
-    let sql = "PREPARE my_plan(STRING, STRING) AS SELECT * FROM (VALUES(1, 
$1), (2, $2)) AS t (num, letter);";
-
-    let expected_plan = "Prepare: \"my_plan\" [Utf8, Utf8] \
-        \n  Projection: *\
-        \n    SubqueryAlias: t\
-        \n      Projection: column1 AS num, column2 AS letter\
-        \n        Values: (Int64(1), $1), (Int64(2), $2)";
-
-    let expected_dt = "[Utf8, Utf8]";
-
-    let plan = prepare_stmt_quick_test(sql, expected_plan, expected_dt);
-
-    ///////////////////
-    // replace params with values
-    let param_values = vec![
-        ScalarValue::from("a".to_string()),
-        ScalarValue::from("b".to_string()),
-    ];
-    let expected_plan = "Projection: *\
-        \n  SubqueryAlias: t\
-        \n    Projection: column1 AS num, column2 AS letter\
-        \n      Values: (Int64(1), Utf8(\"a\") AS $1), (Int64(2), Utf8(\"b\") 
AS $2)";
-
-    prepare_stmt_replace_params_quick_test(plan, param_values, expected_plan);
-}
-
 #[test]
 fn test_prepare_statement_unknown_list_param() {
     let sql = "SELECT id from person where id = $2";
@@ -4320,44 +3833,6 @@ fn test_prepare_statement_bad_list_idx() {
     assert_contains!(err.to_string(), "Error during planning: Failed to parse 
placeholder id: invalid digit found in string");
 }
 
-#[test]
-fn test_table_alias() {
-    let sql = "select * from (\
-          (select id from person) t1 \
-            CROSS JOIN \
-          (select age from person) t2 \
-        ) as f";
-
-    let expected = "Projection: *\
-        \n  SubqueryAlias: f\
-        \n    Cross Join: \
-        \n      SubqueryAlias: t1\
-        \n        Projection: person.id\
-        \n          TableScan: person\
-        \n      SubqueryAlias: t2\
-        \n        Projection: person.age\
-        \n          TableScan: person";
-    quick_test(sql, expected);
-
-    let sql = "select * from (\
-          (select id from person) t1 \
-            CROSS JOIN \
-          (select age from person) t2 \
-        ) as f (c1, c2)";
-
-    let expected = "Projection: *\
-        \n  SubqueryAlias: f\
-        \n    Projection: t1.id AS c1, t2.age AS c2\
-        \n      Cross Join: \
-        \n        SubqueryAlias: t1\
-        \n          Projection: person.id\
-        \n            TableScan: person\
-        \n        SubqueryAlias: t2\
-        \n          Projection: person.age\
-        \n            TableScan: person";
-    quick_test(sql, expected);
-}
-
 #[test]
 fn test_inner_join_with_cast_key() {
     let sql = "SELECT person.id, person.age
diff --git a/datafusion/sqllogictest/test_files/alias.slt 
b/datafusion/sqllogictest/test_files/alias.slt
new file mode 100644
index 0000000000..340ffb6078
--- /dev/null
+++ b/datafusion/sqllogictest/test_files/alias.slt
@@ -0,0 +1,59 @@
+
+# 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.
+
+
+# test table alias
+statement count 0
+create table t1(id int);
+
+statement count 0
+create table t2(age int);
+
+query TT
+explain select * from ((select id from t1) cross join (select age from t2)) as 
f;
+----
+logical_plan
+01)SubqueryAlias: f
+02)--Cross Join: 
+03)----TableScan: t1 projection=[id]
+04)----TableScan: t2 projection=[age]
+physical_plan
+01)CrossJoinExec
+02)--DataSourceExec: partitions=1, partition_sizes=[0]
+03)--DataSourceExec: partitions=1, partition_sizes=[0]
+
+query TT
+explain select * from ((select id from t1) cross join (select age from t2)) as 
f(c1, c2);
+----
+logical_plan
+01)SubqueryAlias: f
+02)--Projection: t1.id AS c1, t2.age AS c2
+03)----Cross Join: 
+04)------TableScan: t1 projection=[id]
+05)------TableScan: t2 projection=[age]
+physical_plan
+01)ProjectionExec: expr=[id@0 as c1, age@1 as c2]
+02)--CrossJoinExec
+03)----DataSourceExec: partitions=1, partition_sizes=[0]
+04)----DataSourceExec: partitions=1, partition_sizes=[0]
+
+statement count 0
+drop table t1;
+
+statement count 0
+drop table t2;
\ No newline at end of file
diff --git a/datafusion/sqllogictest/test_files/copy.slt 
b/datafusion/sqllogictest/test_files/copy.slt
index f39ff56ce4..e2bb23e357 100644
--- a/datafusion/sqllogictest/test_files/copy.slt
+++ b/datafusion/sqllogictest/test_files/copy.slt
@@ -631,3 +631,20 @@ COPY source_table  to '/tmp/table.parquet' (row_group_size 
55 + 102);
 # Copy using execution.keep_partition_by_columns with an invalid value
 query error DataFusion error: Invalid or Unsupported Configuration: provided 
value for 'execution.keep_partition_by_columns' was not recognized: 
"invalid_value"
 COPY source_table  to '/tmp/table.parquet' OPTIONS 
(execution.keep_partition_by_columns invalid_value);
+
+statement count 0
+create table t;
+
+query TT
+explain COPY (select * from t limit 10) to 'output.csv';
+----
+logical_plan
+01)CopyTo: format=csv output_url=output.csv options: ()
+02)--Limit: skip=0, fetch=10
+03)----TableScan: t projection=[], fetch=10
+physical_plan
+01)DataSinkExec: sink=CsvSink(file_groups=[])
+02)--DataSourceExec: partitions=1, partition_sizes=[0], fetch=10
+
+statement count 0
+drop table t;
diff --git a/datafusion/sqllogictest/test_files/cte.slt 
b/datafusion/sqllogictest/test_files/cte.slt
index 95b9b5a925..e019af9775 100644
--- a/datafusion/sqllogictest/test_files/cte.slt
+++ b/datafusion/sqllogictest/test_files/cte.slt
@@ -859,3 +859,149 @@ SELECT * FROM
 400 500 1
 400 500 2
 400 500 3
+
+query error DataFusion error: Error during planning: Source table contains 3 
columns but only 1 names given as column alias
+with numbers(a) as (select 1, 2, 3) select * from numbers;
+
+query TT
+explain with numbers(a,b,c) as (select 1 as x, 2 as y, 3 as z) select * from 
numbers;
+----
+logical_plan
+01)SubqueryAlias: numbers
+02)--Projection: Int64(1) AS a, Int64(2) AS b, Int64(3) AS c
+03)----EmptyRelation
+physical_plan
+01)ProjectionExec: expr=[1 as a, 2 as b, 3 as c]
+02)--PlaceholderRowExec
+
+query TT
+explain with numbers(a,b,c) as (select 1,2,3) select * from numbers;
+----
+logical_plan
+01)SubqueryAlias: numbers
+02)--Projection: Int64(1) AS a, Int64(2) AS b, Int64(3) AS c
+03)----EmptyRelation
+physical_plan
+01)ProjectionExec: expr=[1 as a, 2 as b, 3 as c]
+02)--PlaceholderRowExec
+
+query TT
+explain with numbers as (select 1 as a, 2 as b, 3 as c) select * from numbers;
+----
+logical_plan
+01)SubqueryAlias: numbers
+02)--Projection: Int64(1) AS a, Int64(2) AS b, Int64(3) AS c
+03)----EmptyRelation
+physical_plan
+01)ProjectionExec: expr=[1 as a, 2 as b, 3 as c]
+02)--PlaceholderRowExec
+
+statement count 0
+create table person (id int, name string, primary key(id))
+
+query TT
+explain with cte as (select * from person) SELECT * FROM person WHERE EXISTS 
(SELECT * FROM cte WHERE id = person.id);
+----
+logical_plan
+01)LeftSemi Join: person.id = __correlated_sq_1.id
+02)--TableScan: person projection=[id, name]
+03)--SubqueryAlias: __correlated_sq_1
+04)----SubqueryAlias: cte
+05)------TableScan: person projection=[id]
+physical_plan
+01)CoalesceBatchesExec: target_batch_size=8182
+02)--HashJoinExec: mode=Partitioned, join_type=LeftSemi, on=[(id@0, id@0)]
+03)----DataSourceExec: partitions=1, partition_sizes=[0]
+04)----DataSourceExec: partitions=1, partition_sizes=[0]
+
+statement count 0
+drop table person;
+
+statement count 0
+create table j1(a int);
+
+statement count 0
+create table j2(b int);
+
+query TT
+explain SELECT * FROM j1, LATERAL (SELECT 1) AS j2;
+----
+logical_plan
+01)Cross Join: 
+02)--TableScan: j1 projection=[a]
+03)--SubqueryAlias: j2
+04)----Projection: Int64(1)
+05)------EmptyRelation
+physical_plan
+01)CrossJoinExec
+02)--DataSourceExec: partitions=1, partition_sizes=[0]
+03)--ProjectionExec: expr=[1 as Int64(1)]
+04)----PlaceholderRowExec
+
+statement count 0
+drop table j1;
+
+statement count 0
+drop table j2;
+
+query TT
+explain WITH RECURSIVE numbers AS (
+  select 1 as n
+  UNION ALL
+  select n + 1 FROM numbers WHERE N < 10
+) select * from numbers;
+----
+logical_plan
+01)SubqueryAlias: numbers
+02)--RecursiveQuery: is_distinct=false
+03)----Projection: Int64(1) AS n
+04)------EmptyRelation
+05)----Projection: numbers.n + Int64(1)
+06)------Filter: numbers.n < Int64(10)
+07)--------TableScan: numbers
+physical_plan
+01)RecursiveQueryExec: name=numbers, is_distinct=false
+02)--ProjectionExec: expr=[1 as n]
+03)----PlaceholderRowExec
+04)--CoalescePartitionsExec
+05)----ProjectionExec: expr=[n@0 + 1 as numbers.n + Int64(1)]
+06)------CoalesceBatchesExec: target_batch_size=8182
+07)--------FilterExec: n@0 < 10
+08)----------RepartitionExec: partitioning=RoundRobinBatch(4), 
input_partitions=1
+09)------------WorkTableExec: name=numbers
+
+query TT
+explain WITH RECURSIVE numbers AS (
+  select 1 as n
+  UNION ALL
+  select n + 1 FROM numbers WHERE N < 10
+) select * from numbers;
+----
+logical_plan
+01)SubqueryAlias: numbers
+02)--RecursiveQuery: is_distinct=false
+03)----Projection: Int64(1) AS n
+04)------EmptyRelation
+05)----Projection: numbers.n + Int64(1)
+06)------Filter: numbers.n < Int64(10)
+07)--------TableScan: numbers
+physical_plan
+01)RecursiveQueryExec: name=numbers, is_distinct=false
+02)--ProjectionExec: expr=[1 as n]
+03)----PlaceholderRowExec
+04)--CoalescePartitionsExec
+05)----ProjectionExec: expr=[n@0 + 1 as numbers.n + Int64(1)]
+06)------CoalesceBatchesExec: target_batch_size=8182
+07)--------FilterExec: n@0 < 10
+08)----------RepartitionExec: partitioning=RoundRobinBatch(4), 
input_partitions=1
+09)------------WorkTableExec: name=numbers
+
+statement count 0
+set datafusion.execution.enable_recursive_ctes = false;
+
+query error DataFusion error: This feature is not implemented: Recursive CTEs 
are not enabled
+explain WITH RECURSIVE numbers AS (
+  select 1 as n
+  UNION ALL
+  select n + 1 FROM numbers WHERE N < 10
+) select * from numbers;
diff --git a/datafusion/sqllogictest/test_files/group_by.slt 
b/datafusion/sqllogictest/test_files/group_by.slt
index 2b3ebcda15..0cc8045dcc 100644
--- a/datafusion/sqllogictest/test_files/group_by.slt
+++ b/datafusion/sqllogictest/test_files/group_by.slt
@@ -5537,3 +5537,32 @@ drop view t
 
 statement ok
 drop table source;
+
+
+# test select_wildcard_with_groupby
+statement count 0
+create table t(a int, b int, c int, "😀" int);
+
+query TT
+explain select * from t group by a, b, c, "😀";
+----
+logical_plan
+01)Aggregate: groupBy=[[t.a, t.b, t.c, t.😀]], aggr=[[]]
+02)--TableScan: t projection=[a, b, c, 😀]
+physical_plan
+01)AggregateExec: mode=Single, gby=[a@0 as a, b@1 as b, c@2 as c, 😀@3 as 😀], 
aggr=[]
+02)--DataSourceExec: partitions=1, partition_sizes=[0]
+
+query TT
+explain select * from (select a, b from t) as c group by a, b;
+----
+logical_plan
+01)Aggregate: groupBy=[[c.a, c.b]], aggr=[[]]
+02)--SubqueryAlias: c
+03)----TableScan: t projection=[a, b]
+physical_plan
+01)AggregateExec: mode=Single, gby=[a@0 as a, b@1 as b], aggr=[]
+02)--DataSourceExec: partitions=1, partition_sizes=[0]
+
+statement count 0
+drop table t;
diff --git a/datafusion/sqllogictest/test_files/joins.slt 
b/datafusion/sqllogictest/test_files/joins.slt
index 0397e0c367..50af06dc40 100644
--- a/datafusion/sqllogictest/test_files/joins.slt
+++ b/datafusion/sqllogictest/test_files/joins.slt
@@ -4541,3 +4541,269 @@ DROP TABLE test
 
 statement ok
 set datafusion.execution.target_partitions = 1;
+
+# test using_join_multiple_keys_subquery
+statement count 0
+create table person(id int, age int, state int);
+
+statement count 0
+create table lineitem(c1 int);
+
+query TT
+explain SELECT * FROM person a join person b using (id, age);
+----
+logical_plan
+01)Projection: a.id, a.age, a.state, b.state
+02)--Inner Join: a.id = b.id, a.age = b.age
+03)----SubqueryAlias: a
+04)------TableScan: person projection=[id, age, state]
+05)----SubqueryAlias: b
+06)------TableScan: person projection=[id, age, state]
+physical_plan
+01)CoalesceBatchesExec: target_batch_size=3
+02)--HashJoinExec: mode=CollectLeft, join_type=Inner, on=[(id@0, id@0), 
(age@1, age@1)], projection=[id@0, age@1, state@2, state@5]
+03)----DataSourceExec: partitions=1, partition_sizes=[0]
+04)----DataSourceExec: partitions=1, partition_sizes=[0]
+
+query TT
+explain SELECT age FROM (SELECT * FROM person a join person b using (id, age, 
state));
+----
+logical_plan
+01)Projection: a.age
+02)--Inner Join: a.id = b.id, a.age = b.age, a.state = b.state
+03)----SubqueryAlias: a
+04)------TableScan: person projection=[id, age, state]
+05)----SubqueryAlias: b
+06)------TableScan: person projection=[id, age, state]
+physical_plan
+01)CoalesceBatchesExec: target_batch_size=3
+02)--HashJoinExec: mode=CollectLeft, join_type=Inner, on=[(id@0, id@0), 
(age@1, age@1), (state@2, state@2)], projection=[age@1]
+03)----DataSourceExec: partitions=1, partition_sizes=[0]
+04)----DataSourceExec: partitions=1, partition_sizes=[0]
+
+query TT
+explain SELECT a.* FROM person a join person b using (id, age);
+----
+logical_plan
+01)Projection: a.id, a.age, a.state
+02)--Inner Join: a.id = b.id, a.age = b.age
+03)----SubqueryAlias: a
+04)------TableScan: person projection=[id, age, state]
+05)----SubqueryAlias: b
+06)------TableScan: person projection=[id, age]
+physical_plan
+01)CoalesceBatchesExec: target_batch_size=3
+02)--HashJoinExec: mode=CollectLeft, join_type=Inner, on=[(id@0, id@0), 
(age@1, age@1)], projection=[id@0, age@1, state@2]
+03)----DataSourceExec: partitions=1, partition_sizes=[0]
+04)----DataSourceExec: partitions=1, partition_sizes=[0]
+
+query TT
+explain SELECT a.*, b.* FROM person a join person b using (id, age);
+----
+logical_plan
+01)Inner Join: a.id = b.id, a.age = b.age
+02)--SubqueryAlias: a
+03)----TableScan: person projection=[id, age, state]
+04)--SubqueryAlias: b
+05)----TableScan: person projection=[id, age, state]
+physical_plan
+01)CoalesceBatchesExec: target_batch_size=3
+02)--HashJoinExec: mode=CollectLeft, join_type=Inner, on=[(id@0, id@0), 
(age@1, age@1)]
+03)----DataSourceExec: partitions=1, partition_sizes=[0]
+04)----DataSourceExec: partitions=1, partition_sizes=[0]
+
+query TT
+explain SELECT * FROM person a join person b using (id, age, state) join 
person c using (id, age, state);
+----
+logical_plan
+01)Projection: a.id, a.age, a.state
+02)--Inner Join: a.id = c.id, a.age = c.age, a.state = c.state
+03)----Projection: a.id, a.age, a.state
+04)------Inner Join: a.id = b.id, a.age = b.age, a.state = b.state
+05)--------SubqueryAlias: a
+06)----------TableScan: person projection=[id, age, state]
+07)--------SubqueryAlias: b
+08)----------TableScan: person projection=[id, age, state]
+09)----SubqueryAlias: c
+10)------TableScan: person projection=[id, age, state]
+physical_plan
+01)CoalesceBatchesExec: target_batch_size=3
+02)--HashJoinExec: mode=CollectLeft, join_type=Inner, on=[(id@0, id@0), 
(age@1, age@1), (state@2, state@2)], projection=[id@0, age@1, state@2]
+03)----CoalesceBatchesExec: target_batch_size=3
+04)------HashJoinExec: mode=CollectLeft, join_type=Inner, on=[(id@0, id@0), 
(age@1, age@1), (state@2, state@2)], projection=[id@0, age@1, state@2]
+05)--------DataSourceExec: partitions=1, partition_sizes=[0]
+06)--------DataSourceExec: partitions=1, partition_sizes=[0]
+07)----DataSourceExec: partitions=1, partition_sizes=[0]
+
+query TT
+explain SELECT * FROM person a NATURAL JOIN lineitem b;
+----
+logical_plan
+01)Cross Join: 
+02)--SubqueryAlias: a
+03)----TableScan: person projection=[id, age, state]
+04)--SubqueryAlias: b
+05)----TableScan: lineitem projection=[c1]
+physical_plan
+01)CrossJoinExec
+02)--DataSourceExec: partitions=1, partition_sizes=[0]
+03)--DataSourceExec: partitions=1, partition_sizes=[0]
+
+query TT
+explain SELECT * FROM lineitem JOIN lineitem as lineitem2 USING (c1)
+----
+logical_plan
+01)Projection: lineitem.c1
+02)--Inner Join: lineitem.c1 = lineitem2.c1
+03)----TableScan: lineitem projection=[c1]
+04)----SubqueryAlias: lineitem2
+05)------TableScan: lineitem projection=[c1]
+physical_plan
+01)CoalesceBatchesExec: target_batch_size=3
+02)--HashJoinExec: mode=CollectLeft, join_type=Inner, on=[(c1@0, c1@0)], 
projection=[c1@0]
+03)----DataSourceExec: partitions=1, partition_sizes=[0]
+04)----DataSourceExec: partitions=1, partition_sizes=[0]
+
+statement count 0
+drop table person;
+
+statement count 0
+drop table lineitem;
+
+statement count 0
+create table j1(j1_string varchar, j1_id int);
+
+statement count 0
+create table j2(j2_string varchar, j2_id int);
+
+statement count 0
+create table j3(j3_string varchar, j3_id int);
+
+statement count 0
+create table j4(j4_string varchar, j4_id int);
+
+query TT
+explain SELECT j1_string, j2_string FROM j1, LATERAL (SELECT * FROM j2 WHERE 
j1_id < j2_id) AS j2;
+----
+logical_plan
+01)Cross Join: 
+02)--TableScan: j1 projection=[j1_string]
+03)--SubqueryAlias: j2
+04)----Projection: j2.j2_string
+05)------Subquery:
+06)--------Filter: outer_ref(j1.j1_id) < j2.j2_id
+07)----------TableScan: j2 projection=[j2_string, j2_id]
+physical_plan_error This feature is not implemented: Physical plan does not 
support logical expression OuterReferenceColumn(Int32, Column { relation: 
Some(Bare { table: "j1" }), name: "j1_id" })
+
+query TT
+explain SELECT * FROM j1 JOIN (j2 JOIN j3 ON(j2_id = j3_id - 2)) ON(j1_id = 
j2_id), LATERAL (SELECT * FROM j3 WHERE j3_string = j2_string) as j4
+----
+logical_plan
+01)Cross Join: 
+02)--Inner Join: CAST(j2.j2_id AS Int64) = CAST(j3.j3_id AS Int64) - Int64(2)
+03)----Inner Join: j1.j1_id = j2.j2_id
+04)------TableScan: j1 projection=[j1_string, j1_id]
+05)------TableScan: j2 projection=[j2_string, j2_id]
+06)----TableScan: j3 projection=[j3_string, j3_id]
+07)--SubqueryAlias: j4
+08)----Subquery:
+09)------Filter: j3.j3_string = outer_ref(j2.j2_string)
+10)--------TableScan: j3 projection=[j3_string, j3_id]
+physical_plan_error This feature is not implemented: Physical plan does not 
support logical expression OuterReferenceColumn(Utf8, Column { relation: 
Some(Bare { table: "j2" }), name: "j2_string" })
+
+query TT
+explain SELECT * FROM j1, LATERAL (SELECT * FROM j1, LATERAL (SELECT * FROM j2 
WHERE j1_id = j2_id) as j2) as j2;
+----
+logical_plan
+01)Cross Join: 
+02)--TableScan: j1 projection=[j1_string, j1_id]
+03)--SubqueryAlias: j2
+04)----Subquery:
+05)------Cross Join: 
+06)--------TableScan: j1 projection=[j1_string, j1_id]
+07)--------SubqueryAlias: j2
+08)----------Subquery:
+09)------------Filter: outer_ref(j1.j1_id) = j2.j2_id
+10)--------------TableScan: j2 projection=[j2_string, j2_id]
+physical_plan_error This feature is not implemented: Physical plan does not 
support logical expression OuterReferenceColumn(Int32, Column { relation: 
Some(Bare { table: "j1" }), name: "j1_id" })
+
+query TT
+explain SELECT j1_string, j2_string FROM j1 LEFT JOIN LATERAL (SELECT * FROM 
j2 WHERE j1_id < j2_id) AS j2 ON(true);
+----
+logical_plan
+01)Left Join: 
+02)--TableScan: j1 projection=[j1_string]
+03)--SubqueryAlias: j2
+04)----Projection: j2.j2_string
+05)------Subquery:
+06)--------Filter: outer_ref(j1.j1_id) < j2.j2_id
+07)----------TableScan: j2 projection=[j2_string, j2_id]
+physical_plan_error This feature is not implemented: Physical plan does not 
support logical expression OuterReferenceColumn(Int32, Column { relation: 
Some(Bare { table: "j1" }), name: "j1_id" })
+
+query TT
+explain SELECT * FROM j1, (j2 LEFT JOIN LATERAL (SELECT * FROM j3 WHERE j1_id 
+ j2_id = j3_id) AS j3 ON(true));
+----
+logical_plan
+01)Cross Join: 
+02)--TableScan: j1 projection=[j1_string, j1_id]
+03)--Left Join: 
+04)----TableScan: j2 projection=[j2_string, j2_id]
+05)----SubqueryAlias: j3
+06)------Subquery:
+07)--------Filter: outer_ref(j1.j1_id) + outer_ref(j2.j2_id) = j3.j3_id
+08)----------TableScan: j3 projection=[j3_string, j3_id]
+physical_plan_error This feature is not implemented: Physical plan does not 
support logical expression OuterReferenceColumn(Int32, Column { relation: 
Some(Bare { table: "j1" }), name: "j1_id" })
+
+query TT
+explain SELECT * FROM j1, LATERAL (SELECT 1) AS j2;
+----
+logical_plan
+01)Cross Join: 
+02)--TableScan: j1 projection=[j1_string, j1_id]
+03)--SubqueryAlias: j2
+04)----Projection: Int64(1)
+05)------EmptyRelation
+physical_plan
+01)CrossJoinExec
+02)--DataSourceExec: partitions=1, partition_sizes=[0]
+03)--ProjectionExec: expr=[1 as Int64(1)]
+04)----PlaceholderRowExec
+
+statement count 0
+drop table j1;
+
+statement count 0
+drop table j2;
+
+statement count 0
+drop table j3;
+
+statement count 0
+drop table j4;
+
+statement count 0
+create table person(id int);
+
+statement count 0
+create table orders(customer_id int);
+
+query TT
+explain SELECT * FROM person INNER JOIN orders ON orders.customer_id * 2 = 
person.id + 10
+----
+logical_plan
+01)Inner Join: CAST(person.id AS Int64) + Int64(10) = CAST(orders.customer_id 
AS Int64) * Int64(2)
+02)--TableScan: person projection=[id]
+03)--TableScan: orders projection=[customer_id]
+physical_plan
+01)CoalesceBatchesExec: target_batch_size=3
+02)--HashJoinExec: mode=CollectLeft, join_type=Inner, on=[(person.id + 
Int64(10)@1, orders.customer_id * Int64(2)@1)], projection=[id@0, customer_id@2]
+03)----ProjectionExec: expr=[id@0 as id, CAST(id@0 AS Int64) + 10 as person.id 
+ Int64(10)]
+04)------DataSourceExec: partitions=1, partition_sizes=[0]
+05)----ProjectionExec: expr=[customer_id@0 as customer_id, CAST(customer_id@0 
AS Int64) * 2 as orders.customer_id * Int64(2)]
+06)------DataSourceExec: partitions=1, partition_sizes=[0]
+
+statement count 0
+drop table person;
+
+statement count 0
+drop table orders;
diff --git a/datafusion/sqllogictest/test_files/prepare.slt 
b/datafusion/sqllogictest/test_files/prepare.slt
index 5d0f417640..33df0d26f3 100644
--- a/datafusion/sqllogictest/test_files/prepare.slt
+++ b/datafusion/sqllogictest/test_files/prepare.slt
@@ -312,3 +312,18 @@ SET datafusion.explain.logical_plan_only=false;
 
 statement ok
 DROP TABLE person;
+
+statement ok
+SET datafusion.explain.logical_plan_only=true;
+
+statement count 0
+PREPARE my_plan(STRING, STRING) AS SELECT * FROM (VALUES(1, $1), (2, $2)) AS t 
(num, letter);
+
+statement count 5
+explain PREPARE my_plan(STRING, STRING) AS SELECT * FROM (VALUES(1, $1), (2, 
$2)) AS t (num, letter);
+
+query IT
+EXECUTE my_plan('a', 'b');
+----
+1 a
+2 b
diff --git a/datafusion/sqllogictest/test_files/select.slt 
b/datafusion/sqllogictest/test_files/select.slt
index f1ac0696bf..d5e0c44976 100644
--- a/datafusion/sqllogictest/test_files/select.slt
+++ b/datafusion/sqllogictest/test_files/select.slt
@@ -1820,6 +1820,9 @@ query I
 select a from t;
 ----
 
+statement count 0
+drop table t;
+
 statement ok
 set datafusion.optimizer.max_passes=3;
 
@@ -1842,3 +1845,13 @@ SELECT t1.v1 FROM (SELECT 1 AS "t1.v1");
 # Test issue: https://github.com/apache/datafusion/issues/14124
 query error DataFusion error: Arrow error: Arithmetic overflow: Overflow 
happened on: 10000 \* 100000000000000000000000000000000000
 SELECT ('0.54321543215432154321543215432154321'::DECIMAL(35,35) + 
10000)::VARCHAR
+
+# where_selection_with_ambiguous_column
+statement ok
+CREATE TABLE t(a int, b int, id int);
+
+query error DataFusion error: Schema error: Ambiguous reference to unqualified 
field id
+select * from t a, t b where id = id + 1;
+
+statement count 0
+drop table t;
diff --git a/datafusion/sqllogictest/test_files/subquery.slt 
b/datafusion/sqllogictest/test_files/subquery.slt
index 207bb72fd5..5a722c2288 100644
--- a/datafusion/sqllogictest/test_files/subquery.slt
+++ b/datafusion/sqllogictest/test_files/subquery.slt
@@ -1431,3 +1431,23 @@ drop table t1;
 
 statement count 0
 drop table t2;
+
+
+# test exists_subquery_wildcard
+statement count 0
+create table person(id int, last_name int, state int);
+
+query TT
+explain SELECT id FROM person p WHERE EXISTS 
+    (SELECT * FROM person WHERE last_name = p.last_name AND state = p.state)
+----
+logical_plan
+01)Projection: p.id
+02)--LeftSemi Join: p.last_name = __correlated_sq_1.last_name, p.state = 
__correlated_sq_1.state
+03)----SubqueryAlias: p
+04)------TableScan: person projection=[id, last_name, state]
+05)----SubqueryAlias: __correlated_sq_1
+06)------TableScan: person projection=[last_name, state]
+
+statement count 0
+drop table person;
diff --git a/datafusion/sqllogictest/test_files/wildcard.slt 
b/datafusion/sqllogictest/test_files/wildcard.slt
index 7c076f040f..1a480eac0c 100644
--- a/datafusion/sqllogictest/test_files/wildcard.slt
+++ b/datafusion/sqllogictest/test_files/wildcard.slt
@@ -145,3 +145,18 @@ DROP TABLE t2;
 
 statement ok
 DROP TABLE aggregate_simple;
+
+statement ok
+create table t(a int, b int, c int) as values (1, 2, 3);
+
+query error DataFusion error: Error during planning: Projections require 
unique expression names but the expression "t\.a" at position 0 and "t\.a" at 
position 3 have the same name\. Consider aliasing \("AS"\) one of them\.
+select *, a from t;
+
+# a is aliased to other name so the query is valid
+query IIII
+select *, a as aka from t;
+----
+1 2 3 1
+
+statement count 0
+drop table t;


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to