Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
109 changes: 86 additions & 23 deletions crates/squawk_fmt/src/fmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -349,10 +349,32 @@ fn build_insert<'a>(insert: &ast::Insert) -> Doc<'a> {
.append(build_overriding_clause(overriding));
}
if let Some(source) = insert.insert_source() {
doc = doc
.append(Doc::line_or_space())
.append(leading_comments(source.syntax()))
.append(build_insert_source(source));
let source_comments = leading_comments(source.syntax());
match source {
ast::InsertSource::SelectVariant(ast::SelectVariant::Values(values))
if values
.row_list()
.is_some_and(|rows| rows.rows().count() > 1) =>
{
doc = doc
.append(Doc::line_or_space())
.append(source_comments)
.append(Doc::text("values"))
.group()
.append(build_values_rows(&values, true));
for clause in values.tail_clauses() {
doc = doc
.append(Doc::line_or_space())
.append(build_select_tail_clause(clause));
}
}
source => {
doc = doc
.append(Doc::line_or_space())
.append(source_comments)
.append(build_insert_source(source));
}
}
}
if let Some(on_conflict) = insert.on_conflict_clause() {
doc = doc
Expand Down Expand Up @@ -10123,7 +10145,24 @@ fn build_values<'a>(values: &ast::Values) -> Doc<'a> {
}
}

let mut values_doc = Doc::text("values");
doc = doc.append(
Doc::text("values")
.append(build_values_rows(values, false))
.group(),
);

for clause in values.tail_clauses() {
doc = doc
.append(Doc::line_or_space())
.append(build_select_tail_clause(clause));
}

doc.append(build_semicolon(values.semicolon_token()))
.group()
}

fn build_values_rows<'a>(values: &ast::Values, nest_rows: bool) -> Doc<'a> {
let mut doc = Doc::nil();
if let Some(row_list) = values.row_list() {
let rows = row_list.rows().map(|row| {
(
Expand All @@ -10132,23 +10171,23 @@ fn build_values<'a>(values: &ast::Values) -> Doc<'a> {
)
});
if let Some(rows) = build_comma_separated_docs(rows) {
values_doc = values_doc.append(
let multiple_rows = row_list.rows().count() > 1;
let separator = if nest_rows && multiple_rows {
Doc::line_or_space()
} else {
Doc::space()
.append(leading_comments(row_list.syntax()))
.append(rows),
);
};
let rows = separator
.append(leading_comments(row_list.syntax()))
.append(rows);
doc = doc.append(if nest_rows && multiple_rows {
rows.nest(2).group()
} else {
rows
});
}
}
doc = doc.append(values_doc.group());

for clause in values.tail_clauses() {
doc = doc
.append(Doc::line_or_space())
.append(build_select_tail_clause(clause));
}

doc.append(build_semicolon(values.semicolon_token()))
.group()
doc
}

fn build_row<'a>(row: ast::Row) -> Doc<'a> {
Expand Down Expand Up @@ -17976,10 +18015,12 @@ 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_json_table = matches!(
let single_nested_table = matches!(
single_item.next(),
Some(ast::FromListItem::FromItem(
ast::FromItem::JsonTableFromItem(_)
ast::FromItem::GraphTableFromItem(_)
| ast::FromItem::JsonTableFromItem(_)
| ast::FromItem::XmlTableFromItem(_)
))
) && single_item.next().is_none();

Expand All @@ -17991,7 +18032,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_json_table {
let body = if single_nested_table {
body
} else {
body.nest(2)
Expand Down Expand Up @@ -19319,7 +19360,7 @@ fn build_expr<'a>(expr: ast::Expr) -> Doc<'a> {
ast::Expr::FieldExpr(field_expr) => build_field_expr(field_expr),
ast::Expr::IndexExpr(index_expr) => build_index_expr(index_expr),
ast::Expr::Literal(literal) => build_literal(literal),
ast::Expr::NameRef(name_ref) => build_name(name_ref.syntax()),
ast::Expr::NameRef(name_ref) => build_expr_name_ref(name_ref),
ast::Expr::ParenExpr(paren_expr) => build_paren_expr(paren_expr),
ast::Expr::PostfixExpr(postfix_expr) => build_postfix_expr(postfix_expr),
ast::Expr::PrefixExpr(prefix_expr) => build_prefix_expr(prefix_expr),
Expand All @@ -19328,6 +19369,28 @@ fn build_expr<'a>(expr: ast::Expr) -> Doc<'a> {
}
}

fn build_expr_name_ref<'a>(name_ref: ast::NameRef) -> Doc<'a> {
let sql_value_function = name_ref
.current_catalog_token()
.or_else(|| name_ref.current_date_token())
.or_else(|| name_ref.current_role_token())
.or_else(|| name_ref.current_schema_token())
.or_else(|| name_ref.current_time_token())
.or_else(|| name_ref.current_timestamp_token())
.or_else(|| name_ref.current_user_token())
.or_else(|| name_ref.localtime_token())
.or_else(|| name_ref.localtimestamp_token())
.or_else(|| name_ref.session_user_token())
.or_else(|| name_ref.system_user_token())
.or_else(|| name_ref.user_token());

if let Some(token) = sql_value_function {
Doc::text(token.text().to_ascii_lowercase())
} else {
build_name(name_ref.syntax())
}
}

fn build_array_expr<'a>(array_expr: ast::ArrayExpr) -> Doc<'a> {
let mut doc = Doc::nil();

Expand Down
6 changes: 3 additions & 3 deletions crates/squawk_fmt/tests/after/alter_policy.snap
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ alter /* policy */ policy /* name */ account_access_policy
/* to */ to /* first role */ account_administrator,
/* second role */ account_auditor
/* using */ using /* left paren */ (
/* expression */ owner_identifier = "current_user" /* right paren */
/* expression */ owner_identifier = current_user /* right paren */
)
/* with */ with /* check */ check /* left paren */ (
/* expression */ account_is_active
Expand All @@ -19,8 +19,8 @@ alter policy account_access_policy
using (
account_identifier
= a_very_long_session_account_identifier_function(
"current_user",
"current_role"
current_user,
current_role
)
);

Expand Down
6 changes: 3 additions & 3 deletions crates/squawk_fmt/tests/after/create_policy.snap
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ create policy extraordinarily_long_account_access_policy_name
to extraordinarily_long_account_administrator_role,
extraordinarily_long_account_auditor_role
using (
account_owner_identifier = "current_user" and account_identifier > 1000000
account_owner_identifier = current_user and account_identifier > 1000000
)
with check (account_is_active and account_owner_identifier = "current_user");
with check (account_is_active and account_owner_identifier = current_user);

-- comments in every position
create /* policy */ policy /* name */ account_access
Expand All @@ -23,7 +23,7 @@ create /* policy */ policy /* name */ account_access
/* to */ to /* first role */ account_admin /* comma */,
/* second role */ account_auditor
/* using */ using /* left paren */ (
/* expression */ owner_name = "current_user" /* right paren */
/* expression */ owner_name = current_user /* right paren */
)
/* with */ with /* check */ check /* check left paren */ (
/* check expression */ active /* check right paren */
Expand Down
54 changes: 27 additions & 27 deletions crates/squawk_fmt/tests/after/from.snap
Original file line number Diff line number Diff line change
Expand Up @@ -76,37 +76,37 @@ from /* before lateral */ lateral /* before rows */ rows /* before from */ from
);
select *
from xmltable(
'/rows/row' passing doc
columns
id int8 path '@id' not null,
ord for ordinality,
value text default 'unknown' null
) as parsed;
'/rows/row' passing doc
columns
id int8 path '@id' not null,
ord for ordinality,
value text default 'unknown' null
) as parsed;
select *
from lateral xmltable(
xmlnamespaces('urn:a' as a, default 'urn:default'),
a_very_long_xml_row_expression passing by ref
a_very_long_xml_document_expression by value
columns
a_very_long_first_xml_column_name a_very_long_xml_column_type
path a_very_long_xml_path_expression,
a_very_long_ordinality_column_name for ordinality
) as a_very_long_xml_table_alias;
xmlnamespaces('urn:a' as a, default 'urn:default'),
a_very_long_xml_row_expression passing by ref
a_very_long_xml_document_expression by value
columns
a_very_long_first_xml_column_name a_very_long_xml_column_type
path a_very_long_xml_path_expression,
a_very_long_ordinality_column_name for ordinality
) as a_very_long_xml_table_alias;
select *
from /* before lateral */ lateral /* before xmltable */ xmltable /* before opening paren */(
/* before namespaces */ xmlnamespaces /* before namespace opening paren */(
/* before namespace expression */ 'urn:a' /* before as */ as /* before prefix */ a /* before namespace comma */,
/* before default */ default /* before default expression */ 'urn:default' /* before namespace closing paren */
) /* before outer comma */,
/* before row */ '/rows/row'
/* before passing */ passing /* before first by */ by /* before ref */ ref
/* before document */ doc /* before second by */ by /* before value */ value
/* before columns */ columns
/* before first column */ id /* before type */ int8
/* before path */ path /* before path expression */ '@id'
/* before not */ not /* before null */ null /* before column comma */,
/* before ordinality column */ ord /* before for */ for /* before ordinality */ ordinality /* before closing paren */
) /* before alias */ as /* before alias name */ parsed;
/* before namespaces */ xmlnamespaces /* before namespace opening paren */(
/* before namespace expression */ 'urn:a' /* before as */ as /* before prefix */ a /* before namespace comma */,
/* before default */ default /* before default expression */ 'urn:default' /* before namespace closing paren */
) /* before outer comma */,
/* before row */ '/rows/row'
/* before passing */ passing /* before first by */ by /* before ref */ ref
/* before document */ doc /* before second by */ by /* before value */ value
/* before columns */ columns
/* before first column */ id /* before type */ int8
/* before path */ path /* before path expression */ '@id'
/* before not */ not /* before null */ null /* before column comma */,
/* before ordinality column */ ord /* before for */ for /* before ordinality */ ordinality /* before closing paren */
) /* before alias */ as /* before alias name */ parsed;
select *
from json_table(
doc,
Expand Down
Loading
Loading