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 56af232994 Migrate datafusion/sql tests to insta, part4 (#15548)
56af232994 is described below

commit 56af232994efa3003f29111b36a66681ca101ecc
Author: Tommy shu <[email protected]>
AuthorDate: Thu Apr 3 12:39:10 2025 -0400

    Migrate datafusion/sql tests to insta, part4 (#15548)
    
    * WIP: all `quick_test` migrated to `insta`
    
    * Remove `quick_test_with_options()`
    
    * resolve comments
    
    * Refactor SQL integration tests for decimal parsing and identifier 
normalization
    
    * replace `generate_logical_plan()` to `logical_plan().unwrap()`
    
    * Strip backtrace from logical plan error in SQL integration test
---
 datafusion/sql/tests/sql_integration.rs | 1350 +++++++++++++++++++------------
 1 file changed, 837 insertions(+), 513 deletions(-)

diff --git a/datafusion/sql/tests/sql_integration.rs 
b/datafusion/sql/tests/sql_integration.rs
index 663bf9ea1f..edc1fe3576 100644
--- a/datafusion/sql/tests/sql_integration.rs
+++ b/datafusion/sql/tests/sql_integration.rs
@@ -56,108 +56,233 @@ mod cases;
 mod common;
 
 #[test]
-fn parse_decimals() {
-    let test_data = [
-        ("1", "Int64(1)"),
-        ("001", "Int64(1)"),
-        ("0.1", "Decimal128(Some(1),1,1)"),
-        ("0.01", "Decimal128(Some(1),2,2)"),
-        ("1.0", "Decimal128(Some(10),2,1)"),
-        ("10.01", "Decimal128(Some(1001),4,2)"),
-        (
-            "10000000000000000000.00",
-            "Decimal128(Some(1000000000000000000000),22,2)",
-        ),
-        ("18446744073709551615", "UInt64(18446744073709551615)"),
-        (
-            "18446744073709551616",
-            "Decimal128(Some(18446744073709551616),20,0)",
-        ),
-    ];
-    for (a, b) in test_data {
-        let sql = format!("SELECT {a}");
-        let expected = format!("Projection: {b}\n  EmptyRelation");
-        quick_test_with_options(
-            &sql,
-            &expected,
-            ParserOptions {
-                parse_float_as_decimal: true,
-                enable_ident_normalization: false,
-                support_varchar_with_length: false,
-                map_varchar_to_utf8view: false,
-                enable_options_value_normalization: false,
-                collect_spans: false,
-            },
-        );
-    }
+fn parse_decimals_1() {
+    let sql = "SELECT 1";
+    let options = parse_decimals_parser_options();
+    let plan = logical_plan_with_options(sql, options).unwrap();
+    assert_snapshot!(
+        plan,
+        @r#"
+        Projection: Int64(1)
+          EmptyRelation
+        "#
+    );
 }
 
 #[test]
-fn parse_ident_normalization() {
-    let test_data = [
-        (
-            "SELECT CHARACTER_LENGTH('str')",
-            "Ok(Projection: character_length(Utf8(\"str\"))\n  EmptyRelation)",
-            false,
-        ),
-        (
-            "SELECT CONCAT('Hello', 'World')",
-            "Ok(Projection: concat(Utf8(\"Hello\"), Utf8(\"World\"))\n  
EmptyRelation)",
-            false,
-        ),
-        (
-            "SELECT age FROM person",
-            "Ok(Projection: person.age\n  TableScan: person)",
-            true,
-        ),
-        (
-            "SELECT AGE FROM PERSON",
-            "Ok(Projection: person.age\n  TableScan: person)",
-            true,
-        ),
-        (
-            "SELECT AGE FROM PERSON",
-            "Error during planning: No table named: PERSON found",
-            false,
-        ),
-        (
-            "SELECT Id FROM UPPERCASE_test",
-            "Ok(Projection: UPPERCASE_test.Id\
-                \n  TableScan: UPPERCASE_test)",
-            false,
-        ),
-        (
-            "SELECT \"Id\", lower FROM \"UPPERCASE_test\"",
-            "Ok(Projection: UPPERCASE_test.Id, UPPERCASE_test.lower\
-                \n  TableScan: UPPERCASE_test)",
-            true,
-        ),
-    ];
+fn parse_decimals_2() {
+    let sql = "SELECT 001";
+    let options = parse_decimals_parser_options();
+    let plan = logical_plan_with_options(sql, options).unwrap();
+    assert_snapshot!(
+        plan,
+        @r#"
+        Projection: Int64(1)
+          EmptyRelation
+        "#
+    );
+}
 
-    for (sql, expected, enable_ident_normalization) in test_data {
-        let plan = logical_plan_with_options(
-            sql,
-            ParserOptions {
-                parse_float_as_decimal: false,
-                enable_ident_normalization,
-                support_varchar_with_length: false,
-                map_varchar_to_utf8view: false,
-                enable_options_value_normalization: false,
-                collect_spans: false,
-            },
-        );
-        if plan.is_ok() {
-            let plan = plan.unwrap();
-            assert_eq!(expected, format!("Ok({plan})"));
-        } else {
-            assert_eq!(expected, plan.unwrap_err().strip_backtrace());
-        }
-    }
+#[test]
+fn parse_decimals_3() {
+    let sql = "SELECT 0.1";
+    let options = parse_decimals_parser_options();
+    let plan = logical_plan_with_options(sql, options).unwrap();
+    assert_snapshot!(
+        plan,
+        @r#"
+        Projection: Decimal128(Some(1),1,1)
+          EmptyRelation
+        "#
+    );
+}
+
+#[test]
+fn parse_decimals_4() {
+    let sql = "SELECT 0.01";
+    let options = parse_decimals_parser_options();
+    let plan = logical_plan_with_options(sql, options).unwrap();
+    assert_snapshot!(
+        plan,
+        @r#"
+        Projection: Decimal128(Some(1),2,2)
+          EmptyRelation
+        "#
+    );
+}
+
+#[test]
+fn parse_decimals_5() {
+    let sql = "SELECT 1.0";
+    let options = parse_decimals_parser_options();
+    let plan = logical_plan_with_options(sql, options).unwrap();
+    assert_snapshot!(
+        plan,
+        @r#"
+        Projection: Decimal128(Some(10),2,1)
+          EmptyRelation
+        "#
+    );
+}
+
+#[test]
+fn parse_decimals_6() {
+    let sql = "SELECT 10.01";
+    let options = parse_decimals_parser_options();
+    let plan = logical_plan_with_options(sql, options).unwrap();
+    assert_snapshot!(
+        plan,
+        @r#"
+        Projection: Decimal128(Some(1001),4,2)
+          EmptyRelation
+        "#
+    );
+}
+
+#[test]
+fn parse_decimals_7() {
+    let sql = "SELECT 10000000000000000000.00";
+    let options = parse_decimals_parser_options();
+    let plan = logical_plan_with_options(sql, options).unwrap();
+    assert_snapshot!(
+        plan,
+        @r#"
+        Projection: Decimal128(Some(1000000000000000000000),22,2)
+          EmptyRelation
+        "#
+    );
+}
+
+#[test]
+fn parse_decimals_8() {
+    let sql = "SELECT 18446744073709551615";
+    let options = parse_decimals_parser_options();
+    let plan = logical_plan_with_options(sql, options).unwrap();
+    assert_snapshot!(
+        plan,
+        @r#"
+        Projection: UInt64(18446744073709551615)
+          EmptyRelation
+        "#
+    );
+}
+
+#[test]
+fn parse_decimals_9() {
+    let sql = "SELECT 18446744073709551616";
+    let options = parse_decimals_parser_options();
+    let plan = logical_plan_with_options(sql, options).unwrap();
+    assert_snapshot!(
+        plan,
+        @r#"
+        Projection: Decimal128(Some(18446744073709551616),20,0)
+          EmptyRelation
+        "#
+    );
+}
+
+#[test]
+fn parse_ident_normalization_1() {
+    let sql = "SELECT CHARACTER_LENGTH('str')";
+    let parser_option = 
ident_normalization_parser_options_no_ident_normalization();
+    let plan = logical_plan_with_options(sql, parser_option).unwrap();
+    assert_snapshot!(
+        plan,
+        @r#"
+        Projection: character_length(Utf8("str"))
+          EmptyRelation
+        "#
+    );
+}
+
+#[test]
+fn parse_ident_normalization_2() {
+    let sql = "SELECT CONCAT('Hello', 'World')";
+    let parser_option = 
ident_normalization_parser_options_no_ident_normalization();
+    let plan = logical_plan_with_options(sql, parser_option).unwrap();
+    assert_snapshot!(
+        plan,
+        @r#"
+        Projection: concat(Utf8("Hello"), Utf8("World"))
+          EmptyRelation
+        "#
+    );
+}
+
+#[test]
+fn parse_ident_normalization_3() {
+    let sql = "SELECT age FROM person";
+    let parser_option = 
ident_normalization_parser_options_ident_normalization();
+    let plan = logical_plan_with_options(sql, parser_option).unwrap();
+    assert_snapshot!(
+        plan,
+        @r#"
+        Projection: person.age
+          TableScan: person
+        "#
+    );
+}
+
+#[test]
+fn parse_ident_normalization_4() {
+    let sql = "SELECT AGE FROM PERSON";
+    let parser_option = 
ident_normalization_parser_options_ident_normalization();
+    let plan = logical_plan_with_options(sql, parser_option).unwrap();
+    assert_snapshot!(
+        plan,
+        @r#"
+        Projection: person.age
+          TableScan: person
+        "#
+    );
+}
+
+#[test]
+fn parse_ident_normalization_5() {
+    let sql = "SELECT AGE FROM PERSON";
+    let parser_option = 
ident_normalization_parser_options_no_ident_normalization();
+    let plan = logical_plan_with_options(sql, parser_option)
+        .unwrap_err()
+        .strip_backtrace();
+    assert_snapshot!(
+        plan,
+        @r#"
+        Error during planning: No table named: PERSON found
+        "#
+    );
+}
+
+#[test]
+fn parse_ident_normalization_6() {
+    let sql = "SELECT Id FROM UPPERCASE_test";
+    let parser_option = 
ident_normalization_parser_options_no_ident_normalization();
+    let plan = logical_plan_with_options(sql, parser_option).unwrap();
+    assert_snapshot!(
+        plan,
+        @r#"
+        Projection: UPPERCASE_test.Id
+          TableScan: UPPERCASE_test
+        "#
+    );
+}
+
+#[test]
+fn parse_ident_normalization_7() {
+    let sql = r#"SELECT "Id", lower FROM "UPPERCASE_test""#;
+    let parser_option = 
ident_normalization_parser_options_ident_normalization();
+    let plan = logical_plan_with_options(sql, parser_option).unwrap();
+    assert_snapshot!(
+        plan,
+        @r#"
+        Projection: UPPERCASE_test.Id, UPPERCASE_test.lower
+          TableScan: UPPERCASE_test
+        "#
+    );
 }
 
 #[test]
 fn select_no_relation() {
-    let plan = generate_logical_plan("SELECT 1");
+    let plan = logical_plan("SELECT 1").unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -169,7 +294,7 @@ fn select_no_relation() {
 
 #[test]
 fn test_real_f32() {
-    let plan = generate_logical_plan("SELECT CAST(1.1 AS REAL)");
+    let plan = logical_plan("SELECT CAST(1.1 AS REAL)").unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -181,7 +306,7 @@ fn test_real_f32() {
 
 #[test]
 fn test_int_decimal_default() {
-    let plan = generate_logical_plan("SELECT CAST(10 AS DECIMAL)");
+    let plan = logical_plan("SELECT CAST(10 AS DECIMAL)").unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -193,7 +318,7 @@ fn test_int_decimal_default() {
 
 #[test]
 fn test_int_decimal_no_scale() {
-    let plan = generate_logical_plan("SELECT CAST(10 AS DECIMAL(5))");
+    let plan = logical_plan("SELECT CAST(10 AS DECIMAL(5))").unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -205,7 +330,7 @@ fn test_int_decimal_no_scale() {
 
 #[test]
 fn test_tinyint() {
-    let plan = generate_logical_plan("SELECT CAST(6 AS TINYINT)");
+    let plan = logical_plan("SELECT CAST(6 AS TINYINT)").unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -217,7 +342,7 @@ fn test_tinyint() {
 
 #[test]
 fn cast_from_subquery() {
-    let plan = generate_logical_plan("SELECT CAST (a AS FLOAT) FROM (SELECT 1 
AS a)");
+    let plan = logical_plan("SELECT CAST (a AS FLOAT) FROM (SELECT 1 AS 
a)").unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -230,7 +355,7 @@ fn cast_from_subquery() {
 
 #[test]
 fn try_cast_from_aggregation() {
-    let plan = generate_logical_plan("SELECT TRY_CAST(sum(age) AS FLOAT) FROM 
person");
+    let plan = logical_plan("SELECT TRY_CAST(sum(age) AS FLOAT) FROM 
person").unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -257,7 +382,7 @@ fn cast_to_invalid_decimal_type_precision_0() {
 fn cast_to_invalid_decimal_type_precision_gt_38() {
     // precision > 38
     let sql = "SELECT CAST(10 AS DECIMAL(39))";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -294,7 +419,7 @@ fn cast_to_invalid_decimal_type_precision_lt_scale() {
 #[test]
 fn plan_create_table_with_pk() {
     let sql = "create table person (id int, name string, primary key(id))";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -304,7 +429,7 @@ fn plan_create_table_with_pk() {
     );
 
     let sql = "create table person (id int primary key, name string)";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -315,7 +440,7 @@ fn plan_create_table_with_pk() {
 
     let sql =
         "create table person (id int, name string unique not null, primary 
key(id))";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -325,7 +450,7 @@ fn plan_create_table_with_pk() {
     );
 
     let sql = "create table person (id int, name varchar,  primary key(name,  
id));";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -338,7 +463,7 @@ fn plan_create_table_with_pk() {
 #[test]
 fn plan_create_table_with_multi_pk() {
     let sql = "create table person (id int, name string primary key, primary 
key(id))";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -351,7 +476,7 @@ fn plan_create_table_with_multi_pk() {
 #[test]
 fn plan_create_table_with_unique() {
     let sql = "create table person (id int unique, name string)";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -364,7 +489,7 @@ fn plan_create_table_with_unique() {
 #[test]
 fn plan_create_table_no_pk() {
     let sql = "create table person (id int, name string)";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -377,7 +502,7 @@ fn plan_create_table_no_pk() {
 #[test]
 fn plan_create_table_check_constraint() {
     let sql = "create table person (id int, name string, unique(id))";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -390,7 +515,7 @@ fn plan_create_table_check_constraint() {
 #[test]
 fn plan_start_transaction() {
     let sql = "start transaction";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -402,7 +527,7 @@ fn plan_start_transaction() {
 #[test]
 fn plan_start_transaction_isolation() {
     let sql = "start transaction isolation level read committed";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -414,7 +539,7 @@ fn plan_start_transaction_isolation() {
 #[test]
 fn plan_start_transaction_read_only() {
     let sql = "start transaction read only";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -426,7 +551,7 @@ fn plan_start_transaction_read_only() {
 #[test]
 fn plan_start_transaction_fully_qualified() {
     let sql = "start transaction isolation level read committed read only";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -442,7 +567,7 @@ isolation level read committed
 read only
 isolation level repeatable read
 "#;
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -454,7 +579,7 @@ isolation level repeatable read
 #[test]
 fn plan_commit_transaction() {
     let sql = "commit transaction";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -466,7 +591,7 @@ fn plan_commit_transaction() {
 #[test]
 fn plan_commit_transaction_chained() {
     let sql = "commit transaction and chain";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -478,7 +603,7 @@ fn plan_commit_transaction_chained() {
 #[test]
 fn plan_rollback_transaction() {
     let sql = "rollback transaction";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -490,7 +615,7 @@ fn plan_rollback_transaction() {
 #[test]
 fn plan_rollback_transaction_chained() {
     let sql = "rollback transaction and chain";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -502,7 +627,7 @@ fn plan_rollback_transaction_chained() {
 #[test]
 fn plan_copy_to() {
     let sql = "COPY test_decimal to 'output.csv' STORED AS CSV";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -515,7 +640,7 @@ fn plan_copy_to() {
 #[test]
 fn plan_explain_copy_to() {
     let sql = "EXPLAIN COPY test_decimal to 'output.csv'";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -529,7 +654,7 @@ fn plan_explain_copy_to() {
 #[test]
 fn plan_explain_copy_to_format() {
     let sql = "EXPLAIN COPY test_decimal to 'output.tbl' STORED AS CSV";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -544,7 +669,7 @@ fn plan_explain_copy_to_format() {
 fn plan_insert() {
     let sql =
         "insert into person (id, first_name, last_name) values (1, 'Alan', 
'Turing')";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -558,7 +683,7 @@ fn plan_insert() {
 #[test]
 fn plan_insert_no_target_columns() {
     let sql = "INSERT INTO test_decimal VALUES (1, 2), (3, 4)";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -604,7 +729,7 @@ fn test_insert_schema_errors(#[case] sql: &str, #[case] 
error: &str) {
 #[test]
 fn plan_update() {
     let sql = "update person set last_name='Kay' where id=1";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -631,7 +756,7 @@ fn update_column_does_not_exist(#[case] sql: &str) {
 #[test]
 fn plan_delete() {
     let sql = "delete from person where id=1";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -646,7 +771,7 @@ fn plan_delete() {
 fn plan_delete_quoted_identifier_case_sensitive() {
     let sql =
         "DELETE FROM \"SomeCatalog\".\"SomeSchema\".\"UPPERCASE_test\" WHERE 
\"Id\" = 1";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -679,7 +804,7 @@ fn select_repeated_column() {
 
 #[test]
 fn select_scalar_func_with_literal_no_relation() {
-    let plan = generate_logical_plan("SELECT sqrt(9)");
+    let plan = logical_plan("SELECT sqrt(9)").unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -693,7 +818,7 @@ fn select_scalar_func_with_literal_no_relation() {
 fn select_simple_filter() {
     let sql = "SELECT id, first_name, last_name \
                    FROM person WHERE state = 'CO'";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -722,7 +847,7 @@ fn select_filter_cannot_use_alias() {
 fn select_neg_filter() {
     let sql = "SELECT id, first_name, last_name \
                    FROM person WHERE NOT state";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -737,7 +862,7 @@ fn select_neg_filter() {
 fn select_compound_filter() {
     let sql = "SELECT id, first_name, last_name \
                    FROM person WHERE state = 'CO' AND age >= 21 AND age <= 65";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -751,7 +876,7 @@ fn select_compound_filter() {
 #[test]
 fn test_timestamp_filter() {
     let sql = "SELECT state FROM person WHERE birth_date < CAST 
(158412331400600000 as timestamp)";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -765,7 +890,7 @@ fn test_timestamp_filter() {
 #[test]
 fn test_date_filter() {
     let sql = "SELECT state FROM person WHERE birth_date < CAST ('2020-01-01' 
as date)";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -786,7 +911,7 @@ fn select_all_boolean_operators() {
                    AND age >= 21 \
                    AND age < 65 \
                    AND age <= 65";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -800,7 +925,7 @@ fn select_all_boolean_operators() {
 #[test]
 fn select_between() {
     let sql = "SELECT state FROM person WHERE age BETWEEN 21 AND 65";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -814,7 +939,7 @@ fn select_between() {
 #[test]
 fn select_between_negated() {
     let sql = "SELECT state FROM person WHERE age NOT BETWEEN 21 AND 65";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -835,7 +960,7 @@ fn select_nested() {
                        FROM person
                      ) AS a
                    ) AS b";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -858,7 +983,7 @@ fn select_nested_with_filters() {
                      WHERE age > 20
                    ) AS a
                    WHERE fn1 = 'X' AND age < 30";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -876,7 +1001,7 @@ fn select_nested_with_filters() {
 fn table_with_column_alias() {
     let sql = "SELECT a, b, c
                    FROM lineitem l (a, b, c)";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -915,7 +1040,7 @@ fn select_with_ambiguous_column() {
 fn join_with_ambiguous_column() {
     // This is legal.
     let sql = "SELECT id FROM person a join person b using(id)";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -932,7 +1057,7 @@ fn join_with_ambiguous_column() {
 #[test]
 fn natural_left_join() {
     let sql = "SELECT l_item_id FROM lineitem a NATURAL LEFT JOIN lineitem b";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -949,7 +1074,7 @@ fn natural_left_join() {
 #[test]
 fn natural_right_join() {
     let sql = "SELECT l_item_id FROM lineitem a NATURAL RIGHT JOIN lineitem b";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -1040,7 +1165,7 @@ fn select_aggregate_with_having_that_reuses_aggregate() {
     let sql = "SELECT MAX(age)
                    FROM person
                    HAVING MAX(age) < 30";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -1057,7 +1182,7 @@ fn 
select_aggregate_with_having_with_aggregate_not_in_select() {
     let sql = "SELECT max(age)
                    FROM person
                    HAVING max(first_name) > 'M'";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -1090,7 +1215,7 @@ fn 
select_aggregate_aliased_with_having_referencing_aggregate_by_its_alias() {
                    FROM person
                    HAVING max_age < 30";
     // FIXME: add test for having in execution
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -1107,7 +1232,7 @@ fn 
select_aggregate_aliased_with_having_that_reuses_aggregate_but_not_by_its_ali
     let sql = "SELECT max(age) as max_age
                    FROM person
                    HAVING max(age) < 30";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -1125,7 +1250,7 @@ fn select_aggregate_with_group_by_with_having() {
                    FROM person
                    GROUP BY first_name
                    HAVING first_name = 'M'";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -1144,7 +1269,7 @@ fn select_aggregate_with_group_by_with_having_and_where() 
{
                    WHERE id > 5
                    GROUP BY first_name
                    HAVING MAX(age) < 100";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -1164,7 +1289,7 @@ fn 
select_aggregate_with_group_by_with_having_and_where_filtering_on_aggregate_c
                    WHERE id > 5 AND age > 18
                    GROUP BY first_name
                    HAVING MAX(age) < 100";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -1183,7 +1308,7 @@ fn 
select_aggregate_with_group_by_with_having_using_column_by_alias() {
                    FROM person
                    GROUP BY first_name
                    HAVING MAX(age) > 2 AND fn = 'M'";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -1202,7 +1327,7 @@ fn 
select_aggregate_with_group_by_with_having_using_columns_with_and_without_the
                    FROM person
                    GROUP BY first_name
                    HAVING MAX(age) > 2 AND max_age < 5 AND first_name = 'M' 
AND fn = 'N'";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -1220,7 +1345,7 @@ fn 
select_aggregate_with_group_by_with_having_that_reuses_aggregate() {
                    FROM person
                    GROUP BY first_name
                    HAVING MAX(age) > 100";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -1254,7 +1379,7 @@ fn 
select_aggregate_with_group_by_with_having_that_reuses_aggregate_multiple_tim
                    FROM person
                    GROUP BY first_name
                    HAVING MAX(age) > 100 AND MAX(age) < 200";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -1272,7 +1397,7 @@ fn 
select_aggregate_with_group_by_with_having_using_aggregate_not_in_select() {
                    FROM person
                    GROUP BY first_name
                    HAVING MAX(age) > 100 AND MIN(id) < 50";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -1291,7 +1416,7 @@ fn 
select_aggregate_aliased_with_group_by_with_having_referencing_aggregate_by_i
                    FROM person
                    GROUP BY first_name
                    HAVING max_age > 100";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -1310,7 +1435,7 @@ fn 
select_aggregate_compound_aliased_with_group_by_with_having_referencing_compo
                    FROM person
                    GROUP BY first_name
                    HAVING max_age_plus_one > 100";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -1329,7 +1454,7 @@ fn 
select_aggregate_with_group_by_with_having_using_derived_column_aggregate_not
                    FROM person
                    GROUP BY first_name
                    HAVING MAX(age) > 100 AND MIN(id - 2) < 50";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -1347,7 +1472,7 @@ fn 
select_aggregate_with_group_by_with_having_using_count_star_not_in_select() {
                    FROM person
                    GROUP BY first_name
                    HAVING MAX(age) > 100 AND count(*) < 50";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -1362,7 +1487,7 @@ fn 
select_aggregate_with_group_by_with_having_using_count_star_not_in_select() {
 #[test]
 fn select_binary_expr() {
     let sql = "SELECT age + salary from person";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -1375,7 +1500,7 @@ fn select_binary_expr() {
 #[test]
 fn select_binary_expr_nested() {
     let sql = "SELECT (age + salary)/2 from person";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -1387,7 +1512,7 @@ fn select_binary_expr_nested() {
 
 #[test]
 fn select_simple_aggregate() {
-    let plan = generate_logical_plan("SELECT MIN(age) FROM person");
+    let plan = logical_plan("SELECT MIN(age) FROM person").unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -1400,7 +1525,7 @@ fn select_simple_aggregate() {
 
 #[test]
 fn test_sum_aggregate() {
-    let plan = generate_logical_plan("SELECT sum(age) from person");
+    let plan = logical_plan("SELECT sum(age) from person").unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -1433,7 +1558,7 @@ fn select_simple_aggregate_repeated_aggregate() {
 
 #[test]
 fn select_simple_aggregate_repeated_aggregate_with_single_alias() {
-    let plan = generate_logical_plan("SELECT MIN(age), MIN(age) AS a FROM 
person");
+    let plan = logical_plan("SELECT MIN(age), MIN(age) AS a FROM 
person").unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -1446,7 +1571,7 @@ fn 
select_simple_aggregate_repeated_aggregate_with_single_alias() {
 
 #[test]
 fn select_simple_aggregate_repeated_aggregate_with_unique_aliases() {
-    let plan = generate_logical_plan("SELECT MIN(age) AS a, MIN(age) AS b FROM 
person");
+    let plan = logical_plan("SELECT MIN(age) AS a, MIN(age) AS b FROM 
person").unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -1459,9 +1584,9 @@ fn 
select_simple_aggregate_repeated_aggregate_with_unique_aliases() {
 
 #[test]
 fn select_from_typed_string_values() {
-    let plan = generate_logical_plan(
+    let plan = logical_plan(
         "SELECT col1, col2 FROM (VALUES (TIMESTAMP '2021-06-10 17:01:00Z', 
DATE '2004-04-09')) as t (col1, col2)",
-    );
+    ).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -1488,9 +1613,9 @@ fn 
select_simple_aggregate_repeated_aggregate_with_repeated_aliases() {
 
 #[test]
 fn select_simple_aggregate_with_groupby() {
-    let plan = generate_logical_plan(
-        "SELECT state, MIN(age), MAX(age) FROM person GROUP BY state",
-    );
+    let plan =
+        logical_plan("SELECT state, MIN(age), MAX(age) FROM person GROUP BY 
state")
+            .unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -1503,9 +1628,9 @@ fn select_simple_aggregate_with_groupby() {
 
 #[test]
 fn select_simple_aggregate_with_groupby_with_aliases() {
-    let plan = generate_logical_plan(
-        "SELECT state AS a, MIN(age) AS b FROM person GROUP BY state",
-    );
+    let plan =
+        logical_plan("SELECT state AS a, MIN(age) AS b FROM person GROUP BY 
state")
+            .unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -1532,7 +1657,7 @@ fn 
select_simple_aggregate_with_groupby_with_aliases_repeated() {
 #[test]
 fn select_simple_aggregate_with_groupby_column_unselected() {
     let plan =
-        generate_logical_plan("SELECT MIN(age), MAX(age) FROM person GROUP BY 
state");
+        logical_plan("SELECT MIN(age), MAX(age) FROM person GROUP BY 
state").unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -1579,7 +1704,7 @@ fn select_interval_out_of_range() {
 #[test]
 fn 
select_simple_aggregate_with_groupby_and_column_is_in_aggregate_and_groupby() {
     let plan =
-        generate_logical_plan("SELECT MAX(first_name) FROM person GROUP BY 
first_name");
+        logical_plan("SELECT MAX(first_name) FROM person GROUP BY 
first_name").unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -1592,9 +1717,8 @@ fn 
select_simple_aggregate_with_groupby_and_column_is_in_aggregate_and_groupby()
 
 #[test]
 fn select_simple_aggregate_with_groupby_can_use_positions() {
-    let plan = generate_logical_plan(
-        "SELECT state, age AS b, count(1) FROM person GROUP BY 1, 2",
-    );
+    let plan = logical_plan("SELECT state, age AS b, count(1) FROM person 
GROUP BY 1, 2")
+        .unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -1603,9 +1727,8 @@ fn 
select_simple_aggregate_with_groupby_can_use_positions() {
             TableScan: person
         "#
     );
-    let plan = generate_logical_plan(
-        "SELECT state, age AS b, count(1) FROM person GROUP BY 2, 1",
-    );
+    let plan = logical_plan("SELECT state, age AS b, count(1) FROM person 
GROUP BY 2, 1")
+        .unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -1642,7 +1765,7 @@ fn 
select_simple_aggregate_with_groupby_position_out_of_range() {
 #[test]
 fn select_simple_aggregate_with_groupby_can_use_alias() {
     let plan =
-        generate_logical_plan("SELECT state AS a, MIN(age) AS b FROM person 
GROUP BY a");
+        logical_plan("SELECT state AS a, MIN(age) AS b FROM person GROUP BY 
a").unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -1668,9 +1791,9 @@ fn 
select_simple_aggregate_with_groupby_aggregate_repeated() {
 
 #[test]
 fn select_simple_aggregate_with_groupby_aggregate_repeated_and_one_has_alias() 
{
-    let plan = generate_logical_plan(
-        "SELECT state, MIN(age), MIN(age) AS ma FROM person GROUP BY state",
-    );
+    let plan =
+        logical_plan("SELECT state, MIN(age), MIN(age) AS ma FROM person GROUP 
BY state")
+            .unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -1684,7 +1807,7 @@ fn 
select_simple_aggregate_with_groupby_aggregate_repeated_and_one_has_alias() {
 #[test]
 fn select_simple_aggregate_with_groupby_non_column_expression_unselected() {
     let plan =
-        generate_logical_plan("SELECT MIN(first_name) FROM person GROUP BY age 
+ 1");
+        logical_plan("SELECT MIN(first_name) FROM person GROUP BY age + 
1").unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -1697,9 +1820,9 @@ fn 
select_simple_aggregate_with_groupby_non_column_expression_unselected() {
 
 #[test]
 fn 
select_simple_aggregate_with_groupby_non_column_expression_selected_and_resolvable()
 {
-    let plan = generate_logical_plan(
-        "SELECT age + 1, MIN(first_name) FROM person GROUP BY age + 1",
-    );
+    let plan =
+        logical_plan("SELECT age + 1, MIN(first_name) FROM person GROUP BY age 
+ 1")
+            .unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -1708,9 +1831,9 @@ fn 
select_simple_aggregate_with_groupby_non_column_expression_selected_and_resol
             TableScan: person
         "#
     );
-    let plan = generate_logical_plan(
-        "SELECT MIN(first_name), age + 1 FROM person GROUP BY age + 1",
-    );
+    let plan =
+        logical_plan("SELECT MIN(first_name), age + 1 FROM person GROUP BY age 
+ 1")
+            .unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -1723,9 +1846,9 @@ fn 
select_simple_aggregate_with_groupby_non_column_expression_selected_and_resol
 
 #[test]
 fn 
select_simple_aggregate_with_groupby_non_column_expression_nested_and_resolvable()
 {
-    let plan = generate_logical_plan(
+    let plan = logical_plan(
         "SELECT ((age + 1) / 2) * (age + 1), MIN(first_name) FROM person GROUP 
BY age + 1"
-    );
+    ).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -1766,48 +1889,63 @@ fn 
select_simple_aggregate_with_groupby_non_column_expression_and_its_column_sel
 
 #[test]
 fn select_simple_aggregate_nested_in_binary_expr_with_groupby() {
-    quick_test(
-        "SELECT state, MIN(age) < 10 FROM person GROUP BY state",
-        "Projection: person.state, min(person.age) < Int64(10)\
-             \n  Aggregate: groupBy=[[person.state]], aggr=[[min(person.age)]]\
-             \n    TableScan: person",
+    let plan =
+        logical_plan("SELECT state, MIN(age) < 10 FROM person GROUP BY 
state").unwrap();
+    assert_snapshot!(
+        plan,
+        @r#"
+        Projection: person.state, min(person.age) < Int64(10)
+          Aggregate: groupBy=[[person.state]], aggr=[[min(person.age)]]
+            TableScan: person
+        "#
     );
 }
 
 #[test]
 fn select_simple_aggregate_and_nested_groupby_column() {
-    quick_test(
-        "SELECT age + 1, MAX(first_name) FROM person GROUP BY age",
-        "Projection: person.age + Int64(1), max(person.first_name)\
-             \n  Aggregate: groupBy=[[person.age]], 
aggr=[[max(person.first_name)]]\
-             \n    TableScan: person",
+    let plan =
+        logical_plan("SELECT MAX(first_name), age + 1 FROM person GROUP BY 
age").unwrap();
+    assert_snapshot!(
+        plan,
+        @r#"
+        Projection: max(person.first_name), person.age + Int64(1)
+          Aggregate: groupBy=[[person.age]], aggr=[[max(person.first_name)]]
+            TableScan: person
+        "#
     );
 }
 
 #[test]
 fn select_aggregate_compounded_with_groupby_column() {
-    quick_test(
-        "SELECT age + MIN(salary) FROM person GROUP BY age",
-        "Projection: person.age + min(person.salary)\
-             \n  Aggregate: groupBy=[[person.age]], 
aggr=[[min(person.salary)]]\
-             \n    TableScan: person",
+    let plan = logical_plan("SELECT age + MIN(salary) FROM person GROUP BY 
age").unwrap();
+    assert_snapshot!(
+        plan,
+        @r#"
+        Projection: person.age + min(person.salary)
+          Aggregate: groupBy=[[person.age]], aggr=[[min(person.salary)]]
+            TableScan: person
+        "#
     );
 }
 
 #[test]
 fn select_aggregate_with_non_column_inner_expression_with_groupby() {
-    quick_test(
-        "SELECT state, MIN(age + 1) FROM person GROUP BY state",
-        "Projection: person.state, min(person.age + Int64(1))\
-            \n  Aggregate: groupBy=[[person.state]], aggr=[[min(person.age + 
Int64(1))]]\
-            \n    TableScan: person",
+    let plan =
+        logical_plan("SELECT state, MIN(age + 1) FROM person GROUP BY 
state").unwrap();
+    assert_snapshot!(
+        plan,
+        @r#"
+        Projection: person.state, min(person.age + Int64(1))
+          Aggregate: groupBy=[[person.state]], aggr=[[min(person.age + 
Int64(1))]]
+            TableScan: person
+        "#
     );
 }
 
 #[test]
 fn select_count_one() {
     let sql = "SELECT count(1) FROM person";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -1821,7 +1959,7 @@ Projection: count(Int64(1))
 #[test]
 fn select_count_column() {
     let sql = "SELECT count(id) FROM person";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -1835,7 +1973,7 @@ Projection: count(person.id)
 #[test]
 fn select_approx_median() {
     let sql = "SELECT approx_median(age) FROM person";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -1849,7 +1987,7 @@ Projection: approx_median(person.age)
 #[test]
 fn select_scalar_func() {
     let sql = "SELECT sqrt(age) FROM person";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -1862,7 +2000,7 @@ Projection: sqrt(person.age)
 #[test]
 fn select_aliased_scalar_func() {
     let sql = "SELECT sqrt(person.age) AS square_people FROM person";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -1876,7 +2014,7 @@ Projection: sqrt(person.age) AS square_people
 fn select_where_nullif_division() {
     let sql = "SELECT c3/(c4+c5) \
                    FROM aggregate_test_100 WHERE c3/nullif(c4+c5, 0) > 0.1";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -1890,7 +2028,7 @@ Projection: aggregate_test_100.c3 / 
(aggregate_test_100.c4 + aggregate_test_100.
 #[test]
 fn select_where_with_negative_operator() {
     let sql = "SELECT c3 FROM aggregate_test_100 WHERE c3 > -0.1 AND -c4 > 0";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -1904,7 +2042,7 @@ Projection: aggregate_test_100.c3
 #[test]
 fn select_where_with_positive_operator() {
     let sql = "SELECT c3 FROM aggregate_test_100 WHERE c3 > +0.1 AND +c4 > 0";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -1920,7 +2058,7 @@ fn select_where_compound_identifiers() {
     let sql = "SELECT aggregate_test_100.c3 \
     FROM public.aggregate_test_100 \
     WHERE aggregate_test_100.c3 > 0.1";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -1934,7 +2072,7 @@ Projection: public.aggregate_test_100.c3
 #[test]
 fn select_order_by_index() {
     let sql = "SELECT id FROM person ORDER BY 1";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -1948,7 +2086,7 @@ Sort: person.id ASC NULLS LAST
 #[test]
 fn select_order_by_multiple_index() {
     let sql = "SELECT id, state, age FROM person ORDER BY 1, 3";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -1990,74 +2128,102 @@ fn select_order_by_index_oob() {
 }
 
 #[test]
-fn select_order_by() {
+fn select_with_order_by() {
     let sql = "SELECT id FROM person ORDER BY id";
-    let expected = "Sort: person.id ASC NULLS LAST\
-                        \n  Projection: person.id\
-                        \n    TableScan: person";
-    quick_test(sql, expected);
+    let plan = logical_plan(sql).unwrap();
+    assert_snapshot!(
+        plan,
+        @r#"
+Sort: person.id ASC NULLS LAST
+  Projection: person.id
+    TableScan: person
+"#
+    );
 }
 
 #[test]
 fn select_order_by_desc() {
     let sql = "SELECT id FROM person ORDER BY id DESC";
-    let expected = "Sort: person.id DESC NULLS FIRST\
-                        \n  Projection: person.id\
-                        \n    TableScan: person";
-    quick_test(sql, expected);
+    let plan = logical_plan(sql).unwrap();
+    assert_snapshot!(
+        plan,
+        @r#"
+Sort: person.id DESC NULLS FIRST
+  Projection: person.id
+    TableScan: person
+"#
+    );
 }
 
 #[test]
 fn select_order_by_nulls_last() {
-    quick_test(
-        "SELECT id FROM person ORDER BY id DESC NULLS LAST",
-        "Sort: person.id DESC NULLS LAST\
-            \n  Projection: person.id\
-            \n    TableScan: person",
+    let plan = logical_plan("SELECT id FROM person ORDER BY id DESC NULLS 
LAST").unwrap();
+    assert_snapshot!(
+        plan,
+        @r#"
+Sort: person.id DESC NULLS LAST
+  Projection: person.id
+    TableScan: person
+"#
     );
 
-    quick_test(
-        "SELECT id FROM person ORDER BY id NULLS LAST",
-        "Sort: person.id ASC NULLS LAST\
-            \n  Projection: person.id\
-            \n    TableScan: person",
+    let plan = logical_plan("SELECT id FROM person ORDER BY id NULLS 
LAST").unwrap();
+    assert_snapshot!(
+        plan,
+        @r#"
+Sort: person.id ASC NULLS LAST
+  Projection: person.id
+    TableScan: person
+"#
     );
 }
 
 #[test]
 fn select_group_by() {
     let sql = "SELECT state FROM person GROUP BY state";
-    let expected = "Projection: person.state\
-                        \n  Aggregate: groupBy=[[person.state]], aggr=[[]]\
-                        \n    TableScan: person";
-
-    quick_test(sql, expected);
+    let plan = logical_plan(sql).unwrap();
+    assert_snapshot!(
+        plan,
+        @r#"
+Projection: person.state
+  Aggregate: groupBy=[[person.state]], aggr=[[]]
+    TableScan: person
+"#
+    );
 }
 
 #[test]
 fn select_group_by_columns_not_in_select() {
     let sql = "SELECT MAX(age) FROM person GROUP BY state";
-    let expected = "Projection: max(person.age)\
-                        \n  Aggregate: groupBy=[[person.state]], 
aggr=[[max(person.age)]]\
-                        \n    TableScan: person";
-
-    quick_test(sql, expected);
+    let plan = logical_plan(sql).unwrap();
+    assert_snapshot!(
+        plan,
+        @r#"
+Projection: max(person.age)
+  Aggregate: groupBy=[[person.state]], aggr=[[max(person.age)]]
+    TableScan: person
+"#
+    );
 }
 
 #[test]
 fn select_group_by_count_star() {
     let sql = "SELECT state, count(*) FROM person GROUP BY state";
-    let expected = "Projection: person.state, count(*)\
-                        \n  Aggregate: groupBy=[[person.state]], 
aggr=[[count(*)]]\
-                        \n    TableScan: person";
-
-    quick_test(sql, expected);
+    let plan = logical_plan(sql).unwrap();
+    assert_snapshot!(
+        plan,
+        @r#"
+Projection: person.state, count(*)
+  Aggregate: groupBy=[[person.state]], aggr=[[count(*)]]
+    TableScan: person
+"#
+    );
 }
 
 #[test]
 fn select_group_by_needs_projection() {
     let sql = "SELECT count(state), state FROM person GROUP BY state";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -2071,10 +2237,15 @@ fn select_group_by_needs_projection() {
 #[test]
 fn select_7480_1() {
     let sql = "SELECT c1, MIN(c12) FROM aggregate_test_100 GROUP BY c1, c13";
-    let expected = "Projection: aggregate_test_100.c1, 
min(aggregate_test_100.c12)\
-                       \n  Aggregate: groupBy=[[aggregate_test_100.c1, 
aggregate_test_100.c13]], aggr=[[min(aggregate_test_100.c12)]]\
-                       \n    TableScan: aggregate_test_100";
-    quick_test(sql, expected);
+    let plan = logical_plan(sql).unwrap();
+    assert_snapshot!(
+        plan,
+        @r#"
+Projection: aggregate_test_100.c1, min(aggregate_test_100.c12)
+  Aggregate: groupBy=[[aggregate_test_100.c1, aggregate_test_100.c13]], 
aggr=[[min(aggregate_test_100.c12)]]
+    TableScan: aggregate_test_100
+"#
+    );
 }
 
 #[test]
@@ -2093,14 +2264,19 @@ fn select_7480_2() {
 #[test]
 fn create_external_table_csv() {
     let sql = "CREATE EXTERNAL TABLE t(c1 int) STORED AS CSV LOCATION 
'foo.csv'";
-    let expected = "CreateExternalTable: Bare { table: \"t\" }";
-    quick_test(sql, expected);
+    let plan = logical_plan(sql).unwrap();
+    assert_snapshot!(
+        plan,
+        @r#"
+CreateExternalTable: Bare { table: "t" }
+"#
+    );
 }
 
 #[test]
 fn create_external_table_with_pk() {
     let sql = "CREATE EXTERNAL TABLE t(c1 int, primary key(c1)) STORED AS CSV 
LOCATION 'foo.csv'";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -2112,7 +2288,7 @@ CreateExternalTable: Bare { table: "t" } 
constraints=[PrimaryKey([0])]
 #[test]
 fn create_external_table_wih_schema() {
     let sql = "CREATE EXTERNAL TABLE staging.foo STORED AS CSV LOCATION 
'foo.csv'";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -2124,7 +2300,7 @@ CreateExternalTable: Partial { schema: "staging", table: 
"foo" }
 #[test]
 fn create_schema_with_quoted_name() {
     let sql = "CREATE SCHEMA \"quoted_schema_name\"";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -2136,7 +2312,7 @@ CreateCatalogSchema: "quoted_schema_name"
 #[test]
 fn create_schema_with_quoted_unnormalized_name() {
     let sql = "CREATE SCHEMA \"Foo\"";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -2148,7 +2324,7 @@ CreateCatalogSchema: "Foo"
 #[test]
 fn create_schema_with_unquoted_normalized_name() {
     let sql = "CREATE SCHEMA Foo";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -2160,14 +2336,19 @@ CreateCatalogSchema: "foo"
 #[test]
 fn create_external_table_custom() {
     let sql = "CREATE EXTERNAL TABLE dt STORED AS DELTATABLE LOCATION 
's3://bucket/schema/table';";
-    let expected = r#"CreateExternalTable: Bare { table: "dt" }"#;
-    quick_test(sql, expected);
+    let plan = logical_plan(sql).unwrap();
+    assert_snapshot!(
+        plan,
+        @r#"
+CreateExternalTable: Bare { table: "dt" }
+"#
+    );
 }
 
 #[test]
 fn create_external_table_csv_no_schema() {
     let sql = "CREATE EXTERNAL TABLE t STORED AS CSV LOCATION 'foo.csv'";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -2186,9 +2367,18 @@ fn create_external_table_with_compression_type() {
         "CREATE EXTERNAL TABLE t(c1 int) STORED AS JSON LOCATION 
'foo.json.bz2' OPTIONS ('format.compression' 'bzip2')",
         "CREATE EXTERNAL TABLE t(c1 int) STORED AS NONSTANDARD LOCATION 
'foo.unk' OPTIONS ('format.compression' 'gzip')",
          ];
-    for sql in sqls {
-        let expected = "CreateExternalTable: Bare { table: \"t\" }";
-        quick_test(sql, expected);
+
+    allow_duplicates! {
+        for sql in sqls {
+            let plan = logical_plan(sql).unwrap();
+            assert_snapshot!(
+                plan,
+                @r#"
+                CreateExternalTable: Bare { table: "t" }
+                "#
+            );
+        }
+
     }
 
     // negative case
@@ -2219,29 +2409,47 @@ fn create_external_table_with_compression_type() {
 #[test]
 fn create_external_table_parquet() {
     let sql = "CREATE EXTERNAL TABLE t(c1 int) STORED AS PARQUET LOCATION 
'foo.parquet'";
-    let expected = "CreateExternalTable: Bare { table: \"t\" }";
-    quick_test(sql, expected);
+    let plan = logical_plan(sql).unwrap();
+    assert_snapshot!(
+        plan,
+        @r#"
+CreateExternalTable: Bare { table: "t" }
+"#
+    );
 }
 
 #[test]
 fn create_external_table_parquet_sort_order() {
     let sql = "create external table foo(a varchar, b varchar, c timestamp) 
stored as parquet location '/tmp/foo' with order (c)";
-    let expected = "CreateExternalTable: Bare { table: \"foo\" }";
-    quick_test(sql, expected);
+    let plan = logical_plan(sql).unwrap();
+    assert_snapshot!(
+        plan,
+        @r#"
+CreateExternalTable: Bare { table: "foo" }
+"#
+    );
 }
 
 #[test]
 fn create_external_table_parquet_no_schema() {
     let sql = "CREATE EXTERNAL TABLE t STORED AS PARQUET LOCATION 
'foo.parquet'";
-    let expected = "CreateExternalTable: Bare { table: \"t\" }";
-    quick_test(sql, expected);
+    let plan = logical_plan(sql).unwrap();
+    assert_snapshot!(
+        plan,
+        @r#"CreateExternalTable: Bare { table: "t" }"#
+    );
 }
 
 #[test]
 fn create_external_table_parquet_no_schema_sort_order() {
     let sql = "CREATE EXTERNAL TABLE t STORED AS PARQUET LOCATION 
'foo.parquet' WITH ORDER (id)";
-    let expected = "CreateExternalTable: Bare { table: \"t\" }";
-    quick_test(sql, expected);
+    let plan = logical_plan(sql).unwrap();
+    assert_snapshot!(
+        plan,
+        @r#"
+CreateExternalTable: Bare { table: "t" }
+"#
+    );
 }
 
 #[test]
@@ -2250,11 +2458,16 @@ fn equijoin_explicit_syntax() {
             FROM person \
             JOIN orders \
             ON id = customer_id";
-    let expected = "Projection: person.id, orders.order_id\
-            \n  Inner Join:  Filter: person.id = orders.customer_id\
-            \n    TableScan: person\
-            \n    TableScan: orders";
-    quick_test(sql, expected);
+    let plan = logical_plan(sql).unwrap();
+    assert_snapshot!(
+        plan,
+        @r#"
+Projection: person.id, orders.order_id
+  Inner Join:  Filter: person.id = orders.customer_id
+    TableScan: person
+    TableScan: orders
+"#
+    );
 }
 
 #[test]
@@ -2263,12 +2476,16 @@ fn equijoin_with_condition() {
             FROM person \
             JOIN orders \
             ON id = customer_id AND order_id > 1 ";
-    let expected = "Projection: person.id, orders.order_id\
-            \n  Inner Join:  Filter: person.id = orders.customer_id AND 
orders.order_id > Int64(1)\
-            \n    TableScan: person\
-            \n    TableScan: orders";
-
-    quick_test(sql, expected);
+    let plan = logical_plan(sql).unwrap();
+    assert_snapshot!(
+        plan,
+        @r#"
+Projection: person.id, orders.order_id
+  Inner Join:  Filter: person.id = orders.customer_id AND orders.order_id > 
Int64(1)
+    TableScan: person
+    TableScan: orders
+"#
+    );
 }
 
 #[test]
@@ -2277,11 +2494,16 @@ fn left_equijoin_with_conditions() {
             FROM person \
             LEFT JOIN orders \
             ON id = customer_id AND order_id > 1 AND age < 30";
-    let expected = "Projection: person.id, orders.order_id\
-            \n  Left Join:  Filter: person.id = orders.customer_id AND 
orders.order_id > Int64(1) AND person.age < Int64(30)\
-            \n    TableScan: person\
-            \n    TableScan: orders";
-    quick_test(sql, expected);
+    let plan = logical_plan(sql).unwrap();
+    assert_snapshot!(
+        plan,
+        @r#"
+Projection: person.id, orders.order_id
+  Left Join:  Filter: person.id = orders.customer_id AND orders.order_id > 
Int64(1) AND person.age < Int64(30)
+    TableScan: person
+    TableScan: orders
+"#
+    );
 }
 
 #[test]
@@ -2290,7 +2512,7 @@ fn right_equijoin_with_conditions() {
             FROM person \
             RIGHT JOIN orders \
             ON id = customer_id AND id > 1 AND order_id < 100";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -2308,7 +2530,7 @@ fn full_equijoin_with_conditions() {
             FROM person \
             FULL JOIN orders \
             ON id = customer_id AND id > 1 AND order_id < 100";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -2326,7 +2548,7 @@ fn join_with_table_name() {
             FROM person \
             JOIN orders \
             ON person.id = orders.customer_id";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -2344,7 +2566,7 @@ fn join_with_using() {
             FROM person \
             JOIN person as person2 \
             USING (id)";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -2363,7 +2585,7 @@ fn equijoin_explicit_syntax_3_tables() {
             FROM person \
             JOIN orders ON id = customer_id \
             JOIN lineitem ON o_item_id = l_item_id";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -2382,7 +2604,7 @@ fn boolean_literal_in_condition_expression() {
     let sql = "SELECT order_id \
         FROM orders \
         WHERE delivered = false OR delivered = true";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -2396,7 +2618,7 @@ Projection: orders.order_id
 #[test]
 fn union() {
     let sql = "SELECT order_id from orders UNION SELECT order_id FROM orders";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -2413,7 +2635,7 @@ Distinct:
 #[test]
 fn union_by_name_different_columns() {
     let sql = "SELECT order_id from orders UNION BY NAME SELECT order_id, 1 
FROM orders";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -2432,7 +2654,7 @@ Distinct:
 #[test]
 fn union_by_name_same_column_names() {
     let sql = "SELECT order_id from orders UNION SELECT order_id FROM orders";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -2449,7 +2671,7 @@ Distinct:
 #[test]
 fn union_all() {
     let sql = "SELECT order_id from orders UNION ALL SELECT order_id FROM 
orders";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -2466,7 +2688,7 @@ Union
 fn union_all_by_name_different_columns() {
     let sql =
         "SELECT order_id from orders UNION ALL BY NAME SELECT order_id, 1 FROM 
orders";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -2484,7 +2706,7 @@ Union
 #[test]
 fn union_all_by_name_same_column_names() {
     let sql = "SELECT order_id from orders UNION ALL BY NAME SELECT order_id 
FROM orders";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -2502,7 +2724,7 @@ Union
 #[test]
 fn empty_over() {
     let sql = "SELECT order_id, MAX(order_id) OVER () from orders";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -2516,7 +2738,7 @@ Projection: orders.order_id, max(orders.order_id) ROWS 
BETWEEN UNBOUNDED PRECEDI
 #[test]
 fn empty_over_with_alias() {
     let sql = "SELECT order_id oid, MAX(order_id) OVER () max_oid from orders";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -2530,7 +2752,7 @@ Projection: orders.order_id AS oid, max(orders.order_id) 
ROWS BETWEEN UNBOUNDED
 #[test]
 fn empty_over_dup_with_alias() {
     let sql = "SELECT order_id oid, MAX(order_id) OVER () max_oid, 
MAX(order_id) OVER () max_oid_dup from orders";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -2544,7 +2766,7 @@ Projection: orders.order_id AS oid, max(orders.order_id) 
ROWS BETWEEN UNBOUNDED
 #[test]
 fn empty_over_dup_with_different_sort() {
     let sql = "SELECT order_id oid, MAX(order_id) OVER (), MAX(order_id) OVER 
(ORDER BY order_id) from orders";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -2559,7 +2781,7 @@ Projection: orders.order_id AS oid, max(orders.order_id) 
ROWS BETWEEN UNBOUNDED
 #[test]
 fn empty_over_plus() {
     let sql = "SELECT order_id, MAX(qty * 1.1) OVER () from orders";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -2573,7 +2795,7 @@ Projection: orders.order_id, max(orders.qty * 
Float64(1.1)) ROWS BETWEEN UNBOUND
 #[test]
 fn empty_over_multiple() {
     let sql = "SELECT order_id, MAX(qty) OVER (), min(qty) over (), avg(qty) 
OVER () from orders";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -2596,7 +2818,7 @@ Projection: orders.order_id, max(orders.qty) ROWS BETWEEN 
UNBOUNDED PRECEDING AN
 #[test]
 fn over_partition_by() {
     let sql = "SELECT order_id, MAX(qty) OVER (PARTITION BY order_id) from 
orders";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -2622,7 +2844,7 @@ Projection: orders.order_id, max(orders.qty) PARTITION BY 
[orders.order_id] ROWS
 #[test]
 fn over_order_by() {
     let sql = "SELECT order_id, MAX(qty) OVER (ORDER BY order_id), MIN(qty) 
OVER (ORDER BY order_id DESC) from orders";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -2637,7 +2859,7 @@ Projection: orders.order_id, max(orders.qty) ORDER BY 
[orders.order_id ASC NULLS
 #[test]
 fn over_order_by_with_window_frame_double_end() {
     let sql = "SELECT order_id, MAX(qty) OVER (ORDER BY order_id ROWS BETWEEN 
3 PRECEDING and 3 FOLLOWING), MIN(qty) OVER (ORDER BY order_id DESC) from 
orders";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -2652,7 +2874,7 @@ Projection: orders.order_id, max(orders.qty) ORDER BY 
[orders.order_id ASC NULLS
 #[test]
 fn over_order_by_with_window_frame_single_end() {
     let sql = "SELECT order_id, MAX(qty) OVER (ORDER BY order_id ROWS 3 
PRECEDING), MIN(qty) OVER (ORDER BY order_id DESC) from orders";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -2667,7 +2889,7 @@ Projection: orders.order_id, max(orders.qty) ORDER BY 
[orders.order_id ASC NULLS
 #[test]
 fn over_order_by_with_window_frame_single_end_groups() {
     let sql = "SELECT order_id, MAX(qty) OVER (ORDER BY order_id GROUPS 3 
PRECEDING), MIN(qty) OVER (ORDER BY order_id DESC) from orders";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -2694,12 +2916,16 @@ Projection: orders.order_id, max(orders.qty) ORDER BY 
[orders.order_id ASC NULLS
 #[test]
 fn over_order_by_two_sort_keys() {
     let sql = "SELECT order_id, MAX(qty) OVER (ORDER BY order_id), MIN(qty) 
OVER (ORDER BY (order_id + 1)) from orders";
-    let expected = "\
-        Projection: orders.order_id, max(orders.qty) ORDER BY [orders.order_id 
ASC NULLS LAST] RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW, 
min(orders.qty) ORDER BY [orders.order_id + Int64(1) ASC NULLS LAST] RANGE 
BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW\
-        \n  WindowAggr: windowExpr=[[max(orders.qty) ORDER BY [orders.order_id 
ASC NULLS LAST] RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW]]\
-        \n    WindowAggr: windowExpr=[[min(orders.qty) ORDER BY 
[orders.order_id + Int64(1) ASC NULLS LAST] RANGE BETWEEN UNBOUNDED PRECEDING 
AND CURRENT ROW]]\
-        \n      TableScan: orders";
-    quick_test(sql, expected);
+    let plan = logical_plan(sql).unwrap();
+    assert_snapshot!(
+        plan,
+        @r#"
+Projection: orders.order_id, max(orders.qty) ORDER BY [orders.order_id ASC 
NULLS LAST] RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW, min(orders.qty) 
ORDER BY [orders.order_id + Int64(1) ASC NULLS LAST] RANGE BETWEEN UNBOUNDED 
PRECEDING AND CURRENT ROW
+  WindowAggr: windowExpr=[[max(orders.qty) ORDER BY [orders.order_id ASC NULLS 
LAST] RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW]]
+    WindowAggr: windowExpr=[[min(orders.qty) ORDER BY [orders.order_id + 
Int64(1) ASC NULLS LAST] RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW]]
+      TableScan: orders
+"#
+    );
 }
 
 /// psql result
@@ -2718,13 +2944,17 @@ fn over_order_by_two_sort_keys() {
 #[test]
 fn over_order_by_sort_keys_sorting() {
     let sql = "SELECT order_id, MAX(qty) OVER (ORDER BY qty, order_id), 
sum(qty) OVER (), MIN(qty) OVER (ORDER BY order_id, qty) from orders";
-    let expected = "\
-        Projection: orders.order_id, max(orders.qty) ORDER BY [orders.qty ASC 
NULLS LAST, orders.order_id ASC NULLS LAST] RANGE BETWEEN UNBOUNDED PRECEDING 
AND CURRENT ROW, sum(orders.qty) ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED 
FOLLOWING, min(orders.qty) ORDER BY [orders.order_id ASC NULLS LAST, orders.qty 
ASC NULLS LAST] RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW\
-        \n  WindowAggr: windowExpr=[[sum(orders.qty) ROWS BETWEEN UNBOUNDED 
PRECEDING AND UNBOUNDED FOLLOWING]]\
-        \n    WindowAggr: windowExpr=[[max(orders.qty) ORDER BY [orders.qty 
ASC NULLS LAST, orders.order_id ASC NULLS LAST] RANGE BETWEEN UNBOUNDED 
PRECEDING AND CURRENT ROW]]\
-        \n      WindowAggr: windowExpr=[[min(orders.qty) ORDER BY 
[orders.order_id ASC NULLS LAST, orders.qty ASC NULLS LAST] RANGE BETWEEN 
UNBOUNDED PRECEDING AND CURRENT ROW]]\
-        \n        TableScan: orders";
-    quick_test(sql, expected);
+    let plan = logical_plan(sql).unwrap();
+    assert_snapshot!(
+        plan,
+        @r#"
+Projection: orders.order_id, max(orders.qty) ORDER BY [orders.qty ASC NULLS 
LAST, orders.order_id ASC NULLS LAST] RANGE BETWEEN UNBOUNDED PRECEDING AND 
CURRENT ROW, sum(orders.qty) ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED 
FOLLOWING, min(orders.qty) ORDER BY [orders.order_id ASC NULLS LAST, orders.qty 
ASC NULLS LAST] RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
+  WindowAggr: windowExpr=[[sum(orders.qty) ROWS BETWEEN UNBOUNDED PRECEDING 
AND UNBOUNDED FOLLOWING]]
+    WindowAggr: windowExpr=[[max(orders.qty) ORDER BY [orders.qty ASC NULLS 
LAST, orders.order_id ASC NULLS LAST] RANGE BETWEEN UNBOUNDED PRECEDING AND 
CURRENT ROW]]
+      WindowAggr: windowExpr=[[min(orders.qty) ORDER BY [orders.order_id ASC 
NULLS LAST, orders.qty ASC NULLS LAST] RANGE BETWEEN UNBOUNDED PRECEDING AND 
CURRENT ROW]]
+        TableScan: orders
+"#
+    );
 }
 
 /// psql result
@@ -2741,13 +2971,17 @@ fn over_order_by_sort_keys_sorting() {
 #[test]
 fn over_order_by_sort_keys_sorting_prefix_compacting() {
     let sql = "SELECT order_id, MAX(qty) OVER (ORDER BY order_id), sum(qty) 
OVER (), MIN(qty) OVER (ORDER BY order_id, qty) from orders";
-    let expected = "\
-        Projection: orders.order_id, max(orders.qty) ORDER BY [orders.order_id 
ASC NULLS LAST] RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW, 
sum(orders.qty) ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING, 
min(orders.qty) ORDER BY [orders.order_id ASC NULLS LAST, orders.qty ASC NULLS 
LAST] RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW\
-        \n  WindowAggr: windowExpr=[[sum(orders.qty) ROWS BETWEEN UNBOUNDED 
PRECEDING AND UNBOUNDED FOLLOWING]]\
-        \n    WindowAggr: windowExpr=[[max(orders.qty) ORDER BY 
[orders.order_id ASC NULLS LAST] RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT 
ROW]]\
-        \n      WindowAggr: windowExpr=[[min(orders.qty) ORDER BY 
[orders.order_id ASC NULLS LAST, orders.qty ASC NULLS LAST] RANGE BETWEEN 
UNBOUNDED PRECEDING AND CURRENT ROW]]\
-        \n        TableScan: orders";
-    quick_test(sql, expected);
+    let plan = logical_plan(sql).unwrap();
+    assert_snapshot!(
+        plan,
+        @r#"
+Projection: orders.order_id, max(orders.qty) ORDER BY [orders.order_id ASC 
NULLS LAST] RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW, sum(orders.qty) 
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING, min(orders.qty) ORDER 
BY [orders.order_id ASC NULLS LAST, orders.qty ASC NULLS LAST] RANGE BETWEEN 
UNBOUNDED PRECEDING AND CURRENT ROW
+  WindowAggr: windowExpr=[[sum(orders.qty) ROWS BETWEEN UNBOUNDED PRECEDING 
AND UNBOUNDED FOLLOWING]]
+    WindowAggr: windowExpr=[[max(orders.qty) ORDER BY [orders.order_id ASC 
NULLS LAST] RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW]]
+      WindowAggr: windowExpr=[[min(orders.qty) ORDER BY [orders.order_id ASC 
NULLS LAST, orders.qty ASC NULLS LAST] RANGE BETWEEN UNBOUNDED PRECEDING AND 
CURRENT ROW]]
+        TableScan: orders
+"#
+    );
 }
 
 /// psql result
@@ -2769,14 +3003,18 @@ fn over_order_by_sort_keys_sorting_prefix_compacting() {
 #[test]
 fn over_order_by_sort_keys_sorting_global_order_compacting() {
     let sql = "SELECT order_id, MAX(qty) OVER (ORDER BY qty, order_id), 
sum(qty) OVER (), MIN(qty) OVER (ORDER BY order_id, qty) from orders ORDER BY 
order_id";
-    let expected = "\
-        Sort: orders.order_id ASC NULLS LAST\
-        \n  Projection: orders.order_id, max(orders.qty) ORDER BY [orders.qty 
ASC NULLS LAST, orders.order_id ASC NULLS LAST] RANGE BETWEEN UNBOUNDED 
PRECEDING AND CURRENT ROW, sum(orders.qty) ROWS BETWEEN UNBOUNDED PRECEDING AND 
UNBOUNDED FOLLOWING, min(orders.qty) ORDER BY [orders.order_id ASC NULLS LAST, 
orders.qty ASC NULLS LAST] RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW\
-        \n    WindowAggr: windowExpr=[[sum(orders.qty) ROWS BETWEEN UNBOUNDED 
PRECEDING AND UNBOUNDED FOLLOWING]]\
-        \n      WindowAggr: windowExpr=[[max(orders.qty) ORDER BY [orders.qty 
ASC NULLS LAST, orders.order_id ASC NULLS LAST] RANGE BETWEEN UNBOUNDED 
PRECEDING AND CURRENT ROW]]\
-        \n        WindowAggr: windowExpr=[[min(orders.qty) ORDER BY 
[orders.order_id ASC NULLS LAST, orders.qty ASC NULLS LAST] RANGE BETWEEN 
UNBOUNDED PRECEDING AND CURRENT ROW]]\
-        \n          TableScan: orders";
-    quick_test(sql, expected);
+    let plan = logical_plan(sql).unwrap();
+    assert_snapshot!(
+        plan,
+        @r#"
+Sort: orders.order_id ASC NULLS LAST
+  Projection: orders.order_id, max(orders.qty) ORDER BY [orders.qty ASC NULLS 
LAST, orders.order_id ASC NULLS LAST] RANGE BETWEEN UNBOUNDED PRECEDING AND 
CURRENT ROW, sum(orders.qty) ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED 
FOLLOWING, min(orders.qty) ORDER BY [orders.order_id ASC NULLS LAST, orders.qty 
ASC NULLS LAST] RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
+    WindowAggr: windowExpr=[[sum(orders.qty) ROWS BETWEEN UNBOUNDED PRECEDING 
AND UNBOUNDED FOLLOWING]]
+      WindowAggr: windowExpr=[[max(orders.qty) ORDER BY [orders.qty ASC NULLS 
LAST, orders.order_id ASC NULLS LAST] RANGE BETWEEN UNBOUNDED PRECEDING AND 
CURRENT ROW]]
+        WindowAggr: windowExpr=[[min(orders.qty) ORDER BY [orders.order_id ASC 
NULLS LAST, orders.qty ASC NULLS LAST] RANGE BETWEEN UNBOUNDED PRECEDING AND 
CURRENT ROW]]
+          TableScan: orders
+"#
+    );
 }
 
 /// psql result
@@ -2792,11 +3030,15 @@ fn 
over_order_by_sort_keys_sorting_global_order_compacting() {
 fn over_partition_by_order_by() {
     let sql =
         "SELECT order_id, MAX(qty) OVER (PARTITION BY order_id ORDER BY qty) 
from orders";
-    let expected = "\
-        Projection: orders.order_id, max(orders.qty) PARTITION BY 
[orders.order_id] ORDER BY [orders.qty ASC NULLS LAST] RANGE BETWEEN UNBOUNDED 
PRECEDING AND CURRENT ROW\
-        \n  WindowAggr: windowExpr=[[max(orders.qty) PARTITION BY 
[orders.order_id] ORDER BY [orders.qty ASC NULLS LAST] RANGE BETWEEN UNBOUNDED 
PRECEDING AND CURRENT ROW]]\
-        \n    TableScan: orders";
-    quick_test(sql, expected);
+    let plan = logical_plan(sql).unwrap();
+    assert_snapshot!(
+        plan,
+        @r#"
+Projection: orders.order_id, max(orders.qty) PARTITION BY [orders.order_id] 
ORDER BY [orders.qty ASC NULLS LAST] RANGE BETWEEN UNBOUNDED PRECEDING AND 
CURRENT ROW
+  WindowAggr: windowExpr=[[max(orders.qty) PARTITION BY [orders.order_id] 
ORDER BY [orders.qty ASC NULLS LAST] RANGE BETWEEN UNBOUNDED PRECEDING AND 
CURRENT ROW]]
+    TableScan: orders
+"#
+    );
 }
 
 /// psql result
@@ -2812,11 +3054,15 @@ fn over_partition_by_order_by() {
 fn over_partition_by_order_by_no_dup() {
     let sql =
         "SELECT order_id, MAX(qty) OVER (PARTITION BY order_id, qty ORDER BY 
qty) from orders";
-    let expected = "\
-        Projection: orders.order_id, max(orders.qty) PARTITION BY 
[orders.order_id, orders.qty] ORDER BY [orders.qty ASC NULLS LAST] RANGE 
BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW\
-        \n  WindowAggr: windowExpr=[[max(orders.qty) PARTITION BY 
[orders.order_id, orders.qty] ORDER BY [orders.qty ASC NULLS LAST] RANGE 
BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW]]\
-        \n    TableScan: orders";
-    quick_test(sql, expected);
+    let plan = logical_plan(sql).unwrap();
+    assert_snapshot!(
+        plan,
+        @r#"
+Projection: orders.order_id, max(orders.qty) PARTITION BY [orders.order_id, 
orders.qty] ORDER BY [orders.qty ASC NULLS LAST] RANGE BETWEEN UNBOUNDED 
PRECEDING AND CURRENT ROW
+  WindowAggr: windowExpr=[[max(orders.qty) PARTITION BY [orders.order_id, 
orders.qty] ORDER BY [orders.qty ASC NULLS LAST] RANGE BETWEEN UNBOUNDED 
PRECEDING AND CURRENT ROW]]
+    TableScan: orders
+"#
+    );
 }
 
 /// psql result
@@ -2835,12 +3081,16 @@ fn over_partition_by_order_by_no_dup() {
 fn over_partition_by_order_by_mix_up() {
     let sql =
             "SELECT order_id, MAX(qty) OVER (PARTITION BY order_id, qty ORDER 
BY qty), MIN(qty) OVER (PARTITION BY qty ORDER BY order_id) from orders";
-    let expected = "\
-        Projection: orders.order_id, max(orders.qty) PARTITION BY 
[orders.order_id, orders.qty] ORDER BY [orders.qty ASC NULLS LAST] RANGE 
BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW, min(orders.qty) PARTITION BY 
[orders.qty] ORDER BY [orders.order_id ASC NULLS LAST] RANGE BETWEEN UNBOUNDED 
PRECEDING AND CURRENT ROW\
-        \n  WindowAggr: windowExpr=[[min(orders.qty) PARTITION BY [orders.qty] 
ORDER BY [orders.order_id ASC NULLS LAST] RANGE BETWEEN UNBOUNDED PRECEDING AND 
CURRENT ROW]]\
-        \n    WindowAggr: windowExpr=[[max(orders.qty) PARTITION BY 
[orders.order_id, orders.qty] ORDER BY [orders.qty ASC NULLS LAST] RANGE 
BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW]]\
-        \n      TableScan: orders";
-    quick_test(sql, expected);
+    let plan = logical_plan(sql).unwrap();
+    assert_snapshot!(
+        plan,
+        @r#"
+Projection: orders.order_id, max(orders.qty) PARTITION BY [orders.order_id, 
orders.qty] ORDER BY [orders.qty ASC NULLS LAST] RANGE BETWEEN UNBOUNDED 
PRECEDING AND CURRENT ROW, min(orders.qty) PARTITION BY [orders.qty] ORDER BY 
[orders.order_id ASC NULLS LAST] RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT 
ROW
+  WindowAggr: windowExpr=[[min(orders.qty) PARTITION BY [orders.qty] ORDER BY 
[orders.order_id ASC NULLS LAST] RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT 
ROW]]
+    WindowAggr: windowExpr=[[max(orders.qty) PARTITION BY [orders.order_id, 
orders.qty] ORDER BY [orders.qty ASC NULLS LAST] RANGE BETWEEN UNBOUNDED 
PRECEDING AND CURRENT ROW]]
+      TableScan: orders
+"#
+    );
 }
 
 /// psql result
@@ -2858,7 +3108,7 @@ fn over_partition_by_order_by_mix_up() {
 fn over_partition_by_order_by_mix_up_prefix() {
     let sql =
             "SELECT order_id, MAX(qty) OVER (PARTITION BY order_id ORDER BY 
qty), MIN(qty) OVER (PARTITION BY order_id, qty ORDER BY price) from orders";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -2874,7 +3124,7 @@ Projection: orders.order_id, max(orders.qty) PARTITION BY 
[orders.order_id] ORDE
 fn approx_median_window() {
     let sql =
         "SELECT order_id, APPROX_MEDIAN(qty) OVER(PARTITION BY order_id) from 
orders";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -2888,7 +3138,7 @@ Projection: orders.order_id, approx_median(orders.qty) 
PARTITION BY [orders.orde
 #[test]
 fn select_typed_date_string() {
     let sql = "SELECT date '2020-12-10' AS date";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -2901,7 +3151,7 @@ Projection: CAST(Utf8("2020-12-10") AS Date32) AS date
 #[test]
 fn select_typed_time_string() {
     let sql = "SELECT TIME '08:09:10.123' AS time";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -2914,51 +3164,65 @@ Projection: CAST(Utf8("08:09:10.123") AS 
Time64(Nanosecond)) AS time
 #[test]
 fn select_multibyte_column() {
     let sql = r#"SELECT "😀" FROM person"#;
-    let expected = "Projection: person.😀\
-            \n  TableScan: person";
-    quick_test(sql, expected);
+    let plan = logical_plan(sql).unwrap();
+    assert_snapshot!(
+        plan,
+        @r#"
+Projection: person.😀
+  TableScan: person
+"#
+    );
 }
 
 #[test]
 fn select_groupby_orderby() {
     // ensure that references are correctly resolved in the order by clause
     // see https://github.com/apache/datafusion/issues/4854
-    let sql = r#"SELECT
-  avg(age) AS "value",
-  date_trunc('month', birth_date) AS "birth_date"
-  FROM person GROUP BY birth_date ORDER BY birth_date;
-"#;
-    // expect that this is not an ambiguous reference
-    let expected =
-        "Sort: birth_date ASC NULLS LAST\
-         \n  Projection: avg(person.age) AS value, date_trunc(Utf8(\"month\"), 
person.birth_date) AS birth_date\
-         \n    Aggregate: groupBy=[[person.birth_date]], 
aggr=[[avg(person.age)]]\
-         \n      TableScan: person";
-    quick_test(sql, expected);
-
-    // Use fully qualified `person.birth_date` as argument to date_trunc, plan 
should be the same
-    let sql = r#"SELECT
-  avg(age) AS "value",
-  date_trunc('month', person.birth_date) AS "birth_date"
-  FROM person GROUP BY birth_date ORDER BY birth_date;
-"#;
-    quick_test(sql, expected);
 
-    // Use fully qualified `person.birth_date` as group by, plan should be the 
same
-    let sql = r#"SELECT
-  avg(age) AS "value",
-  date_trunc('month', birth_date) AS "birth_date"
-  FROM person GROUP BY person.birth_date ORDER BY birth_date;
-"#;
-    quick_test(sql, expected);
-
-    // Use fully qualified `person.birth_date` in both group and date_trunc, 
plan should be the same
-    let sql = r#"SELECT
-  avg(age) AS "value",
-  date_trunc('month', person.birth_date) AS "birth_date"
-  FROM person GROUP BY person.birth_date ORDER BY birth_date;
-"#;
-    quick_test(sql, expected);
+    let sqls = vec![
+        r#"
+        SELECT
+            avg(age) AS "value",
+            date_trunc('month', birth_date) AS "birth_date"
+            FROM person GROUP BY birth_date ORDER BY birth_date;
+        "#,
+        // Use fully qualified `person.birth_date` as argument to date_trunc, 
plan should be the same
+        r#"
+        SELECT
+            avg(age) AS "value",
+            date_trunc('month', person.birth_date) AS "birth_date"
+            FROM person GROUP BY birth_date ORDER BY birth_date;
+        "#,
+        // Use fully qualified `person.birth_date` as group by, plan should be 
the same
+        r#"
+        SELECT
+            avg(age) AS "value",
+            date_trunc('month', birth_date) AS "birth_date"
+            FROM person GROUP BY person.birth_date ORDER BY birth_date;
+        "#,
+        // Use fully qualified `person.birth_date` in both group and 
date_trunc, plan should be the same
+        r#"
+        SELECT
+            avg(age) AS "value",
+            date_trunc('month', person.birth_date) AS "birth_date"
+            FROM person GROUP BY person.birth_date ORDER BY birth_date;
+        "#,
+    ];
+    for sql in sqls {
+        let plan = logical_plan(sql).unwrap();
+        allow_duplicates! {
+            assert_snapshot!(
+                plan,
+                // expect that this is not an ambiguous reference
+                @r#"
+        Sort: birth_date ASC NULLS LAST
+          Projection: avg(person.age) AS value, date_trunc(Utf8("month"), 
person.birth_date) AS birth_date
+            Aggregate: groupBy=[[person.birth_date]], aggr=[[avg(person.age)]]
+              TableScan: person
+        "#
+            );
+        }
+    }
 
     // Use columnized `avg(age)` in the order by
     let sql = r#"SELECT
@@ -2967,13 +3231,16 @@ fn select_groupby_orderby() {
   FROM person GROUP BY person.birth_date ORDER BY avg(age) + avg(age);
 "#;
 
-    let expected =
-        "Sort: avg(person.age) + avg(person.age) ASC NULLS LAST\
-        \n  Projection: avg(person.age) + avg(person.age), 
date_trunc(Utf8(\"month\"), person.birth_date) AS birth_date\
-        \n    Aggregate: groupBy=[[person.birth_date]], 
aggr=[[avg(person.age)]]\
-        \n      TableScan: person";
-
-    quick_test(sql, expected);
+    let plan = logical_plan(sql).unwrap();
+    assert_snapshot!(
+        plan,
+        @r#"
+Sort: avg(person.age) + avg(person.age) ASC NULLS LAST
+  Projection: avg(person.age) + avg(person.age), date_trunc(Utf8("month"), 
person.birth_date) AS birth_date
+    Aggregate: groupBy=[[person.birth_date]], aggr=[[avg(person.age)]]
+      TableScan: person
+"#
+    );
 }
 
 fn logical_plan(sql: &str) -> Result<LogicalPlan> {
@@ -3088,18 +3355,37 @@ impl ScalarUDFImpl for DummyUDF {
     }
 }
 
-/// Create logical plan, write with formatter, compare to expected output
-fn quick_test(sql: &str, expected: &str) {
-    quick_test_with_options(sql, expected, ParserOptions::default())
+fn parse_decimals_parser_options() -> ParserOptions {
+    ParserOptions {
+        parse_float_as_decimal: true,
+        enable_ident_normalization: false,
+        support_varchar_with_length: false,
+        map_varchar_to_utf8view: false,
+        enable_options_value_normalization: false,
+        collect_spans: false,
+    }
 }
 
-fn generate_logical_plan(sql: &str) -> LogicalPlan {
-    logical_plan_with_options(sql, ParserOptions::default()).unwrap()
+fn ident_normalization_parser_options_no_ident_normalization() -> 
ParserOptions {
+    ParserOptions {
+        parse_float_as_decimal: true,
+        enable_ident_normalization: false,
+        support_varchar_with_length: false,
+        map_varchar_to_utf8view: false,
+        enable_options_value_normalization: false,
+        collect_spans: false,
+    }
 }
 
-fn quick_test_with_options(sql: &str, expected: &str, options: ParserOptions) {
-    let plan = logical_plan_with_options(sql, options).unwrap();
-    assert_eq!(format!("{plan}"), expected);
+fn ident_normalization_parser_options_ident_normalization() -> ParserOptions {
+    ParserOptions {
+        parse_float_as_decimal: true,
+        enable_ident_normalization: true,
+        support_varchar_with_length: false,
+        map_varchar_to_utf8view: false,
+        enable_options_value_normalization: false,
+        collect_spans: false,
+    }
 }
 
 fn prepare_stmt_quick_test(
@@ -3126,17 +3412,22 @@ fn prepare_stmt_quick_test(
 
 #[test]
 fn select_partially_qualified_column() {
-    let sql = r#"SELECT person.first_name FROM public.person"#;
-    let expected = "Projection: public.person.first_name\
-            \n  TableScan: public.person";
-    quick_test(sql, expected);
+    let sql = "SELECT person.first_name FROM public.person";
+    let plan = logical_plan(sql).unwrap();
+    assert_snapshot!(
+        plan,
+        @r#"
+Projection: public.person.first_name
+  TableScan: public.person
+"#
+    );
 }
 
 #[test]
 fn cross_join_not_to_inner_join() {
     let sql =
         "select person.id from person, orders, lineitem where person.id = 
person.age;";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -3154,7 +3445,7 @@ Projection: person.id
 #[test]
 fn join_with_aliases() {
     let sql = "select peeps.id, folks.first_name from person as peeps join 
person as folks on peeps.id = folks.id";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -3171,7 +3462,7 @@ Projection: peeps.id, folks.first_name
 #[test]
 fn negative_interval_plus_interval_in_projection() {
     let sql = "select -interval '2 days' + interval '5 days';";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -3184,7 +3475,7 @@ Projection: IntervalMonthDayNano("IntervalMonthDayNano { 
months: 0, days: -2, na
 #[test]
 fn complex_interval_expression_in_projection() {
     let sql = "select -interval '2 days' + interval '5 days'+ (-interval '3 
days' + interval '5 days');";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -3197,7 +3488,7 @@ Projection: IntervalMonthDayNano("IntervalMonthDayNano { 
months: 0, days: -2, na
 #[test]
 fn negative_sum_intervals_in_projection() {
     let sql = "select -((interval '2 days' + interval '5 days') + -(interval 
'4 days' + interval '7 days'));";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -3210,7 +3501,7 @@ Projection: (- IntervalMonthDayNano("IntervalMonthDayNano 
{ months: 0, days: 2,
 #[test]
 fn date_plus_interval_in_projection() {
     let sql = "select t_date32 + interval '5 days' FROM test";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -3226,7 +3517,7 @@ fn date_plus_interval_in_filter() {
                     WHERE t_date64 \
                     BETWEEN cast('1999-12-31' as date) \
                         AND cast('1999-12-31' as date) + interval '30 days'";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -3243,7 +3534,7 @@ fn exists_subquery() {
             (SELECT first_name FROM person \
             WHERE last_name = p.last_name \
             AND state = p.state)";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -3268,7 +3559,7 @@ fn exists_subquery_schema_outer_schema_overlap() {
             WHERE person.id = p2.id \
             AND person.last_name = p.last_name \
             AND person.state = p.state)";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -3293,7 +3584,7 @@ Projection: person.id
 fn in_subquery_uncorrelated() {
     let sql = "SELECT id FROM person p WHERE id IN \
             (SELECT id FROM person)";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -3312,7 +3603,7 @@ Projection: p.id
 fn not_in_subquery_correlated() {
     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 plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -3332,7 +3623,7 @@ Projection: p.id
 fn scalar_subquery() {
     let sql =
         "SELECT p.id, (SELECT MAX(id) FROM person WHERE last_name = 
p.last_name) FROM person p";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -3357,7 +3648,7 @@ fn scalar_subquery_reference_outer_field() {
             FROM j1, j3 \
             WHERE j2_id = j1_id \
             AND j1_id = j3_id)";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -3381,7 +3672,7 @@ Projection: j1.j1_string, j2.j2_string
 fn aggregate_with_rollup() {
     let sql =
         "SELECT id, state, age, count(*) FROM person GROUP BY id, ROLLUP 
(state, age)";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -3396,7 +3687,7 @@ Projection: person.id, person.state, person.age, count(*)
 fn aggregate_with_rollup_with_grouping() {
     let sql = "SELECT id, state, age, grouping(state), grouping(age), 
grouping(state) + grouping(age), count(*) \
         FROM person GROUP BY id, ROLLUP (state, age)";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -3422,7 +3713,7 @@ fn rank_partition_grouping() {
             from
                 person
             group by rollup(state, last_name)";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -3438,7 +3729,7 @@ Projection: sum(person.age) AS total_sum, person.state, 
person.last_name, groupi
 fn aggregate_with_cube() {
     let sql =
         "SELECT id, state, age, count(*) FROM person GROUP BY id, CUBE (state, 
age)";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -3452,7 +3743,7 @@ Projection: person.id, person.state, person.age, count(*)
 #[test]
 fn round_decimal() {
     let sql = "SELECT round(price/3, 2) FROM test_decimal";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -3465,7 +3756,7 @@ Projection: round(test_decimal.price / Int64(3), Int64(2))
 #[test]
 fn aggregate_with_grouping_sets() {
     let sql = "SELECT id, state, age, count(*) FROM person GROUP BY id, 
GROUPING SETS ((state), (state, age), (id, state))";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -3481,7 +3772,7 @@ fn join_on_disjunction_condition() {
     let sql = "SELECT id, order_id \
             FROM person \
             JOIN orders ON id = customer_id OR person.age > 30";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -3498,7 +3789,7 @@ fn join_on_complex_condition() {
     let sql = "SELECT id, order_id \
             FROM person \
             JOIN orders ON id = customer_id AND (person.age > 30 OR 
person.last_name = 'X')";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -3535,7 +3826,7 @@ fn order_by_unaliased_name() {
     // SchemaError(FieldNotFound { qualifier: Some("p"), name: "state", 
valid_fields: ["z", "q"] })
     let sql =
         "select p.state z, sum(age) q from person p group by p.state order by 
p.state";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -3578,7 +3869,7 @@ fn group_by_ambiguous_name() {
 #[test]
 fn test_zero_offset_with_limit() {
     let sql = "select id from person where person.id > 100 LIMIT 5 OFFSET 0;";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -3590,7 +3881,7 @@ Limit: skip=0, fetch=5
     );
     // Flip the order of LIMIT and OFFSET in the query. Plan should remain the 
same.
     let sql = "SELECT id FROM person WHERE person.id > 100 OFFSET 0 LIMIT 5;";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -3605,7 +3896,7 @@ Limit: skip=0, fetch=5
 #[test]
 fn test_offset_no_limit() {
     let sql = "SELECT id FROM person WHERE person.id > 100 OFFSET 5;";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -3620,7 +3911,7 @@ Limit: skip=5, fetch=None
 #[test]
 fn test_offset_after_limit() {
     let sql = "select id from person where person.id > 100 LIMIT 5 OFFSET 3;";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -3635,7 +3926,7 @@ Limit: skip=3, fetch=5
 #[test]
 fn test_offset_before_limit() {
     let sql = "select id from person where person.id > 100 OFFSET 3 LIMIT 5;";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -3650,7 +3941,7 @@ Limit: skip=3, fetch=5
 #[test]
 fn test_distribute_by() {
     let sql = "select id from person distribute by state";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -3686,7 +3977,7 @@ fn test_constant_expr_eq_join() {
             FROM person \
             INNER JOIN orders \
             ON person.id = 10";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -3704,7 +3995,7 @@ fn test_right_left_expr_eq_join() {
             FROM person \
             INNER JOIN orders \
             ON orders.customer_id * 2 = person.id + 10";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -3722,7 +4013,7 @@ fn test_single_column_expr_eq_join() {
             FROM person \
             INNER JOIN orders \
             ON person.id + 10 = orders.customer_id * 2";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -3740,7 +4031,7 @@ fn test_multiple_column_expr_eq_join() {
             FROM person \
             INNER JOIN orders \
             ON person.id + person.age + 10 = orders.customer_id * 2 - 
orders.price";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -3758,7 +4049,7 @@ fn test_left_expr_eq_join() {
             FROM person \
             INNER JOIN orders \
             ON person.id + person.age + 10 = orders.customer_id";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -3776,7 +4067,7 @@ fn test_right_expr_eq_join() {
             FROM person \
             INNER JOIN orders \
             ON person.id = orders.customer_id * 2 - orders.price";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -3794,7 +4085,7 @@ fn test_noneq_with_filter_join() {
     let sql = "SELECT person.id, person.first_name \
         FROM person INNER JOIN orders \
         ON person.age > 10";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -3808,7 +4099,7 @@ Projection: person.id, person.first_name
     let sql = "SELECT person.id, person.first_name \
         FROM person LEFT JOIN orders \
         ON person.age > 10";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -3822,7 +4113,7 @@ Projection: person.id, person.first_name
     let sql = "SELECT person.id, person.first_name \
         FROM person RIGHT JOIN orders \
         ON person.age > 10";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -3836,7 +4127,7 @@ Projection: person.id, person.first_name
     let sql = "SELECT person.id, person.first_name \
         FROM person FULL JOIN orders \
         ON person.age > 10";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -3856,7 +4147,7 @@ fn test_one_side_constant_full_join() {
             FROM person \
             FULL OUTER JOIN orders \
             ON person.id = 10";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -3874,7 +4165,7 @@ fn test_select_join_key_inner_join() {
             FROM person
             INNER JOIN orders
             ON orders.customer_id * 2 = person.id + 10";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -3889,7 +4180,7 @@ Projection: orders.customer_id * Int64(2), person.id + 
Int64(10)
 #[test]
 fn test_select_order_by() {
     let sql = "SELECT '1' from person order by id";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -3949,11 +4240,16 @@ fn test_select_unsupported_syntax_errors(#[case] sql: 
&str, #[case] error: &str)
 fn select_order_by_with_cast() {
     let sql =
         "SELECT first_name AS first_name FROM (SELECT first_name AS first_name 
FROM person) ORDER BY CAST(first_name as INT)";
-    let expected = "Sort: CAST(person.first_name AS Int32) ASC NULLS LAST\
-                        \n  Projection: person.first_name\
-                        \n    Projection: person.first_name\
-                        \n      TableScan: person";
-    quick_test(sql, expected);
+    let plan = logical_plan(sql).unwrap();
+    assert_snapshot!(
+        plan,
+        @r#"
+Sort: CAST(person.first_name AS Int32) ASC NULLS LAST
+  Projection: person.first_name
+    Projection: person.first_name
+      TableScan: person
+"#
+    );
 }
 
 #[test]
@@ -3974,12 +4270,16 @@ fn test_duplicated_left_join_key_inner_join() {
             FROM person
             INNER JOIN orders
             ON person.id * 2 = orders.customer_id + 10 and person.id * 2 = 
orders.order_id";
-
-    let expected = "Projection: person.id, person.age\
-            \n  Inner Join:  Filter: person.id * Int64(2) = orders.customer_id 
+ Int64(10) AND person.id * Int64(2) = orders.order_id\
-            \n    TableScan: person\
-            \n    TableScan: orders";
-    quick_test(sql, expected);
+    let plan = logical_plan(sql).unwrap();
+    assert_snapshot!(
+        plan,
+        @r#"
+Projection: person.id, person.age
+  Inner Join:  Filter: person.id * Int64(2) = orders.customer_id + Int64(10) 
AND person.id * Int64(2) = orders.order_id
+    TableScan: person
+    TableScan: orders
+"#
+    );
 }
 
 #[test]
@@ -3989,12 +4289,16 @@ fn test_duplicated_right_join_key_inner_join() {
             FROM person
             INNER JOIN orders
             ON person.id * 2 = orders.customer_id + 10 and person.id =  
orders.customer_id + 10";
-
-    let expected = "Projection: person.id, person.age\
-            \n  Inner Join:  Filter: person.id * Int64(2) = orders.customer_id 
+ Int64(10) AND person.id = orders.customer_id + Int64(10)\
-            \n    TableScan: person\
-            \n    TableScan: orders";
-    quick_test(sql, expected);
+    let plan = logical_plan(sql).unwrap();
+    assert_snapshot!(
+        plan,
+        @r#"
+Projection: person.id, person.age
+  Inner Join:  Filter: person.id * Int64(2) = orders.customer_id + Int64(10) 
AND person.id = orders.customer_id + Int64(10)
+    TableScan: person
+    TableScan: orders
+"#
+    );
 }
 
 #[test]
@@ -4023,14 +4327,18 @@ fn 
test_ambiguous_column_references_with_in_using_join() {
             from person as p1
             INNER JOIN person as p2
             using(id)";
-
-    let expected = "Projection: p1.id, p1.age, p2.id\
-            \n  Inner Join: Using p1.id = p2.id\
-            \n    SubqueryAlias: p1\
-            \n      TableScan: person\
-            \n    SubqueryAlias: p2\
-            \n      TableScan: person";
-    quick_test(sql, expected);
+    let plan = logical_plan(sql).unwrap();
+    assert_snapshot!(
+        plan,
+        @r#"
+Projection: p1.id, p1.age, p2.id
+  Inner Join: Using p1.id = p2.id
+    SubqueryAlias: p1
+      TableScan: person
+    SubqueryAlias: p2
+      TableScan: person
+"#
+    );
 }
 
 #[test]
@@ -4715,7 +5023,7 @@ fn test_inner_join_with_cast_key() {
             FROM person
             INNER JOIN orders
             ON cast(person.id as Int) = cast(orders.customer_id as Int)";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -4734,7 +5042,7 @@ fn test_multi_grouping_sets() {
             GROUP BY
                 person.id,
                 GROUPING SETS ((person.age,person.salary),(person.age))";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -4749,7 +5057,7 @@ Projection: person.id, person.age
                 person.id,
                 GROUPING SETS ((person.age, person.salary),(person.age)),
                 ROLLUP(person.state, person.birth_date)";
-    let plan = generate_logical_plan(sql);
+    let plan = logical_plan(sql).unwrap();
     assert_snapshot!(
         plan,
         @r#"
@@ -4786,30 +5094,46 @@ fn test_field_not_found_window_function() {
         "###
     );
 
-    let qualified_sql =
-        "SELECT order_id, MAX(qty) OVER (PARTITION BY orders.order_id) from 
orders";
-    let expected = "Projection: orders.order_id, max(orders.qty) PARTITION BY 
[orders.order_id] ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING\n  
WindowAggr: windowExpr=[[max(orders.qty) PARTITION BY [orders.order_id] ROWS 
BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING]]\n    TableScan: orders";
-    quick_test(qualified_sql, expected);
+    let sql = "SELECT order_id, MAX(qty) OVER (PARTITION BY orders.order_id) 
from orders";
+    let plan = logical_plan(sql).unwrap();
+    assert_snapshot!(
+        plan,
+        @r#"
+Projection: orders.order_id, max(orders.qty) PARTITION BY [orders.order_id] 
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
+  WindowAggr: windowExpr=[[max(orders.qty) PARTITION BY [orders.order_id] ROWS 
BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING]]
+    TableScan: orders
+"#
+    );
 }
 
 #[test]
 fn test_parse_escaped_string_literal_value() {
     let sql = r"SELECT character_length('\r\n') AS len";
-    let expected = "Projection: character_length(Utf8(\"\\r\\n\")) AS len\
-    \n  EmptyRelation";
-    quick_test(sql, expected);
-
-    let sql = r"SELECT character_length(E'\r\n') AS len";
-    let expected = "Projection: character_length(Utf8(\"\r\n\")) AS len\
-    \n  EmptyRelation";
-    quick_test(sql, expected);
-
+    let plan = logical_plan(sql).unwrap();
+    assert_snapshot!(
+        plan,
+        @r#"
+    Projection: character_length(Utf8("\r\n")) AS len
+      EmptyRelation
+    "#
+    );
+    let sql = "SELECT character_length(E'\r\n') AS len";
+    let plan = logical_plan(sql).unwrap();
+    assert_snapshot!(
+        plan,
+        @r#"
+Projection: character_length(Utf8("
+")) AS len
+  EmptyRelation
+"#
+    );
     let sql =
         r"SELECT character_length(E'\445') AS len, E'\x4B' AS hex, E'\u0001' 
AS unicode";
-    let expected =
-        "Projection: character_length(Utf8(\"%\")) AS len, Utf8(\"\u{004b}\") 
AS hex, Utf8(\"\u{0001}\") AS unicode\
-    \n  EmptyRelation";
-    quick_test(sql, expected);
+    let plan = logical_plan(sql).unwrap();
+    assert_snapshot!(
+        plan,
+        @"Projection: character_length(Utf8(\"%\")) AS len, Utf8(\"K\") AS 
hex, Utf8(\"\u{1}\") AS unicode\n  EmptyRelation"
+    );
 
     let sql = r"SELECT character_length(E'\000') AS len";
 


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

Reply via email to