diff --git a/crates/squawk_fmt/src/fmt.rs b/crates/squawk_fmt/src/fmt.rs index 00970777..add4ce1a 100644 --- a/crates/squawk_fmt/src/fmt.rs +++ b/crates/squawk_fmt/src/fmt.rs @@ -147,11 +147,54 @@ fn build_table_arg<'a>(create_table: ast::TableArg) -> Doc<'a> { ast::TableArg::Column(column) => build_name(column.name().unwrap().syntax()) .append(Doc::space()) .append(Doc::text(column.ty().unwrap().syntax().to_string())), - ast::TableArg::LikeClause(_like_clause) => todo!(), + ast::TableArg::LikeClause(like_clause) => build_like_clause(&like_clause), ast::TableArg::TableConstraint(_table_constraint) => todo!(), } } +fn build_like_clause<'a>(like_clause: &ast::LikeClause) -> Doc<'a> { + let mut doc = Doc::text("like"); + + if let Some(relation_name) = like_clause.relation_name_ref() { + doc = doc + .append(Doc::space()) + .append(leading_comments(relation_name.syntax())); + if let Some(path) = relation_name.path_ref() { + doc = doc.append(build_path_ref(&path)); + } + } + + let options: Vec> = like_clause + .like_options() + .map(|option| { + Doc::line_or_space() + .append(leading_comments(option.syntax())) + .append(build_like_option(&option)) + }) + .collect(); + if !options.is_empty() { + doc = doc.append(Doc::list(options).nest(2).group()); + } + + doc +} + +fn build_like_option<'a>(option: &ast::LikeOption) -> Doc<'a> { + let (keyword, property) = match option { + ast::LikeOption::ExcludingProperty(n) => ("excluding", n.table_property()), + ast::LikeOption::IncludingProperty(n) => ("including", n.table_property()), + }; + + let mut doc = Doc::text(keyword); + if let Some(property) = property { + doc = doc + .append(Doc::space()) + .append(leading_comments(property.syntax())) + .append(build_keyword_node(property.syntax())); + } + doc +} + fn build_select_doc<'a>(select: &ast::Select) -> Doc<'a> { let mut doc = Doc::text("select").append(Doc::line_or_space()); diff --git a/crates/squawk_fmt/tests/after/create_table_like.snap b/crates/squawk_fmt/tests/after/create_table_like.snap new file mode 100644 index 00000000..21170705 --- /dev/null +++ b/crates/squawk_fmt/tests/after/create_table_like.snap @@ -0,0 +1,44 @@ +--- +source: crates/squawk_fmt/tests/tests.rs +input_file: crates/squawk_fmt/tests/before/create_table_like.sql +--- +create table t(like foo); +create table t( + like foo, + id int +); +create table t( + id int, + like foo, + like bar +); + +-- like options +create table t(like foo including all); +create table t(like foo excluding indexes); +create table t( + like foo including defaults excluding constraints including identity +); +create table t( + like foo + including comments + including compression + including generated + including statistics + including storage +); + +-- table names +create table t(like public.accounts); +create table t(like "Public"."Users" including all); +create table t(like foo.bar); +create table t(like "select"); +create table t(like U&"d!0061tum" uescape '!' including all); + +-- comments +create table t(like /* a */ foo /* b */ including /* c */ all); +create table t( + like foo + -- a line comment + including all +); diff --git a/crates/squawk_fmt/tests/before/create_table_like.sql b/crates/squawk_fmt/tests/before/create_table_like.sql new file mode 100644 index 00000000..ddcb1db4 --- /dev/null +++ b/crates/squawk_fmt/tests/before/create_table_like.sql @@ -0,0 +1,21 @@ +create table t (LIKE foo); +create table t (like foo, id int); +create table t (id int, like foo, like bar); + +-- like options +create table t (like foo INCLUDING ALL); +create table t (like foo EXCLUDING INDEXES); +create table t (like foo INCLUDING DEFAULTS EXCLUDING CONSTRAINTS INCLUDING IDENTITY); +create table t (like foo including comments including compression including generated including statistics including storage); + +-- table names +create table t (like PUBLIC.Accounts); +create table t (like "Public"."Users" including all); +create table t (like "foo"."bar"); +create table t (like "select"); +create table t (like U&"d!0061tum" uescape '!' including all); + +-- comments +create table t (like /* a */ foo /* b */ including /* c */ all); +create table t (like foo -- a line comment +including all);