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

agrove pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/arrow-datafusion.git


The following commit(s) were added to refs/heads/master by this push:
     new fd64e6f2e Improve formatting of logical plans containing subqueries 
(#2899)
fd64e6f2e is described below

commit fd64e6f2e5ca5ba8c33c431b75a3ba9441091970
Author: Andy Grove <[email protected]>
AuthorDate: Wed Jul 13 14:13:45 2022 -0600

    Improve formatting of logical plans containing subqueries (#2899)
---
 datafusion/expr/src/expr.rs                        |  17 ++
 datafusion/expr/src/logical_plan/builder.rs        |  30 ++--
 datafusion/expr/src/logical_plan/plan.rs           | 102 +++++++++---
 datafusion/optimizer/src/filter_push_down.rs       |  10 +-
 datafusion/optimizer/src/limit_push_down.rs        |  16 +-
 .../optimizer/src/subquery_filter_to_join.rs       |  23 +--
 datafusion/sql/src/planner.rs                      | 176 +++++++++------------
 7 files changed, 222 insertions(+), 152 deletions(-)

diff --git a/datafusion/expr/src/expr.rs b/datafusion/expr/src/expr.rs
index 202605b4d..ad0b58fac 100644
--- a/datafusion/expr/src/expr.rs
+++ b/datafusion/expr/src/expr.rs
@@ -484,6 +484,23 @@ impl std::fmt::Display for Expr {
                 /// List of expressions to feed to the functions as arguments
                 ref args,
             } => fmt_function(f, &fun.to_string(), false, args, true),
+            Expr::Exists { negated, .. } => {
+                if *negated {
+                    write!(f, "NOT EXISTS (<subquery>)")
+                } else {
+                    write!(f, "EXISTS (<subquery>)")
+                }
+            }
+            Expr::InSubquery { negated, .. } => {
+                if *negated {
+                    write!(f, "NOT IN (<subquery>)")
+                } else {
+                    write!(f, "IN (<subquery>)")
+                }
+            }
+            Expr::ScalarSubquery(_) => {
+                write!(f, "(<subquery>)")
+            }
             _ => write!(f, "{:?}", self),
         }
     }
diff --git a/datafusion/expr/src/logical_plan/builder.rs 
b/datafusion/expr/src/logical_plan/builder.rs
index a3abc694d..05cc842f1 100644
--- a/datafusion/expr/src/logical_plan/builder.rs
+++ b/datafusion/expr/src/logical_plan/builder.rs
@@ -1217,11 +1217,13 @@ mod tests {
             .filter(exists(Arc::new(subquery)))?
             .build()?;
 
-        let expected = "Filter: EXISTS (\
-            Subquery: Filter: #foo.a = #bar.a\
-            \n  Projection: #foo.a\
-            \n    TableScan: foo)\
-        \n  Projection: #bar.a\n    TableScan: bar";
+        let expected = "Filter: EXISTS (<subquery>)\
+        \n  Subquery:\
+        \n    Filter: #foo.a = #bar.a\
+        \n      Projection: #foo.a\
+        \n        TableScan: foo\
+        \n  Projection: #bar.a\
+        \n    TableScan: bar";
         assert_eq!(expected, format!("{:?}", outer_query));
 
         Ok(())
@@ -1243,9 +1245,11 @@ mod tests {
             .filter(in_subquery(col("a"), Arc::new(subquery)))?
             .build()?;
 
-        let expected = "Filter: #bar.a IN (Subquery: Filter: #foo.a = #bar.a\
-        \n  Projection: #foo.a\
-        \n    TableScan: foo)\
+        let expected = "Filter: #bar.a IN (<subquery>)\
+        \n  Subquery:\
+        \n    Filter: #foo.a = #bar.a\
+        \n      Projection: #foo.a\
+        \n        TableScan: foo\
         \n  Projection: #bar.a\
         \n    TableScan: bar";
         assert_eq!(expected, format!("{:?}", outer_query));
@@ -1268,10 +1272,12 @@ mod tests {
             .project(vec![scalar_subquery(Arc::new(subquery))])?
             .build()?;
 
-        let expected = "Projection: (Subquery: Filter: #foo.a = #bar.a\
-                \n  Projection: #foo.b\
-                \n    TableScan: foo)\
-            \n  TableScan: bar";
+        let expected = "Projection: (<subquery>)\
+        \n  Subquery:\
+        \n    Filter: #foo.a = #bar.a\
+        \n      Projection: #foo.b\
+        \n        TableScan: foo\
+        \n  TableScan: bar";
         assert_eq!(expected, format!("{:?}", outer_query));
 
         Ok(())
diff --git a/datafusion/expr/src/logical_plan/plan.rs 
b/datafusion/expr/src/logical_plan/plan.rs
index 0e52ff253..b0c011449 100644
--- a/datafusion/expr/src/logical_plan/plan.rs
+++ b/datafusion/expr/src/logical_plan/plan.rs
@@ -262,7 +262,7 @@ impl LogicalPlan {
     }
 
     /// returns all inputs of this `LogicalPlan` node. Does not
-    /// include inputs to inputs.
+    /// include inputs to inputs, or subqueries.
     pub fn inputs(self: &LogicalPlan) -> Vec<&LogicalPlan> {
         match self {
             LogicalPlan::Projection(Projection { input, .. }) => vec![input],
@@ -396,8 +396,10 @@ impl LogicalPlan {
         }
 
         let recurse = match self {
-            LogicalPlan::Projection(Projection { input, .. }) => 
input.accept(visitor)?,
-            LogicalPlan::Filter(Filter { input, .. }) => 
input.accept(visitor)?,
+            LogicalPlan::Projection(Projection { .. }) => {
+                self.visit_all_inputs(visitor)?
+            }
+            LogicalPlan::Filter(Filter { .. }) => 
self.visit_all_inputs(visitor)?,
             LogicalPlan::Repartition(Repartition { input, .. }) => {
                 input.accept(visitor)?
             }
@@ -457,6 +459,51 @@ impl LogicalPlan {
 
         Ok(true)
     }
+
+    /// Visit all inputs, including subqueries
+    pub fn visit_all_inputs<V>(&self, visitor: &mut V) -> Result<bool, 
V::Error>
+    where
+        V: PlanVisitor,
+    {
+        for input in self.all_inputs() {
+            if !input.accept(visitor)? {
+                return Ok(false);
+            }
+        }
+
+        Ok(true)
+    }
+
+    /// Get all plan inputs, including subqueries from expressions
+    fn all_inputs(&self) -> Vec<Arc<LogicalPlan>> {
+        let mut inputs = vec![];
+        for expr in self.expressions() {
+            self.collect_subqueries(&expr, &mut inputs);
+        }
+        for input in self.inputs() {
+            inputs.push(Arc::new(input.clone()));
+        }
+        inputs
+    }
+
+    fn collect_subqueries(&self, expr: &Expr, sub: &mut Vec<Arc<LogicalPlan>>) 
{
+        match expr {
+            Expr::BinaryExpr { left, right, .. } => {
+                self.collect_subqueries(left, sub);
+                self.collect_subqueries(right, sub);
+            }
+            Expr::Exists { subquery, .. } => {
+                sub.push(Arc::new(LogicalPlan::Subquery(subquery.clone())));
+            }
+            Expr::InSubquery { subquery, .. } => {
+                sub.push(Arc::new(LogicalPlan::Subquery(subquery.clone())));
+            }
+            Expr::ScalarSubquery(subquery) => {
+                sub.push(Arc::new(LogicalPlan::Subquery(subquery.clone())));
+            }
+            _ => {}
+        }
+    }
 }
 
 // Various implementations for printing out LogicalPlans
@@ -826,8 +873,8 @@ impl LogicalPlan {
                             fetch.map_or_else(|| "None".to_string(), |x| 
x.to_string())
                         )
                     }
-                    LogicalPlan::Subquery(Subquery { subquery, .. }) => {
-                        write!(f, "Subquery: {:?}", subquery)
+                    LogicalPlan::Subquery(Subquery { .. }) => {
+                        write!(f, "Subquery:")
                     }
                     LogicalPlan::SubqueryAlias(SubqueryAlias { ref alias, .. 
}) => {
                         write!(f, "SubqueryAlias: {}", alias)
@@ -1245,7 +1292,7 @@ pub struct Subquery {
 
 impl Debug for Subquery {
     fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
-        write!(f, "Subquery: {:?}", self.subquery)
+        write!(f, "<subquery>")
     }
 }
 
@@ -1360,8 +1407,9 @@ pub trait ToStringifiedPlan {
 mod tests {
     use super::*;
     use crate::logical_plan::table_scan;
-    use crate::{col, lit};
+    use crate::{col, in_subquery, lit};
     use arrow::datatypes::{DataType, Field, Schema};
+    use datafusion_common::Result;
 
     fn employee_schema() -> Schema {
         Schema::new(vec![
@@ -1373,42 +1421,47 @@ mod tests {
         ])
     }
 
-    fn display_plan() -> LogicalPlan {
-        table_scan(Some("employee_csv"), &employee_schema(), Some(vec![0, 3]))
-            .unwrap()
-            .filter(col("state").eq(lit("CO")))
-            .unwrap()
-            .project(vec![col("id")])
-            .unwrap()
+    fn display_plan() -> Result<LogicalPlan> {
+        let plan1 = table_scan(Some("employee_csv"), &employee_schema(), 
Some(vec![3]))?
+            .build()?;
+
+        table_scan(Some("employee_csv"), &employee_schema(), Some(vec![0, 3]))?
+            .filter(in_subquery(col("state"), Arc::new(plan1)))?
+            .project(vec![col("id")])?
             .build()
-            .unwrap()
     }
 
     #[test]
-    fn test_display_indent() {
-        let plan = display_plan();
+    fn test_display_indent() -> Result<()> {
+        let plan = display_plan()?;
 
         let expected = "Projection: #employee_csv.id\
-        \n  Filter: #employee_csv.state = Utf8(\"CO\")\
+        \n  Filter: #employee_csv.state IN (<subquery>)\
+        \n    Subquery:\
+        \n      TableScan: employee_csv projection=[state]\
         \n    TableScan: employee_csv projection=[id, state]";
 
         assert_eq!(expected, format!("{}", plan.display_indent()));
+        Ok(())
     }
 
     #[test]
-    fn test_display_indent_schema() {
-        let plan = display_plan();
+    fn test_display_indent_schema() -> Result<()> {
+        let plan = display_plan()?;
 
         let expected = "Projection: #employee_csv.id [id:Int32]\
-                        \n  Filter: #employee_csv.state = Utf8(\"CO\") 
[id:Int32, state:Utf8]\
-                        \n    TableScan: employee_csv projection=[id, state] 
[id:Int32, state:Utf8]";
+        \n  Filter: #employee_csv.state IN (<subquery>) [id:Int32, state:Utf8]\
+        \n    Subquery: [state:Utf8]\
+        \n      TableScan: employee_csv projection=[state] [state:Utf8]\
+        \n    TableScan: employee_csv projection=[id, state] [id:Int32, 
state:Utf8]";
 
         assert_eq!(expected, format!("{}", plan.display_indent_schema()));
+        Ok(())
     }
 
     #[test]
-    fn test_display_graphviz() {
-        let plan = display_plan();
+    fn test_display_graphviz() -> Result<()> {
+        let plan = display_plan()?;
 
         // just test for a few key lines in the output rather than the
         // whole thing to make test mainteance easier.
@@ -1435,6 +1488,7 @@ mod tests {
             "\n{}",
             plan.display_graphviz()
         );
+        Ok(())
     }
 
     /// Tests for the Visitor trait and walking logical plan nodes
diff --git a/datafusion/optimizer/src/filter_push_down.rs 
b/datafusion/optimizer/src/filter_push_down.rs
index c358ed534..2ac5b6e3b 100644
--- a/datafusion/optimizer/src/filter_push_down.rs
+++ b/datafusion/optimizer/src/filter_push_down.rs
@@ -2072,7 +2072,10 @@ mod tests {
 
         // filter on col b in subquery
         let expected_before = "\
-        Filter: #b IN (Subquery: Projection: #sq.c\n  TableScan: sq)\
+        Filter: #b IN (<subquery>)\
+        \n  Subquery:\
+        \n    Projection: #sq.c\
+        \n      TableScan: sq\
         \n  Projection: #test.a AS b, #test.c\
         \n    TableScan: test";
         assert_eq!(format!("{:?}", plan), expected_before);
@@ -2080,7 +2083,10 @@ mod tests {
         // rewrite filter col b to test.a
         let expected_after = "\
         Projection: #test.a AS b, #test.c\
-        \n  Filter: #test.a IN (Subquery: Projection: #sq.c\n  TableScan: sq)\
+        \n  Filter: #test.a IN (<subquery>)\
+        \n    Subquery:\
+        \n      Projection: #sq.c\
+        \n        TableScan: sq\
         \n    TableScan: test";
         assert_optimized_plan_eq(&plan, expected_after);
 
diff --git a/datafusion/optimizer/src/limit_push_down.rs 
b/datafusion/optimizer/src/limit_push_down.rs
index 9726be087..f92061b41 100644
--- a/datafusion/optimizer/src/limit_push_down.rs
+++ b/datafusion/optimizer/src/limit_push_down.rs
@@ -676,9 +676,11 @@ mod test {
 
         // Limit pushdown Not supported in sub_query
         let expected = "Limit: skip=10, fetch=100\
-        \n  Filter: EXISTS (Subquery: Filter: #test1.a = #test1.a\
-        \n  Projection: #test1.a\
-        \n    TableScan: test1)\
+        \n  Filter: EXISTS (<subquery>)\
+        \n    Subquery:\
+        \n      Filter: #test1.a = #test1.a\
+        \n        Projection: #test1.a\
+        \n          TableScan: test1\
         \n    Projection: #test2.a\
         \n      TableScan: test2";
 
@@ -705,9 +707,11 @@ mod test {
 
         // Limit pushdown Not supported in sub_query
         let expected = "Limit: skip=10, fetch=100\
-        \n  Filter: EXISTS (Subquery: Filter: #test1.a = #test1.a\
-        \n  Projection: #test1.a\
-        \n    TableScan: test1)\
+        \n  Filter: EXISTS (<subquery>)\
+        \n    Subquery:\
+        \n      Filter: #test1.a = #test1.a\
+        \n        Projection: #test1.a\
+        \n          TableScan: test1\
         \n    Projection: #test2.a\
         \n      TableScan: test2";
 
diff --git a/datafusion/optimizer/src/subquery_filter_to_join.rs 
b/datafusion/optimizer/src/subquery_filter_to_join.rs
index b173e425f..092f315bc 100644
--- a/datafusion/optimizer/src/subquery_filter_to_join.rs
+++ b/datafusion/optimizer/src/subquery_filter_to_join.rs
@@ -328,9 +328,10 @@ mod tests {
             .build()?;
 
         let expected = "Projection: #test.b [b:UInt32]\
-        \n  Filter: #test.a = UInt32(1) AND #test.b < UInt32(30) OR #test.c IN 
(\
-        Subquery: Projection: #sq.c\
-        \n  TableScan: sq) [a:UInt32, b:UInt32, c:UInt32]\
+        \n  Filter: #test.a = UInt32(1) AND #test.b < UInt32(30) OR #test.c IN 
(<subquery>) [a:UInt32, b:UInt32, c:UInt32]\
+        \n    Subquery: [c:UInt32]\
+        \n      Projection: #sq.c [c:UInt32]\
+        \n        TableScan: sq [a:UInt32, b:UInt32, c:UInt32]\
         \n    TableScan: test [a:UInt32, b:UInt32, c:UInt32]";
 
         assert_optimized_plan_eq(&plan, expected);
@@ -352,9 +353,13 @@ mod tests {
             .build()?;
 
         let expected = "Projection: #test.b [b:UInt32]\
-        \n  Filter: #test.a = UInt32(1) OR #test.b IN (Subquery: Projection: 
#sq1.c\
-            \n  TableScan: sq1) AND #test.c IN (Subquery: Projection: #sq2.c\
-            \n  TableScan: sq2) [a:UInt32, b:UInt32, c:UInt32]\
+        \n  Filter: #test.a = UInt32(1) OR #test.b IN (<subquery>) AND #test.c 
IN (<subquery>) [a:UInt32, b:UInt32, c:UInt32]\
+        \n    Subquery: [c:UInt32]\
+        \n      Projection: #sq1.c [c:UInt32]\
+        \n        TableScan: sq1 [a:UInt32, b:UInt32, c:UInt32]\
+        \n    Subquery: [c:UInt32]\
+        \n      Projection: #sq2.c [c:UInt32]\
+        \n        TableScan: sq2 [a:UInt32, b:UInt32, c:UInt32]\
         \n    TableScan: test [a:UInt32, b:UInt32, c:UInt32]";
 
         assert_optimized_plan_eq(&plan, expected);
@@ -405,9 +410,9 @@ mod tests {
             .build()?;
 
         let expected = "Projection: #wrapped.b [b:UInt32]\
-        \n  Filter: #wrapped.b < UInt32(30) OR #wrapped.c IN (\
-        Subquery: Projection: #sq_outer.c\
-        \n  TableScan: sq_outer) [b:UInt32, c:UInt32]\
+        \n  Filter: #wrapped.b < UInt32(30) OR #wrapped.c IN (<subquery>) 
[b:UInt32, c:UInt32]\
+        \n    Subquery: [c:UInt32]\n      Projection: #sq_outer.c [c:UInt32]\
+        \n        TableScan: sq_outer [a:UInt32, b:UInt32, c:UInt32]\
         \n    Projection: #test.b, #test.c, alias=wrapped [b:UInt32, c:UInt32]\
         \n      Semi Join: #test.c = #sq_inner.c [a:UInt32, b:UInt32, 
c:UInt32]\
         \n        TableScan: test [a:UInt32, b:UInt32, c:UInt32]\
diff --git a/datafusion/sql/src/planner.rs b/datafusion/sql/src/planner.rs
index 250b4e9c8..edabbf8f2 100644
--- a/datafusion/sql/src/planner.rs
+++ b/datafusion/sql/src/planner.rs
@@ -4657,18 +4657,15 @@ mod tests {
             WHERE last_name = p.last_name \
             AND state = p.state)";
 
-        let subquery_expected = "Subquery: Projection: #person.first_name\
-        \n  Filter: #person.last_name = #p.last_name AND #person.state = 
#p.state\
-        \n    TableScan: person";
-
-        let expected = format!(
-            "Projection: #p.id\
-        \n  Filter: EXISTS ({})\
+        let expected = "Projection: #p.id\
+        \n  Filter: EXISTS (<subquery>)\
+        \n    Subquery:\
+        \n      Projection: #person.first_name\
+        \n        Filter: #person.last_name = #p.last_name AND #person.state = 
#p.state\
+        \n          TableScan: person\
         \n    SubqueryAlias: p\
-        \n      TableScan: person",
-            subquery_expected
-        );
-        quick_test(sql, &expected);
+        \n      TableScan: person";
+        quick_test(sql, expected);
     }
 
     #[test]
@@ -4681,23 +4678,20 @@ mod tests {
             AND person.last_name = p.last_name \
             AND person.state = p.state)";
 
-        let subquery_expected = "Subquery: Projection: #person.first_name\
-        \n  Filter: #person.last_name = #p.last_name AND #person.state = 
#p.state\
-        \n    Inner Join: #person.id = #p2.id\
+        let expected = "Projection: #person.id\
+        \n  Filter: EXISTS (<subquery>)\
+        \n    Subquery:\
+        \n      Projection: #person.first_name\
+        \n        Filter: #person.last_name = #p.last_name AND #person.state = 
#p.state\
+        \n          Inner Join: #person.id = #p2.id\
+        \n            TableScan: person\
+        \n            SubqueryAlias: p2\
+        \n              TableScan: person\
+        \n    Inner Join: #person.id = #p.id\
         \n      TableScan: person\
-        \n      SubqueryAlias: p2\
+        \n      SubqueryAlias: p\
         \n        TableScan: person";
-
-        let expected = format!(
-            "Projection: #person.id\
-            \n  Filter: EXISTS ({})\
-            \n    Inner Join: #person.id = #p.id\
-            \n      TableScan: person\
-            \n      SubqueryAlias: p\
-            \n        TableScan: person",
-            subquery_expected
-        );
-        quick_test(sql, &expected);
+        quick_test(sql, expected);
     }
 
     #[test]
@@ -4707,19 +4701,15 @@ mod tests {
             WHERE last_name = p.last_name \
             AND state = p.state)";
 
-        let subquery_expected = "Subquery: Projection: #person.id, 
#person.first_name, \
-        #person.last_name, #person.age, #person.state, #person.salary, 
#person.birth_date, #person.😀\
-            \n  Filter: #person.last_name = #p.last_name AND #person.state = 
#p.state\
-            \n    TableScan: person";
-
-        let expected = format!(
-            "Projection: #p.id\
-            \n  Filter: EXISTS ({})\
-            \n    SubqueryAlias: p\
-            \n      TableScan: person",
-            subquery_expected
-        );
-        quick_test(sql, &expected);
+        let expected = "Projection: #p.id\
+        \n  Filter: EXISTS (<subquery>)\
+        \n    Subquery:\
+        \n      Projection: #person.id, #person.first_name, #person.last_name, 
#person.age, #person.state, #person.salary, #person.birth_date, #person.😀\
+        \n        Filter: #person.last_name = #p.last_name AND #person.state = 
#p.state\
+        \n          TableScan: person\
+        \n    SubqueryAlias: p\
+        \n      TableScan: person";
+        quick_test(sql, expected);
     }
 
     #[test]
@@ -4727,17 +4717,14 @@ mod tests {
         let sql = "SELECT id FROM person p WHERE id IN \
             (SELECT id FROM person)";
 
-        let subquery_expected = "Subquery: Projection: #person.id\
-        \n  TableScan: person";
-
-        let expected = format!(
-            "Projection: #p.id\
-            \n  Filter: #p.id IN ({})\
-            \n    SubqueryAlias: p\
-            \n      TableScan: person",
-            subquery_expected
-        );
-        quick_test(sql, &expected);
+        let expected = "Projection: #p.id\
+        \n  Filter: #p.id IN (<subquery>)\
+        \n    Subquery:\
+        \n      Projection: #person.id\
+        \n        TableScan: person\
+        \n    SubqueryAlias: p\
+        \n      TableScan: person";
+        quick_test(sql, expected);
     }
 
     #[test]
@@ -4745,36 +4732,30 @@ mod tests {
         let sql = "SELECT id FROM person p WHERE id NOT IN \
             (SELECT id FROM person WHERE last_name = p.last_name AND state = 
'CO')";
 
-        let subquery_expected = "Subquery: Projection: #person.id\
-        \n  Filter: #person.last_name = #p.last_name AND #person.state = 
Utf8(\"CO\")\
-        \n    TableScan: person";
-
-        let expected = format!(
-            "Projection: #p.id\
-            \n  Filter: #p.id NOT IN ({})\
-            \n    SubqueryAlias: p\
-            \n      TableScan: person",
-            subquery_expected
-        );
-        quick_test(sql, &expected);
+        let expected = "Projection: #p.id\
+        \n  Filter: #p.id NOT IN (<subquery>)\
+        \n    Subquery:\
+        \n      Projection: #person.id\
+        \n        Filter: #person.last_name = #p.last_name AND #person.state = 
Utf8(\"CO\")\
+        \n          TableScan: person\
+        \n    SubqueryAlias: p\
+        \n      TableScan: person";
+        quick_test(sql, expected);
     }
 
     #[test]
     fn scalar_subquery() {
         let sql = "SELECT p.id, (SELECT MAX(id) FROM person WHERE last_name = 
p.last_name) FROM person p";
 
-        let subquery_expected = "Subquery: Projection: #MAX(person.id)\
-        \n  Aggregate: groupBy=[[]], aggr=[[MAX(#person.id)]]\
-        \n    Filter: #person.last_name = #p.last_name\
-        \n      TableScan: person";
-
-        let expected = format!(
-            "Projection: #p.id, ({})\
-            \n  SubqueryAlias: p\
-            \n    TableScan: person",
-            subquery_expected
-        );
-        quick_test(sql, &expected);
+        let expected = "Projection: #p.id, (<subquery>)\
+        \n  Subquery:\
+        \n    Projection: #MAX(person.id)\
+        \n      Aggregate: groupBy=[[]], aggr=[[MAX(#person.id)]]\
+        \n        Filter: #person.last_name = #p.last_name\
+        \n          TableScan: person\
+        \n  SubqueryAlias: p\
+        \n    TableScan: person";
+        quick_test(sql, expected);
     }
 
     #[test]
@@ -4787,23 +4768,20 @@ mod tests {
             WHERE j2_id = j1_id \
             AND j1_id = j3_id)";
 
-        let subquery = "Subquery: Projection: #COUNT(UInt8(1))\
-            \n  Aggregate: groupBy=[[]], aggr=[[COUNT(UInt8(1))]]\
-            \n    Filter: #j2.j2_id = #j1.j1_id\
-            \n      Inner Join: #j1.j1_id = #j3.j3_id\
-            \n        TableScan: j1\
-            \n        TableScan: j3";
-
-        let expected = format!(
-            "Projection: #j1.j1_string, #j2.j2_string\
-            \n  Filter: #j1.j1_id = #j2.j2_id - Int64(1) AND #j2.j2_id < ({})\
-            \n    CrossJoin:\
-            \n      TableScan: j1\
-            \n      TableScan: j2",
-            subquery
-        );
+        let expected = "Projection: #j1.j1_string, #j2.j2_string\
+        \n  Filter: #j1.j1_id = #j2.j2_id - Int64(1) AND #j2.j2_id < 
(<subquery>)\
+        \n    Subquery:\
+        \n      Projection: #COUNT(UInt8(1))\
+        \n        Aggregate: groupBy=[[]], aggr=[[COUNT(UInt8(1))]]\
+        \n          Filter: #j2.j2_id = #j1.j1_id\
+        \n            Inner Join: #j1.j1_id = #j3.j3_id\
+        \n              TableScan: j1\
+        \n              TableScan: j3\
+        \n    CrossJoin:\
+        \n      TableScan: j1\
+        \n      TableScan: j2";
 
-        quick_test(sql, &expected);
+        quick_test(sql, expected);
     }
 
     #[tokio::test]
@@ -4812,16 +4790,16 @@ mod tests {
         cte AS (SELECT * FROM person) \
         SELECT * FROM person WHERE EXISTS (SELECT * FROM cte WHERE id = 
person.id)";
 
-        let subquery = "Subquery: Projection: #cte.id, #cte.first_name, 
#cte.last_name, #cte.age, #cte.state, #cte.salary, #cte.birth_date, #cte.😀\
-        \n  Filter: #cte.id = #person.id\
-        \n    Projection: #person.id, #person.first_name, #person.last_name, 
#person.age, #person.state, #person.salary, #person.birth_date, #person.😀, 
alias=cte\
-        \n      TableScan: person";
-
-        let expected = format!("Projection: #person.id, #person.first_name, 
#person.last_name, #person.age, #person.state, #person.salary, 
#person.birth_date, #person.😀\
-        \n  Filter: EXISTS ({})\
-        \n    TableScan: person", subquery);
+        let expected = "Projection: #person.id, #person.first_name, 
#person.last_name, #person.age, #person.state, #person.salary, 
#person.birth_date, #person.😀\
+        \n  Filter: EXISTS (<subquery>)\
+        \n    Subquery:\
+        \n      Projection: #cte.id, #cte.first_name, #cte.last_name, 
#cte.age, #cte.state, #cte.salary, #cte.birth_date, #cte.😀\
+        \n        Filter: #cte.id = #person.id\
+        \n          Projection: #person.id, #person.first_name, 
#person.last_name, #person.age, #person.state, #person.salary, 
#person.birth_date, #person.😀, alias=cte\
+        \n            TableScan: person\
+        \n    TableScan: person";
 
-        quick_test(sql, &expected)
+        quick_test(sql, expected)
     }
 
     #[tokio::test]

Reply via email to