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]