diff --git a/crates/squawk_fmt/src/fmt.rs b/crates/squawk_fmt/src/fmt.rs index 4d4544c6..49c89b55 100644 --- a/crates/squawk_fmt/src/fmt.rs +++ b/crates/squawk_fmt/src/fmt.rs @@ -665,11 +665,10 @@ fn build_returning_clause<'a>(returning: ast::ReturningClause) -> Doc<'a> { if let Some(target_list) = returning.target_list() { let targets = join_comma_separated(build_targets(&target_list), TrailingComments::All) .unwrap_or_else(Doc::nil); - doc = doc - .append(space_before(target_list.syntax())) - .append(targets.nest(2).group()); + let hug = is_single_inline_target_list(&target_list); + doc = append_clause_body(doc, target_list.syntax(), targets, hug); } - doc + doc.group() } fn build_returning_option_list<'a>(options: ast::ReturningOptionList) -> Doc<'a> { @@ -1060,36 +1059,58 @@ fn build_set_clause<'a>(set_clause: ast::SetClause) -> Doc<'a> { .map(|token| leading_comments(&token).append(Doc::text("set"))) .unwrap_or_else(Doc::nil); if let Some(columns) = set_clause.set_column_list() { + let inline_bracketed_expr = match columns.set_columns().exactly_one() { + Ok(ast::SetColumn::SetSingleColumn(column)) => set_column_has_bracketed_expr(&column), + _ => false, + }; let items = columns.set_columns().map(|column| { let syntax = column.syntax().clone(); ( - leading_comments(column.syntax()).append(build_set_column(column)), + leading_comments(column.syntax()) + .append(build_set_column(column, inline_bracketed_expr)), syntax, ) }); if let Some(items) = build_comma_separated_docs(items) { - doc = doc.append(line_before(columns.syntax()).append(items).nest(2).group()); + doc = append_clause_body(doc, columns.syntax(), items, inline_bracketed_expr); } } - doc + doc.group() +} + +fn set_column_has_bracketed_expr(column: &ast::SetSingleColumn) -> bool { + column + .set_expr() + .and_then(|expr| expr.expr()) + .is_some_and(|expr| is_inline_bracketed_expr(&expr)) } -fn build_set_column<'a>(column: ast::SetColumn) -> Doc<'a> { +fn build_set_column<'a>(column: ast::SetColumn, bracketed_expr: bool) -> Doc<'a> { match column { ast::SetColumn::SetSingleColumn(column) => { - let mut doc = column + let doc = column .column_target() .map(build_column_target) .unwrap_or_else(Doc::nil); + let mut value = Doc::nil(); if let Some(eq_token) = column.eq_token() { - doc = doc.append(line_before(&eq_token).append(Doc::text("=")).nest(2)); + let separator = if bracketed_expr { + space_before(&eq_token) + } else { + line_before(&eq_token) + }; + value = value.append(separator).append(Doc::text("=")); } if let Some(expr) = column.set_expr() { - doc = doc + value = value .append(space_before(expr.syntax())) .append(build_set_expr(expr)); } - doc.group() + if bracketed_expr { + doc.append(value) + } else { + doc.append(value.nest(2)).group() + } } ast::SetColumn::SetMultipleColumns(columns) => { let mut doc = columns @@ -5194,8 +5215,8 @@ fn build_privileges<'a>(privileges: ast::Privileges) -> Doc<'a> { } } -fn build_path_items<'a>(items: Vec<(SyntaxNode, ast::PathRef)>) -> Doc<'a> { - build_comma_separated_docs(items.into_iter().map(|(syntax, path)| { +fn build_path_items<'a>(items: impl Iterator) -> Doc<'a> { + build_comma_separated_docs(items.map(|(syntax, path)| { ( leading_comments(&syntax).append(build_path_ref(&path)), syntax, @@ -5204,8 +5225,8 @@ fn build_path_items<'a>(items: Vec<(SyntaxNode, ast::PathRef)>) -> Doc<'a> { .unwrap_or_else(Doc::nil) } -fn build_name_items<'a>(items: Vec) -> Doc<'a> { - build_comma_separated_docs(items.into_iter().map(|syntax| { +fn build_name_items<'a>(items: impl Iterator) -> Doc<'a> { + build_comma_separated_docs(items.map(|syntax| { let doc = leading_comments(&syntax).append(build_name(&syntax)); (doc, syntax) })) @@ -5263,11 +5284,7 @@ fn build_routine_sig<'a>(sig: ast::RoutineSig) -> Doc<'a> { fn build_privilege_objects<'a>(objects: ast::PrivilegeObjects) -> Doc<'a> { match objects { ast::PrivilegeObjects::PrivilegeAllFunctionsInSchema(node) => { - let items = build_name_items( - node.schema_refs() - .map(|item| item.syntax().clone()) - .collect(), - ); + let items = build_name_items(node.schema_refs().map(|item| item.syntax().clone())); append_privilege_items( build_keyword_tokens([ (node.all_token(), "all"), @@ -5279,11 +5296,7 @@ fn build_privilege_objects<'a>(objects: ast::PrivilegeObjects) -> Doc<'a> { ) } ast::PrivilegeObjects::PrivilegeAllProceduresInSchema(node) => { - let items = build_name_items( - node.schema_refs() - .map(|item| item.syntax().clone()) - .collect(), - ); + let items = build_name_items(node.schema_refs().map(|item| item.syntax().clone())); append_privilege_items( build_keyword_tokens([ (node.all_token(), "all"), @@ -5295,11 +5308,7 @@ fn build_privilege_objects<'a>(objects: ast::PrivilegeObjects) -> Doc<'a> { ) } ast::PrivilegeObjects::PrivilegeAllRoutinesInSchema(node) => { - let items = build_name_items( - node.schema_refs() - .map(|item| item.syntax().clone()) - .collect(), - ); + let items = build_name_items(node.schema_refs().map(|item| item.syntax().clone())); append_privilege_items( build_keyword_tokens([ (node.all_token(), "all"), @@ -5311,11 +5320,7 @@ fn build_privilege_objects<'a>(objects: ast::PrivilegeObjects) -> Doc<'a> { ) } ast::PrivilegeObjects::PrivilegeAllSequencesInSchema(node) => { - let items = build_name_items( - node.schema_refs() - .map(|item| item.syntax().clone()) - .collect(), - ); + let items = build_name_items(node.schema_refs().map(|item| item.syntax().clone())); append_privilege_items( build_keyword_tokens([ (node.all_token(), "all"), @@ -5327,11 +5332,7 @@ fn build_privilege_objects<'a>(objects: ast::PrivilegeObjects) -> Doc<'a> { ) } ast::PrivilegeObjects::PrivilegeAllTablesInSchema(node) => { - let items = build_name_items( - node.schema_refs() - .map(|item| item.syntax().clone()) - .collect(), - ); + let items = build_name_items(node.schema_refs().map(|item| item.syntax().clone())); append_privilege_items( build_keyword_tokens([ (node.all_token(), "all"), @@ -5343,33 +5344,23 @@ fn build_privilege_objects<'a>(objects: ast::PrivilegeObjects) -> Doc<'a> { ) } ast::PrivilegeObjects::PrivilegeDatabase(node) => { - let items = build_name_items( - node.database_refs() - .map(|item| item.syntax().clone()) - .collect(), - ); + let items = build_name_items(node.database_refs().map(|item| item.syntax().clone())); append_privilege_items( build_keyword_tokens([(node.database_token(), "database")]), items, ) } - ast::PrivilegeObjects::PrivilegeDefault(node) => build_path_items( - node.relation_name_refs() - .filter_map(|item| { - let syntax = item.syntax().clone(); - item.path_ref().map(|path| (syntax, path)) - }) - .collect(), - ), + ast::PrivilegeObjects::PrivilegeDefault(node) => { + build_path_items(node.relation_name_refs().filter_map(|item| { + let syntax = item.syntax().clone(); + item.path_ref().map(|path| (syntax, path)) + })) + } ast::PrivilegeObjects::PrivilegeDomain(node) => { - let items = build_path_items( - node.domain_refs() - .filter_map(|item| { - let syntax = item.syntax().clone(); - item.path_ref().map(|path| (syntax, path)) - }) - .collect(), - ); + let items = build_path_items(node.domain_refs().filter_map(|item| { + let syntax = item.syntax().clone(); + item.path_ref().map(|path| (syntax, path)) + })); append_privilege_items( build_keyword_tokens([(node.domain_token(), "domain")]), items, @@ -5378,8 +5369,7 @@ fn build_privilege_objects<'a>(objects: ast::PrivilegeObjects) -> Doc<'a> { ast::PrivilegeObjects::PrivilegeForeignDataWrapper(node) => { let items = build_name_items( node.foreign_data_wrapper_refs() - .map(|item| item.syntax().clone()) - .collect(), + .map(|item| item.syntax().clone()), ); append_privilege_items( build_keyword_tokens([ @@ -5391,11 +5381,7 @@ fn build_privilege_objects<'a>(objects: ast::PrivilegeObjects) -> Doc<'a> { ) } ast::PrivilegeObjects::PrivilegeForeignServer(node) => { - let items = build_name_items( - node.server_refs() - .map(|item| item.syntax().clone()) - .collect(), - ); + let items = build_name_items(node.server_refs().map(|item| item.syntax().clone())); append_privilege_items( build_keyword_tokens([ (node.foreign_token(), "foreign"), @@ -5405,11 +5391,7 @@ fn build_privilege_objects<'a>(objects: ast::PrivilegeObjects) -> Doc<'a> { ) } ast::PrivilegeObjects::PrivilegeLanguage(node) => { - let items = build_name_items( - node.language_refs() - .map(|item| item.syntax().clone()) - .collect(), - ); + let items = build_name_items(node.language_refs().map(|item| item.syntax().clone())); append_privilege_items( build_keyword_tokens([(node.language_token(), "language")]), items, @@ -5433,14 +5415,10 @@ fn build_privilege_objects<'a>(objects: ast::PrivilegeObjects) -> Doc<'a> { ) } ast::PrivilegeObjects::PrivilegePropertyGraph(node) => { - let items = build_path_items( - node.property_graph_refs() - .filter_map(|item| { - let syntax = item.syntax().clone(); - item.path_ref().map(|path| (syntax, path)) - }) - .collect(), - ); + let items = build_path_items(node.property_graph_refs().filter_map(|item| { + let syntax = item.syntax().clone(); + item.path_ref().map(|path| (syntax, path)) + })); append_privilege_items( build_keyword_tokens([ (node.property_token(), "property"), @@ -5450,61 +5428,41 @@ fn build_privilege_objects<'a>(objects: ast::PrivilegeObjects) -> Doc<'a> { ) } ast::PrivilegeObjects::PrivilegeSchema(node) => { - let items = build_name_items( - node.schema_refs() - .map(|item| item.syntax().clone()) - .collect(), - ); + let items = build_name_items(node.schema_refs().map(|item| item.syntax().clone())); append_privilege_items( build_keyword_tokens([(node.schema_token(), "schema")]), items, ) } ast::PrivilegeObjects::PrivilegeSequence(node) => { - let items = build_path_items( - node.sequence_refs() - .filter_map(|item| { - let syntax = item.syntax().clone(); - item.path_ref().map(|path| (syntax, path)) - }) - .collect(), - ); + let items = build_path_items(node.sequence_refs().filter_map(|item| { + let syntax = item.syntax().clone(); + item.path_ref().map(|path| (syntax, path)) + })); append_privilege_items( build_keyword_tokens([(node.sequence_token(), "sequence")]), items, ) } ast::PrivilegeObjects::PrivilegeTable(node) => { - let items = build_path_items( - node.relation_name_refs() - .filter_map(|item| { - let syntax = item.syntax().clone(); - item.path_ref().map(|path| (syntax, path)) - }) - .collect(), - ); + let items = build_path_items(node.relation_name_refs().filter_map(|item| { + let syntax = item.syntax().clone(); + item.path_ref().map(|path| (syntax, path)) + })); append_privilege_items(build_keyword_tokens([(node.table_token(), "table")]), items) } ast::PrivilegeObjects::PrivilegeTablespace(node) => { - let items = build_name_items( - node.tablespace_refs() - .map(|item| item.syntax().clone()) - .collect(), - ); + let items = build_name_items(node.tablespace_refs().map(|item| item.syntax().clone())); append_privilege_items( build_keyword_tokens([(node.tablespace_token(), "tablespace")]), items, ) } ast::PrivilegeObjects::PrivilegeType(node) => { - let items = build_path_items( - node.type_name_refs() - .filter_map(|item| { - let syntax = item.syntax().clone(); - item.path_ref().map(|path| (syntax, path)) - }) - .collect(), - ); + let items = build_path_items(node.type_name_refs().filter_map(|item| { + let syntax = item.syntax().clone(); + item.path_ref().map(|path| (syntax, path)) + })); append_privilege_items(build_keyword_tokens([(node.type_token(), "type")]), items) } ast::PrivilegeObjects::PrivilegeLargeObject(node) => { @@ -7432,6 +7390,14 @@ fn append_nested_clause<'a>(doc: Doc<'a>, syntax: &SyntaxNode, clause: Doc<'a>) doc.append(line_before(syntax).append(clause).nest(2)) } +fn append_clause_body<'a>(doc: Doc<'a>, syntax: &SyntaxNode, body: Doc<'a>, hug: bool) -> Doc<'a> { + if hug { + doc.append(space_before(syntax).nest(2)).append(body) + } else { + doc.append(line_before(syntax).append(body).nest(2).group()) + } +} + fn build_alter_option_list<'a>(list: &ast::AlterOptionList) -> Doc<'a> { let mut doc = Doc::text("options"); if let Some(l_paren) = list.l_paren_token() { @@ -7497,24 +7463,62 @@ fn build_alter_option<'a>(option: &ast::AlterOption) -> Doc<'a> { } } +fn build_default_constraint<'a>(constraint: ast::DefaultConstraint) -> Doc<'a> { + let mut doc = build_constraint_name_clause(constraint.constraint_name_clause()); + if let Some(default) = constraint.default_token() { + doc = doc + .append(leading_comments(&default)) + .append(Doc::text("default")); + } + if let Some(expr) = constraint.expr() { + doc = doc + .append(space_before(expr.syntax())) + .append(build_expr(expr)); + } + let mut doc = doc.group(); + for option in constraint.constraint_options() { + doc = doc.append( + line_before(option.syntax()) + .append(build_constraint_option(option)) + .nest(2), + ); + } + doc.group() +} + +fn build_not_null_constraint<'a>(constraint: ast::NotNullConstraint) -> Doc<'a> { + let mut doc = build_constraint_name_clause(constraint.constraint_name_clause()); + doc = doc.append(build_keyword_tokens([ + (constraint.not_token(), "not"), + (constraint.null_token(), "null"), + ])); + if let Some(column) = constraint.column_name_ref() { + doc = doc + .append(space_before(column.syntax())) + .append(build_name(column.syntax())); + } + append_constraint_options(doc, constraint.constraint_options()) + .nest(2) + .group() +} + +fn build_null_constraint<'a>(constraint: ast::NullConstraint) -> Doc<'a> { + let mut doc = build_constraint_name_clause(constraint.constraint_name_clause()); + if let Some(null) = constraint.null_token() { + doc = doc + .append(leading_comments(&null)) + .append(Doc::text("null")); + } + append_constraint_options(doc, constraint.constraint_options()) + .nest(2) + .group() +} + fn build_column_constraint<'a>(constraint: ast::ColumnConstraint) -> Doc<'a> { match constraint { ast::ColumnConstraint::CheckConstraint(constraint) => build_check_constraint(constraint), ast::ColumnConstraint::DefaultConstraint(constraint) => { - let mut doc = build_constraint_name_clause(constraint.constraint_name_clause()); - if let Some(default) = constraint.default_token() { - doc = doc - .append(leading_comments(&default)) - .append(Doc::text("default")); - } - if let Some(expr) = constraint.expr() { - doc = doc - .append(space_before(expr.syntax())) - .append(build_expr(expr)); - } - append_constraint_options(doc, constraint.constraint_options()) - .nest(2) - .group() + build_default_constraint(constraint) } ast::ColumnConstraint::ExcludeConstraint(constraint) => { build_exclude_constraint(constraint) @@ -7523,33 +7527,9 @@ fn build_column_constraint<'a>(constraint: ast::ColumnConstraint) -> Doc<'a> { build_generated_constraint(constraint) } ast::ColumnConstraint::NotNullConstraint(constraint) => { - let mut doc = build_constraint_name_clause(constraint.constraint_name_clause()); - if let Some(not) = constraint.not_token() { - doc = doc.append(leading_comments(¬)).append(Doc::text("not")); - } - if let Some(null) = constraint.null_token() { - doc = doc.append(space_before(&null)).append(Doc::text("null")); - } - if let Some(column) = constraint.column_name_ref() { - doc = doc - .append(space_before(column.syntax())) - .append(build_name(column.syntax())); - } - append_constraint_options(doc, constraint.constraint_options()) - .nest(2) - .group() - } - ast::ColumnConstraint::NullConstraint(constraint) => { - let mut doc = build_constraint_name_clause(constraint.constraint_name_clause()); - if let Some(null) = constraint.null_token() { - doc = doc - .append(leading_comments(&null)) - .append(Doc::text("null")); - } - append_constraint_options(doc, constraint.constraint_options()) - .nest(2) - .group() + build_not_null_constraint(constraint) } + ast::ColumnConstraint::NullConstraint(constraint) => build_null_constraint(constraint), ast::ColumnConstraint::PrimaryKeyConstraint(constraint) => { build_primary_key_constraint(constraint) } @@ -7801,7 +7781,7 @@ fn build_table_constraint<'a>(constraint: ast::TableConstraint) -> Doc<'a> { build_foreign_key_constraint(constraint) } ast::TableConstraint::NotNullConstraint(constraint) => { - build_domain_constraint(constraint.into()) + build_not_null_constraint(constraint) } ast::TableConstraint::PrimaryKeyConstraint(constraint) => { build_primary_key_constraint(constraint) @@ -7852,11 +7832,11 @@ fn build_check_constraint<'a>(constraint: ast::CheckConstraint) -> Doc<'a> { let mut options = Doc::nil(); for option in constraint.constraint_options() { - options = options - .append(line_before(option.syntax())) - .append(build_keyword_node(option.syntax())); + options = append_nested_node(options, option, |option| { + build_keyword_node(option.syntax()) + }); } - doc.append(options.nest(2)).group() + doc.append(options).group() } fn build_primary_key_constraint<'a>(constraint: ast::PrimaryKeyConstraint) -> Doc<'a> { @@ -8943,7 +8923,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 single_def = window.window_defs().exactly_one().is_ok(); let defs = window.window_defs().map(|def| { ( leading_comments(def.syntax()).append(build_window_def(def.clone())), @@ -13002,51 +12982,12 @@ fn build_alter_domain<'a>(stmt: &ast::AlterDomain) -> Doc<'a> { fn build_domain_constraint<'a>(constraint: ast::Constraint) -> Doc<'a> { match constraint { ast::Constraint::CheckConstraint(node) => build_check_constraint(node), - ast::Constraint::DefaultConstraint(node) => { - let mut doc = build_constraint_name_clause(node.constraint_name_clause()); - if let Some(default) = node.default_token() { - doc = doc - .append(leading_comments(&default)) - .append(Doc::text("default")); - } - if let Some(expr) = node.expr() { - doc = doc - .append(space_before(expr.syntax())) - .append(build_expr(expr)); - } - append_constraint_options(doc, node.constraint_options()) - .nest(2) - .group() - } + ast::Constraint::DefaultConstraint(node) => build_default_constraint(node), ast::Constraint::ExcludeConstraint(node) => build_exclude_constraint(node), ast::Constraint::ForeignKeyConstraint(node) => build_foreign_key_constraint(node), ast::Constraint::GeneratedConstraint(node) => build_generated_constraint(node), - ast::Constraint::NotNullConstraint(node) => { - let mut doc = build_constraint_name_clause(node.constraint_name_clause()); - doc = doc.append(build_keyword_tokens([ - (node.not_token(), "not"), - (node.null_token(), "null"), - ])); - if let Some(column) = node.column_name_ref() { - doc = doc - .append(space_before(column.syntax())) - .append(build_name(column.syntax())); - } - append_constraint_options(doc, node.constraint_options()) - .nest(2) - .group() - } - ast::Constraint::NullConstraint(node) => { - let mut doc = build_constraint_name_clause(node.constraint_name_clause()); - if let Some(null) = node.null_token() { - doc = doc - .append(leading_comments(&null)) - .append(Doc::text("null")); - } - append_constraint_options(doc, node.constraint_options()) - .nest(2) - .group() - } + ast::Constraint::NotNullConstraint(node) => build_not_null_constraint(node), + ast::Constraint::NullConstraint(node) => build_null_constraint(node), ast::Constraint::PrimaryKeyConstraint(node) => build_primary_key_constraint(node), ast::Constraint::ReferencesConstraint(node) => build_references_constraint(node), ast::Constraint::UniqueConstraint(node) => build_unique_constraint(node), @@ -14704,6 +14645,41 @@ fn build_select_doc<'a>(select: &ast::Select) -> Doc<'a> { build_select_doc_ungrouped(select).group() } +fn is_inline_bracketed_expr(expr: &ast::Expr) -> bool { + match expr { + ast::Expr::ArrayExpr(array_expr) => { + array_expr.select_variant().is_some() || array_expr.exprs().next().is_some() + } + ast::Expr::CallExpr(call_expr) => match call_expr.arg_list() { + Some(arg_list) => arg_list_has_body(&arg_list), + None => true, + }, + ast::Expr::ParenExpr(_) => true, + ast::Expr::TupleExpr(tuple_expr) => tuple_expr.exprs().next().is_some(), + ast::Expr::CastExpr(cast_expr) => { + cast_expr.cast_token().is_some() || cast_expr.treat_token().is_some() + } + _ => false, + } +} + +fn ends_with_inline_bracketed_expr(expr: &ast::Expr) -> bool { + match expr { + ast::Expr::BinExpr(bin_expr) => bin_expr + .rhs() + .as_ref() + .is_some_and(is_inline_bracketed_expr), + expr => is_inline_bracketed_expr(expr), + } +} + +fn is_single_inline_target_list(target_list: &ast::TargetList) -> bool { + match target_list.targets().exactly_one() { + Ok(target) => target.expr().as_ref().is_some_and(is_inline_bracketed_expr), + Err(_) => false, + } +} + fn has_single_inline_target(select: &ast::Select) -> bool { let Some(select_clause) = select.select_clause() else { return false; @@ -14711,22 +14687,10 @@ fn has_single_inline_target(select: &ast::Select) -> bool { if select_clause.select_quantifier().is_some() { return false; } - let Some(target_list) = select_clause.target_list() else { - return false; - }; - let mut targets = target_list.targets(); - let Some(target) = targets.next() else { - return false; - }; - if targets.next().is_some() { - return false; - } - matches!( - target.expr(), - Some(ast::Expr::ArrayExpr(_)) - | Some(ast::Expr::CallExpr(_)) - | Some(ast::Expr::ParenExpr(_)) - ) + select_clause + .target_list() + .as_ref() + .is_some_and(is_single_inline_target_list) } fn build_select_doc_ungrouped<'a>(select: &ast::Select) -> Doc<'a> { @@ -14889,8 +14853,9 @@ fn build_join<'a>(join: ast::Join) -> Doc<'a> { fn build_join_on_clause<'a>(on_clause: ast::OnClause) -> Doc<'a> { let mut doc = Doc::text("on"); if let Some(expr) = on_clause.expr() { - let expr_doc = leading_comments(expr.syntax()).append(build_expr(expr)); - doc = doc.append(Doc::line_or_space().append(expr_doc).nest(2)); + let syntax = expr.syntax().clone(); + let hug = ends_with_inline_bracketed_expr(&expr); + doc = append_clause_body(doc, &syntax, build_expr(expr), hug); } doc } @@ -15826,16 +15791,13 @@ fn build_from_alias<'a>(alias: Option) -> Doc<'a> { fn build_from_alias_columns<'a>(columns: ast::FromAliasColumns) -> Doc<'a> { match columns { ast::FromAliasColumns::ColumnList(list) => { - let items = list - .column_names() - .map(|name| { - let syntax = name.syntax().clone(); - ( - leading_comments(&syntax).append(build_name(&syntax)), - syntax, - ) - }) - .collect(); + let items = list.column_names().map(|name| { + let syntax = name.syntax().clone(); + ( + leading_comments(&syntax).append(build_name(&syntax)), + syntax, + ) + }); comments_before(list.syntax()).append(build_from_alias_column_list( list.l_paren_token(), items, @@ -15843,25 +15805,22 @@ fn build_from_alias_columns<'a>(columns: ast::FromAliasColumns) -> Doc<'a> { )) } ast::FromAliasColumns::ColumnDefList(list) => { - let items = list - .column_defs() - .map(|column| { - let syntax = column.syntax().clone(); - let mut doc = leading_comments(&syntax); - if let Some(name) = column.name() { - doc = doc.append(build_name(name.syntax())); - } - if let Some(ty) = column.ty() { - doc = doc.append(space_before(ty.syntax())).append(build_type(ty)); - } - if let Some(collate) = column.collate() { - doc = doc - .append(space_before(collate.syntax())) - .append(build_collate_expr(collate)); - } - (doc, syntax) - }) - .collect(); + let items = list.column_defs().map(|column| { + let syntax = column.syntax().clone(); + let mut doc = leading_comments(&syntax); + if let Some(name) = column.name() { + doc = doc.append(build_name(name.syntax())); + } + if let Some(ty) = column.ty() { + doc = doc.append(space_before(ty.syntax())).append(build_type(ty)); + } + if let Some(collate) = column.collate() { + doc = doc + .append(space_before(collate.syntax())) + .append(build_collate_expr(collate)); + } + (doc, syntax) + }); comments_before(list.syntax()).append(build_from_alias_column_list( list.l_paren_token(), items, @@ -15873,7 +15832,7 @@ fn build_from_alias_columns<'a>(columns: ast::FromAliasColumns) -> Doc<'a> { fn build_from_alias_column_list<'a>( l_paren: Option, - items: Vec<(Doc<'a>, SyntaxNode)>, + items: impl Iterator, SyntaxNode)>, r_paren: Option, ) -> Doc<'a> { let mut doc = Doc::nil(); @@ -15882,27 +15841,23 @@ fn build_from_alias_column_list<'a>( } doc = doc.append(Doc::text("(")); - let body = build_comma_separated_docs(items.into_iter()).unwrap_or_else(Doc::nil); + let body = build_comma_separated_docs(items).unwrap_or_else(Doc::nil); doc.append(wrap_body(body, r_paren)) .append(Doc::text(")")) .group() } fn build_group_by_list<'a>(list: ast::GroupByList) -> Doc<'a> { - let group_bys: Vec<_> = list - .group_bys() - .map(|group_by| { - let syntax = group_by.syntax().clone(); - ( - leading_comments(&syntax).append(build_group_by(group_by)), - syntax, - ) - }) - .collect(); - let single_group_by = group_bys.len() == 1; - let body = leading_comments(list.syntax()).append( - join_comma_separated(group_bys.into_iter(), TrailingComments::All).unwrap_or_else(Doc::nil), - ); + let single_group_by = list.group_bys().exactly_one().is_ok(); + let group_bys = list.group_bys().map(|group_by| { + let syntax = group_by.syntax().clone(); + ( + leading_comments(&syntax).append(build_group_by(group_by)), + syntax, + ) + }); + let body = leading_comments(list.syntax()) + .append(join_comma_separated(group_bys, TrailingComments::All).unwrap_or_else(Doc::nil)); if single_group_by { Doc::space().append(body) } else { @@ -15965,12 +15920,10 @@ fn build_grouping_exprs<'a>( exprs: impl Iterator, r_paren: Option, ) -> Doc<'a> { - let exprs: Vec<_> = exprs - .map(|expr| { - let syntax = expr.syntax().clone(); - (leading_comments(&syntax).append(build_expr(expr)), syntax) - }) - .collect(); + let exprs = exprs.map(|expr| { + let syntax = expr.syntax().clone(); + (leading_comments(&syntax).append(build_expr(expr)), syntax) + }); build_grouping_list(l_paren, exprs, r_paren) } @@ -15979,21 +15932,19 @@ fn build_grouping_group_bys<'a>( group_bys: impl Iterator, r_paren: Option, ) -> Doc<'a> { - let group_bys = group_bys - .map(|group_by| { - let syntax = group_by.syntax().clone(); - ( - leading_comments(&syntax).append(build_group_by(group_by)), - syntax, - ) - }) - .collect(); + let group_bys = group_bys.map(|group_by| { + let syntax = group_by.syntax().clone(); + ( + leading_comments(&syntax).append(build_group_by(group_by)), + syntax, + ) + }); build_grouping_list(l_paren, group_bys, r_paren) } fn build_grouping_list<'a>( l_paren: Option, - items: Vec<(Doc<'a>, SyntaxNode)>, + items: impl Iterator, SyntaxNode)>, r_paren: Option, ) -> Doc<'a> { let mut doc = Doc::nil(); @@ -16002,7 +15953,7 @@ fn build_grouping_list<'a>( } doc = doc.append(Doc::text("(")); - doc = doc.append(match build_comma_separated_docs(items.into_iter()) { + doc = doc.append(match build_comma_separated_docs(items) { Some(body) => wrap_body(body, r_paren), None => wrap_empty_body(r_paren), }); @@ -16661,17 +16612,24 @@ fn build_where_clause<'a>(where_clause: ast::WhereClause) -> Doc<'a> { .map(|token| leading_comments(&token).append(Doc::text("where"))) .unwrap_or_else(Doc::nil); if let Some(expr) = where_clause.expr() { - let expr_doc = match expr.clone() { - ast::Expr::BinExpr(bin_expr) => { - if let Some(logical) = bin_expr.op().as_ref().and_then(logical_op) { - build_logical_expr(bin_expr, logical) - } else { - build_expr(expr.clone()) - } + let syntax = expr.syntax().clone(); + let logical = match &expr { + ast::Expr::BinExpr(bin_expr) => bin_expr + .op() + .as_ref() + .and_then(logical_op) + .map(|logical| (bin_expr.clone(), logical)), + _ => None, + }; + doc = match logical { + Some((bin_expr, logical)) => { + append_nested_clause(doc, &syntax, build_logical_expr(bin_expr, logical)) + } + None => { + let hug = ends_with_inline_bracketed_expr(&expr); + append_clause_body(doc, &syntax, build_expr(expr), hug) } - _ => build_expr(expr.clone()), }; - doc = append_nested_clause(doc, expr.syntax(), expr_doc); } doc.group() } @@ -18179,7 +18137,14 @@ fn build_parenthesized_expr_or_select_fn<'a>( body = body .append(leading_comments(select.syntax())) .append(match select { - ast::SelectVariant::Select(select) => build_select_doc_ungrouped(&select), + ast::SelectVariant::Select(select) => { + let doc = build_select_doc_ungrouped(&select); + if select.from_clause().is_none() { + doc.group() + } else { + doc + } + } select => build_select_variant(select), }); } @@ -18188,10 +18153,14 @@ fn build_parenthesized_expr_or_select_fn<'a>( doc.append(Doc::text(")")).group() } -fn build_call_arg_list<'a>(arg_list: ast::ArgList) -> Doc<'a> { - let has_body = arg_list.star_token().is_some() +fn arg_list_has_body(arg_list: &ast::ArgList) -> bool { + arg_list.star_token().is_some() || arg_list.all_or_distinct().is_some() - || arg_list.args().next().is_some(); + || arg_list.args().next().is_some() +} + +fn build_call_arg_list<'a>(arg_list: ast::ArgList) -> Doc<'a> { + let has_body = arg_list_has_body(&arg_list); let mut doc = Doc::nil(); if let Some(l_paren) = arg_list.l_paren_token() { doc = doc.append(comments_before(&l_paren)); @@ -18267,6 +18236,12 @@ fn build_order_by_clause<'a>(clause: ast::OrderByClause) -> Doc<'a> { doc = doc.append(Doc::text("by")); if let Some(list) = clause.sort_by_list() { + let hug = match list.sort_bys().exactly_one() { + Ok(sort_by) => sort_by + .expr() + .is_some_and(|expr| is_inline_bracketed_expr(&expr)), + Err(_) => false, + }; let items = list.sort_bys().map(|sort_by| { let syntax = sort_by.syntax().clone(); ( @@ -18274,9 +18249,8 @@ fn build_order_by_clause<'a>(clause: ast::OrderByClause) -> Doc<'a> { syntax, ) }); - let body = leading_comments(list.syntax()) - .append(join_comma_separated(items, TrailingComments::All).unwrap_or_else(Doc::nil)); - doc = doc.append(Doc::line_or_space().append(body).nest(2)); + let body = join_comma_separated(items, TrailingComments::All).unwrap_or_else(Doc::nil); + doc = append_clause_body(doc, list.syntax(), body, hug); } doc.group() } @@ -18442,13 +18416,15 @@ fn build_cast_expr<'a>(cast_expr: ast::CastExpr) -> Doc<'a> { if let Some(l_paren) = cast_expr.l_paren_token() { doc = doc.append(comments_before(&l_paren)); } + let as_and_type = Doc::text("as") + .append(line_before(ty.syntax())) + .append(build_type(ty)) + .group(); let body = leading_comments(expr.syntax()) .append(build_expr(expr)) .append(line_before(&as_token)) - .append(Doc::text("as")) - .append(line_before(ty.syntax())) - .append(build_type(ty)); - let body = body.group(); + .append(as_and_type) + .group(); doc = doc .append(Doc::text("(")) .append(wrap_body(body, cast_expr.r_paren_token())) @@ -18751,14 +18727,8 @@ fn build_bin_expr<'a>(bin_expr: ast::BinExpr) -> Doc<'a> { let rhs = bin_expr.rhs().unwrap(); let comments = comment_run_before(rhs.syntax()); let after_op = comments.before_node(Doc::space()); - let rhs_is_uncommented_quantifier = comments.is_empty() - && match &rhs { - ast::Expr::CallExpr(call) => { - call.all_fn().is_some() || call.any_fn().is_some() || call.some_fn().is_some() - } - _ => false, - }; - let separator = if rhs_is_uncommented_quantifier { + let rhs_requires_inline_separator = comments.is_empty() && is_inline_bracketed_expr(&rhs); + let separator = if rhs_requires_inline_separator { Doc::space() } else { Doc::line_or_space() @@ -18770,7 +18740,7 @@ fn build_bin_expr<'a>(bin_expr: ast::BinExpr) -> Doc<'a> { .append(build_op(bin_expr.op().unwrap())) .append(after_op) .append(build_expr(rhs)); - if rhs_is_uncommented_quantifier { + if rhs_requires_inline_separator { doc } else { doc.nest(2).group() @@ -19230,7 +19200,7 @@ fn build_literal<'a>(lit: ast::Literal) -> Doc<'a> { } fn build_string_literal<'a>(lit: &ast::Literal) -> Doc<'a> { - let parts: Vec> = lit + let parts = lit .syntax() .children_with_tokens() .filter_map(|el| match el { @@ -19238,9 +19208,8 @@ fn build_string_literal<'a>(lit: &ast::Literal) -> Doc<'a> { Some(Doc::text(format_string_token(&t))) } _ => None, - }) - .collect(); - Doc::list(Itertools::intersperse(parts.into_iter(), Doc::hard_line()).collect()) + }); + Doc::list(Itertools::intersperse(parts, Doc::hard_line()).collect()) } fn format_string_token(t: &SyntaxToken) -> String { diff --git a/crates/squawk_fmt/tests/after/alter_policy.snap b/crates/squawk_fmt/tests/after/alter_policy.snap index 2a811b2b..80625057 100644 --- a/crates/squawk_fmt/tests/after/alter_policy.snap +++ b/crates/squawk_fmt/tests/after/alter_policy.snap @@ -17,11 +17,10 @@ alter /* policy */ policy /* name */ account_access_policy alter policy account_access_policy on public.accounts using ( - account_identifier - = a_very_long_session_account_identifier_function( - current_user, - current_role - ) + account_identifier = a_very_long_session_account_identifier_function( + current_user, + current_role + ) ); alter policy account_access_policy diff --git a/crates/squawk_fmt/tests/after/alter_table.snap b/crates/squawk_fmt/tests/after/alter_table.snap index 076a540b..aebbeda5 100644 --- a/crates/squawk_fmt/tests/after/alter_table.snap +++ b/crates/squawk_fmt/tests/after/alter_table.snap @@ -162,3 +162,10 @@ alter /* table */ table /* relation */ options_test /* set */ set /* left paren */ ( /* option */ json /* equals */ = /* value */ constraint /* right paren */ ) /* semicolon */; + +-- parenthesized default expressions are only indented once +alter table t + add column a int + default ( + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + ); diff --git a/crates/squawk_fmt/tests/after/create_domain.snap b/crates/squawk_fmt/tests/after/create_domain.snap index eef565d8..72d338f9 100644 --- a/crates/squawk_fmt/tests/after/create_domain.snap +++ b/crates/squawk_fmt/tests/after/create_domain.snap @@ -27,3 +27,10 @@ create /* before domain */ domain /* before name */ public.commented_domain create domain d text null collate "C"; create domain d text default 5 collate "C" not null; + +-- parenthesized default expressions are only indented once +create domain d + as int + default ( + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + ); diff --git a/crates/squawk_fmt/tests/after/create_table.snap b/crates/squawk_fmt/tests/after/create_table.snap index 900944f2..ddba99df 100644 --- a/crates/squawk_fmt/tests/after/create_table.snap +++ b/crates/squawk_fmt/tests/after/create_table.snap @@ -165,3 +165,35 @@ create table t ( -- end inner ); -- trailing end -- after + +-- parenthesized default expressions are only indented once +create table t ( + a int default ( + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + ) +); + +-- comments in parenthesized default expressions +create table default_expression_comments ( + a int /* before default */ default /* before open */ ( + /* before expression */ greatest( + /* before first */ 1 /* before comma */, + /* before second */ 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16 /* before call close */ + ) /* before default close */ + ) /* before comma */, + b int +); diff --git a/crates/squawk_fmt/tests/after/from.snap b/crates/squawk_fmt/tests/after/from.snap index 712218fb..8fba00ca 100644 --- a/crates/squawk_fmt/tests/after/from.snap +++ b/crates/squawk_fmt/tests/after/from.snap @@ -36,8 +36,7 @@ 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 as */ as /* before type */ int8 /* before closing paren */ ) /* before alias */ as /* before alias name */ converted; select * from (select 1) as selected; select * diff --git a/crates/squawk_fmt/tests/after/insert.snap b/crates/squawk_fmt/tests/after/insert.snap index 27d68c93..8d2f8f9e 100644 --- a/crates/squawk_fmt/tests/after/insert.snap +++ b/crates/squawk_fmt/tests/after/insert.snap @@ -90,5 +90,6 @@ values ( 1, -- values 2 ) -returning a, -- returning +returning + a, -- returning b; diff --git a/crates/squawk_fmt/tests/after/merge.snap b/crates/squawk_fmt/tests/after/merge.snap index 91b8c789..900f9f11 100644 --- a/crates/squawk_fmt/tests/after/merge.snap +++ b/crates/squawk_fmt/tests/after/merge.snap @@ -82,4 +82,5 @@ merge /* before into */ into /* before target */ only /* before target open */(/ ) /* before fifth when */ when not matched then insert /* before default */ default /* before default values */ values -/* before returning */ returning /* before return target */ t.id /* before semicolon */; +/* before returning */ returning + /* before return target */ t.id /* before semicolon */; diff --git a/crates/squawk_fmt/tests/after/select_clauses.snap b/crates/squawk_fmt/tests/after/select_clauses.snap index 528f7470..4d23c687 100644 --- a/crates/squawk_fmt/tests/after/select_clauses.snap +++ b/crates/squawk_fmt/tests/after/select_clauses.snap @@ -92,3 +92,141 @@ select order by a, -- order by b; + +select + 1 +order by ( + select count(*) + from a_very_long_relation_name_that_forces_the_parenthesized_subquery_to_wrap +); + +select + 1 +order /* before by */ by /* before expression */ ( + /* before select */ select count(*) + from a_very_long_relation_name_that_forces_the_parenthesized_subquery_to_wrap /* before close */ +) /* before semicolon */; + +select + category, + current_price > ( + select avg(current_price) + from a_very_long_relation_name_that_forces_the_parenthesized_subquery_to_wrap + ) as above_average, + count(*) filter ( + where current_price > ( + select avg(current_price) + from a_very_long_relation_name_that_forces_the_parenthesized_subquery_to_wrap + ) + ) as expensive_count +from item i + join category_prices p on i.current_price > ( + select avg(current_price) + from a_very_long_relation_name_that_forces_the_parenthesized_subquery_to_wrap + ) +where current_price > ( + select avg(current_price) + from item + where category = i.category or color = i.color +) +group by category +having count(*) > ( + select count(*) + from a_very_long_relation_name_that_forces_the_parenthesized_subquery_to_wrap +) +order by count; + +select 1 +from t +where current_price = any( + select 10000000000000000000000000000000000000000000000000 +); + +select 1 +from t +where current_price = any( + select 1 -- foo +); + +select * +from item +where exists( + select current_price + from a_very_long_relation_name_abcdefghijklmn +); + +select * +from item +where my_predicate_function( + aaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbb +); + +select * +from item +where cast( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa as boolean +); + +select * +from item +where /* before predicate */ exists( + /* before subquery */ select current_price + from a_very_long_relation_name_abcdefghijklmn /* before close */ +); + +select * +from item +where -- before predicate + exists(select current_price from a_very_long_relation_name_abcdefghijklmn); + +select 1 +from t +where a = array[ + a_very_long_first_array_expression, + a_very_long_second_array_expression, + a_very_long_third_array_expressiona_very_long_second_array_expression +]; + +select * +from item +where + aaaaaaaaaaaaaaaaaaaaaaaaaa = 1 + and my_predicate_function(bbbbbbbbbbbbbbbbbbbbbbbbb); + +select * +from t +order by -- before sort expression + f(a); + +select * +from t +order by -- before sort expression + a desc; + +select * +from t +order by + a_very_long_sort_expression_name_that_does_not_fit_on_a_single_line_abcdef; + +select * +from a + join b on -- before condition + a.id = f(b.id); + +select * +from a + join b on -- before condition + a.id = b.id; + +select * +from a + join b on + -- own line + a.id = b.id; + +select * +from t +where + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + = calculate_something(); diff --git a/crates/squawk_fmt/tests/after/select_comments.snap b/crates/squawk_fmt/tests/after/select_comments.snap index 4ea654fe..134ee17a 100644 --- a/crates/squawk_fmt/tests/after/select_comments.snap +++ b/crates/squawk_fmt/tests/after/select_comments.snap @@ -77,10 +77,9 @@ select ( 1 -- final paren item ); -select - ( - 1, 2 -- final tuple item - ); +select ( + 1, 2 -- final tuple item +); select array[ 1 -- final array item diff --git a/crates/squawk_fmt/tests/after/select_expr.snap b/crates/squawk_fmt/tests/after/select_expr.snap index dc0f6025..9e0b0d4a 100644 --- a/crates/squawk_fmt/tests/after/select_expr.snap +++ b/crates/squawk_fmt/tests/after/select_expr.snap @@ -140,6 +140,9 @@ select /* before expr */ array[4] /* before closing paren */ ) /* after any */, exists(select 1 from things), + exists( + select 10000000000000000000000000000000000000000000000000000000000000000 + ), exists((select 1)), exists(table things), 5 = any(values (1), (5)), @@ -158,8 +161,7 @@ select from a_very_long_exists_relation_name ), /* before exists */ exists /* before opening paren */( - /* before select */ select - 1 /* before closing paren */ + /* before select */ select 1 /* before closing paren */ ) /* after exists */, collation for (b + c), collation for ( @@ -657,13 +659,11 @@ select int8 '1', cast( a_very_long_cast_input_expression - as - a_very_long_type_schema_name.a_very_long_cast_type_name + as a_very_long_type_schema_name.a_very_long_cast_type_name ), treat( a_very_long_treat_input_expression - as - a_very_long_type_schema_name.a_very_long_treat_type_name + as a_very_long_type_schema_name.a_very_long_treat_type_name ), a_very_long_postgres_cast_input_expression::a_very_long_type_schema_name.a_very_long_postgres_cast_type_name, a_very_long_type_schema_name.a_very_long_type_literal_type_name 'a very long type literal input value', @@ -870,17 +870,15 @@ select array[ 1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ]; -select - ( - 1, -- tuple expr - 2 - ); +select ( + 1, -- tuple expr + 2 +); -select - row( - 1, -- row expr - 2 - ); +select row( + 1, -- row expr + 2 +); select array[ 1, -- array expr @@ -891,3 +889,8 @@ select count( a, -- call args b ); + +select cast( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + as numeric(10, 2) +); diff --git a/crates/squawk_fmt/tests/after/types.snap b/crates/squawk_fmt/tests/after/types.snap index 8bdcd579..2c24e1ca 100644 --- a/crates/squawk_fmt/tests/after/types.snap +++ b/crates/squawk_fmt/tests/after/types.snap @@ -165,13 +165,11 @@ select ), cast( a_very_long_expression_name_long_long_long_long_long_long - as - character varying(12345) + as character varying(12345) ), treat( a_very_long_expression_name - as - a_very_long_type_schema_name.a_very_long_type_name + as a_very_long_type_schema_name.a_very_long_type_name ), a_very_long_type_schema_name.a_very_long_type_name(12345) 'a very long typed string literal value', interval 'a very long interval literal value' day to second(12345); diff --git a/crates/squawk_fmt/tests/after/update.snap b/crates/squawk_fmt/tests/after/update.snap index ed180bb9..1fe2c93c 100644 --- a/crates/squawk_fmt/tests/after/update.snap +++ b/crates/squawk_fmt/tests/after/update.snap @@ -63,3 +63,61 @@ from source -- trailing from where foo.id = source.id -- trailing where returning foo.id; -- trailing returning -- bottom + +update foo +set a = ( + select count(*) + from a_very_long_relation_name_that_forces_the_subquery_to_wrap_ab +); + +update foo +set a = array[ + a_very_long_first_array_expression, + a_very_long_second_array_expression, + a_very_long_third_array_expression +]; + +update foo +set a = coalesce( + a_very_long_first_expression, + a_very_long_second_expression, + a_very_long_third_expression +); + +update foo +set a = 1 +returning ( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbb +); + +update foo +set a = 1 +returning + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbb; + +update foo +set -- before column + a = f(1); + +update foo +set -- before column + a = 1, + b = 2; + +update foo +set a = 1 +returning -- before target + f(a); + +update foo +set a = 1 +returning -- before target + a, + b; + +update foo +set a = 1 +returning + a_very_long_returning_target_name_that_definitely_does_not_fit_here_okay; diff --git a/crates/squawk_fmt/tests/before/alter_table.sql b/crates/squawk_fmt/tests/before/alter_table.sql index 05901ade..6999b97a 100644 --- a/crates/squawk_fmt/tests/before/alter_table.sql +++ b/crates/squawk_fmt/tests/before/alter_table.sql @@ -69,3 +69,6 @@ ALTER /* table */ TABLE /* relation */ sales_range /* split */ SPLIT /* partitio ALTER TABLE options_test ALTER COLUMN metadata SET (json = constraint); ALTER /* table */ TABLE /* relation */ options_test /* alter */ ALTER /* column */ COLUMN /* name */ metadata /* set */ SET /* left paren */ (/* option */ json /* equals */ = /* value */ constraint /* right paren */) /* semicolon */; + +-- parenthesized default expressions are only indented once +alter table t add column a int default (1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16); diff --git a/crates/squawk_fmt/tests/before/create_domain.sql b/crates/squawk_fmt/tests/before/create_domain.sql index 61ae9d3c..8e6ec8f9 100644 --- a/crates/squawk_fmt/tests/before/create_domain.sql +++ b/crates/squawk_fmt/tests/before/create_domain.sql @@ -6,3 +6,6 @@ create domain extraordinarily_long_schema_name.extraordinarily_long_domain_name create domain d text null collate "C"; create domain d text default 5 collate "C" not null; + +-- parenthesized default expressions are only indented once +create domain d as int default (1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16); diff --git a/crates/squawk_fmt/tests/before/create_table.sql b/crates/squawk_fmt/tests/before/create_table.sql index cb45ecbd..070e4fc2 100644 --- a/crates/squawk_fmt/tests/before/create_table.sql +++ b/crates/squawk_fmt/tests/before/create_table.sql @@ -92,3 +92,8 @@ create table t ( ); -- trailing end -- after +-- parenthesized default expressions are only indented once +create table t (a int default (1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16)); + +-- comments in parenthesized default expressions +create table default_expression_comments (a int /* before default */ default /* before open */ (/* before expression */ greatest(/* before first */ 1 /* before comma */, /* before second */ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 /* before call close */) /* before default close */) /* before comma */, b int); diff --git a/crates/squawk_fmt/tests/before/select_clauses.sql b/crates/squawk_fmt/tests/before/select_clauses.sql index fc569a0d..b8baa127 100644 --- a/crates/squawk_fmt/tests/before/select_clauses.sql +++ b/crates/squawk_fmt/tests/before/select_clauses.sql @@ -21,3 +21,79 @@ select * from t window w as (partition by aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa), w2 select 1 order by a, -- order by b; + +select 1 order by (select count(*) from a_very_long_relation_name_that_forces_the_parenthesized_subquery_to_wrap); + +select 1 order /* before by */ by /* before expression */ (/* before select */ select count(*) from a_very_long_relation_name_that_forces_the_parenthesized_subquery_to_wrap /* before close */) /* before semicolon */; + +select + category, + current_price > ( + select avg(current_price) + from a_very_long_relation_name_that_forces_the_parenthesized_subquery_to_wrap + ) as above_average, + count(*) filter (where current_price > ( + select avg(current_price) + from a_very_long_relation_name_that_forces_the_parenthesized_subquery_to_wrap + )) as expensive_count +from item i +join category_prices p on i.current_price > ( + select avg(current_price) + from a_very_long_relation_name_that_forces_the_parenthesized_subquery_to_wrap +) +where current_price > ( + select avg(current_price) + from item + where category = i.category or color = i.color +) +group by category +having count(*) > ( + select count(*) + from a_very_long_relation_name_that_forces_the_parenthesized_subquery_to_wrap +) +order by count; + +select 1 +from t +where current_price = any(select 10000000000000000000000000000000000000000000000000 +); + +select 1 +from t +where current_price = any(select 1 -- foo +); + +select * from item where exists(select current_price from a_very_long_relation_name_abcdefghijklmn); + +select * from item where my_predicate_function(aaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbb); + +select * from item where cast(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa as boolean); + +select * from item where /* before predicate */ exists(/* before subquery */ select current_price from a_very_long_relation_name_abcdefghijklmn /* before close */); + +select * from item where -- before predicate +exists(select current_price from a_very_long_relation_name_abcdefghijklmn); + +select 1 from t where a = array[a_very_long_first_array_expression, a_very_long_second_array_expression, a_very_long_third_array_expressiona_very_long_second_array_expression]; + +select * from item where aaaaaaaaaaaaaaaaaaaaaaaaaa = 1 and my_predicate_function(bbbbbbbbbbbbbbbbbbbbbbbbb); + +select * from t order by -- before sort expression +f(a); + +select * from t order by -- before sort expression +a desc; + +select * from t order by a_very_long_sort_expression_name_that_does_not_fit_on_a_single_line_abcdef; + +select * from a join b on -- before condition +a.id = f(b.id); + +select * from a join b on -- before condition +a.id = b.id; + +select * from a join b on +-- own line +a.id = b.id; + +select * from t where aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa = calculate_something(); diff --git a/crates/squawk_fmt/tests/before/select_expr.sql b/crates/squawk_fmt/tests/before/select_expr.sql index 7d8c5962..c8a02268 100644 --- a/crates/squawk_fmt/tests/before/select_expr.sql +++ b/crates/squawk_fmt/tests/before/select_expr.sql @@ -75,6 +75,7 @@ select 3 = SOME ( ARRAY [ 3 ] ), 4 /* before op */ = /* before any */ ANY /* before opening paren */ ( /* before expr */ ARRAY [ 4 ] /* before closing paren */ ) /* after any */, EXISTS ( SELECT 1 FROM things ), + EXISTS(SELECT 10000000000000000000000000000000000000000000000000000000000000000), EXISTS((SELECT 1)), EXISTS(TABLE things), 5 = ANY(VALUES (1), (5)), @@ -384,3 +385,6 @@ select array[1, -- array expr select count(a, -- call args b); + +select cast(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa as numeric( + 10, 2)); diff --git a/crates/squawk_fmt/tests/before/update.sql b/crates/squawk_fmt/tests/before/update.sql index 3990e8b0..8e9e03bc 100644 --- a/crates/squawk_fmt/tests/before/update.sql +++ b/crates/squawk_fmt/tests/before/update.sql @@ -22,3 +22,27 @@ from source -- trailing from where foo.id = source.id -- trailing where returning foo.id; -- trailing returning -- bottom + +update foo set a = (select count(*) from a_very_long_relation_name_that_forces_the_subquery_to_wrap_ab); + +update foo set a = array[a_very_long_first_array_expression, a_very_long_second_array_expression, a_very_long_third_array_expression]; + +update foo set a = coalesce(a_very_long_first_expression, a_very_long_second_expression, a_very_long_third_expression); + +UPDATE foo SET a = 1 RETURNING (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbbbbb); + +UPDATE foo SET a = 1 RETURNING aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbbbbb; + +update foo set -- before column +a = f(1); + +update foo set -- before column +a = 1, b = 2; + +update foo set a = 1 returning -- before target +f(a); + +update foo set a = 1 returning -- before target +a, b; + +update foo set a = 1 returning a_very_long_returning_target_name_that_definitely_does_not_fit_here_okay;