diff --git a/crates/squawk_fmt/src/fmt.rs b/crates/squawk_fmt/src/fmt.rs index cb9a46cf..3bf3fc66 100644 --- a/crates/squawk_fmt/src/fmt.rs +++ b/crates/squawk_fmt/src/fmt.rs @@ -9888,6 +9888,7 @@ fn build_having_clause<'a>(having: ast::HavingClause) -> Doc<'a> { } fn build_window_clause<'a>(window: ast::WindowClause) -> Doc<'a> { + let single_def = window.window_defs().count() == 1; let defs = window.window_defs().map(|def| { ( leading_comments(def.syntax()).append(build_window_def(def.clone())), @@ -9896,7 +9897,11 @@ fn build_window_clause<'a>(window: ast::WindowClause) -> Doc<'a> { }); let mut doc = Doc::text("window"); if let Some(defs) = build_comma_separated_docs(defs) { - doc = doc.append(Doc::space()).append(defs.nest(2)); + doc = if single_def { + doc.append(Doc::space()).append(defs) + } else { + doc.append(Doc::line_or_space().append(defs).nest(2)) + }; } doc.group() } @@ -9958,20 +9963,20 @@ fn build_select_group_by_clause<'a>(group: ast::GroupByClause) -> Doc<'a> { if let Some(by_token) = group.by_token() { doc = doc.append(leading_comments_token(&by_token)); } - doc = doc.append(Doc::text("by")).append(Doc::space()); + doc = doc.append(Doc::text("by")); if let Some(quantifier) = group.all_or_distinct() { doc = doc + .append(Doc::space()) .append(leading_comments(quantifier.syntax())) .append(match quantifier { ast::AllOrDistinct::All(_) => Doc::text("all"), ast::AllOrDistinct::Distinct(_) => Doc::text("distinct"), - }) - .append(Doc::space()); + }); } if let Some(list) = group.group_by_list() { doc = doc.append(build_group_by_list(list)); } - doc + doc.group() } fn build_create_publication<'a>(stmt: &ast::CreatePublication) -> Doc<'a> { @@ -16242,14 +16247,8 @@ fn build_select_doc_ungrouped<'a>(select: &ast::Select) -> Doc<'a> { fn build_from_clause<'a>(from: ast::FromClause) -> Doc<'a> { let mut single_item = from.items(); - let single_nested_table = matches!( - single_item.next(), - Some(ast::FromListItem::FromItem( - ast::FromItem::GraphTableFromItem(_) - | ast::FromItem::JsonTableFromItem(_) - | ast::FromItem::XmlTableFromItem(_) - )) - ) && single_item.next().is_none(); + let single_from_item = matches!(single_item.next(), Some(ast::FromListItem::FromItem(_))) + && single_item.next().is_none(); let items = from.items().map(|item| { let syntax = item.syntax().clone(); @@ -16259,11 +16258,7 @@ fn build_from_clause<'a>(from: ast::FromClause) -> Doc<'a> { ) }); let body = build_comma_separated_docs(items).unwrap_or_else(Doc::nil); - let body = if single_nested_table { - body - } else { - body.nest(2) - }; + let body = if single_from_item { body } else { body.nest(2) }; Doc::text("from").append(Doc::space()).append(body) } @@ -17441,22 +17436,27 @@ fn build_from_alias_column_list<'a>( } fn build_group_by_list<'a>(list: ast::GroupByList) -> Doc<'a> { - leading_comments(list.syntax()).append(build_group_bys(list.group_bys())) -} - -fn build_group_bys<'a>(group_bys: impl Iterator) -> Doc<'a> { - Doc::list( + let group_bys: Vec<_> = list + .group_bys() + .map(|group_by| { + let leading = leading_comments(group_by.syntax()); + let trailing = trailing_comments(group_by.syntax()); + leading.append(build_group_by(group_by)).append(trailing) + }) + .collect(); + let single_group_by = group_bys.len() == 1; + let body = leading_comments(list.syntax()).append(Doc::list( Itertools::intersperse( - group_bys.map(|group_by| { - let leading = leading_comments(group_by.syntax()); - let trailing = trailing_comments(group_by.syntax()); - leading.append(build_group_by(group_by)).append(trailing) - }), + group_bys.into_iter(), Doc::text(",").append(Doc::line_or_space()), ) .collect(), - ) - .nest(2) + )); + if single_group_by { + Doc::space().append(body) + } else { + Doc::line_or_space().append(body).nest(2) + } } fn build_group_by<'a>(group_by: ast::GroupBy) -> Doc<'a> { diff --git a/crates/squawk_fmt/tests/after/from.snap b/crates/squawk_fmt/tests/after/from.snap index 05d6340f..238a8474 100644 --- a/crates/squawk_fmt/tests/after/from.snap +++ b/crates/squawk_fmt/tests/after/from.snap @@ -8,15 +8,15 @@ select * from foo as f (id, display_name); select * from foo f (id int, display_name text collate "C"); select * from foo /* before alias */ as /* before alias name */ f /* before open paren */ ( - /* after open paren */ id /* before comma */, - /* after comma */ display_name /* before close paren */ - ); + /* after open paren */ id /* before comma */, + /* after comma */ display_name /* before close paren */ +); select * from users tablesample bernoulli (10) repeatable (42); select t.id from test_tablesample as t tablesample system (50) repeatable (0); select * from users /* before alias */ as /* before alias name */ u /* before tablesample */ tablesample /* before method */ bernoulli /* before sample opening paren */( - /* before percentage */ 10 /* before sample closing paren */ - ) /* before repeatable */ repeatable /* before seed opening paren */(/* before seed */ 42 /* before seed closing paren */); + /* before percentage */ 10 /* before sample closing paren */ +) /* before repeatable */ repeatable /* before seed opening paren */(/* before seed */ 42 /* before seed closing paren */); select * from generate_series(1, 3); select * from lateral generate_series(1, 3) with ordinality as g (n, ord); select * @@ -30,46 +30,43 @@ from /* before lateral */ lateral /* before call */ generate_series /* before op other; select * from lateral cast( - a_very_long_expression_name as a_very_long_schema_name.a_very_long_type_name - ) as converted; + a_very_long_expression_name as a_very_long_schema_name.a_very_long_type_name +) as converted; select * from collation for (foo) as collation_name; select * from /* before lateral */ lateral /* before cast */ cast /* before opening paren */( - /* before expression */ value - /* before as */ as - /* before type */ int8 /* before closing paren */ - ) /* before alias */ as /* before alias name */ converted; + /* before expression */ value + /* before as */ as + /* before type */ int8 /* before closing paren */ +) /* before alias */ as /* before alias name */ converted; select * from (select 1) as selected; select * from lateral ( - select a_very_long_parenthesized_select_expression - from a_very_long_parenthesized_select_relation_name - ) as a_very_long_parenthesized_select_alias; + select a_very_long_parenthesized_select_expression + from a_very_long_parenthesized_select_relation_name +) as a_very_long_parenthesized_select_alias; select * from /* before lateral */ lateral /* before opening paren */ ( - /* before select */ select - /* before target */ value /* before closing paren */ - ) /* before alias */ as /* before alias name */ selected; + /* before select */ select + /* before target */ value /* before closing paren */ +) /* before alias */ as /* before alias name */ selected; select * from rows from ( - generate_series(1, 3), - unnest(array[1, 2]) as (value int8) - ) with ordinality as generated (first_value, second_value, ordinality); + generate_series(1, 3), + unnest(array[1, 2]) as (value int8) +) with ordinality as generated (first_value, second_value, ordinality); select * from /* before lateral */ lateral /* before rows */ rows /* before from */ from /* before opening paren */( - /* before first argument */ generate_series( - 1, - 3 - ) /* before argument comma */, - /* before second argument */ unnest( - array[1, 2] - ) /* before as */ as /* before column list */ ( - /* before column */ value /* before type */ int8 /* before column list close */ - ) /* before rows close */ - ) /* before with */ with /* before ordinality */ ordinality /* before alias */ as /* before alias name */ generated ( - value, - ordinality - ); + /* before first argument */ generate_series(1, 3) /* before argument comma */, + /* before second argument */ unnest( + array[1, 2] + ) /* before as */ as /* before column list */ ( + /* before column */ value /* before type */ int8 /* before column list close */ + ) /* before rows close */ +) /* before with */ with /* before ordinality */ ordinality /* before alias */ as /* before alias name */ generated ( + value, + ordinality +); select * from xmltable( '/rows/row' passing doc @@ -180,28 +177,28 @@ select * select * from lateral a_very_long_function_name( - a_very_long_first_argument_name, - a_very_long_second_argument_name, - a_very_long_third_argument_name - ) with ordinality as a_very_long_function_alias ( - a_very_long_value_column_alias, - a_very_long_ordinality_column_alias - ); + a_very_long_first_argument_name, + a_very_long_second_argument_name, + a_very_long_third_argument_name +) with ordinality as a_very_long_function_alias ( + a_very_long_value_column_alias, + a_very_long_ordinality_column_alias +); select * from a_very_long_schema_name.a_very_long_relation_name as a_very_long_relation_alias ( - a_very_long_first_column_alias, - a_very_long_second_column_alias, - a_very_long_third_column_alias - ); + a_very_long_first_column_alias, + a_very_long_second_column_alias, + a_very_long_third_column_alias +); select * from a_very_long_relation_name a_very_long_relation_alias ( - a_very_long_first_column_name a_very_long_type_schema.a_very_long_first_type_name, - a_very_long_second_column_name a_very_long_type_schema.a_very_long_second_type_name collate a_very_long_collation_name - ); + a_very_long_first_column_name a_very_long_type_schema.a_very_long_first_type_name, + a_very_long_second_column_name a_very_long_type_schema.a_very_long_second_type_name collate a_very_long_collation_name +); select * from a_very_long_relation_name tablesample bernoulli ( - a_very_long_sampling_percentage_expression - ) repeatable (a_very_long_repeatable_seed_expression); + a_very_long_sampling_percentage_expression +) repeatable (a_very_long_repeatable_seed_expression); select * from only a_very_long_schema_name.a_very_long_first_relation_name * as a_very_long_first_alias, a_very_long_schema_name.a_very_long_second_relation_name as a_very_long_second_alias; @@ -276,3 +273,15 @@ from statistics /* before base alias */ s /* before nested join */ join /* before nested relation */ attributes /* before nested alias */ a /* before on */ on /* before left operand */ a.attnum /* before equals */ = /* before right operand */ u.attnum; + +select * +from generate_series( + 1, + 30000000000000000000000000000000000000000 +) with ordinality as g (n, ord); + +select * +from unnest(fooooooooooooooooooooooooooooooooooooooooo) as u ( + value int8, + other text +); diff --git a/crates/squawk_fmt/tests/after/group_by.snap b/crates/squawk_fmt/tests/after/group_by.snap index 65d45a27..d7b59f7c 100644 --- a/crates/squawk_fmt/tests/after/group_by.snap +++ b/crates/squawk_fmt/tests/after/group_by.snap @@ -9,32 +9,80 @@ select 1 group by distinct grouping sets ((), (1, 2), rollup (3), cube (4)); select 1 group by grouping sets ( - (first_very_long_grouping_expression, second_very_long_grouping_expression), - rollup ( - third_very_long_grouping_expression, - fourth_very_long_grouping_expression - ), - cube ( - fifth_very_long_grouping_expression, - sixth_very_long_grouping_expression - ) - ); + (first_very_long_grouping_expression, second_very_long_grouping_expression), + rollup ( + third_very_long_grouping_expression, + fourth_very_long_grouping_expression + ), + cube ( + fifth_very_long_grouping_expression, + sixth_very_long_grouping_expression + ) +); select 1 group /* before by */ by /* before distinct */ distinct /* before grouping */ grouping /* before sets */ sets /* before outer paren */( - /* before rollup */ rollup /* before rollup paren */( - /* before first expression */ 1 /* before expression comma */, - /* before second expression */ 2 /* before rollup close */ - ) /* before group-by comma */, - /* before cube */ cube /* before cube paren */( - /* before cube expression */ 3 /* before cube close */ - ) /* before second group-by comma */, - /* before nested grouping */ grouping /* before nested sets */ sets /* before nested paren */( - /* before empty tuple */ () /* before nested comma */, - /* before grouping expression */ ( - 4 /* before tuple comma */, - /* before tuple expression */ 5 /* before tuple close */ - ) /* before nested close */ - ) /* before outer close */ - ) /* before semicolon */; + /* before rollup */ rollup /* before rollup paren */( + /* before first expression */ 1 /* before expression comma */, + /* before second expression */ 2 /* before rollup close */ + ) /* before group-by comma */, + /* before cube */ cube /* before cube paren */( + /* before cube expression */ 3 /* before cube close */ + ) /* before second group-by comma */, + /* before nested grouping */ grouping /* before nested sets */ sets /* before nested paren */( + /* before empty tuple */ () /* before nested comma */, + /* before grouping expression */ ( + 4 /* before tuple comma */, + /* before tuple expression */ 5 /* before tuple close */ + ) /* before nested close */ + ) /* before outer close */ +) /* before semicolon */; + +select * +from t +group by grouping sets ( + ( + long, + nameeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee + ), + (long) +) +window w as ( + partition by loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong +); + +select * +from t +group by rollup ( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb +); + +select * +from t +group by + cube (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa), + rollup (bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb); + +select * +from t +group by a_very_long_column_name_one + a_very_long_column_name_two + + a_very_long_column_name_three; + +select * +from t +group by + grouping sets ( + ( + long, + nameeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee + ), + (long) + ), + rollup (other, another) +window + w as ( + partition by loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong + ), + w2 as (partition by shortish order by other_column); diff --git a/crates/squawk_fmt/tests/after/paren_select.snap b/crates/squawk_fmt/tests/after/paren_select.snap index 70623686..cb1a3235 100644 --- a/crates/squawk_fmt/tests/after/paren_select.snap +++ b/crates/squawk_fmt/tests/after/paren_select.snap @@ -1,6 +1,5 @@ --- source: crates/squawk_fmt/tests/tests.rs -assertion_line: 29 input_file: crates/squawk_fmt/tests/before/paren_select.sql --- (select 1) order by 1 for update limit 10 offset 2 rows; @@ -38,13 +37,13 @@ select * from (((select 1) union select 2) limit 1) as t; select * from ( - /* after outer open */ ( - (/* before left select */ select 1 /* before left close */) - /* before union */ union - /* before right select */ select 2 /* before compound close */ - ) - /* before inner limit */ limit /* before limit value */ 1 /* before outer close */ - ) /* before alias */ as t; + /* after outer open */ ( + (/* before left select */ select 1 /* before left close */) + /* before union */ union + /* before right select */ select 2 /* before compound close */ + ) + /* before inner limit */ limit /* before limit value */ 1 /* before outer close */ +) /* before alias */ as t; ((select 1) limit 2) order by 3; (select 1) offset 1 limit 2; diff --git a/crates/squawk_fmt/tests/after/select.snap b/crates/squawk_fmt/tests/after/select.snap index 235118c3..640a18ff 100644 --- a/crates/squawk_fmt/tests/after/select.snap +++ b/crates/squawk_fmt/tests/after/select.snap @@ -28,7 +28,8 @@ select a_very_long_second_target_expression a_very_long_second_column_alias, a_very_long_third_target_expression as "A Very Long Quoted Third Column Alias" from a_very_long_schema_name.a_very_long_table_name as a_very_long_table_alias -group by a_very_long_first_target_expression, +group by + a_very_long_first_target_expression, a_very_long_second_target_expression, a_very_long_third_target_expression; diff --git a/crates/squawk_fmt/tests/after/select_clauses.snap b/crates/squawk_fmt/tests/after/select_clauses.snap index ada3c46d..17279da7 100644 --- a/crates/squawk_fmt/tests/after/select_clauses.snap +++ b/crates/squawk_fmt/tests/after/select_clauses.snap @@ -27,9 +27,9 @@ where a_very_long_filter_column_name > a_very_long_filter_threshold_value group by a_very_long_result_column_name having count(*) > a_very_long_having_threshold_value window a_very_long_window_name as ( - partition by a_very_long_partition_column_name - order by a_very_long_order_column_name - ) + partition by a_very_long_partition_column_name + order by a_very_long_order_column_name +) order by a_very_long_result_column_name desc for no key update of a_very_long_common_table_expression_name skip locked limit a_very_long_limit_expression @@ -46,8 +46,8 @@ with /* before recursive */ recursive /* before cte */ cte/* before columns */ ( /* before group */ group /* before by */ by /* before group expression */ x /* before having */ having /* before having expression */ count(*) > 0 /* before window */ window /* before window name */ win /* before window as */ as /* before window open */ ( - /* before partition */ partition /* before partition by */ by /* before partition expression */ x /* before window close */ - ) + /* before partition */ partition /* before partition by */ by /* before partition expression */ x /* before window close */ +) /* before order */ order /* before order by */ by /* before order expression */ x /* before desc */ desc /* before locking */ for /* before lock strength */ update /* before locking of */ of /* before locked relation */ cte /* before lock wait */ nowait @@ -80,3 +80,9 @@ order by thousand select x from foo offset 1 limit 2; select x from foo limit 2 for update; + +select * +from t +window + w as (partition by aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa), + w2 as (partition by bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb); diff --git a/crates/squawk_fmt/tests/after/select_into.snap b/crates/squawk_fmt/tests/after/select_into.snap index cf67ce9e..837df429 100644 --- a/crates/squawk_fmt/tests/after/select_into.snap +++ b/crates/squawk_fmt/tests/after/select_into.snap @@ -64,8 +64,8 @@ from source /* before where */ where /* before where expression */ a > 1 /* before having */ having /* before having expression */ count(*) > 1 /* before window */ window /* before window name */ named_window /* before window as */ as /* before window open */ ( - /* before partition */ partition /* before partition by */ by a /* before window close */ - ) + /* before partition */ partition /* before partition by */ by a /* before window close */ +) /* before locking */ for /* before lock strength */ update /* before locking of */ of /* before locked relation */ source /* before lock wait */ nowait /* before limit */ limit /* before limit value */ 10 /* before offset */ offset /* before offset value */ 2 /* before rows */ rows; diff --git a/crates/squawk_fmt/tests/before/from.sql b/crates/squawk_fmt/tests/before/from.sql index b06c8d6e..7a70e792 100644 --- a/crates/squawk_fmt/tests/before/from.sql +++ b/crates/squawk_fmt/tests/before/from.sql @@ -63,3 +63,7 @@ select a_very_long_column_name from a_very_long_schema_name.a_very_long_table_na select s.stxrelid::regclass as relation, array_agg(a.attname order by u.ord) as stats_columns from pg_statistic_ext s cross join lateral unnest(s.stxkeys::int2[]) with ordinality as u(attnum, ord) join pg_attribute a on a.attrelid = s.stxrelid and a.attnum = u.attnum; select * from statistics /* before base alias */ s /* before cross */ cross /* before cross join */ join /* before lateral */ lateral /* before function */ unnest /* before function opening paren */ ( /* before argument */ s.keys /* before cast */ ::int2[] /* before function closing paren */ ) /* before with */ with /* before ordinality */ ordinality /* before function alias */ as /* before function alias name */ u /* before alias opening paren */ ( /* before first alias column */ attnum /* before alias comma */, /* before second alias column */ ord /* before alias closing paren */ ) /* before nested join */ join /* before nested relation */ attributes /* before nested alias */ a /* before on */ on /* before left operand */ a.attnum /* before equals */ = /* before right operand */ u.attnum; + +select * from generate_series(1, 30000000000000000000000000000000000000000) with ordinality as g (n, ord); + +select * from unnest(fooooooooooooooooooooooooooooooooooooooooo) as u (value int8, other text); diff --git a/crates/squawk_fmt/tests/before/group_by.sql b/crates/squawk_fmt/tests/before/group_by.sql index 678d1cb9..ab559a67 100644 --- a/crates/squawk_fmt/tests/before/group_by.sql +++ b/crates/squawk_fmt/tests/before/group_by.sql @@ -18,3 +18,13 @@ group /* before by */ by /* before distinct */ distinct /* before grouping */ gr /* before grouping expression */ (4 /* before tuple comma */, /* before tuple expression */ 5 /* before tuple close */) /* before nested close */ ) /* before outer close */ ) /* before semicolon */; + +select * from t group by grouping sets ((long, nameeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee), (long)) window w as (partition by loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong); + +select * from t group by rollup (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb); + +select * from t group by cube (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa), rollup (bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb); + +select * from t group by a_very_long_column_name_one + a_very_long_column_name_two + a_very_long_column_name_three; + +select * from t group by grouping sets ((long, nameeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee), (long)), rollup (other, another) window w as (partition by loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong), w2 as (partition by shortish order by other_column); diff --git a/crates/squawk_fmt/tests/before/select_clauses.sql b/crates/squawk_fmt/tests/before/select_clauses.sql index e0a57869..185c92a9 100644 --- a/crates/squawk_fmt/tests/before/select_clauses.sql +++ b/crates/squawk_fmt/tests/before/select_clauses.sql @@ -16,3 +16,5 @@ select thousand from onek where thousand < 995 order by thousand /* before offse select x from foo offset 1 limit 2; select x from foo limit 2 for update; + +select * from t window w as (partition by aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa), w2 as (partition by bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb);