@@ -5304,7 +5304,11 @@ impl<'a> Parser<'a> {
53045304 } else if self.parse_keyword(Keyword::DATABASE) {
53055305 self.parse_create_database()
53065306 } else if self.parse_keyword(Keyword::ROLE) {
5307- self.parse_create_role().map(Into::into)
5307+ self.parse_create_role(RoleKeyword::Role).map(Into::into)
5308+ } else if self.dialect.supports_user_group_statements()
5309+ && self.parse_keyword(Keyword::GROUP)
5310+ {
5311+ self.parse_create_role(RoleKeyword::Group).map(Into::into)
53085312 } else if self.parse_keyword(Keyword::SEQUENCE) {
53095313 self.parse_create_sequence(temporary)
53105314 } else if self.parse_keyword(Keyword::COLLATION) {
@@ -6884,8 +6888,11 @@ impl<'a> Parser<'a> {
68846888 }
68856889 }
68866890
6887- /// Parse a `CREATE ROLE` statement.
6888- pub fn parse_create_role(&mut self) -> Result<CreateRole, ParserError> {
6891+ /// Parse a `CREATE ROLE` or `CREATE GROUP` statement, after the keyword has been consumed.
6892+ pub fn parse_create_role(
6893+ &mut self,
6894+ role_keyword: RoleKeyword,
6895+ ) -> Result<CreateRole, ParserError> {
68896896 let if_not_exists = self.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]);
68906897 let names = self.parse_comma_separated(|p| p.parse_object_name(false))?;
68916898
@@ -7088,6 +7095,7 @@ impl<'a> Parser<'a> {
70887095 }
70897096
70907097 Ok(CreateRole {
7098+ keyword: role_keyword,
70917099 names,
70927100 if_not_exists,
70937101 login,
@@ -7587,6 +7595,10 @@ impl<'a> Parser<'a> {
75877595 ObjectType::Index
75887596 } else if self.parse_keyword(Keyword::ROLE) {
75897597 ObjectType::Role
7598+ } else if self.dialect.supports_user_group_statements()
7599+ && self.parse_keyword(Keyword::GROUP)
7600+ {
7601+ ObjectType::Group
75907602 } else if self.parse_keyword(Keyword::SCHEMA) {
75917603 ObjectType::Schema
75927604 } else if self.parse_keyword(Keyword::DATABASE) {
@@ -7630,7 +7642,7 @@ impl<'a> Parser<'a> {
76307642 };
76317643 } else {
76327644 return self.expected_ref(
7633- "COLLATION, CONNECTOR, DATABASE, EXTENSION, FUNCTION, INDEX, OPERATOR, POLICY, PROCEDURE, ROLE, SCHEMA, SECRET, SEQUENCE, STAGE, TABLE, TRIGGER, TYPE, VIEW, MATERIALIZED VIEW, USER or WAREHOUSE after DROP",
7645+ "COLLATION, CONNECTOR, DATABASE, EXTENSION, FUNCTION, GROUP, INDEX, OPERATOR, POLICY, PROCEDURE, ROLE, SCHEMA, SECRET, SEQUENCE, STAGE, TABLE, TRIGGER, TYPE, VIEW, MATERIALIZED VIEW, USER or WAREHOUSE after DROP",
76347646 self.peek_token_ref(),
76357647 );
76367648 };
@@ -7646,9 +7658,11 @@ impl<'a> Parser<'a> {
76467658 if cascade && restrict {
76477659 return parser_err!("Cannot specify both CASCADE and RESTRICT in DROP", loc);
76487660 }
7649- if object_type == ObjectType::Role && (cascade || restrict || purge) {
7661+ if matches!(object_type, ObjectType::Role | ObjectType::Group)
7662+ && (cascade || restrict || purge)
7663+ {
76507664 return parser_err!(
7651- "Cannot specify CASCADE, RESTRICT, or PURGE in DROP ROLE" ,
7665+ format!( "Cannot specify CASCADE, RESTRICT, or PURGE in DROP {object_type}") ,
76527666 loc
76537667 );
76547668 }
0 commit comments