Skip to content

Commit e23877c

Browse files
authored
Add support for various Snowflake grantees (apache#1640)
1 parent 02d60cc commit e23877c

File tree

4 files changed

+128
-2
lines changed

4 files changed

+128
-2
lines changed

src/ast/mod.rs

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3159,7 +3159,7 @@ pub enum Statement {
31593159
Grant {
31603160
privileges: Privileges,
31613161
objects: GrantObjects,
3162-
grantees: Vec<Ident>,
3162+
grantees: Vec<Grantee>,
31633163
with_grant_option: bool,
31643164
granted_by: Option<Ident>,
31653165
},
@@ -5366,6 +5366,66 @@ impl fmt::Display for Action {
53665366
}
53675367
}
53685368

5369+
/// The principal that receives the privileges
5370+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5371+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5372+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5373+
pub struct Grantee {
5374+
pub grantee_type: GranteesType,
5375+
pub name: Option<ObjectName>,
5376+
}
5377+
5378+
impl fmt::Display for Grantee {
5379+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5380+
match self.grantee_type {
5381+
GranteesType::Role => {
5382+
write!(f, "ROLE ")?;
5383+
}
5384+
GranteesType::Share => {
5385+
write!(f, "SHARE ")?;
5386+
}
5387+
GranteesType::User => {
5388+
write!(f, "USER ")?;
5389+
}
5390+
GranteesType::Group => {
5391+
write!(f, "GROUP ")?;
5392+
}
5393+
GranteesType::Public => {
5394+
write!(f, "PUBLIC ")?;
5395+
}
5396+
GranteesType::DatabaseRole => {
5397+
write!(f, "DATABASE ROLE ")?;
5398+
}
5399+
GranteesType::Application => {
5400+
write!(f, "APPLICATION ")?;
5401+
}
5402+
GranteesType::ApplicationRole => {
5403+
write!(f, "APPLICATION ROLE ")?;
5404+
}
5405+
GranteesType::None => (),
5406+
}
5407+
if let Some(ref name) = self.name {
5408+
write!(f, "{}", name)?;
5409+
}
5410+
Ok(())
5411+
}
5412+
}
5413+
5414+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5415+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5416+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5417+
pub enum GranteesType {
5418+
Role,
5419+
Share,
5420+
User,
5421+
Group,
5422+
Public,
5423+
DatabaseRole,
5424+
Application,
5425+
ApplicationRole,
5426+
None,
5427+
}
5428+
53695429
/// Objects on which privileges are granted in a GRANT statement.
53705430
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
53715431
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]

src/keywords.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -615,6 +615,7 @@ define_keywords!(
615615
PROCEDURE,
616616
PROGRAM,
617617
PROJECTION,
618+
PUBLIC,
618619
PURGE,
619620
QUALIFY,
620621
QUARTER,

src/parser/mod.rs

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11611,7 +11611,7 @@ impl<'a> Parser<'a> {
1161111611
let (privileges, objects) = self.parse_grant_revoke_privileges_objects()?;
1161211612

1161311613
self.expect_keyword_is(Keyword::TO)?;
11614-
let grantees = self.parse_comma_separated(|p| p.parse_identifier())?;
11614+
let grantees = self.parse_grantees()?;
1161511615

1161611616
let with_grant_option =
1161711617
self.parse_keywords(&[Keyword::WITH, Keyword::GRANT, Keyword::OPTION]);
@@ -11629,6 +11629,62 @@ impl<'a> Parser<'a> {
1162911629
})
1163011630
}
1163111631

11632+
fn parse_grantees(&mut self) -> Result<Vec<Grantee>, ParserError> {
11633+
let mut values = vec![];
11634+
let mut grantee_type = GranteesType::None;
11635+
loop {
11636+
grantee_type = if self.parse_keyword(Keyword::ROLE) {
11637+
GranteesType::Role
11638+
} else if self.parse_keyword(Keyword::USER) {
11639+
GranteesType::User
11640+
} else if self.parse_keyword(Keyword::SHARE) {
11641+
GranteesType::Share
11642+
} else if self.parse_keyword(Keyword::GROUP) {
11643+
GranteesType::Group
11644+
} else if self.parse_keyword(Keyword::PUBLIC) {
11645+
GranteesType::Public
11646+
} else if self.parse_keywords(&[Keyword::DATABASE, Keyword::ROLE]) {
11647+
GranteesType::DatabaseRole
11648+
} else if self.parse_keywords(&[Keyword::APPLICATION, Keyword::ROLE]) {
11649+
GranteesType::ApplicationRole
11650+
} else if self.parse_keyword(Keyword::APPLICATION) {
11651+
GranteesType::Application
11652+
} else {
11653+
grantee_type // keep from previous iteraton, if not specified
11654+
};
11655+
11656+
let grantee = if grantee_type == GranteesType::Public {
11657+
Grantee {
11658+
grantee_type: grantee_type.clone(),
11659+
name: None,
11660+
}
11661+
} else {
11662+
let mut name = self.parse_object_name(false)?;
11663+
if self.consume_token(&Token::Colon) {
11664+
// Redshift supports namespace prefix for extenrnal users and groups:
11665+
// <Namespace>:<GroupName> or <Namespace>:<UserName>
11666+
// https://docs.aws.amazon.com/redshift/latest/mgmt/redshift-iam-access-control-native-idp.html
11667+
let ident = self.parse_identifier()?;
11668+
if let Some(n) = name.0.first() {
11669+
name = ObjectName(vec![Ident::new(format!("{}:{}", n.value, ident.value))]);
11670+
};
11671+
}
11672+
Grantee {
11673+
grantee_type: grantee_type.clone(),
11674+
name: Some(name),
11675+
}
11676+
};
11677+
11678+
values.push(grantee);
11679+
11680+
if !self.consume_token(&Token::Comma) {
11681+
break;
11682+
}
11683+
}
11684+
11685+
Ok(values)
11686+
}
11687+
1163211688
pub fn parse_grant_revoke_privileges_objects(
1163311689
&mut self,
1163411690
) -> Result<(Privileges, GrantObjects), ParserError> {

tests/sqlparser_common.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8497,6 +8497,15 @@ fn parse_grant() {
84978497
},
84988498
_ => unreachable!(),
84998499
}
8500+
8501+
verified_stmt("GRANT SELECT ON ALL TABLES IN SCHEMA db1.sc1 TO ROLE role1");
8502+
verified_stmt("GRANT SELECT ON ALL TABLES IN SCHEMA db1.sc1 TO ROLE role1 WITH GRANT OPTION");
8503+
verified_stmt("GRANT SELECT ON ALL TABLES IN SCHEMA db1.sc1 TO DATABASE ROLE role1");
8504+
verified_stmt("GRANT SELECT ON ALL TABLES IN SCHEMA db1.sc1 TO APPLICATION role1");
8505+
verified_stmt("GRANT SELECT ON ALL TABLES IN SCHEMA db1.sc1 TO APPLICATION ROLE role1");
8506+
verified_stmt("GRANT SELECT ON ALL TABLES IN SCHEMA db1.sc1 TO SHARE share1");
8507+
verified_stmt("GRANT USAGE ON SCHEMA sc1 TO a:b");
8508+
verified_stmt("GRANT USAGE ON SCHEMA sc1 TO GROUP group1");
85008509
}
85018510

85028511
#[test]

0 commit comments

Comments
 (0)