Skip to content

Commit 648fc44

Browse files
yoavcloudayman-sigma
authored andcommitted
Add support for various Snowflake grantees (apache#1640)
1 parent c922bbe commit 648fc44

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
@@ -3177,7 +3177,7 @@ pub enum Statement {
31773177
Grant {
31783178
privileges: Privileges,
31793179
objects: GrantObjects,
3180-
grantees: Vec<Ident>,
3180+
grantees: Vec<Grantee>,
31813181
with_grant_option: bool,
31823182
granted_by: Option<Ident>,
31833183
},
@@ -5384,6 +5384,66 @@ impl fmt::Display for Action {
53845384
}
53855385
}
53865386

5387+
/// The principal that receives the privileges
5388+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5389+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5390+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5391+
pub struct Grantee {
5392+
pub grantee_type: GranteesType,
5393+
pub name: Option<ObjectName>,
5394+
}
5395+
5396+
impl fmt::Display for Grantee {
5397+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5398+
match self.grantee_type {
5399+
GranteesType::Role => {
5400+
write!(f, "ROLE ")?;
5401+
}
5402+
GranteesType::Share => {
5403+
write!(f, "SHARE ")?;
5404+
}
5405+
GranteesType::User => {
5406+
write!(f, "USER ")?;
5407+
}
5408+
GranteesType::Group => {
5409+
write!(f, "GROUP ")?;
5410+
}
5411+
GranteesType::Public => {
5412+
write!(f, "PUBLIC ")?;
5413+
}
5414+
GranteesType::DatabaseRole => {
5415+
write!(f, "DATABASE ROLE ")?;
5416+
}
5417+
GranteesType::Application => {
5418+
write!(f, "APPLICATION ")?;
5419+
}
5420+
GranteesType::ApplicationRole => {
5421+
write!(f, "APPLICATION ROLE ")?;
5422+
}
5423+
GranteesType::None => (),
5424+
}
5425+
if let Some(ref name) = self.name {
5426+
write!(f, "{}", name)?;
5427+
}
5428+
Ok(())
5429+
}
5430+
}
5431+
5432+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5433+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5434+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5435+
pub enum GranteesType {
5436+
Role,
5437+
Share,
5438+
User,
5439+
Group,
5440+
Public,
5441+
DatabaseRole,
5442+
Application,
5443+
ApplicationRole,
5444+
None,
5445+
}
5446+
53875447
/// Objects on which privileges are granted in a GRANT statement.
53885448
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
53895449
#[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
@@ -11621,7 +11621,7 @@ impl<'a> Parser<'a> {
1162111621
let (privileges, objects) = self.parse_grant_revoke_privileges_objects()?;
1162211622

1162311623
self.expect_keyword_is(Keyword::TO)?;
11624-
let grantees = self.parse_comma_separated(|p| p.parse_identifier())?;
11624+
let grantees = self.parse_grantees()?;
1162511625

1162611626
let with_grant_option =
1162711627
self.parse_keywords(&[Keyword::WITH, Keyword::GRANT, Keyword::OPTION]);
@@ -11639,6 +11639,62 @@ impl<'a> Parser<'a> {
1163911639
})
1164011640
}
1164111641

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

tests/sqlparser_common.rs

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

85038512
#[test]

0 commit comments

Comments
 (0)