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

alamb 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 cd96b26cae Migrate subtrait tests to insta, part1 (#15444)
cd96b26cae is described below

commit cd96b26cae392e3bdaf3cf3a25b7ba68c45fb641
Author: Tommy shu <[email protected]>
AuthorDate: Fri Mar 28 13:44:10 2025 -0400

    Migrate subtrait tests to insta, part1 (#15444)
    
    * add `cargo insta` to dev dependencies
    
    * migrate `consumer_intergration.rs` tests to `insta`
    
    * Revert "migrate `consumer_intergration.rs` tests to `insta`"
    
    This reverts commit c3be2ebfeaeb5afff841810e38eff657f1b86a3f.
    
    * migrate `consumer_integration.rs` to `insta` inline snapshot
    
    * migrate logical plans tests to use `insta` snapshots
    
    * migrate emit_kind_tests to use `insta` snapshots
    
    * migrate function_test to use `insta` snapshots for assertions
    
    * migrate substrait_validations tests to use insta snapshots, missing 
`insta` mapping to `assert!`
    
    * revert `handle_emit_as_project_without_volatile_exprs` back to 
`assert_eq!` and remove `format!` for `assert_snapshot!`
    
    * migrate function and validation tests to use plan directly in 
assert_snapshot!
    
    * migrate serialize tests to use insta snapshots for assertions
    
    * migrate logical_plans test to use insta snapshots for assertions
---
 Cargo.lock                                         |   1 +
 datafusion/substrait/Cargo.toml                    |   1 +
 .../substrait/tests/cases/consumer_integration.rs  | 608 +++++++++++----------
 .../substrait/tests/cases/emit_kind_tests.rs       |  72 +--
 datafusion/substrait/tests/cases/function_test.rs  |  17 +-
 datafusion/substrait/tests/cases/logical_plans.rs  |  80 +--
 datafusion/substrait/tests/cases/serialize.rs      |  29 +-
 .../substrait/tests/cases/substrait_validations.rs |  37 +-
 8 files changed, 462 insertions(+), 383 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 8019b7fe3d..8aba95bdcc 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2612,6 +2612,7 @@ dependencies = [
  "chrono",
  "datafusion",
  "datafusion-functions-aggregate",
+ "insta",
  "itertools 0.14.0",
  "object_store",
  "pbjson-types",
diff --git a/datafusion/substrait/Cargo.toml b/datafusion/substrait/Cargo.toml
index edc3b8d2f2..d23e986914 100644
--- a/datafusion/substrait/Cargo.toml
+++ b/datafusion/substrait/Cargo.toml
@@ -48,6 +48,7 @@ datafusion = { workspace = true, features = 
["nested_expressions"] }
 datafusion-functions-aggregate = { workspace = true }
 serde_json = "1.0"
 tokio = { workspace = true }
+insta = { workspace = true }
 
 [features]
 default = ["physical"]
diff --git a/datafusion/substrait/tests/cases/consumer_integration.rs 
b/datafusion/substrait/tests/cases/consumer_integration.rs
index 1f1a15abb8..af9d923782 100644
--- a/datafusion/substrait/tests/cases/consumer_integration.rs
+++ b/datafusion/substrait/tests/cases/consumer_integration.rs
@@ -28,6 +28,7 @@ mod tests {
     use datafusion::common::Result;
     use datafusion::prelude::SessionContext;
     use datafusion_substrait::logical_plan::consumer::from_substrait_plan;
+    use insta::assert_snapshot;
     use std::fs::File;
     use std::io::BufReader;
     use substrait::proto::Plan;
@@ -49,125 +50,137 @@ mod tests {
     #[tokio::test]
     async fn tpch_test_01() -> Result<()> {
         let plan_str = tpch_plan_to_string(1).await?;
-        assert_eq!(
-            plan_str,
-            "Projection: LINEITEM.L_RETURNFLAG, LINEITEM.L_LINESTATUS, 
sum(LINEITEM.L_QUANTITY) AS SUM_QTY, sum(LINEITEM.L_EXTENDEDPRICE) AS 
SUM_BASE_PRICE, sum(LINEITEM.L_EXTENDEDPRICE * Int32(1) - LINEITEM.L_DISCOUNT) 
AS SUM_DISC_PRICE, sum(LINEITEM.L_EXTENDEDPRICE * Int32(1) - 
LINEITEM.L_DISCOUNT * Int32(1) + LINEITEM.L_TAX) AS SUM_CHARGE, 
avg(LINEITEM.L_QUANTITY) AS AVG_QTY, avg(LINEITEM.L_EXTENDEDPRICE) AS 
AVG_PRICE, avg(LINEITEM.L_DISCOUNT) AS AVG_DISC, count(Int64(1)) AS COUNT_ORDER\
-            \n  Sort: LINEITEM.L_RETURNFLAG ASC NULLS LAST, 
LINEITEM.L_LINESTATUS ASC NULLS LAST\
-            \n    Aggregate: groupBy=[[LINEITEM.L_RETURNFLAG, 
LINEITEM.L_LINESTATUS]], aggr=[[sum(LINEITEM.L_QUANTITY), 
sum(LINEITEM.L_EXTENDEDPRICE), sum(LINEITEM.L_EXTENDEDPRICE * Int32(1) - 
LINEITEM.L_DISCOUNT), sum(LINEITEM.L_EXTENDEDPRICE * Int32(1) - 
LINEITEM.L_DISCOUNT * Int32(1) + LINEITEM.L_TAX), avg(LINEITEM.L_QUANTITY), 
avg(LINEITEM.L_EXTENDEDPRICE), avg(LINEITEM.L_DISCOUNT), count(Int64(1))]]\
-            \n      Projection: LINEITEM.L_RETURNFLAG, LINEITEM.L_LINESTATUS, 
LINEITEM.L_QUANTITY, LINEITEM.L_EXTENDEDPRICE, LINEITEM.L_EXTENDEDPRICE * 
(CAST(Int32(1) AS Decimal128(15, 2)) - LINEITEM.L_DISCOUNT), 
LINEITEM.L_EXTENDEDPRICE * (CAST(Int32(1) AS Decimal128(15, 2)) - 
LINEITEM.L_DISCOUNT) * (CAST(Int32(1) AS Decimal128(15, 2)) + LINEITEM.L_TAX), 
LINEITEM.L_DISCOUNT\
-            \n        Filter: LINEITEM.L_SHIPDATE <= Date32(\"1998-12-01\") - 
IntervalDayTime(\"IntervalDayTime { days: 0, milliseconds: 10368000 }\")\
-            \n          TableScan: LINEITEM"
-        );
+        assert_snapshot!(
+        plan_str,
+        @r#"
+            Projection: LINEITEM.L_RETURNFLAG, LINEITEM.L_LINESTATUS, 
sum(LINEITEM.L_QUANTITY) AS SUM_QTY, sum(LINEITEM.L_EXTENDEDPRICE) AS 
SUM_BASE_PRICE, sum(LINEITEM.L_EXTENDEDPRICE * Int32(1) - LINEITEM.L_DISCOUNT) 
AS SUM_DISC_PRICE, sum(LINEITEM.L_EXTENDEDPRICE * Int32(1) - 
LINEITEM.L_DISCOUNT * Int32(1) + LINEITEM.L_TAX) AS SUM_CHARGE, 
avg(LINEITEM.L_QUANTITY) AS AVG_QTY, avg(LINEITEM.L_EXTENDEDPRICE) AS 
AVG_PRICE, avg(LINEITEM.L_DISCOUNT) AS AVG_DISC, count(Int64(1)) AS COUNT_ORDER
+              Sort: LINEITEM.L_RETURNFLAG ASC NULLS LAST, 
LINEITEM.L_LINESTATUS ASC NULLS LAST
+                Aggregate: groupBy=[[LINEITEM.L_RETURNFLAG, 
LINEITEM.L_LINESTATUS]], aggr=[[sum(LINEITEM.L_QUANTITY), 
sum(LINEITEM.L_EXTENDEDPRICE), sum(LINEITEM.L_EXTENDEDPRICE * Int32(1) - 
LINEITEM.L_DISCOUNT), sum(LINEITEM.L_EXTENDEDPRICE * Int32(1) - 
LINEITEM.L_DISCOUNT * Int32(1) + LINEITEM.L_TAX), avg(LINEITEM.L_QUANTITY), 
avg(LINEITEM.L_EXTENDEDPRICE), avg(LINEITEM.L_DISCOUNT), count(Int64(1))]]
+                  Projection: LINEITEM.L_RETURNFLAG, LINEITEM.L_LINESTATUS, 
LINEITEM.L_QUANTITY, LINEITEM.L_EXTENDEDPRICE, LINEITEM.L_EXTENDEDPRICE * 
(CAST(Int32(1) AS Decimal128(15, 2)) - LINEITEM.L_DISCOUNT), 
LINEITEM.L_EXTENDEDPRICE * (CAST(Int32(1) AS Decimal128(15, 2)) - 
LINEITEM.L_DISCOUNT) * (CAST(Int32(1) AS Decimal128(15, 2)) + LINEITEM.L_TAX), 
LINEITEM.L_DISCOUNT
+                    Filter: LINEITEM.L_SHIPDATE <= Date32("1998-12-01") - 
IntervalDayTime("IntervalDayTime { days: 0, milliseconds: 10368000 }")
+                      TableScan: LINEITEM
+            "#
+                );
         Ok(())
     }
 
     #[tokio::test]
     async fn tpch_test_02() -> Result<()> {
         let plan_str = tpch_plan_to_string(2).await?;
-        assert_eq!(
-            plan_str,
-            "Limit: skip=0, fetch=100\
-            \n  Sort: SUPPLIER.S_ACCTBAL DESC NULLS FIRST, NATION.N_NAME ASC 
NULLS LAST, SUPPLIER.S_NAME ASC NULLS LAST, PART.P_PARTKEY ASC NULLS LAST\
-            \n    Projection: SUPPLIER.S_ACCTBAL, SUPPLIER.S_NAME, 
NATION.N_NAME, PART.P_PARTKEY, PART.P_MFGR, SUPPLIER.S_ADDRESS, 
SUPPLIER.S_PHONE, SUPPLIER.S_COMMENT\
-            \n      Filter: PART.P_PARTKEY = PARTSUPP.PS_PARTKEY AND 
SUPPLIER.S_SUPPKEY = PARTSUPP.PS_SUPPKEY AND PART.P_SIZE = Int32(15) AND 
PART.P_TYPE LIKE CAST(Utf8(\"%BRASS\") AS Utf8) AND SUPPLIER.S_NATIONKEY = 
NATION.N_NATIONKEY AND NATION.N_REGIONKEY = REGION.R_REGIONKEY AND 
REGION.R_NAME = Utf8(\"EUROPE\") AND PARTSUPP.PS_SUPPLYCOST = (<subquery>)\
-            \n        Subquery:\
-            \n          Aggregate: groupBy=[[]], 
aggr=[[min(PARTSUPP.PS_SUPPLYCOST)]]\
-            \n            Projection: PARTSUPP.PS_SUPPLYCOST\
-            \n              Filter: PARTSUPP.PS_PARTKEY = PARTSUPP.PS_PARTKEY 
AND SUPPLIER.S_SUPPKEY = PARTSUPP.PS_SUPPKEY AND SUPPLIER.S_NATIONKEY = 
NATION.N_NATIONKEY AND NATION.N_REGIONKEY = REGION.R_REGIONKEY AND 
REGION.R_NAME = Utf8(\"EUROPE\")\
-            \n                Cross Join: \
-            \n                  Cross Join: \
-            \n                    Cross Join: \
-            \n                      TableScan: PARTSUPP\
-            \n                      TableScan: SUPPLIER\
-            \n                    TableScan: NATION\
-            \n                  TableScan: REGION\
-            \n        Cross Join: \
-            \n          Cross Join: \
-            \n            Cross Join: \
-            \n              Cross Join: \
-            \n                TableScan: PART\
-            \n                TableScan: SUPPLIER\
-            \n              TableScan: PARTSUPP\
-            \n            TableScan: NATION\
-            \n          TableScan: REGION"
-        );
+        assert_snapshot!(
+        plan_str,
+        @r#"
+            Limit: skip=0, fetch=100
+              Sort: SUPPLIER.S_ACCTBAL DESC NULLS FIRST, NATION.N_NAME ASC 
NULLS LAST, SUPPLIER.S_NAME ASC NULLS LAST, PART.P_PARTKEY ASC NULLS LAST
+                Projection: SUPPLIER.S_ACCTBAL, SUPPLIER.S_NAME, 
NATION.N_NAME, PART.P_PARTKEY, PART.P_MFGR, SUPPLIER.S_ADDRESS, 
SUPPLIER.S_PHONE, SUPPLIER.S_COMMENT
+                  Filter: PART.P_PARTKEY = PARTSUPP.PS_PARTKEY AND 
SUPPLIER.S_SUPPKEY = PARTSUPP.PS_SUPPKEY AND PART.P_SIZE = Int32(15) AND 
PART.P_TYPE LIKE CAST(Utf8("%BRASS") AS Utf8) AND SUPPLIER.S_NATIONKEY = 
NATION.N_NATIONKEY AND NATION.N_REGIONKEY = REGION.R_REGIONKEY AND 
REGION.R_NAME = Utf8("EUROPE") AND PARTSUPP.PS_SUPPLYCOST = (<subquery>)
+                    Subquery:
+                      Aggregate: groupBy=[[]], 
aggr=[[min(PARTSUPP.PS_SUPPLYCOST)]]
+                        Projection: PARTSUPP.PS_SUPPLYCOST
+                          Filter: PARTSUPP.PS_PARTKEY = PARTSUPP.PS_PARTKEY 
AND SUPPLIER.S_SUPPKEY = PARTSUPP.PS_SUPPKEY AND SUPPLIER.S_NATIONKEY = 
NATION.N_NATIONKEY AND NATION.N_REGIONKEY = REGION.R_REGIONKEY AND 
REGION.R_NAME = Utf8("EUROPE")
+                            Cross Join: 
+                              Cross Join: 
+                                Cross Join: 
+                                  TableScan: PARTSUPP
+                                  TableScan: SUPPLIER
+                                TableScan: NATION
+                              TableScan: REGION
+                    Cross Join: 
+                      Cross Join: 
+                        Cross Join: 
+                          Cross Join: 
+                            TableScan: PART
+                            TableScan: SUPPLIER
+                          TableScan: PARTSUPP
+                        TableScan: NATION
+                      TableScan: REGION
+            "#
+                );
         Ok(())
     }
 
     #[tokio::test]
     async fn tpch_test_03() -> Result<()> {
         let plan_str = tpch_plan_to_string(3).await?;
-        assert_eq!(
-            plan_str,
-            "Projection: LINEITEM.L_ORDERKEY, sum(LINEITEM.L_EXTENDEDPRICE * 
Int32(1) - LINEITEM.L_DISCOUNT) AS REVENUE, ORDERS.O_ORDERDATE, 
ORDERS.O_SHIPPRIORITY\
-            \n  Limit: skip=0, fetch=10\
-            \n    Sort: sum(LINEITEM.L_EXTENDEDPRICE * Int32(1) - 
LINEITEM.L_DISCOUNT) DESC NULLS FIRST, ORDERS.O_ORDERDATE ASC NULLS LAST\
-            \n      Projection: LINEITEM.L_ORDERKEY, 
sum(LINEITEM.L_EXTENDEDPRICE * Int32(1) - LINEITEM.L_DISCOUNT), 
ORDERS.O_ORDERDATE, ORDERS.O_SHIPPRIORITY\
-            \n        Aggregate: groupBy=[[LINEITEM.L_ORDERKEY, 
ORDERS.O_ORDERDATE, ORDERS.O_SHIPPRIORITY]], 
aggr=[[sum(LINEITEM.L_EXTENDEDPRICE * Int32(1) - LINEITEM.L_DISCOUNT)]]\
-            \n          Projection: LINEITEM.L_ORDERKEY, ORDERS.O_ORDERDATE, 
ORDERS.O_SHIPPRIORITY, LINEITEM.L_EXTENDEDPRICE * (CAST(Int32(1) AS 
Decimal128(15, 2)) - LINEITEM.L_DISCOUNT)\
-            \n            Filter: CUSTOMER.C_MKTSEGMENT = Utf8(\"BUILDING\") 
AND CUSTOMER.C_CUSTKEY = ORDERS.O_CUSTKEY AND LINEITEM.L_ORDERKEY = 
ORDERS.O_ORDERKEY AND ORDERS.O_ORDERDATE < CAST(Utf8(\"1995-03-15\") AS Date32) 
AND LINEITEM.L_SHIPDATE > CAST(Utf8(\"1995-03-15\") AS Date32)\
-            \n              Cross Join: \
-            \n                Cross Join: \
-            \n                  TableScan: LINEITEM\
-            \n                  TableScan: CUSTOMER\
-            \n                TableScan: ORDERS"
-        );
+        assert_snapshot!(
+        plan_str,
+        @r#"
+            Projection: LINEITEM.L_ORDERKEY, sum(LINEITEM.L_EXTENDEDPRICE * 
Int32(1) - LINEITEM.L_DISCOUNT) AS REVENUE, ORDERS.O_ORDERDATE, 
ORDERS.O_SHIPPRIORITY
+              Limit: skip=0, fetch=10
+                Sort: sum(LINEITEM.L_EXTENDEDPRICE * Int32(1) - 
LINEITEM.L_DISCOUNT) DESC NULLS FIRST, ORDERS.O_ORDERDATE ASC NULLS LAST
+                  Projection: LINEITEM.L_ORDERKEY, 
sum(LINEITEM.L_EXTENDEDPRICE * Int32(1) - LINEITEM.L_DISCOUNT), 
ORDERS.O_ORDERDATE, ORDERS.O_SHIPPRIORITY
+                    Aggregate: groupBy=[[LINEITEM.L_ORDERKEY, 
ORDERS.O_ORDERDATE, ORDERS.O_SHIPPRIORITY]], 
aggr=[[sum(LINEITEM.L_EXTENDEDPRICE * Int32(1) - LINEITEM.L_DISCOUNT)]]
+                      Projection: LINEITEM.L_ORDERKEY, ORDERS.O_ORDERDATE, 
ORDERS.O_SHIPPRIORITY, LINEITEM.L_EXTENDEDPRICE * (CAST(Int32(1) AS 
Decimal128(15, 2)) - LINEITEM.L_DISCOUNT)
+                        Filter: CUSTOMER.C_MKTSEGMENT = Utf8("BUILDING") AND 
CUSTOMER.C_CUSTKEY = ORDERS.O_CUSTKEY AND LINEITEM.L_ORDERKEY = 
ORDERS.O_ORDERKEY AND ORDERS.O_ORDERDATE < CAST(Utf8("1995-03-15") AS Date32) 
AND LINEITEM.L_SHIPDATE > CAST(Utf8("1995-03-15") AS Date32)
+                          Cross Join: 
+                            Cross Join: 
+                              TableScan: LINEITEM
+                              TableScan: CUSTOMER
+                            TableScan: ORDERS
+            "#
+                );
         Ok(())
     }
 
     #[tokio::test]
     async fn tpch_test_04() -> Result<()> {
         let plan_str = tpch_plan_to_string(4).await?;
-        assert_eq!(
-            plan_str,
-            "Projection: ORDERS.O_ORDERPRIORITY, count(Int64(1)) AS 
ORDER_COUNT\
-            \n  Sort: ORDERS.O_ORDERPRIORITY ASC NULLS LAST\
-            \n    Aggregate: groupBy=[[ORDERS.O_ORDERPRIORITY]], 
aggr=[[count(Int64(1))]]\
-            \n      Projection: ORDERS.O_ORDERPRIORITY\
-            \n        Filter: ORDERS.O_ORDERDATE >= CAST(Utf8(\"1993-07-01\") 
AS Date32) AND ORDERS.O_ORDERDATE < CAST(Utf8(\"1993-10-01\") AS Date32) AND 
EXISTS (<subquery>)\
-            \n          Subquery:\
-            \n            Filter: LINEITEM.L_ORDERKEY = LINEITEM.L_ORDERKEY 
AND LINEITEM.L_COMMITDATE < LINEITEM.L_RECEIPTDATE\
-            \n              TableScan: LINEITEM\
-            \n          TableScan: ORDERS"
-        );
+        assert_snapshot!(
+        plan_str,
+        @r#"
+            Projection: ORDERS.O_ORDERPRIORITY, count(Int64(1)) AS ORDER_COUNT
+              Sort: ORDERS.O_ORDERPRIORITY ASC NULLS LAST
+                Aggregate: groupBy=[[ORDERS.O_ORDERPRIORITY]], 
aggr=[[count(Int64(1))]]
+                  Projection: ORDERS.O_ORDERPRIORITY
+                    Filter: ORDERS.O_ORDERDATE >= CAST(Utf8("1993-07-01") AS 
Date32) AND ORDERS.O_ORDERDATE < CAST(Utf8("1993-10-01") AS Date32) AND EXISTS 
(<subquery>)
+                      Subquery:
+                        Filter: LINEITEM.L_ORDERKEY = LINEITEM.L_ORDERKEY AND 
LINEITEM.L_COMMITDATE < LINEITEM.L_RECEIPTDATE
+                          TableScan: LINEITEM
+                      TableScan: ORDERS
+            "#
+                );
         Ok(())
     }
 
     #[tokio::test]
     async fn tpch_test_05() -> Result<()> {
         let plan_str = tpch_plan_to_string(5).await?;
-        assert_eq!(
-            plan_str,
-            "Projection: NATION.N_NAME, sum(LINEITEM.L_EXTENDEDPRICE * 
Int32(1) - LINEITEM.L_DISCOUNT) AS REVENUE\
-            \n  Sort: sum(LINEITEM.L_EXTENDEDPRICE * Int32(1) - 
LINEITEM.L_DISCOUNT) DESC NULLS FIRST\
-            \n    Aggregate: groupBy=[[NATION.N_NAME]], 
aggr=[[sum(LINEITEM.L_EXTENDEDPRICE * Int32(1) - LINEITEM.L_DISCOUNT)]]\
-            \n      Projection: NATION.N_NAME, LINEITEM.L_EXTENDEDPRICE * 
(CAST(Int32(1) AS Decimal128(15, 2)) - LINEITEM.L_DISCOUNT)\
-            \n        Filter: CUSTOMER.C_CUSTKEY = ORDERS.O_CUSTKEY AND 
LINEITEM.L_ORDERKEY = ORDERS.O_ORDERKEY AND LINEITEM.L_SUPPKEY = 
SUPPLIER.S_SUPPKEY AND CUSTOMER.C_NATIONKEY = SUPPLIER.S_NATIONKEY AND 
SUPPLIER.S_NATIONKEY = NATION.N_NATIONKEY AND NATION.N_REGIONKEY = 
REGION.R_REGIONKEY AND REGION.R_NAME = Utf8(\"ASIA\") AND ORDERS.O_ORDERDATE >= 
CAST(Utf8(\"1994-01-01\") AS Date32) AND ORDERS.O_ORDERDATE < 
CAST(Utf8(\"1995-01-01\") AS Date32)\
-            \n          Cross Join: \
-            \n            Cross Join: \
-            \n              Cross Join: \
-            \n                Cross Join: \
-            \n                  Cross Join: \
-            \n                    TableScan: CUSTOMER\
-            \n                    TableScan: ORDERS\
-            \n                  TableScan: LINEITEM\
-            \n                TableScan: SUPPLIER\
-            \n              TableScan: NATION\
-            \n            TableScan: REGION"
-        );
+        assert_snapshot!(
+        plan_str,
+        @r#"
+            Projection: NATION.N_NAME, sum(LINEITEM.L_EXTENDEDPRICE * Int32(1) 
- LINEITEM.L_DISCOUNT) AS REVENUE
+              Sort: sum(LINEITEM.L_EXTENDEDPRICE * Int32(1) - 
LINEITEM.L_DISCOUNT) DESC NULLS FIRST
+                Aggregate: groupBy=[[NATION.N_NAME]], 
aggr=[[sum(LINEITEM.L_EXTENDEDPRICE * Int32(1) - LINEITEM.L_DISCOUNT)]]
+                  Projection: NATION.N_NAME, LINEITEM.L_EXTENDEDPRICE * 
(CAST(Int32(1) AS Decimal128(15, 2)) - LINEITEM.L_DISCOUNT)
+                    Filter: CUSTOMER.C_CUSTKEY = ORDERS.O_CUSTKEY AND 
LINEITEM.L_ORDERKEY = ORDERS.O_ORDERKEY AND LINEITEM.L_SUPPKEY = 
SUPPLIER.S_SUPPKEY AND CUSTOMER.C_NATIONKEY = SUPPLIER.S_NATIONKEY AND 
SUPPLIER.S_NATIONKEY = NATION.N_NATIONKEY AND NATION.N_REGIONKEY = 
REGION.R_REGIONKEY AND REGION.R_NAME = Utf8("ASIA") AND ORDERS.O_ORDERDATE >= 
CAST(Utf8("1994-01-01") AS Date32) AND ORDERS.O_ORDERDATE < 
CAST(Utf8("1995-01-01") AS Date32)
+                      Cross Join: 
+                        Cross Join: 
+                          Cross Join: 
+                            Cross Join: 
+                              Cross Join: 
+                                TableScan: CUSTOMER
+                                TableScan: ORDERS
+                              TableScan: LINEITEM
+                            TableScan: SUPPLIER
+                          TableScan: NATION
+                        TableScan: REGION
+            "#
+                );
         Ok(())
     }
 
     #[tokio::test]
     async fn tpch_test_06() -> Result<()> {
         let plan_str = tpch_plan_to_string(6).await?;
-        assert_eq!(
-            plan_str,
-             "Aggregate: groupBy=[[]], aggr=[[sum(LINEITEM.L_EXTENDEDPRICE * 
LINEITEM.L_DISCOUNT) AS REVENUE]]\
-            \n  Projection: LINEITEM.L_EXTENDEDPRICE * LINEITEM.L_DISCOUNT\
-            \n    Filter: LINEITEM.L_SHIPDATE >= CAST(Utf8(\"1994-01-01\") AS 
Date32) AND LINEITEM.L_SHIPDATE < CAST(Utf8(\"1995-01-01\") AS Date32) AND 
LINEITEM.L_DISCOUNT >= Decimal128(Some(5),3,2) AND LINEITEM.L_DISCOUNT <= 
Decimal128(Some(7),3,2) AND LINEITEM.L_QUANTITY < CAST(Int32(24) AS 
Decimal128(15, 2))\
-            \n      TableScan: LINEITEM"
-        );
+        assert_snapshot!(
+        plan_str,
+        @r#"
+            Aggregate: groupBy=[[]], aggr=[[sum(LINEITEM.L_EXTENDEDPRICE * 
LINEITEM.L_DISCOUNT) AS REVENUE]]
+              Projection: LINEITEM.L_EXTENDEDPRICE * LINEITEM.L_DISCOUNT
+                Filter: LINEITEM.L_SHIPDATE >= CAST(Utf8("1994-01-01") AS 
Date32) AND LINEITEM.L_SHIPDATE < CAST(Utf8("1995-01-01") AS Date32) AND 
LINEITEM.L_DISCOUNT >= Decimal128(Some(5),3,2) AND LINEITEM.L_DISCOUNT <= 
Decimal128(Some(7),3,2) AND LINEITEM.L_QUANTITY < CAST(Int32(24) AS 
Decimal128(15, 2))
+                  TableScan: LINEITEM
+            "#
+                );
         Ok(())
     }
 
@@ -175,7 +188,7 @@ mod tests {
     #[tokio::test]
     async fn tpch_test_07() -> Result<()> {
         let plan_str = tpch_plan_to_string(7).await?;
-        assert_eq!(plan_str, "Missing support for enum function arguments");
+        assert_snapshot!(plan_str, "Missing support for enum function 
arguments");
         Ok(())
     }
 
@@ -183,7 +196,7 @@ mod tests {
     #[tokio::test]
     async fn tpch_test_08() -> Result<()> {
         let plan_str = tpch_plan_to_string(8).await?;
-        assert_eq!(plan_str, "Missing support for enum function arguments");
+        assert_snapshot!(plan_str, "Missing support for enum function 
arguments");
         Ok(())
     }
 
@@ -191,112 +204,121 @@ mod tests {
     #[tokio::test]
     async fn tpch_test_09() -> Result<()> {
         let plan_str = tpch_plan_to_string(9).await?;
-        assert_eq!(plan_str, "Missing support for enum function arguments");
+        assert_snapshot!(plan_str, "Missing support for enum function 
arguments");
         Ok(())
     }
 
     #[tokio::test]
     async fn tpch_test_10() -> Result<()> {
         let plan_str = tpch_plan_to_string(10).await?;
-        assert_eq!(
-            plan_str,
-            "Projection: CUSTOMER.C_CUSTKEY, CUSTOMER.C_NAME, 
sum(LINEITEM.L_EXTENDEDPRICE * Int32(1) - LINEITEM.L_DISCOUNT) AS REVENUE, 
CUSTOMER.C_ACCTBAL, NATION.N_NAME, CUSTOMER.C_ADDRESS, CUSTOMER.C_PHONE, 
CUSTOMER.C_COMMENT\
-            \n  Limit: skip=0, fetch=20\
-            \n    Sort: sum(LINEITEM.L_EXTENDEDPRICE * Int32(1) - 
LINEITEM.L_DISCOUNT) DESC NULLS FIRST\
-            \n      Projection: CUSTOMER.C_CUSTKEY, CUSTOMER.C_NAME, 
sum(LINEITEM.L_EXTENDEDPRICE * Int32(1) - LINEITEM.L_DISCOUNT), 
CUSTOMER.C_ACCTBAL, NATION.N_NAME, CUSTOMER.C_ADDRESS, CUSTOMER.C_PHONE, 
CUSTOMER.C_COMMENT\
-            \n        Aggregate: groupBy=[[CUSTOMER.C_CUSTKEY, 
CUSTOMER.C_NAME, CUSTOMER.C_ACCTBAL, CUSTOMER.C_PHONE, NATION.N_NAME, 
CUSTOMER.C_ADDRESS, CUSTOMER.C_COMMENT]], aggr=[[sum(LINEITEM.L_EXTENDEDPRICE * 
Int32(1) - LINEITEM.L_DISCOUNT)]]\
-            \n          Projection: CUSTOMER.C_CUSTKEY, CUSTOMER.C_NAME, 
CUSTOMER.C_ACCTBAL, CUSTOMER.C_PHONE, NATION.N_NAME, CUSTOMER.C_ADDRESS, 
CUSTOMER.C_COMMENT, LINEITEM.L_EXTENDEDPRICE * (CAST(Int32(1) AS Decimal128(15, 
2)) - LINEITEM.L_DISCOUNT)\
-            \n            Filter: CUSTOMER.C_CUSTKEY = ORDERS.O_CUSTKEY AND 
LINEITEM.L_ORDERKEY = ORDERS.O_ORDERKEY AND ORDERS.O_ORDERDATE >= 
CAST(Utf8(\"1993-10-01\") AS Date32) AND ORDERS.O_ORDERDATE < 
CAST(Utf8(\"1994-01-01\") AS Date32) AND LINEITEM.L_RETURNFLAG = Utf8(\"R\") 
AND CUSTOMER.C_NATIONKEY = NATION.N_NATIONKEY\
-            \n              Cross Join: \
-            \n                Cross Join: \
-            \n                  Cross Join: \
-            \n                    TableScan: CUSTOMER\
-            \n                    TableScan: ORDERS\
-            \n                  TableScan: LINEITEM\
-            \n                TableScan: NATION"
-        );
+        assert_snapshot!(
+        plan_str,
+        @r#"
+            Projection: CUSTOMER.C_CUSTKEY, CUSTOMER.C_NAME, 
sum(LINEITEM.L_EXTENDEDPRICE * Int32(1) - LINEITEM.L_DISCOUNT) AS REVENUE, 
CUSTOMER.C_ACCTBAL, NATION.N_NAME, CUSTOMER.C_ADDRESS, CUSTOMER.C_PHONE, 
CUSTOMER.C_COMMENT
+              Limit: skip=0, fetch=20
+                Sort: sum(LINEITEM.L_EXTENDEDPRICE * Int32(1) - 
LINEITEM.L_DISCOUNT) DESC NULLS FIRST
+                  Projection: CUSTOMER.C_CUSTKEY, CUSTOMER.C_NAME, 
sum(LINEITEM.L_EXTENDEDPRICE * Int32(1) - LINEITEM.L_DISCOUNT), 
CUSTOMER.C_ACCTBAL, NATION.N_NAME, CUSTOMER.C_ADDRESS, CUSTOMER.C_PHONE, 
CUSTOMER.C_COMMENT
+                    Aggregate: groupBy=[[CUSTOMER.C_CUSTKEY, CUSTOMER.C_NAME, 
CUSTOMER.C_ACCTBAL, CUSTOMER.C_PHONE, NATION.N_NAME, CUSTOMER.C_ADDRESS, 
CUSTOMER.C_COMMENT]], aggr=[[sum(LINEITEM.L_EXTENDEDPRICE * Int32(1) - 
LINEITEM.L_DISCOUNT)]]
+                      Projection: CUSTOMER.C_CUSTKEY, CUSTOMER.C_NAME, 
CUSTOMER.C_ACCTBAL, CUSTOMER.C_PHONE, NATION.N_NAME, CUSTOMER.C_ADDRESS, 
CUSTOMER.C_COMMENT, LINEITEM.L_EXTENDEDPRICE * (CAST(Int32(1) AS Decimal128(15, 
2)) - LINEITEM.L_DISCOUNT)
+                        Filter: CUSTOMER.C_CUSTKEY = ORDERS.O_CUSTKEY AND 
LINEITEM.L_ORDERKEY = ORDERS.O_ORDERKEY AND ORDERS.O_ORDERDATE >= 
CAST(Utf8("1993-10-01") AS Date32) AND ORDERS.O_ORDERDATE < 
CAST(Utf8("1994-01-01") AS Date32) AND LINEITEM.L_RETURNFLAG = Utf8("R") AND 
CUSTOMER.C_NATIONKEY = NATION.N_NATIONKEY
+                          Cross Join: 
+                            Cross Join: 
+                              Cross Join: 
+                                TableScan: CUSTOMER
+                                TableScan: ORDERS
+                              TableScan: LINEITEM
+                            TableScan: NATION
+            "#
+                );
         Ok(())
     }
 
     #[tokio::test]
     async fn tpch_test_11() -> Result<()> {
         let plan_str = tpch_plan_to_string(11).await?;
-        assert_eq!(
-            plan_str,
-            "Projection: PARTSUPP.PS_PARTKEY, sum(PARTSUPP.PS_SUPPLYCOST * 
PARTSUPP.PS_AVAILQTY) AS value\
-            \n  Sort: sum(PARTSUPP.PS_SUPPLYCOST * PARTSUPP.PS_AVAILQTY) DESC 
NULLS FIRST\
-            \n    Filter: sum(PARTSUPP.PS_SUPPLYCOST * PARTSUPP.PS_AVAILQTY) > 
(<subquery>)\
-            \n      Subquery:\
-            \n        Projection: sum(PARTSUPP.PS_SUPPLYCOST * 
PARTSUPP.PS_AVAILQTY) * Decimal128(Some(1000000),11,10)\
-            \n          Aggregate: groupBy=[[]], 
aggr=[[sum(PARTSUPP.PS_SUPPLYCOST * PARTSUPP.PS_AVAILQTY)]]\
-            \n            Projection: PARTSUPP.PS_SUPPLYCOST * 
CAST(PARTSUPP.PS_AVAILQTY AS Decimal128(19, 0))\
-            \n              Filter: PARTSUPP.PS_SUPPKEY = SUPPLIER.S_SUPPKEY 
AND SUPPLIER.S_NATIONKEY = NATION.N_NATIONKEY AND NATION.N_NAME = 
Utf8(\"JAPAN\")\
-            \n                Cross Join: \
-            \n                  Cross Join: \
-            \n                    TableScan: PARTSUPP\
-            \n                    TableScan: SUPPLIER\
-            \n                  TableScan: NATION\
-            \n      Aggregate: groupBy=[[PARTSUPP.PS_PARTKEY]], 
aggr=[[sum(PARTSUPP.PS_SUPPLYCOST * PARTSUPP.PS_AVAILQTY)]]\
-            \n        Projection: PARTSUPP.PS_PARTKEY, PARTSUPP.PS_SUPPLYCOST 
* CAST(PARTSUPP.PS_AVAILQTY AS Decimal128(19, 0))\
-            \n          Filter: PARTSUPP.PS_SUPPKEY = SUPPLIER.S_SUPPKEY AND 
SUPPLIER.S_NATIONKEY = NATION.N_NATIONKEY AND NATION.N_NAME = Utf8(\"JAPAN\")\
-            \n            Cross Join: \
-            \n              Cross Join: \
-            \n                TableScan: PARTSUPP\
-            \n                TableScan: SUPPLIER\
-            \n              TableScan: NATION"
-        );
+        assert_snapshot!(
+        plan_str,
+        @r#"
+            Projection: PARTSUPP.PS_PARTKEY, sum(PARTSUPP.PS_SUPPLYCOST * 
PARTSUPP.PS_AVAILQTY) AS value
+              Sort: sum(PARTSUPP.PS_SUPPLYCOST * PARTSUPP.PS_AVAILQTY) DESC 
NULLS FIRST
+                Filter: sum(PARTSUPP.PS_SUPPLYCOST * PARTSUPP.PS_AVAILQTY) > 
(<subquery>)
+                  Subquery:
+                    Projection: sum(PARTSUPP.PS_SUPPLYCOST * 
PARTSUPP.PS_AVAILQTY) * Decimal128(Some(1000000),11,10)
+                      Aggregate: groupBy=[[]], 
aggr=[[sum(PARTSUPP.PS_SUPPLYCOST * PARTSUPP.PS_AVAILQTY)]]
+                        Projection: PARTSUPP.PS_SUPPLYCOST * 
CAST(PARTSUPP.PS_AVAILQTY AS Decimal128(19, 0))
+                          Filter: PARTSUPP.PS_SUPPKEY = SUPPLIER.S_SUPPKEY AND 
SUPPLIER.S_NATIONKEY = NATION.N_NATIONKEY AND NATION.N_NAME = Utf8("JAPAN")
+                            Cross Join: 
+                              Cross Join: 
+                                TableScan: PARTSUPP
+                                TableScan: SUPPLIER
+                              TableScan: NATION
+                  Aggregate: groupBy=[[PARTSUPP.PS_PARTKEY]], 
aggr=[[sum(PARTSUPP.PS_SUPPLYCOST * PARTSUPP.PS_AVAILQTY)]]
+                    Projection: PARTSUPP.PS_PARTKEY, PARTSUPP.PS_SUPPLYCOST * 
CAST(PARTSUPP.PS_AVAILQTY AS Decimal128(19, 0))
+                      Filter: PARTSUPP.PS_SUPPKEY = SUPPLIER.S_SUPPKEY AND 
SUPPLIER.S_NATIONKEY = NATION.N_NATIONKEY AND NATION.N_NAME = Utf8("JAPAN")
+                        Cross Join: 
+                          Cross Join: 
+                            TableScan: PARTSUPP
+                            TableScan: SUPPLIER
+                          TableScan: NATION
+            "#
+                );
         Ok(())
     }
 
     #[tokio::test]
     async fn tpch_test_12() -> Result<()> {
         let plan_str = tpch_plan_to_string(12).await?;
-        assert_eq!(
-            plan_str,
-            "Projection: LINEITEM.L_SHIPMODE, sum(CASE WHEN 
ORDERS.O_ORDERPRIORITY = Utf8(\"1-URGENT\") OR ORDERS.O_ORDERPRIORITY = 
Utf8(\"2-HIGH\") THEN Int32(1) ELSE Int32(0) END) AS HIGH_LINE_COUNT, sum(CASE 
WHEN ORDERS.O_ORDERPRIORITY != Utf8(\"1-URGENT\") AND ORDERS.O_ORDERPRIORITY != 
Utf8(\"2-HIGH\") THEN Int32(1) ELSE Int32(0) END) AS LOW_LINE_COUNT\
-            \n  Sort: LINEITEM.L_SHIPMODE ASC NULLS LAST\
-            \n    Aggregate: groupBy=[[LINEITEM.L_SHIPMODE]], aggr=[[sum(CASE 
WHEN ORDERS.O_ORDERPRIORITY = Utf8(\"1-URGENT\") OR ORDERS.O_ORDERPRIORITY = 
Utf8(\"2-HIGH\") THEN Int32(1) ELSE Int32(0) END), sum(CASE WHEN 
ORDERS.O_ORDERPRIORITY != Utf8(\"1-URGENT\") AND ORDERS.O_ORDERPRIORITY != 
Utf8(\"2-HIGH\") THEN Int32(1) ELSE Int32(0) END)]]\
-            \n      Projection: LINEITEM.L_SHIPMODE, CASE WHEN 
ORDERS.O_ORDERPRIORITY = Utf8(\"1-URGENT\") OR ORDERS.O_ORDERPRIORITY = 
Utf8(\"2-HIGH\") THEN Int32(1) ELSE Int32(0) END, CASE WHEN 
ORDERS.O_ORDERPRIORITY != Utf8(\"1-URGENT\") AND ORDERS.O_ORDERPRIORITY != 
Utf8(\"2-HIGH\") THEN Int32(1) ELSE Int32(0) END\
-            \n        Filter: ORDERS.O_ORDERKEY = LINEITEM.L_ORDERKEY AND 
(LINEITEM.L_SHIPMODE = CAST(Utf8(\"MAIL\") AS Utf8) OR LINEITEM.L_SHIPMODE = 
CAST(Utf8(\"SHIP\") AS Utf8)) AND LINEITEM.L_COMMITDATE < 
LINEITEM.L_RECEIPTDATE AND LINEITEM.L_SHIPDATE < LINEITEM.L_COMMITDATE AND 
LINEITEM.L_RECEIPTDATE >= CAST(Utf8(\"1994-01-01\") AS Date32) AND 
LINEITEM.L_RECEIPTDATE < CAST(Utf8(\"1995-01-01\") AS Date32)\
-            \n          Cross Join: \
-            \n            TableScan: ORDERS\
-            \n            TableScan: LINEITEM"
-        );
+        assert_snapshot!(
+        plan_str,
+        @r#"
+            Projection: LINEITEM.L_SHIPMODE, sum(CASE WHEN 
ORDERS.O_ORDERPRIORITY = Utf8("1-URGENT") OR ORDERS.O_ORDERPRIORITY = 
Utf8("2-HIGH") THEN Int32(1) ELSE Int32(0) END) AS HIGH_LINE_COUNT, sum(CASE 
WHEN ORDERS.O_ORDERPRIORITY != Utf8("1-URGENT") AND ORDERS.O_ORDERPRIORITY != 
Utf8("2-HIGH") THEN Int32(1) ELSE Int32(0) END) AS LOW_LINE_COUNT
+              Sort: LINEITEM.L_SHIPMODE ASC NULLS LAST
+                Aggregate: groupBy=[[LINEITEM.L_SHIPMODE]], aggr=[[sum(CASE 
WHEN ORDERS.O_ORDERPRIORITY = Utf8("1-URGENT") OR ORDERS.O_ORDERPRIORITY = 
Utf8("2-HIGH") THEN Int32(1) ELSE Int32(0) END), sum(CASE WHEN 
ORDERS.O_ORDERPRIORITY != Utf8("1-URGENT") AND ORDERS.O_ORDERPRIORITY != 
Utf8("2-HIGH") THEN Int32(1) ELSE Int32(0) END)]]
+                  Projection: LINEITEM.L_SHIPMODE, CASE WHEN 
ORDERS.O_ORDERPRIORITY = Utf8("1-URGENT") OR ORDERS.O_ORDERPRIORITY = 
Utf8("2-HIGH") THEN Int32(1) ELSE Int32(0) END, CASE WHEN 
ORDERS.O_ORDERPRIORITY != Utf8("1-URGENT") AND ORDERS.O_ORDERPRIORITY != 
Utf8("2-HIGH") THEN Int32(1) ELSE Int32(0) END
+                    Filter: ORDERS.O_ORDERKEY = LINEITEM.L_ORDERKEY AND 
(LINEITEM.L_SHIPMODE = CAST(Utf8("MAIL") AS Utf8) OR LINEITEM.L_SHIPMODE = 
CAST(Utf8("SHIP") AS Utf8)) AND LINEITEM.L_COMMITDATE < LINEITEM.L_RECEIPTDATE 
AND LINEITEM.L_SHIPDATE < LINEITEM.L_COMMITDATE AND LINEITEM.L_RECEIPTDATE >= 
CAST(Utf8("1994-01-01") AS Date32) AND LINEITEM.L_RECEIPTDATE < 
CAST(Utf8("1995-01-01") AS Date32)
+                      Cross Join: 
+                        TableScan: ORDERS
+                        TableScan: LINEITEM
+            "#
+                );
         Ok(())
     }
 
     #[tokio::test]
     async fn tpch_test_13() -> Result<()> {
         let plan_str = tpch_plan_to_string(13).await?;
-        assert_eq!(
+        assert_snapshot!(
             plan_str,
-            "Projection: count(ORDERS.O_ORDERKEY) AS C_COUNT, count(Int64(1)) 
AS CUSTDIST\
-            \n  Sort: count(Int64(1)) DESC NULLS FIRST, 
count(ORDERS.O_ORDERKEY) DESC NULLS FIRST\
-            \n    Projection: count(ORDERS.O_ORDERKEY), count(Int64(1))\
-            \n      Aggregate: groupBy=[[count(ORDERS.O_ORDERKEY)]], 
aggr=[[count(Int64(1))]]\
-            \n        Projection: count(ORDERS.O_ORDERKEY)\
-            \n          Aggregate: groupBy=[[CUSTOMER.C_CUSTKEY]], 
aggr=[[count(ORDERS.O_ORDERKEY)]]\
-            \n            Projection: CUSTOMER.C_CUSTKEY, ORDERS.O_ORDERKEY\
-            \n              Left Join: CUSTOMER.C_CUSTKEY = ORDERS.O_CUSTKEY 
Filter: NOT ORDERS.O_COMMENT LIKE CAST(Utf8(\"%special%requests%\") AS Utf8)\
-            \n                TableScan: CUSTOMER\
-            \n                TableScan: ORDERS"
-        );
+            @r#"
+            Projection: count(ORDERS.O_ORDERKEY) AS C_COUNT, count(Int64(1)) 
AS CUSTDIST
+              Sort: count(Int64(1)) DESC NULLS FIRST, count(ORDERS.O_ORDERKEY) 
DESC NULLS FIRST
+                Projection: count(ORDERS.O_ORDERKEY), count(Int64(1))
+                  Aggregate: groupBy=[[count(ORDERS.O_ORDERKEY)]], 
aggr=[[count(Int64(1))]]
+                    Projection: count(ORDERS.O_ORDERKEY)
+                      Aggregate: groupBy=[[CUSTOMER.C_CUSTKEY]], 
aggr=[[count(ORDERS.O_ORDERKEY)]]
+                        Projection: CUSTOMER.C_CUSTKEY, ORDERS.O_ORDERKEY
+                          Left Join: CUSTOMER.C_CUSTKEY = ORDERS.O_CUSTKEY 
Filter: NOT ORDERS.O_COMMENT LIKE CAST(Utf8("%special%requests%") AS Utf8)
+                            TableScan: CUSTOMER
+                            TableScan: ORDERS
+            "#        );
         Ok(())
     }
 
     #[tokio::test]
     async fn tpch_test_14() -> Result<()> {
         let plan_str = tpch_plan_to_string(14).await?;
-        assert_eq!(
-            plan_str,
-            "Projection: Decimal128(Some(10000),5,2) * sum(CASE WHEN 
PART.P_TYPE LIKE Utf8(\"PROMO%\") THEN LINEITEM.L_EXTENDEDPRICE * Int32(1) - 
LINEITEM.L_DISCOUNT ELSE Decimal128(Some(0),19,4) END) / 
sum(LINEITEM.L_EXTENDEDPRICE * Int32(1) - LINEITEM.L_DISCOUNT) AS PROMO_REVENUE\
-            \n  Aggregate: groupBy=[[]], aggr=[[sum(CASE WHEN PART.P_TYPE LIKE 
Utf8(\"PROMO%\") THEN LINEITEM.L_EXTENDEDPRICE * Int32(1) - LINEITEM.L_DISCOUNT 
ELSE Decimal128(Some(0),19,4) END), sum(LINEITEM.L_EXTENDEDPRICE * Int32(1) - 
LINEITEM.L_DISCOUNT)]]\
-            \n    Projection: CASE WHEN PART.P_TYPE LIKE CAST(Utf8(\"PROMO%\") 
AS Utf8) THEN LINEITEM.L_EXTENDEDPRICE * (CAST(Int32(1) AS Decimal128(15, 2)) - 
LINEITEM.L_DISCOUNT) ELSE Decimal128(Some(0),19,4) END, 
LINEITEM.L_EXTENDEDPRICE * (CAST(Int32(1) AS Decimal128(15, 2)) - 
LINEITEM.L_DISCOUNT)\
-            \n      Filter: LINEITEM.L_PARTKEY = PART.P_PARTKEY AND 
LINEITEM.L_SHIPDATE >= Date32(\"1995-09-01\") AND LINEITEM.L_SHIPDATE < 
CAST(Utf8(\"1995-10-01\") AS Date32)\
-            \n        Cross Join: \
-            \n          TableScan: LINEITEM\
-            \n          TableScan: PART"
-        );
+        assert_snapshot!(
+        plan_str,
+        @r#"
+            Projection: Decimal128(Some(10000),5,2) * sum(CASE WHEN 
PART.P_TYPE LIKE Utf8("PROMO%") THEN LINEITEM.L_EXTENDEDPRICE * Int32(1) - 
LINEITEM.L_DISCOUNT ELSE Decimal128(Some(0),19,4) END) / 
sum(LINEITEM.L_EXTENDEDPRICE * Int32(1) - LINEITEM.L_DISCOUNT) AS PROMO_REVENUE
+              Aggregate: groupBy=[[]], aggr=[[sum(CASE WHEN PART.P_TYPE LIKE 
Utf8("PROMO%") THEN LINEITEM.L_EXTENDEDPRICE * Int32(1) - LINEITEM.L_DISCOUNT 
ELSE Decimal128(Some(0),19,4) END), sum(LINEITEM.L_EXTENDEDPRICE * Int32(1) - 
LINEITEM.L_DISCOUNT)]]
+                Projection: CASE WHEN PART.P_TYPE LIKE CAST(Utf8("PROMO%") AS 
Utf8) THEN LINEITEM.L_EXTENDEDPRICE * (CAST(Int32(1) AS Decimal128(15, 2)) - 
LINEITEM.L_DISCOUNT) ELSE Decimal128(Some(0),19,4) END, 
LINEITEM.L_EXTENDEDPRICE * (CAST(Int32(1) AS Decimal128(15, 2)) - 
LINEITEM.L_DISCOUNT)
+                  Filter: LINEITEM.L_PARTKEY = PART.P_PARTKEY AND 
LINEITEM.L_SHIPDATE >= Date32("1995-09-01") AND LINEITEM.L_SHIPDATE < 
CAST(Utf8("1995-10-01") AS Date32)
+                    Cross Join: 
+                      TableScan: LINEITEM
+                      TableScan: PART
+            "#
+                );
         Ok(())
     }
 
@@ -304,28 +326,30 @@ mod tests {
     #[tokio::test]
     async fn tpch_test_15() -> Result<()> {
         let plan_str = tpch_plan_to_string(15).await?;
-        assert_eq!(plan_str, "Test file is empty");
+        assert_snapshot!(plan_str, "Test file is empty");
         Ok(())
     }
 
     #[tokio::test]
     async fn tpch_test_16() -> Result<()> {
         let plan_str = tpch_plan_to_string(16).await?;
-        assert_eq!(
-            plan_str,
-            "Projection: PART.P_BRAND, PART.P_TYPE, PART.P_SIZE, 
count(DISTINCT PARTSUPP.PS_SUPPKEY) AS SUPPLIER_CNT\
-            \n  Sort: count(DISTINCT PARTSUPP.PS_SUPPKEY) DESC NULLS FIRST, 
PART.P_BRAND ASC NULLS LAST, PART.P_TYPE ASC NULLS LAST, PART.P_SIZE ASC NULLS 
LAST\
-            \n    Aggregate: groupBy=[[PART.P_BRAND, PART.P_TYPE, 
PART.P_SIZE]], aggr=[[count(DISTINCT PARTSUPP.PS_SUPPKEY)]]\
-            \n      Projection: PART.P_BRAND, PART.P_TYPE, PART.P_SIZE, 
PARTSUPP.PS_SUPPKEY\
-            \n        Filter: PART.P_PARTKEY = PARTSUPP.PS_PARTKEY AND 
PART.P_BRAND != Utf8(\"Brand#45\") AND NOT PART.P_TYPE LIKE CAST(Utf8(\"MEDIUM 
POLISHED%\") AS Utf8) AND (PART.P_SIZE = Int32(49) OR PART.P_SIZE = Int32(14) 
OR PART.P_SIZE = Int32(23) OR PART.P_SIZE = Int32(45) OR PART.P_SIZE = 
Int32(19) OR PART.P_SIZE = Int32(3) OR PART.P_SIZE = Int32(36) OR PART.P_SIZE = 
Int32(9)) AND NOT PARTSUPP.PS_SUPPKEY IN (<subquery>)\
-            \n          Subquery:\
-            \n            Projection: SUPPLIER.S_SUPPKEY\
-            \n              Filter: SUPPLIER.S_COMMENT LIKE 
CAST(Utf8(\"%Customer%Complaints%\") AS Utf8)\
-            \n                TableScan: SUPPLIER\
-            \n          Cross Join: \
-            \n            TableScan: PARTSUPP\
-            \n            TableScan: PART"
-        );
+        assert_snapshot!(
+        plan_str,
+        @r#"
+            Projection: PART.P_BRAND, PART.P_TYPE, PART.P_SIZE, count(DISTINCT 
PARTSUPP.PS_SUPPKEY) AS SUPPLIER_CNT
+              Sort: count(DISTINCT PARTSUPP.PS_SUPPKEY) DESC NULLS FIRST, 
PART.P_BRAND ASC NULLS LAST, PART.P_TYPE ASC NULLS LAST, PART.P_SIZE ASC NULLS 
LAST
+                Aggregate: groupBy=[[PART.P_BRAND, PART.P_TYPE, PART.P_SIZE]], 
aggr=[[count(DISTINCT PARTSUPP.PS_SUPPKEY)]]
+                  Projection: PART.P_BRAND, PART.P_TYPE, PART.P_SIZE, 
PARTSUPP.PS_SUPPKEY
+                    Filter: PART.P_PARTKEY = PARTSUPP.PS_PARTKEY AND 
PART.P_BRAND != Utf8("Brand#45") AND NOT PART.P_TYPE LIKE CAST(Utf8("MEDIUM 
POLISHED%") AS Utf8) AND (PART.P_SIZE = Int32(49) OR PART.P_SIZE = Int32(14) OR 
PART.P_SIZE = Int32(23) OR PART.P_SIZE = Int32(45) OR PART.P_SIZE = Int32(19) 
OR PART.P_SIZE = Int32(3) OR PART.P_SIZE = Int32(36) OR PART.P_SIZE = Int32(9)) 
AND NOT PARTSUPP.PS_SUPPKEY IN (<subquery>)
+                      Subquery:
+                        Projection: SUPPLIER.S_SUPPKEY
+                          Filter: SUPPLIER.S_COMMENT LIKE 
CAST(Utf8("%Customer%Complaints%") AS Utf8)
+                            TableScan: SUPPLIER
+                      Cross Join: 
+                        TableScan: PARTSUPP
+                        TableScan: PART
+            "#
+                );
         Ok(())
     }
 
@@ -333,127 +357,137 @@ mod tests {
     #[tokio::test]
     async fn tpch_test_17() -> Result<()> {
         let plan_str = tpch_plan_to_string(17).await?;
-        assert_eq!(plan_str, "panics due to out of bounds field access");
+        assert_snapshot!(plan_str, "panics due to out of bounds field access");
         Ok(())
     }
 
     #[tokio::test]
     async fn tpch_test_18() -> Result<()> {
         let plan_str = tpch_plan_to_string(18).await?;
-        assert_eq!(
-            plan_str,
-            "Projection: CUSTOMER.C_NAME, CUSTOMER.C_CUSTKEY, 
ORDERS.O_ORDERKEY, ORDERS.O_ORDERDATE, ORDERS.O_TOTALPRICE, 
sum(LINEITEM.L_QUANTITY) AS EXPR$5\
-            \n  Limit: skip=0, fetch=100\
-            \n    Sort: ORDERS.O_TOTALPRICE DESC NULLS FIRST, 
ORDERS.O_ORDERDATE ASC NULLS LAST\
-            \n      Aggregate: groupBy=[[CUSTOMER.C_NAME, CUSTOMER.C_CUSTKEY, 
ORDERS.O_ORDERKEY, ORDERS.O_ORDERDATE, ORDERS.O_TOTALPRICE]], 
aggr=[[sum(LINEITEM.L_QUANTITY)]]\
-            \n        Projection: CUSTOMER.C_NAME, CUSTOMER.C_CUSTKEY, 
ORDERS.O_ORDERKEY, ORDERS.O_ORDERDATE, ORDERS.O_TOTALPRICE, LINEITEM.L_QUANTITY\
-            \n          Filter: ORDERS.O_ORDERKEY IN (<subquery>) AND 
CUSTOMER.C_CUSTKEY = ORDERS.O_CUSTKEY AND ORDERS.O_ORDERKEY = 
LINEITEM.L_ORDERKEY\
-            \n            Subquery:\
-            \n              Projection: LINEITEM.L_ORDERKEY\
-            \n                Filter: sum(LINEITEM.L_QUANTITY) > 
CAST(Int32(300) AS Decimal128(15, 2))\
-            \n                  Aggregate: groupBy=[[LINEITEM.L_ORDERKEY]], 
aggr=[[sum(LINEITEM.L_QUANTITY)]]\
-            \n                    Projection: LINEITEM.L_ORDERKEY, 
LINEITEM.L_QUANTITY\
-            \n                      TableScan: LINEITEM\
-            \n            Cross Join: \
-            \n              Cross Join: \
-            \n                TableScan: CUSTOMER\
-            \n                TableScan: ORDERS\
-            \n              TableScan: LINEITEM"
-        );
+        assert_snapshot!(
+        plan_str,
+        @r#"
+            Projection: CUSTOMER.C_NAME, CUSTOMER.C_CUSTKEY, 
ORDERS.O_ORDERKEY, ORDERS.O_ORDERDATE, ORDERS.O_TOTALPRICE, 
sum(LINEITEM.L_QUANTITY) AS EXPR$5
+              Limit: skip=0, fetch=100
+                Sort: ORDERS.O_TOTALPRICE DESC NULLS FIRST, ORDERS.O_ORDERDATE 
ASC NULLS LAST
+                  Aggregate: groupBy=[[CUSTOMER.C_NAME, CUSTOMER.C_CUSTKEY, 
ORDERS.O_ORDERKEY, ORDERS.O_ORDERDATE, ORDERS.O_TOTALPRICE]], 
aggr=[[sum(LINEITEM.L_QUANTITY)]]
+                    Projection: CUSTOMER.C_NAME, CUSTOMER.C_CUSTKEY, 
ORDERS.O_ORDERKEY, ORDERS.O_ORDERDATE, ORDERS.O_TOTALPRICE, LINEITEM.L_QUANTITY
+                      Filter: ORDERS.O_ORDERKEY IN (<subquery>) AND 
CUSTOMER.C_CUSTKEY = ORDERS.O_CUSTKEY AND ORDERS.O_ORDERKEY = 
LINEITEM.L_ORDERKEY
+                        Subquery:
+                          Projection: LINEITEM.L_ORDERKEY
+                            Filter: sum(LINEITEM.L_QUANTITY) > CAST(Int32(300) 
AS Decimal128(15, 2))
+                              Aggregate: groupBy=[[LINEITEM.L_ORDERKEY]], 
aggr=[[sum(LINEITEM.L_QUANTITY)]]
+                                Projection: LINEITEM.L_ORDERKEY, 
LINEITEM.L_QUANTITY
+                                  TableScan: LINEITEM
+                        Cross Join: 
+                          Cross Join: 
+                            TableScan: CUSTOMER
+                            TableScan: ORDERS
+                          TableScan: LINEITEM
+            "#
+                );
         Ok(())
     }
     #[tokio::test]
     async fn tpch_test_19() -> Result<()> {
         let plan_str = tpch_plan_to_string(19).await?;
-        assert_eq!(
-            plan_str,
-            "Aggregate: groupBy=[[]], aggr=[[sum(LINEITEM.L_EXTENDEDPRICE * 
Int32(1) - LINEITEM.L_DISCOUNT) AS REVENUE]]\
-            \n  Projection: LINEITEM.L_EXTENDEDPRICE * (CAST(Int32(1) AS 
Decimal128(15, 2)) - LINEITEM.L_DISCOUNT)\
-            \n    Filter: PART.P_PARTKEY = LINEITEM.L_PARTKEY AND PART.P_BRAND 
= Utf8(\"Brand#12\") AND (PART.P_CONTAINER = CAST(Utf8(\"SM CASE\") AS Utf8) OR 
PART.P_CONTAINER = CAST(Utf8(\"SM BOX\") AS Utf8) OR PART.P_CONTAINER = 
CAST(Utf8(\"SM PACK\") AS Utf8) OR PART.P_CONTAINER = CAST(Utf8(\"SM PKG\") AS 
Utf8)) AND LINEITEM.L_QUANTITY >= CAST(Int32(1) AS Decimal128(15, 2)) AND 
LINEITEM.L_QUANTITY <= CAST(Int32(1) + Int32(10) AS Decimal128(15, 2)) AND 
PART.P_SIZE >= Int32(1) AND PART. [...]
-            \n      Cross Join: \
-            \n        TableScan: LINEITEM\
-            \n        TableScan: PART"
-        );
+        assert_snapshot!(
+        plan_str,
+        @r#"
+            Aggregate: groupBy=[[]], aggr=[[sum(LINEITEM.L_EXTENDEDPRICE * 
Int32(1) - LINEITEM.L_DISCOUNT) AS REVENUE]]
+              Projection: LINEITEM.L_EXTENDEDPRICE * (CAST(Int32(1) AS 
Decimal128(15, 2)) - LINEITEM.L_DISCOUNT)
+                Filter: PART.P_PARTKEY = LINEITEM.L_PARTKEY AND PART.P_BRAND = 
Utf8("Brand#12") AND (PART.P_CONTAINER = CAST(Utf8("SM CASE") AS Utf8) OR 
PART.P_CONTAINER = CAST(Utf8("SM BOX") AS Utf8) OR PART.P_CONTAINER = 
CAST(Utf8("SM PACK") AS Utf8) OR PART.P_CONTAINER = CAST(Utf8("SM PKG") AS 
Utf8)) AND LINEITEM.L_QUANTITY >= CAST(Int32(1) AS Decimal128(15, 2)) AND 
LINEITEM.L_QUANTITY <= CAST(Int32(1) + Int32(10) AS Decimal128(15, 2)) AND 
PART.P_SIZE >= Int32(1) AND PART.P_SIZE <= In [...]
+                  Cross Join: 
+                    TableScan: LINEITEM
+                    TableScan: PART
+            "#
+                );
         Ok(())
     }
 
     #[tokio::test]
     async fn tpch_test_20() -> Result<()> {
         let plan_str = tpch_plan_to_string(20).await?;
-        assert_eq!(
-            plan_str,
-            "Sort: SUPPLIER.S_NAME ASC NULLS LAST\
-            \n  Projection: SUPPLIER.S_NAME, SUPPLIER.S_ADDRESS\
-            \n    Filter: SUPPLIER.S_SUPPKEY IN (<subquery>) AND 
SUPPLIER.S_NATIONKEY = NATION.N_NATIONKEY AND NATION.N_NAME = Utf8(\"CANADA\")\
-            \n      Subquery:\
-            \n        Projection: PARTSUPP.PS_SUPPKEY\
-            \n          Filter: PARTSUPP.PS_PARTKEY IN (<subquery>) AND 
CAST(PARTSUPP.PS_AVAILQTY AS Decimal128(19, 0)) > (<subquery>)\
-            \n            Subquery:\
-            \n              Projection: PART.P_PARTKEY\
-            \n                Filter: PART.P_NAME LIKE CAST(Utf8(\"forest%\") 
AS Utf8)\
-            \n                  TableScan: PART\
-            \n            Subquery:\
-            \n              Projection: Decimal128(Some(5),2,1) * 
sum(LINEITEM.L_QUANTITY)\
-            \n                Aggregate: groupBy=[[]], 
aggr=[[sum(LINEITEM.L_QUANTITY)]]\
-            \n                  Projection: LINEITEM.L_QUANTITY\
-            \n                    Filter: LINEITEM.L_PARTKEY = 
LINEITEM.L_ORDERKEY AND LINEITEM.L_SUPPKEY = LINEITEM.L_PARTKEY AND 
LINEITEM.L_SHIPDATE >= CAST(Utf8(\"1994-01-01\") AS Date32) AND 
LINEITEM.L_SHIPDATE < CAST(Utf8(\"1995-01-01\") AS Date32)\
-            \n                      TableScan: LINEITEM\
-            \n            TableScan: PARTSUPP\
-            \n      Cross Join: \
-            \n        TableScan: SUPPLIER\
-            \n        TableScan: NATION"
-        );
+        assert_snapshot!(
+        plan_str,
+        @r#"
+            Sort: SUPPLIER.S_NAME ASC NULLS LAST
+              Projection: SUPPLIER.S_NAME, SUPPLIER.S_ADDRESS
+                Filter: SUPPLIER.S_SUPPKEY IN (<subquery>) AND 
SUPPLIER.S_NATIONKEY = NATION.N_NATIONKEY AND NATION.N_NAME = Utf8("CANADA")
+                  Subquery:
+                    Projection: PARTSUPP.PS_SUPPKEY
+                      Filter: PARTSUPP.PS_PARTKEY IN (<subquery>) AND 
CAST(PARTSUPP.PS_AVAILQTY AS Decimal128(19, 0)) > (<subquery>)
+                        Subquery:
+                          Projection: PART.P_PARTKEY
+                            Filter: PART.P_NAME LIKE CAST(Utf8("forest%") AS 
Utf8)
+                              TableScan: PART
+                        Subquery:
+                          Projection: Decimal128(Some(5),2,1) * 
sum(LINEITEM.L_QUANTITY)
+                            Aggregate: groupBy=[[]], 
aggr=[[sum(LINEITEM.L_QUANTITY)]]
+                              Projection: LINEITEM.L_QUANTITY
+                                Filter: LINEITEM.L_PARTKEY = 
LINEITEM.L_ORDERKEY AND LINEITEM.L_SUPPKEY = LINEITEM.L_PARTKEY AND 
LINEITEM.L_SHIPDATE >= CAST(Utf8("1994-01-01") AS Date32) AND 
LINEITEM.L_SHIPDATE < CAST(Utf8("1995-01-01") AS Date32)
+                                  TableScan: LINEITEM
+                        TableScan: PARTSUPP
+                  Cross Join: 
+                    TableScan: SUPPLIER
+                    TableScan: NATION
+            "#
+                );
         Ok(())
     }
 
     #[tokio::test]
     async fn tpch_test_21() -> Result<()> {
         let plan_str = tpch_plan_to_string(21).await?;
-        assert_eq!(
-            plan_str,
-            "Projection: SUPPLIER.S_NAME, count(Int64(1)) AS NUMWAIT\
-            \n  Limit: skip=0, fetch=100\
-            \n    Sort: count(Int64(1)) DESC NULLS FIRST, SUPPLIER.S_NAME ASC 
NULLS LAST\
-            \n      Aggregate: groupBy=[[SUPPLIER.S_NAME]], 
aggr=[[count(Int64(1))]]\
-            \n        Projection: SUPPLIER.S_NAME\
-            \n          Filter: SUPPLIER.S_SUPPKEY = LINEITEM.L_SUPPKEY AND 
ORDERS.O_ORDERKEY = LINEITEM.L_ORDERKEY AND ORDERS.O_ORDERSTATUS = Utf8(\"F\") 
AND LINEITEM.L_RECEIPTDATE > LINEITEM.L_COMMITDATE AND EXISTS (<subquery>) AND 
NOT EXISTS (<subquery>) AND SUPPLIER.S_NATIONKEY = NATION.N_NATIONKEY AND 
NATION.N_NAME = Utf8(\"SAUDI ARABIA\")\
-            \n            Subquery:\
-            \n              Filter: LINEITEM.L_ORDERKEY = LINEITEM.L_TAX AND 
LINEITEM.L_SUPPKEY != LINEITEM.L_LINESTATUS\
-            \n                TableScan: LINEITEM\
-            \n            Subquery:\
-            \n              Filter: LINEITEM.L_ORDERKEY = LINEITEM.L_TAX AND 
LINEITEM.L_SUPPKEY != LINEITEM.L_LINESTATUS AND LINEITEM.L_RECEIPTDATE > 
LINEITEM.L_COMMITDATE\
-            \n                TableScan: LINEITEM\
-            \n            Cross Join: \
-            \n              Cross Join: \
-            \n                Cross Join: \
-            \n                  TableScan: SUPPLIER\
-            \n                  TableScan: LINEITEM\
-            \n                TableScan: ORDERS\
-            \n              TableScan: NATION"
-        );
+        assert_snapshot!(
+        plan_str,
+        @r#"
+        Projection: SUPPLIER.S_NAME, count(Int64(1)) AS NUMWAIT
+          Limit: skip=0, fetch=100
+            Sort: count(Int64(1)) DESC NULLS FIRST, SUPPLIER.S_NAME ASC NULLS 
LAST
+              Aggregate: groupBy=[[SUPPLIER.S_NAME]], aggr=[[count(Int64(1))]]
+                Projection: SUPPLIER.S_NAME
+                  Filter: SUPPLIER.S_SUPPKEY = LINEITEM.L_SUPPKEY AND 
ORDERS.O_ORDERKEY = LINEITEM.L_ORDERKEY AND ORDERS.O_ORDERSTATUS = Utf8("F") 
AND LINEITEM.L_RECEIPTDATE > LINEITEM.L_COMMITDATE AND EXISTS (<subquery>) AND 
NOT EXISTS (<subquery>) AND SUPPLIER.S_NATIONKEY = NATION.N_NATIONKEY AND 
NATION.N_NAME = Utf8("SAUDI ARABIA")
+                    Subquery:
+                      Filter: LINEITEM.L_ORDERKEY = LINEITEM.L_TAX AND 
LINEITEM.L_SUPPKEY != LINEITEM.L_LINESTATUS
+                        TableScan: LINEITEM
+                    Subquery:
+                      Filter: LINEITEM.L_ORDERKEY = LINEITEM.L_TAX AND 
LINEITEM.L_SUPPKEY != LINEITEM.L_LINESTATUS AND LINEITEM.L_RECEIPTDATE > 
LINEITEM.L_COMMITDATE
+                        TableScan: LINEITEM
+                    Cross Join: 
+                      Cross Join: 
+                        Cross Join: 
+                          TableScan: SUPPLIER
+                          TableScan: LINEITEM
+                        TableScan: ORDERS
+                      TableScan: NATION
+        "#
+                        );
         Ok(())
     }
 
     #[tokio::test]
     async fn tpch_test_22() -> Result<()> {
         let plan_str = tpch_plan_to_string(22).await?;
-        assert_eq!(
-            plan_str,
-            "Projection: substr(CUSTOMER.C_PHONE,Int32(1),Int32(2)) AS 
CNTRYCODE, count(Int64(1)) AS NUMCUST, sum(CUSTOMER.C_ACCTBAL) AS TOTACCTBAL\
-            \n  Sort: substr(CUSTOMER.C_PHONE,Int32(1),Int32(2)) ASC NULLS 
LAST\
-            \n    Aggregate: 
groupBy=[[substr(CUSTOMER.C_PHONE,Int32(1),Int32(2))]], aggr=[[count(Int64(1)), 
sum(CUSTOMER.C_ACCTBAL)]]\
-            \n      Projection: substr(CUSTOMER.C_PHONE, Int32(1), Int32(2)), 
CUSTOMER.C_ACCTBAL\
-            \n        Filter: (substr(CUSTOMER.C_PHONE, Int32(1), Int32(2)) = 
CAST(Utf8(\"13\") AS Utf8) OR substr(CUSTOMER.C_PHONE, Int32(1), Int32(2)) = 
CAST(Utf8(\"31\") AS Utf8) OR substr(CUSTOMER.C_PHONE, Int32(1), Int32(2)) = 
CAST(Utf8(\"23\") AS Utf8) OR substr(CUSTOMER.C_PHONE, Int32(1), Int32(2)) = 
CAST(Utf8(\"29\") AS Utf8) OR substr(CUSTOMER.C_PHONE, Int32(1), Int32(2)) = 
CAST(Utf8(\"30\") AS Utf8) OR substr(CUSTOMER.C_PHONE, Int32(1), Int32(2)) = 
CAST(Utf8(\"18\") AS Utf8) OR [...]
-            \n          Subquery:\
-            \n            Aggregate: groupBy=[[]], 
aggr=[[avg(CUSTOMER.C_ACCTBAL)]]\
-            \n              Projection: CUSTOMER.C_ACCTBAL\
-            \n                Filter: CUSTOMER.C_ACCTBAL > 
Decimal128(Some(0),3,2) AND (substr(CUSTOMER.C_PHONE, Int32(1), Int32(2)) = 
CAST(Utf8(\"13\") AS Utf8) OR substr(CUSTOMER.C_PHONE, Int32(1), Int32(2)) = 
CAST(Utf8(\"31\") AS Utf8) OR substr(CUSTOMER.C_PHONE, Int32(1), Int32(2)) = 
CAST(Utf8(\"23\") AS Utf8) OR substr(CUSTOMER.C_PHONE, Int32(1), Int32(2)) = 
CAST(Utf8(\"29\") AS Utf8) OR substr(CUSTOMER.C_PHONE, Int32(1), Int32(2)) = 
CAST(Utf8(\"30\") AS Utf8) OR substr(CUSTOMER.C_P [...]
-            \n                  TableScan: CUSTOMER\
-            \n          Subquery:\
-            \n            Filter: ORDERS.O_CUSTKEY = ORDERS.O_ORDERKEY\
-            \n              TableScan: ORDERS\
-            \n          TableScan: CUSTOMER"
-        );
+        assert_snapshot!(
+        plan_str,
+        @r#"
+        Projection: substr(CUSTOMER.C_PHONE,Int32(1),Int32(2)) AS CNTRYCODE, 
count(Int64(1)) AS NUMCUST, sum(CUSTOMER.C_ACCTBAL) AS TOTACCTBAL
+          Sort: substr(CUSTOMER.C_PHONE,Int32(1),Int32(2)) ASC NULLS LAST
+            Aggregate: groupBy=[[substr(CUSTOMER.C_PHONE,Int32(1),Int32(2))]], 
aggr=[[count(Int64(1)), sum(CUSTOMER.C_ACCTBAL)]]
+              Projection: substr(CUSTOMER.C_PHONE, Int32(1), Int32(2)), 
CUSTOMER.C_ACCTBAL
+                Filter: (substr(CUSTOMER.C_PHONE, Int32(1), Int32(2)) = 
CAST(Utf8("13") AS Utf8) OR substr(CUSTOMER.C_PHONE, Int32(1), Int32(2)) = 
CAST(Utf8("31") AS Utf8) OR substr(CUSTOMER.C_PHONE, Int32(1), Int32(2)) = 
CAST(Utf8("23") AS Utf8) OR substr(CUSTOMER.C_PHONE, Int32(1), Int32(2)) = 
CAST(Utf8("29") AS Utf8) OR substr(CUSTOMER.C_PHONE, Int32(1), Int32(2)) = 
CAST(Utf8("30") AS Utf8) OR substr(CUSTOMER.C_PHONE, Int32(1), Int32(2)) = 
CAST(Utf8("18") AS Utf8) OR substr(CUSTOMER.C [...]
+                  Subquery:
+                    Aggregate: groupBy=[[]], aggr=[[avg(CUSTOMER.C_ACCTBAL)]]
+                      Projection: CUSTOMER.C_ACCTBAL
+                        Filter: CUSTOMER.C_ACCTBAL > Decimal128(Some(0),3,2) 
AND (substr(CUSTOMER.C_PHONE, Int32(1), Int32(2)) = CAST(Utf8("13") AS Utf8) OR 
substr(CUSTOMER.C_PHONE, Int32(1), Int32(2)) = CAST(Utf8("31") AS Utf8) OR 
substr(CUSTOMER.C_PHONE, Int32(1), Int32(2)) = CAST(Utf8("23") AS Utf8) OR 
substr(CUSTOMER.C_PHONE, Int32(1), Int32(2)) = CAST(Utf8("29") AS Utf8) OR 
substr(CUSTOMER.C_PHONE, Int32(1), Int32(2)) = CAST(Utf8("30") AS Utf8) OR 
substr(CUSTOMER.C_PHONE, Int32(1),  [...]
+                          TableScan: CUSTOMER
+                  Subquery:
+                    Filter: ORDERS.O_CUSTKEY = ORDERS.O_ORDERKEY
+                      TableScan: ORDERS
+                  TableScan: CUSTOMER
+        "#
+                        );
         Ok(())
     }
 
@@ -475,11 +509,13 @@ mod tests {
         let plan_str =
             
test_plan_to_string("select_count_from_select_1.substrait.json").await?;
 
-        assert_eq!(
-            plan_str,
-            "Aggregate: groupBy=[[]], aggr=[[count(Int64(1)) AS count(*)]]\
-            \n  Values: (Int64(0))"
-        );
+        assert_snapshot!(
+        plan_str,
+        @r#"
+            Aggregate: groupBy=[[]], aggr=[[count(Int64(1)) AS count(*)]]
+              Values: (Int64(0))
+            "#
+                );
         Ok(())
     }
 
@@ -487,12 +523,14 @@ mod tests {
     async fn test_select_window_count() -> Result<()> {
         let plan_str = 
test_plan_to_string("select_window_count.substrait.json").await?;
 
-        assert_eq!(
-            plan_str,
-            "Projection: count(Int64(1)) PARTITION BY [DATA.PART] ORDER BY 
[DATA.ORD ASC NULLS LAST] ROWS BETWEEN 1 PRECEDING AND UNBOUNDED FOLLOWING AS 
LEAD_EXPR\
-            \n  WindowAggr: windowExpr=[[count(Int64(1)) PARTITION BY 
[DATA.PART] ORDER BY [DATA.ORD ASC NULLS LAST] ROWS BETWEEN 1 PRECEDING AND 
UNBOUNDED FOLLOWING]]\
-            \n    TableScan: DATA"
-        );
+        assert_snapshot!(
+        plan_str,
+        @r#"
+        Projection: count(Int64(1)) PARTITION BY [DATA.PART] ORDER BY 
[DATA.ORD ASC NULLS LAST] ROWS BETWEEN 1 PRECEDING AND UNBOUNDED FOLLOWING AS 
LEAD_EXPR
+          WindowAggr: windowExpr=[[count(Int64(1)) PARTITION BY [DATA.PART] 
ORDER BY [DATA.ORD ASC NULLS LAST] ROWS BETWEEN 1 PRECEDING AND UNBOUNDED 
FOLLOWING]]
+            TableScan: DATA
+        "#
+                        );
         Ok(())
     }
 }
diff --git a/datafusion/substrait/tests/cases/emit_kind_tests.rs 
b/datafusion/substrait/tests/cases/emit_kind_tests.rs
index 08537d0d11..88db2bc34d 100644
--- a/datafusion/substrait/tests/cases/emit_kind_tests.rs
+++ b/datafusion/substrait/tests/cases/emit_kind_tests.rs
@@ -26,6 +26,7 @@ mod tests {
     use datafusion::prelude::{CsvReadOptions, SessionConfig, SessionContext};
     use datafusion_substrait::logical_plan::consumer::from_substrait_plan;
     use datafusion_substrait::logical_plan::producer::to_substrait_plan;
+    use insta::assert_snapshot;
 
     #[tokio::test]
     async fn project_respects_direct_emit_kind() -> Result<()> {
@@ -35,13 +36,13 @@ mod tests {
         let ctx = add_plan_schemas_to_ctx(SessionContext::new(), &proto_plan)?;
         let plan = from_substrait_plan(&ctx.state(), &proto_plan).await?;
 
-        let plan_str = format!("{}", plan);
-
-        assert_eq!(
-            plan_str,
-            "Projection: DATA.A AS a, DATA.B AS b, DATA.A + Int64(1) AS add1\
-            \n  TableScan: DATA"
-        );
+        assert_snapshot!(
+        plan,
+        @r#"
+            Projection: DATA.A AS a, DATA.B AS b, DATA.A + Int64(1) AS add1
+              TableScan: DATA
+            "#
+                );
         Ok(())
     }
 
@@ -53,15 +54,15 @@ mod tests {
         let ctx = add_plan_schemas_to_ctx(SessionContext::new(), &proto_plan)?;
         let plan = from_substrait_plan(&ctx.state(), &proto_plan).await?;
 
-        let plan_str = format!("{}", plan);
-
-        assert_eq!(
-            plan_str,
-            // Note that duplicate references in the remap are aliased
-            "Projection: DATA.B, DATA.A AS A1, DATA.A AS DATA.A__temp__0 AS A2\
-             \n  Filter: DATA.B = Int64(2)\
-             \n    TableScan: DATA"
-        );
+        assert_snapshot!(
+        plan,
+        // Note that duplicate references in the remap are aliased
+        @r#"
+            Projection: DATA.B, DATA.A AS A1, DATA.A AS DATA.A__temp__0 AS A2
+              Filter: DATA.B = Int64(2)
+                TableScan: DATA
+            "#
+                );
         Ok(())
     }
 
@@ -85,21 +86,24 @@ mod tests {
             .await?;
 
         let plan = df.into_unoptimized_plan();
-        assert_eq!(
-            format!("{}", plan),
-            "Projection: random() AS c1, data.a + Int64(1) AS c2\
-             \n  TableScan: data"
-        );
+        assert_snapshot!(
+            plan,
+            @r#"
+            Projection: random() AS c1, data.a + Int64(1) AS c2
+              TableScan: data
+            "#        );
 
         let proto = to_substrait_plan(&plan, &ctx.state())?;
         let plan2 = from_substrait_plan(&ctx.state(), &proto).await?;
         // note how the Projections are not flattened
-        assert_eq!(
-            format!("{}", plan2),
-            "Projection: random() AS c1, data.a + Int64(1) AS c2\
-             \n  Projection: data.a, data.b, data.c, data.d, data.e, data.f, 
random(), data.a + Int64(1)\
-             \n    TableScan: data"
-        );
+        assert_snapshot!(
+        plan2,
+        @r#"
+            Projection: random() AS c1, data.a + Int64(1) AS c2
+              Projection: data.a, data.b, data.c, data.d, data.e, data.f, 
random(), data.a + Int64(1)
+                TableScan: data
+            "#
+                );
         Ok(())
     }
 
@@ -109,17 +113,21 @@ mod tests {
         let df = ctx.sql("SELECT a + 1, b + 2 FROM data").await?;
 
         let plan = df.into_unoptimized_plan();
-        assert_eq!(
-            format!("{}", plan),
-            "Projection: data.a + Int64(1), data.b + Int64(2)\
-             \n  TableScan: data"
-        );
+        assert_snapshot!(
+        plan,
+        @r#"
+            Projection: data.a + Int64(1), data.b + Int64(2)
+              TableScan: data
+            "#
+                );
 
         let proto = to_substrait_plan(&plan, &ctx.state())?;
         let plan2 = from_substrait_plan(&ctx.state(), &proto).await?;
 
         let plan1str = format!("{plan}");
         let plan2str = format!("{plan2}");
+        println!("{}", plan1str);
+        println!("{}", plan2str);
         assert_eq!(plan1str, plan2str);
 
         Ok(())
diff --git a/datafusion/substrait/tests/cases/function_test.rs 
b/datafusion/substrait/tests/cases/function_test.rs
index 0438084561..1816c64d39 100644
--- a/datafusion/substrait/tests/cases/function_test.rs
+++ b/datafusion/substrait/tests/cases/function_test.rs
@@ -24,6 +24,7 @@ mod tests {
     use datafusion::common::Result;
     use datafusion::prelude::SessionContext;
     use datafusion_substrait::logical_plan::consumer::from_substrait_plan;
+    use insta::assert_snapshot;
 
     #[tokio::test]
     async fn contains_function_test() -> Result<()> {
@@ -31,14 +32,14 @@ mod tests {
         let ctx = add_plan_schemas_to_ctx(SessionContext::new(), &proto_plan)?;
         let plan = from_substrait_plan(&ctx.state(), &proto_plan).await?;
 
-        let plan_str = format!("{}", plan);
-
-        assert_eq!(
-            plan_str,
-            "Projection: nation.n_name\
-            \n  Filter: contains(nation.n_name, Utf8(\"IA\"))\
-            \n    TableScan: nation"
-        );
+        assert_snapshot!(
+        plan,
+        @r#"
+            Projection: nation.n_name
+              Filter: contains(nation.n_name, Utf8("IA"))
+                TableScan: nation
+            "#
+                );
         Ok(())
     }
 }
diff --git a/datafusion/substrait/tests/cases/logical_plans.rs 
b/datafusion/substrait/tests/cases/logical_plans.rs
index 579e3535f1..4dd9719303 100644
--- a/datafusion/substrait/tests/cases/logical_plans.rs
+++ b/datafusion/substrait/tests/cases/logical_plans.rs
@@ -24,6 +24,7 @@ mod tests {
     use datafusion::dataframe::DataFrame;
     use datafusion::prelude::SessionContext;
     use datafusion_substrait::logical_plan::consumer::from_substrait_plan;
+    use insta::assert_snapshot;
 
     #[tokio::test]
     async fn scalar_function_compound_signature() -> Result<()> {
@@ -40,11 +41,13 @@ mod tests {
         let ctx = add_plan_schemas_to_ctx(SessionContext::new(), &proto_plan)?;
         let plan = from_substrait_plan(&ctx.state(), &proto_plan).await?;
 
-        assert_eq!(
-            format!("{}", plan),
-            "Projection: NOT DATA.D AS EXPR$0\
-            \n  TableScan: DATA"
-        );
+        assert_snapshot!(
+        plan,
+        @r#"
+            Projection: NOT DATA.D AS EXPR$0
+              TableScan: DATA
+            "#
+                );
 
         // Trigger execution to ensure plan validity
         DataFrame::new(ctx.state(), plan).show().await?;
@@ -69,12 +72,14 @@ mod tests {
         let ctx = add_plan_schemas_to_ctx(SessionContext::new(), &proto_plan)?;
         let plan = from_substrait_plan(&ctx.state(), &proto_plan).await?;
 
-        assert_eq!(
-            format!("{}", plan),
-            "Projection: sum(DATA.D) PARTITION BY [DATA.PART] ORDER BY 
[DATA.ORD ASC NULLS LAST] ROWS BETWEEN 1 PRECEDING AND UNBOUNDED FOLLOWING AS 
LEAD_EXPR\
-            \n  WindowAggr: windowExpr=[[sum(DATA.D) PARTITION BY [DATA.PART] 
ORDER BY [DATA.ORD ASC NULLS LAST] ROWS BETWEEN 1 PRECEDING AND UNBOUNDED 
FOLLOWING]]\
-            \n    TableScan: DATA"
-        );
+        assert_snapshot!(
+        plan,
+        @r#"
+            Projection: sum(DATA.D) PARTITION BY [DATA.PART] ORDER BY 
[DATA.ORD ASC NULLS LAST] ROWS BETWEEN 1 PRECEDING AND UNBOUNDED FOLLOWING AS 
LEAD_EXPR
+              WindowAggr: windowExpr=[[sum(DATA.D) PARTITION BY [DATA.PART] 
ORDER BY [DATA.ORD ASC NULLS LAST] ROWS BETWEEN 1 PRECEDING AND UNBOUNDED 
FOLLOWING]]
+                TableScan: DATA
+            "#
+                );
 
         // Trigger execution to ensure plan validity
         DataFrame::new(ctx.state(), plan).show().await?;
@@ -94,12 +99,14 @@ mod tests {
         let ctx = add_plan_schemas_to_ctx(SessionContext::new(), &proto_plan)?;
         let plan = from_substrait_plan(&ctx.state(), &proto_plan).await?;
 
-        assert_eq!(
-            format!("{}", plan),
-            "Projection: row_number() ROWS BETWEEN UNBOUNDED PRECEDING AND 
CURRENT ROW AS EXPR$0, row_number() ROWS BETWEEN UNBOUNDED PRECEDING AND 
CURRENT ROW AS row_number() ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT 
ROW__temp__0 AS ALIASED\
-            \n  WindowAggr: windowExpr=[[row_number() ROWS BETWEEN UNBOUNDED 
PRECEDING AND CURRENT ROW]]\
-            \n    TableScan: DATA"
-        );
+        assert_snapshot!(
+        plan,
+        @r#"
+            Projection: row_number() ROWS BETWEEN UNBOUNDED PRECEDING AND 
CURRENT ROW AS EXPR$0, row_number() ROWS BETWEEN UNBOUNDED PRECEDING AND 
CURRENT ROW AS row_number() ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT 
ROW__temp__0 AS ALIASED
+              WindowAggr: windowExpr=[[row_number() ROWS BETWEEN UNBOUNDED 
PRECEDING AND CURRENT ROW]]
+                TableScan: DATA
+            "#
+                );
 
         // Trigger execution to ensure plan validity
         DataFrame::new(ctx.state(), plan).show().await?;
@@ -121,13 +128,15 @@ mod tests {
         let ctx = add_plan_schemas_to_ctx(SessionContext::new(), &proto_plan)?;
         let plan = from_substrait_plan(&ctx.state(), &proto_plan).await?;
 
-        assert_eq!(
-            format!("{}", plan),
-            "Projection: row_number() ROWS BETWEEN UNBOUNDED PRECEDING AND 
CURRENT ROW AS EXPR$0, row_number() PARTITION BY [DATA.A] ROWS BETWEEN 
UNBOUNDED PRECEDING AND CURRENT ROW AS EXPR$1\
-            \n  WindowAggr: windowExpr=[[row_number() ROWS BETWEEN UNBOUNDED 
PRECEDING AND CURRENT ROW]]\
-            \n    WindowAggr: windowExpr=[[row_number() PARTITION BY [DATA.A] 
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW]]\
-            \n      TableScan: DATA"
-        );
+        assert_snapshot!(
+        plan,
+        @r#"
+            Projection: row_number() ROWS BETWEEN UNBOUNDED PRECEDING AND 
CURRENT ROW AS EXPR$0, row_number() PARTITION BY [DATA.A] ROWS BETWEEN 
UNBOUNDED PRECEDING AND CURRENT ROW AS EXPR$1
+              WindowAggr: windowExpr=[[row_number() ROWS BETWEEN UNBOUNDED 
PRECEDING AND CURRENT ROW]]
+                WindowAggr: windowExpr=[[row_number() PARTITION BY [DATA.A] 
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW]]
+                  TableScan: DATA
+            "#
+                );
 
         // Trigger execution to ensure plan validity
         DataFrame::new(ctx.state(), plan).show().await?;
@@ -145,7 +154,12 @@ mod tests {
         let ctx = add_plan_schemas_to_ctx(SessionContext::new(), &proto_plan)?;
         let plan = from_substrait_plan(&ctx.state(), &proto_plan).await?;
 
-        assert_eq!(format!("{}", &plan), "Values: (List([1, 2]))");
+        assert_snapshot!(
+                &plan,
+            @r#"
+        Values: (List([1, 2]))
+        "#
+        );
 
         // Trigger execution to ensure plan validity
         DataFrame::new(ctx.state(), plan).show().await?;
@@ -160,13 +174,15 @@ mod tests {
         let ctx = add_plan_schemas_to_ctx(SessionContext::new(), &proto_plan)?;
         let plan = from_substrait_plan(&ctx.state(), &proto_plan).await?;
 
-        assert_eq!(
-            format!("{}", plan),
-            "Projection: lower(sales.product) AS lower(product), 
sum(count(sales.product)) AS product_count\
-            \n  Aggregate: groupBy=[[sales.product]], 
aggr=[[sum(count(sales.product))]]\
-            \n    Aggregate: groupBy=[[sales.product]], 
aggr=[[count(sales.product)]]\
-            \n      TableScan: sales"
-        );
+        assert_snapshot!(
+        plan,
+        @r#"
+            Projection: lower(sales.product) AS lower(product), 
sum(count(sales.product)) AS product_count
+              Aggregate: groupBy=[[sales.product]], 
aggr=[[sum(count(sales.product))]]
+                Aggregate: groupBy=[[sales.product]], 
aggr=[[count(sales.product)]]
+                  TableScan: sales
+            "#
+                );
 
         // Trigger execution to ensure plan validity
         DataFrame::new(ctx.state(), plan).show().await?;
diff --git a/datafusion/substrait/tests/cases/serialize.rs 
b/datafusion/substrait/tests/cases/serialize.rs
index 02089b9fa9..39c0622e3b 100644
--- a/datafusion/substrait/tests/cases/serialize.rs
+++ b/datafusion/substrait/tests/cases/serialize.rs
@@ -27,6 +27,7 @@ mod tests {
     use datafusion::error::Result;
     use datafusion::prelude::*;
 
+    use insta::assert_snapshot;
     use std::fs;
     use substrait::proto::plan_rel::RelType;
     use substrait::proto::rel_common::{Emit, EmitKind};
@@ -92,11 +93,14 @@ mod tests {
         let df = ctx.sql("SELECT b, a + a, a FROM data").await?;
         let datafusion_plan = df.into_optimized_plan()?;
 
-        assert_eq!(
-            format!("{}", datafusion_plan),
-            "Projection: data.b, data.a + data.a, data.a\
-            \n  TableScan: data projection=[a, b]",
-        );
+        assert_snapshot!(
+                    format!("{}", datafusion_plan),
+                    @r#"
+Projection: data.b, data.a + data.a, data.a
+  TableScan: data projection=[a, b]
+"#
+        ,
+                );
 
         let plan = to_substrait_plan(&datafusion_plan, &ctx.state())?
             .as_ref()
@@ -136,12 +140,15 @@ mod tests {
             .sql("SELECT b, RANK() OVER (PARTITION BY a), c FROM data;")
             .await?;
         let datafusion_plan = df.into_optimized_plan()?;
-        assert_eq!(
-            format!("{}", datafusion_plan),
-            "Projection: data.b, rank() PARTITION BY [data.a] ROWS BETWEEN 
UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING, data.c\
-            \n  WindowAggr: windowExpr=[[rank() PARTITION BY [data.a] ROWS 
BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING]]\
-            \n    TableScan: data projection=[a, b, c]",
-        );
+        assert_snapshot!(
+                    datafusion_plan,
+                    @r#"
+Projection: data.b, rank() PARTITION BY [data.a] ROWS BETWEEN UNBOUNDED 
PRECEDING AND UNBOUNDED FOLLOWING, data.c
+  WindowAggr: windowExpr=[[rank() PARTITION BY [data.a] ROWS BETWEEN UNBOUNDED 
PRECEDING AND UNBOUNDED FOLLOWING]]
+    TableScan: data projection=[a, b, c]
+"#
+        ,
+                );
 
         let plan = to_substrait_plan(&datafusion_plan, &ctx.state())?
             .as_ref()
diff --git a/datafusion/substrait/tests/cases/substrait_validations.rs 
b/datafusion/substrait/tests/cases/substrait_validations.rs
index a7d4d4aa82..a31b3ca385 100644
--- a/datafusion/substrait/tests/cases/substrait_validations.rs
+++ b/datafusion/substrait/tests/cases/substrait_validations.rs
@@ -26,6 +26,7 @@ mod tests {
         use datafusion::datasource::empty::EmptyTable;
         use datafusion::prelude::SessionContext;
         use datafusion_substrait::logical_plan::consumer::from_substrait_plan;
+        use insta::assert_snapshot;
         use std::collections::HashMap;
         use std::sync::Arc;
 
@@ -66,11 +67,13 @@ mod tests {
             let ctx = generate_context_with_table("DATA", df_schema)?;
             let plan = from_substrait_plan(&ctx.state(), &proto_plan).await?;
 
-            assert_eq!(
-                format!("{}", plan),
-                "Projection: DATA.a, DATA.b\
-                \n  TableScan: DATA"
-            );
+            assert_snapshot!(
+            plan,
+            @r#"
+                Projection: DATA.a, DATA.b
+                  TableScan: DATA
+                "#
+                        );
             Ok(())
         }
 
@@ -87,11 +90,13 @@ mod tests {
             let ctx = generate_context_with_table("DATA", df_schema)?;
             let plan = from_substrait_plan(&ctx.state(), &proto_plan).await?;
 
-            assert_eq!(
-                format!("{}", plan),
-                "Projection: DATA.a, DATA.b\
-                \n  TableScan: DATA projection=[a, b]"
-            );
+            assert_snapshot!(
+            plan,
+            @r#"
+                Projection: DATA.a, DATA.b
+                  TableScan: DATA projection=[a, b]
+                "#
+                        );
             Ok(())
         }
 
@@ -110,11 +115,13 @@ mod tests {
             let ctx = generate_context_with_table("DATA", df_schema)?;
             let plan = from_substrait_plan(&ctx.state(), &proto_plan).await?;
 
-            assert_eq!(
-                format!("{}", plan),
-                "Projection: DATA.a, DATA.b\
-                \n  TableScan: DATA projection=[a, b]"
-            );
+            assert_snapshot!(
+            plan,
+            @r#"
+                Projection: DATA.a, DATA.b
+                  TableScan: DATA projection=[a, b]
+                "#
+                        );
             Ok(())
         }
 


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

Reply via email to