diff --git a/crates/squawk_fmt/src/fmt.rs b/crates/squawk_fmt/src/fmt.rs index aa7a22e0..0e97e0c2 100644 --- a/crates/squawk_fmt/src/fmt.rs +++ b/crates/squawk_fmt/src/fmt.rs @@ -6518,6 +6518,9 @@ fn build_set_role<'a>(ctx: &Ctx, set: &ast::SetRole) -> Doc<'a> { .nest(ctx.indent), ); } + if let Some(to) = set.to_token() { + doc = doc.append(line_before(&to).append(Doc::text("to")).nest(ctx.indent)); + } if let Some(target) = set.set_role_target() { doc = doc.append( line_before(target.syntax()) diff --git a/crates/squawk_fmt/tests/after/set_role.snap b/crates/squawk_fmt/tests/after/set_role.snap index 41b4c3eb..81be69ec 100644 --- a/crates/squawk_fmt/tests/after/set_role.snap +++ b/crates/squawk_fmt/tests/after/set_role.snap @@ -12,6 +12,8 @@ set role group legacy_user; set role 'literal role'; +set role to 'api'; + set session role diff --git a/crates/squawk_fmt/tests/before/set_role.sql b/crates/squawk_fmt/tests/before/set_role.sql index fd541b63..df07a992 100644 --- a/crates/squawk_fmt/tests/before/set_role.sql +++ b/crates/squawk_fmt/tests/before/set_role.sql @@ -8,6 +8,8 @@ set role group legacy_user; set role 'literal role'; +set role to 'api'; + set session role an_intentionally_long_role_name_that_makes_this_statement_longer_than_eighty_characters; /* before set */ SET /* before scope */ LOCAL /* before role */ ROLE /* before target */ GROUP /* before role name */ legacy_user /* before semicolon */; diff --git a/crates/squawk_parser/src/grammar.rs b/crates/squawk_parser/src/grammar.rs index 010d1c6e..3e94a3c9 100644 --- a/crates/squawk_parser/src/grammar.rs +++ b/crates/squawk_parser/src/grammar.rs @@ -15462,8 +15462,8 @@ fn opt_set_scope(p: &mut Parser<'_>) { m.complete(p, kind); } -// SET [ SESSION | LOCAL ] ROLE role_name -// SET [ SESSION | LOCAL ] ROLE NONE +// SET [ SESSION | LOCAL ] ROLE [ TO ] role_name +// SET [ SESSION | LOCAL ] ROLE [ TO ] NONE // RESET ROLE fn set_role(p: &mut Parser<'_>) -> CompletedMarker { assert!(p.at(SET_KW)); @@ -15471,6 +15471,7 @@ fn set_role(p: &mut Parser<'_>) -> CompletedMarker { p.bump(SET_KW); opt_set_scope(p); p.expect(ROLE_KW); + p.eat(TO_KW); if p.at(NONE_KW) { let target = p.start(); p.bump(NONE_KW); diff --git a/crates/squawk_parser/tests/data/ok/set_role.sql b/crates/squawk_parser/tests/data/ok/set_role.sql index 7574e387..c6acf4ea 100644 --- a/crates/squawk_parser/tests/data/ok/set_role.sql +++ b/crates/squawk_parser/tests/data/ok/set_role.sql @@ -9,5 +9,7 @@ SET SESSION ROLE foo; set role 'fooo'; +set role to 'api'; + RESET ROLE; diff --git a/crates/squawk_parser/tests/snapshots/tests__set_role_ok.snap b/crates/squawk_parser/tests/snapshots/tests__set_role_ok.snap index 1719ed64..f9450385 100644 --- a/crates/squawk_parser/tests/snapshots/tests__set_role_ok.snap +++ b/crates/squawk_parser/tests/snapshots/tests__set_role_ok.snap @@ -57,6 +57,17 @@ SOURCE_FILE STRING "'fooo'" SEMICOLON ";" WHITESPACE "\n\n" + SET_ROLE + SET_KW "set" + WHITESPACE " " + ROLE_KW "role" + WHITESPACE " " + TO_KW "to" + WHITESPACE " " + LITERAL + STRING "'api'" + SEMICOLON ";" + WHITESPACE "\n\n" RESET_ROLE RESET_KW "RESET" WHITESPACE " " diff --git a/crates/squawk_syntax/src/ast/generated/nodes.rs b/crates/squawk_syntax/src/ast/generated/nodes.rs index e7d19c38..1d92a30d 100644 --- a/crates/squawk_syntax/src/ast/generated/nodes.rs +++ b/crates/squawk_syntax/src/ast/generated/nodes.rs @@ -26057,6 +26057,10 @@ impl SetRole { pub fn set_token(&self) -> Option { support::token(&self.syntax, SyntaxKind::SET_KW) } + #[inline] + pub fn to_token(&self) -> Option { + support::token(&self.syntax, SyntaxKind::TO_KW) + } } #[derive(Debug, Clone, PartialEq, Eq, Hash)] diff --git a/crates/squawk_syntax/src/postgresql.ungram b/crates/squawk_syntax/src/postgresql.ungram index 453aa979..3bfe6a64 100644 --- a/crates/squawk_syntax/src/postgresql.ungram +++ b/crates/squawk_syntax/src/postgresql.ungram @@ -5818,7 +5818,7 @@ Immediate = 'immediate' SetRole = - 'set' SetScope? 'role' SetRoleTarget ';'? + 'set' SetScope? 'role' 'to'? SetRoleTarget ';'? SetRoleTarget = RoleRef