@@ -5327,7 +5327,11 @@ impl<'a> Parser<'a> {
53275327 } else if self.parse_keyword(Keyword::DATABASE) {
53285328 self.parse_create_database()
53295329 } else if self.parse_keyword(Keyword::ROLE) {
5330- self.parse_create_role().map(Into::into)
5330+ self.parse_create_role(RoleKeyword::Role).map(Into::into)
5331+ } else if self.dialect.supports_user_group_statements()
5332+ && self.parse_keyword(Keyword::GROUP)
5333+ {
5334+ self.parse_create_role(RoleKeyword::Group).map(Into::into)
53315335 } else if self.parse_keyword(Keyword::SEQUENCE) {
53325336 self.parse_create_sequence(temporary)
53335337 } else if self.parse_keyword(Keyword::COLLATION) {
@@ -6907,8 +6911,11 @@ impl<'a> Parser<'a> {
69076911 }
69086912 }
69096913
6910- /// Parse a `CREATE ROLE` statement.
6911- pub fn parse_create_role(&mut self) -> Result<CreateRole, ParserError> {
6914+ /// Parse a `CREATE ROLE` or `CREATE GROUP` statement, after the keyword has been consumed.
6915+ pub fn parse_create_role(
6916+ &mut self,
6917+ role_keyword: RoleKeyword,
6918+ ) -> Result<CreateRole, ParserError> {
69126919 let if_not_exists = self.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]);
69136920 let names = self.parse_comma_separated(|p| p.parse_object_name(false))?;
69146921
@@ -7111,6 +7118,7 @@ impl<'a> Parser<'a> {
71117118 }
71127119
71137120 Ok(CreateRole {
7121+ keyword: role_keyword,
71147122 names,
71157123 if_not_exists,
71167124 login,
@@ -7610,6 +7618,10 @@ impl<'a> Parser<'a> {
76107618 ObjectType::Index
76117619 } else if self.parse_keyword(Keyword::ROLE) {
76127620 ObjectType::Role
7621+ } else if self.dialect.supports_user_group_statements()
7622+ && self.parse_keyword(Keyword::GROUP)
7623+ {
7624+ ObjectType::Group
76137625 } else if self.parse_keyword(Keyword::SCHEMA) {
76147626 ObjectType::Schema
76157627 } else if self.parse_keyword(Keyword::DATABASE) {
@@ -7653,7 +7665,7 @@ impl<'a> Parser<'a> {
76537665 };
76547666 } else {
76557667 return self.expected_ref(
7656- "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",
7668+ "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",
76577669 self.peek_token_ref(),
76587670 );
76597671 };
@@ -7669,9 +7681,11 @@ impl<'a> Parser<'a> {
76697681 if cascade && restrict {
76707682 return parser_err!("Cannot specify both CASCADE and RESTRICT in DROP", loc);
76717683 }
7672- if object_type == ObjectType::Role && (cascade || restrict || purge) {
7684+ if matches!(object_type, ObjectType::Role | ObjectType::Group)
7685+ && (cascade || restrict || purge)
7686+ {
76737687 return parser_err!(
7674- "Cannot specify CASCADE, RESTRICT, or PURGE in DROP ROLE" ,
7688+ format!( "Cannot specify CASCADE, RESTRICT, or PURGE in DROP {object_type}") ,
76757689 loc
76767690 );
76777691 }
0 commit comments