diff --git a/src/ast/mod.rs b/src/ast/mod.rs index 8a9a67a74..82be1e666 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -7544,34 +7544,22 @@ pub struct Grantee { impl fmt::Display for Grantee { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self.grantee_type { - GranteesType::Role => { - write!(f, "ROLE ")?; - } - GranteesType::Share => { - write!(f, "SHARE ")?; - } - GranteesType::User => { - write!(f, "USER ")?; - } - GranteesType::Group => { - write!(f, "GROUP ")?; - } - GranteesType::Public => { - write!(f, "PUBLIC ")?; - } - GranteesType::DatabaseRole => { - write!(f, "DATABASE ROLE ")?; - } - GranteesType::Application => { - write!(f, "APPLICATION ")?; - } - GranteesType::ApplicationRole => { - write!(f, "APPLICATION ROLE ")?; + let keyword = match self.grantee_type { + GranteesType::Role => "ROLE", + GranteesType::Share => "SHARE", + GranteesType::User => "USER", + GranteesType::Group => "GROUP", + GranteesType::Public => "PUBLIC", + GranteesType::DatabaseRole => "DATABASE ROLE", + GranteesType::Application => "APPLICATION", + GranteesType::ApplicationRole => "APPLICATION ROLE", + GranteesType::None => "", + }; + f.write_str(keyword)?; + if let Some(name) = &self.name { + if !keyword.is_empty() { + f.write_str(" ")?; } - GranteesType::None => (), - } - if let Some(ref name) = self.name { name.fmt(f)?; } Ok(()) diff --git a/tests/sqlparser_common.rs b/tests/sqlparser_common.rs index bad083602..c3e6e3a6c 100644 --- a/tests/sqlparser_common.rs +++ b/tests/sqlparser_common.rs @@ -10061,6 +10061,9 @@ fn parse_grant() { verified_stmt("GRANT ROLE role1 TO ROLE role2"); verified_stmt("GRANT ROLE role1 TO USER user"); verified_stmt("GRANT CREATE SCHEMA ON DATABASE db1 TO ROLE role1"); + // PUBLIC takes no name, so it must not trail a space. MsSql reserves it as + // an ordinary grantee name. + all_dialects_except(|d| d.is::()).verified_stmt("GRANT SELECT ON t TO PUBLIC"); } #[test]