Skip to content

Commit

Permalink
Add snapshot testing for AST pretty printing (#474)
Browse files Browse the repository at this point in the history
  • Loading branch information
jpschorr authored Jul 9, 2024
1 parent a54868e commit 684fff3
Show file tree
Hide file tree
Showing 22 changed files with 1,126 additions and 28 deletions.
9 changes: 3 additions & 6 deletions deny.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ ignore = [
# Advisory: https://rustsec.org/advisories/RUSTSEC-2021-0145
# atty potential misaligned pointer; used by some pretty-printing deps (criterion, miette, lalrpop)
"RUSTSEC-2021-0145",

# Advisory: https://rustsec.org/advisories/RUSTSEC-2020-0071
# `chrono` uses an old version of `time`, but `chrono` >= 4.2 doesn't use the code path with the issue
"RUSTSEC-2020-0071",
Expand Down Expand Up @@ -126,15 +125,13 @@ allow = [
deny = [
# Use `once_cell` instead
# `OnceCell`s API is under consideration for inclusion in `std`: https://github.com/rust-lang/rust/issues/74465
{ name = "lazy_static", wrappers = ["Inflector", "criterion"]},


{ name = "lazy_static", wrappers = ["Inflector", "criterion", "insta", "console"] },
# Advisory: https://rustsec.org/advisories/RUSTSEC-2020-0071
# `time` < 0.2.23 has a potential (though unlikely) potential segfault
{ name = "time", version ="<0.2.23", wrappers = ["chrono"]},
{ name = "time", version = "<0.2.23", wrappers = ["chrono"] },
# Advisory: https://rustsec.org/advisories/RUSTSEC-2020-0071
# `chrono` uses an old version of `time`, but `chrono` >= 4.2 doesn't use the code path with the issue
{ name = "chrono", version ="<0.4.20"}
{ name = "chrono", version = "<0.4.20" }
]


Expand Down
2 changes: 2 additions & 0 deletions partiql-ast/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ thiserror = "1.0"

[dev-dependencies]
partiql-parser = { path = "../partiql-parser", version = "0.8" }
itertools = "0.13"
insta = "1.38.0"

[features]
default = []
Expand Down
72 changes: 50 additions & 22 deletions partiql-ast/tests/common.rs → partiql-ast/tests/pretty.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
use itertools::Itertools;
use partiql_ast::pretty::ToPretty;
use partiql_parser::ParserResult;

pub fn setup() {
// setup test code goes here
}

#[track_caller]
#[inline]
fn parse(statement: &str) -> ParserResult<'_> {
Expand All @@ -13,19 +10,33 @@ fn parse(statement: &str) -> ParserResult<'_> {

#[track_caller]
#[inline]
fn pretty_print_test(statement: &str) {
fn pretty_print_test(name: &str, statement: &str) {
let res = parse(statement);
assert!(res.is_ok());
let res = res.unwrap();

// TODO https://github.com/partiql/partiql-lang-rust/issues/473
for w in [180, 120, 80, 40, 30, 20, 10] {
println!("{:-<w$}", "");
println!("{}\n", res.ast.to_pretty_string(w).unwrap());
}

let doc = [180, 120, 80, 40, 30, 20, 10]
.into_iter()
.map(|w| {
let header = format!("{:-<w$}", "");
let ast = format!("{}\n", res.ast.to_pretty_string(w).unwrap());
format!("{header}\n{ast}")
})
.join("\n");

let w = 200;
let header = format!("{:=<w$}", "");
let doc = format!("{header}\n{statement}\n{header}\n\n{doc}");

insta::assert_snapshot!(name, doc)
}

#[test]
fn pretty() {
pretty_print_test(
"pretty",
"select foo,bar, baz,thud.*,grunt.a[*].b[2].*, count(1) as n from
<<
{ 'foo': 'foo', 'x': 9, 'y':5, z:-11 },
Expand All @@ -42,6 +53,7 @@ fn pretty() {
#[test]
fn pretty2() {
pretty_print_test(
"pretty2",
"select foo,bar, baz,thud,grunt, count(1) as n from
(SELECT * FROM table1)
where (bar between 3 and 25 AND baz NOT LIKE 'example%') OR foo.a.b[*] IS MISSING
Expand All @@ -52,32 +64,42 @@ fn pretty2() {

#[test]
fn pretty_having_limit_offset() {
pretty_print_test("SELECT a FROM foo GROUP BY a HAVING a > 2 ORDER BY a LIMIT 1 OFFSET 1");
pretty_print_test(
"having_limit_offset",
"SELECT a FROM foo GROUP BY a HAVING a > 2 ORDER BY a LIMIT 1 OFFSET 1",
);
}

#[test]
fn pretty_select_value_unpivot() {
pretty_print_test("SELECT VALUE foo FROM (SELECT VALUE v FROM UNPIVOT e AS v) AS foo");
pretty_print_test(
"select value unpivot",
"SELECT VALUE foo FROM (SELECT VALUE v FROM UNPIVOT e AS v) AS foo",
);
}

#[test]
fn pretty_select_value_tuple_ctor() {
pretty_print_test("SELECT VALUE {'a':v.a, 'b':v.b} FROM [{'a':1, 'b':1}, {'a':2, 'b':2}] AS v");
pretty_print_test(
"pretty_select_value_tuple_ctor",
"SELECT VALUE {'a':v.a, 'b':v.b} FROM [{'a':1, 'b':1}, {'a':2, 'b':2}] AS v",
);
}

#[test]
fn pretty_from_comma() {
pretty_print_test("SELECT a, b FROM T1, T2");
pretty_print_test("pretty_from_comma", "SELECT a, b FROM T1, T2");
}

#[test]
fn pretty_expr_in() {
pretty_print_test("(a, b) IN ((1, 2), (3, 4))");
pretty_print_test("pretty_expr_in", "(a, b) IN ((1, 2), (3, 4))");
}

#[test]
fn pretty_setop() {
pretty_print_test(
"pretty_setop",
"(SELECT a1 FROM b1 ORDER BY c1 LIMIT d1 OFFSET e1)
UNION
(SELECT a2 FROM b2 ORDER BY c2 LIMIT d2 OFFSET e2)
Expand All @@ -88,6 +110,7 @@ fn pretty_setop() {
#[test]
fn pretty_bagop() {
pretty_print_test(
"pretty_bagop",
"
(
(SELECT a1 FROM b1 ORDER BY c1 LIMIT d1 OFFSET e1)
Expand All @@ -103,6 +126,7 @@ fn pretty_bagop() {
#[test]
fn pretty_join() {
pretty_print_test(
"pretty_join",
"
SELECT t1.id AS id, t1.val AS val1, t2.val AS val2
FROM table1 AS t1 JOIN table1_null_row AS t2 ON t1.id = t2.id",
Expand All @@ -111,27 +135,31 @@ fn pretty_join() {

#[test]
fn pretty_kw_fns() {
pretty_print_test("trim(trailing from 'test')");
pretty_print_test("POSITION('abc' IN 'abcdefg')");
pretty_print_test("substring('test', 100, 50)");
pretty_print_test("substring('test', 100)");
pretty_print_test("pretty_kw_fn1", "trim(trailing from 'test')");
pretty_print_test("pretty_kw_fn2", "POSITION('abc' IN 'abcdefg')");
pretty_print_test("pretty_kw_fn3", "substring('test', 100, 50)");
pretty_print_test("pretty_kw_fn4", "substring('test', 100)");
}

#[test]
fn pretty_typed_lits() {
pretty_print_test("TIME WITH TIME ZONE '23:59:59.1234567890+18:00'");
pretty_print_test("TIME (3) WITH TIME ZONE '12:59:31'");
pretty_print_test(
"pretty_typed_lits1",
"TIME WITH TIME ZONE '23:59:59.1234567890+18:00'",
);
pretty_print_test("pretty_typed_lits2", "TIME (3) WITH TIME ZONE '12:59:31'");
}

#[test]
fn pretty_case() {
pretty_print_test("SELECT VALUE CASE WHEN x + 1 < i THEN '< ONE' WHEN x + 1 = f THEN 'TWO' WHEN (x + 1 > d) AND (x + 1 < 100) THEN '>= THREE < 100' ELSE '?' END FROM << -1.0000, i, f, d, 100e0, null, missing >> AS x");
pretty_print_test("SELECT VALUE CASE x + 1 WHEN NULL THEN 'shouldnt be null' WHEN MISSING THEN 'shouldnt be missing' WHEN i THEN 'ONE' WHEN f THEN 'TWO' WHEN d THEN 'THREE' END FROM << i, f, d, null, missing >> AS x");
pretty_print_test("pretty_case_1", "SELECT VALUE CASE WHEN x + 1 < i THEN '< ONE' WHEN x + 1 = f THEN 'TWO' WHEN (x + 1 > d) AND (x + 1 < 100) THEN '>= THREE < 100' ELSE '?' END FROM << -1.0000, i, f, d, 100e0, null, missing >> AS x");
pretty_print_test("pretty_case_2","SELECT VALUE CASE x + 1 WHEN NULL THEN 'shouldnt be null' WHEN MISSING THEN 'shouldnt be missing' WHEN i THEN 'ONE' WHEN f THEN 'TWO' WHEN d THEN 'THREE' END FROM << i, f, d, null, missing >> AS x");
}

#[test]
fn pretty_pivot() {
pretty_print_test(
"pretty_pivot",
"
PIVOT foo.a AT foo.b
FROM <<{'a': 1, 'b':'I'}, {'a': 2, 'b':'II'}, {'a': 3, 'b':'III'}>> AS foo
Expand Down
42 changes: 42 additions & 0 deletions partiql-ast/tests/snapshots/pretty__having_limit_offset.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
---
source: partiql-ast/tests/pretty.rs
expression: doc
---
========================================================================================================================================================================================================
SELECT a FROM foo GROUP BY a HAVING a > 2 ORDER BY a LIMIT 1 OFFSET 1
========================================================================================================================================================================================================

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SELECT a FROM foo GROUP BY a HAVING (a > 2) ORDER BY a LIMIT 1 OFFSET 1

------------------------------------------------------------------------------------------------------------------------
SELECT a FROM foo GROUP BY a HAVING (a > 2) ORDER BY a LIMIT 1 OFFSET 1

--------------------------------------------------------------------------------
SELECT a FROM foo GROUP BY a HAVING (a > 2) ORDER BY a LIMIT 1 OFFSET 1

----------------------------------------
SELECT a FROM foo GROUP BY a
HAVING (a > 2) ORDER BY a LIMIT 1
OFFSET 1

------------------------------
SELECT a FROM foo GROUP BY a
HAVING (a > 2) ORDER BY a
LIMIT 1 OFFSET 1

--------------------
SELECT a FROM foo
GROUP BY a
HAVING (a > 2)
ORDER BY a LIMIT 1
OFFSET 1

----------
SELECT a
FROM foo
GROUP BY a
HAVING (a > 2)
ORDER BY a
LIMIT 1
OFFSET 1
149 changes: 149 additions & 0 deletions partiql-ast/tests/snapshots/pretty__pretty.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
---
source: partiql-ast/tests/pretty.rs
expression: doc
---
========================================================================================================================================================================================================
select foo,bar, baz,thud.*,grunt.a[*].b[2].*, count(1) as n from
<<
{ 'foo': 'foo', 'x': 9, 'y':5, z:-11 },
{ 'foo': 'bar' },
{ 'foo': 'qux' },
{ 'foo': 'bar' },
{ 'foo': 'baz' },
{ 'foo': 'bar' },
{ 'foo': 'baz' }
>> group by foo order by n desc
========================================================================================================================================================================================================

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SELECT foo, bar, baz, thud.*, grunt.a[*].b[2].*, count(1) AS n FROM <<
{ 'foo': 'foo', 'x': 9, 'y': 5, z: -11 },
{ 'foo': 'bar' },
{ 'foo': 'qux' },
{ 'foo': 'bar' },
{ 'foo': 'baz' },
{ 'foo': 'bar' },
{ 'foo': 'baz' }
>> GROUP BY foo ORDER BY n DESC

------------------------------------------------------------------------------------------------------------------------
SELECT foo, bar, baz, thud.*, grunt.a[*].b[2].*, count(1) AS n FROM <<
{ 'foo': 'foo', 'x': 9, 'y': 5, z: -11 },
{ 'foo': 'bar' },
{ 'foo': 'qux' },
{ 'foo': 'bar' },
{ 'foo': 'baz' },
{ 'foo': 'bar' },
{ 'foo': 'baz' }
>> GROUP BY foo ORDER BY n DESC

--------------------------------------------------------------------------------
SELECT foo, bar, baz, thud.*, grunt.a[*].b[2].*, count(1) AS n FROM <<
{ 'foo': 'foo', 'x': 9, 'y': 5, z: -11 },
{ 'foo': 'bar' },
{ 'foo': 'qux' },
{ 'foo': 'bar' },
{ 'foo': 'baz' },
{ 'foo': 'bar' },
{ 'foo': 'baz' }
>> GROUP BY foo ORDER BY n DESC

----------------------------------------
SELECT foo, bar, baz, thud.*,
grunt.a[*].b[2].*, count(1) AS n
FROM <<
{
'foo': 'foo',
'x': 9,
'y': 5,
z: -11
},
{ 'foo': 'bar' },
{ 'foo': 'qux' },
{ 'foo': 'bar' },
{ 'foo': 'baz' },
{ 'foo': 'bar' },
{ 'foo': 'baz' }
>> GROUP BY foo ORDER BY n DESC

------------------------------
SELECT foo, bar, baz, thud.*,
grunt.a[*].b[2].*,
count(1) AS n FROM <<
{
'foo': 'foo',
'x': 9,
'y': 5,
z: -11
},
{ 'foo': 'bar' },
{ 'foo': 'qux' },
{ 'foo': 'bar' },
{ 'foo': 'baz' },
{ 'foo': 'bar' },
{ 'foo': 'baz' }
>> GROUP BY foo
ORDER BY n DESC

--------------------
SELECT foo, bar,
baz, thud.*,
grunt.a[*].b[2].*,
count(1) AS n
FROM <<
{
'foo': 'foo',
'x': 9,
'y': 5,
z: -11
},
{ 'foo': 'bar'
},
{ 'foo': 'qux'
},
{ 'foo': 'bar'
},
{ 'foo': 'baz'
},
{ 'foo': 'bar'
},
{ 'foo': 'baz' }
>> GROUP BY foo
ORDER BY n DESC

----------
SELECT foo,
bar,
baz,
thud.*,
grunt.a[*].b[2].*,
count(1) AS n
FROM <<
{
'foo': 'foo',
'x': 9,
'y': 5,
z: -11
},
{
'foo': 'bar'
},
{
'foo': 'qux'
},
{
'foo': 'bar'
},
{
'foo': 'baz'
},
{
'foo': 'bar'
},
{
'foo': 'baz'
}
>>
GROUP BY
foo
ORDER BY n DESC
Loading

1 comment on commit 684fff3

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PartiQL (rust) Benchmark

Benchmark suite Current: 684fff3 Previous: a54868e Ratio
arith_agg-avg 771998 ns/iter (± 3660) 768879 ns/iter (± 44474) 1.00
arith_agg-avg_distinct 868193 ns/iter (± 32480) 852871 ns/iter (± 4563) 1.02
arith_agg-count 819127 ns/iter (± 13014) 818561 ns/iter (± 24924) 1.00
arith_agg-count_distinct 850385 ns/iter (± 12627) 846734 ns/iter (± 3407) 1.00
arith_agg-min 835124 ns/iter (± 7322) 832601 ns/iter (± 5272) 1.00
arith_agg-min_distinct 864818 ns/iter (± 5042) 859514 ns/iter (± 2662) 1.01
arith_agg-max 826288 ns/iter (± 9355) 827881 ns/iter (± 8412) 1.00
arith_agg-max_distinct 860400 ns/iter (± 3296) 860484 ns/iter (± 2589) 1.00
arith_agg-sum 822396 ns/iter (± 21825) 823950 ns/iter (± 4769) 1.00
arith_agg-sum_distinct 851443 ns/iter (± 4511) 850306 ns/iter (± 2494) 1.00
arith_agg-avg-count-min-max-sum 967909 ns/iter (± 18508) 960769 ns/iter (± 2950) 1.01
arith_agg-avg-count-min-max-sum-group_by 1261195 ns/iter (± 11052) 1270408 ns/iter (± 9721) 0.99
arith_agg-avg-count-min-max-sum-group_by-group_as 1872671 ns/iter (± 20081) 1880159 ns/iter (± 11463) 1.00
arith_agg-avg_distinct-count_distinct-min_distinct-max_distinct-sum_distinct 1178677 ns/iter (± 10540) 1240402 ns/iter (± 20711) 0.95
arith_agg-avg_distinct-count_distinct-min_distinct-max_distinct-sum_distinct-group_by 1589490 ns/iter (± 19655) 1581066 ns/iter (± 63203) 1.01
arith_agg-avg_distinct-count_distinct-min_distinct-max_distinct-sum_distinct-group_by-group_as 2165888 ns/iter (± 8946) 2187305 ns/iter (± 11171) 0.99
parse-1 4269 ns/iter (± 15) 4244 ns/iter (± 32) 1.01
parse-15 39638 ns/iter (± 150) 40550 ns/iter (± 352) 0.98
parse-30 77020 ns/iter (± 352) 78545 ns/iter (± 2822) 0.98
compile-1 4263 ns/iter (± 10) 4394 ns/iter (± 114) 0.97
compile-15 33192 ns/iter (± 197) 33209 ns/iter (± 207) 1.00
compile-30 67869 ns/iter (± 314) 68529 ns/iter (± 190) 0.99
plan-1 69565 ns/iter (± 234) 68549 ns/iter (± 487) 1.01
plan-15 1082605 ns/iter (± 19293) 1078118 ns/iter (± 10086) 1.00
plan-30 2170474 ns/iter (± 56024) 2156664 ns/iter (± 8444) 1.01
eval-1 12909400 ns/iter (± 104669) 13199986 ns/iter (± 178346) 0.98
eval-15 87331642 ns/iter (± 228299) 88062096 ns/iter (± 1058303) 0.99
eval-30 168169555 ns/iter (± 384409) 168580958 ns/iter (± 556192) 1.00
join 9942 ns/iter (± 344) 9884 ns/iter (± 93) 1.01
simple 2482 ns/iter (± 13) 2488 ns/iter (± 17) 1.00
simple-no 428 ns/iter (± 2) 427 ns/iter (± 11) 1.00
numbers 57 ns/iter (± 0) 57 ns/iter (± 0) 1
parse-simple 556 ns/iter (± 9) 565 ns/iter (± 7) 0.98
parse-ion 1736 ns/iter (± 29) 1750 ns/iter (± 9) 0.99
parse-group 5734 ns/iter (± 257) 5900 ns/iter (± 19) 0.97
parse-complex 14833 ns/iter (± 122) 14823 ns/iter (± 106) 1.00
parse-complex-fexpr 21781 ns/iter (± 130) 21985 ns/iter (± 877) 0.99

This comment was automatically generated by workflow using github-action-benchmark.

Please sign in to comment.