Skip to content

Commit bc94b9a

Browse files
yoavcloudayman-sigma
authored andcommitted
Add parsing for GRANT ROLE and GRANT DATABASE ROLE in Snowflake dialect (apache#1689)
1 parent 1ffabcc commit bc94b9a

File tree

5 files changed

+94
-54
lines changed

5 files changed

+94
-54
lines changed

src/ast/mod.rs

+16-4
Original file line numberDiff line numberDiff line change
@@ -3248,7 +3248,7 @@ pub enum Statement {
32483248
/// ```
32493249
Grant {
32503250
privileges: Privileges,
3251-
objects: GrantObjects,
3251+
objects: Option<GrantObjects>,
32523252
grantees: Vec<Grantee>,
32533253
with_grant_option: bool,
32543254
granted_by: Option<Ident>,
@@ -3258,7 +3258,7 @@ pub enum Statement {
32583258
/// ```
32593259
Revoke {
32603260
privileges: Privileges,
3261-
objects: GrantObjects,
3261+
objects: Option<GrantObjects>,
32623262
grantees: Vec<Grantee>,
32633263
granted_by: Option<Ident>,
32643264
cascade: Option<CascadeOption>,
@@ -4803,7 +4803,9 @@ impl fmt::Display for Statement {
48034803
granted_by,
48044804
} => {
48054805
write!(f, "GRANT {privileges} ")?;
4806-
write!(f, "ON {objects} ")?;
4806+
if let Some(objects) = objects {
4807+
write!(f, "ON {objects} ")?;
4808+
}
48074809
write!(f, "TO {}", display_comma_separated(grantees))?;
48084810
if *with_grant_option {
48094811
write!(f, " WITH GRANT OPTION")?;
@@ -4821,7 +4823,9 @@ impl fmt::Display for Statement {
48214823
cascade,
48224824
} => {
48234825
write!(f, "REVOKE {privileges} ")?;
4824-
write!(f, "ON {objects} ")?;
4826+
if let Some(objects) = objects {
4827+
write!(f, "ON {objects} ")?;
4828+
}
48254829
write!(f, "FROM {}", display_comma_separated(grantees))?;
48264830
if let Some(grantor) = granted_by {
48274831
write!(f, " GRANTED BY {grantor}")?;
@@ -5521,6 +5525,9 @@ pub enum Action {
55215525
Create {
55225526
obj_type: Option<ActionCreateObjectType>,
55235527
},
5528+
DatabaseRole {
5529+
role: ObjectName,
5530+
},
55245531
Delete,
55255532
EvolveSchema,
55265533
Execute {
@@ -5554,6 +5561,9 @@ pub enum Action {
55545561
},
55555562
Replicate,
55565563
ResolveAll,
5564+
Role {
5565+
role: Ident,
5566+
},
55575567
Select {
55585568
columns: Option<Vec<Ident>>,
55595569
},
@@ -5583,6 +5593,7 @@ impl fmt::Display for Action {
55835593
write!(f, " {obj_type}")?
55845594
}
55855595
}
5596+
Action::DatabaseRole { role } => write!(f, "DATABASE ROLE {role}")?,
55865597
Action::Delete => f.write_str("DELETE")?,
55875598
Action::EvolveSchema => f.write_str("EVOLVE SCHEMA")?,
55885599
Action::Execute { obj_type } => {
@@ -5609,6 +5620,7 @@ impl fmt::Display for Action {
56095620
Action::References { .. } => f.write_str("REFERENCES")?,
56105621
Action::Replicate => f.write_str("REPLICATE")?,
56115622
Action::ResolveAll => f.write_str("RESOLVE ALL")?,
5623+
Action::Role { role } => write!(f, "ROLE {role}")?,
56125624
Action::Select { .. } => f.write_str("SELECT")?,
56135625
Action::Temporary => f.write_str("TEMPORARY")?,
56145626
Action::Trigger => f.write_str("TRIGGER")?,

src/parser/mod.rs

+48-41
Original file line numberDiff line numberDiff line change
@@ -12140,7 +12140,7 @@ impl<'a> Parser<'a> {
1214012140

1214112141
pub fn parse_grant_revoke_privileges_objects(
1214212142
&mut self,
12143-
) -> Result<(Privileges, GrantObjects), ParserError> {
12143+
) -> Result<(Privileges, Option<GrantObjects>), ParserError> {
1214412144
let privileges = if self.parse_keyword(Keyword::ALL) {
1214512145
Privileges::All {
1214612146
with_privileges_keyword: self.parse_keyword(Keyword::PRIVILEGES),
@@ -12150,48 +12150,49 @@ impl<'a> Parser<'a> {
1215012150
Privileges::Actions(actions)
1215112151
};
1215212152

12153-
self.expect_keyword_is(Keyword::ON)?;
12154-
12155-
let objects = if self.parse_keywords(&[
12156-
Keyword::ALL,
12157-
Keyword::TABLES,
12158-
Keyword::IN,
12159-
Keyword::SCHEMA,
12160-
]) {
12161-
GrantObjects::AllTablesInSchema {
12162-
schemas: self.parse_comma_separated(|p| p.parse_object_name(false))?,
12163-
}
12164-
} else if self.parse_keywords(&[
12165-
Keyword::ALL,
12166-
Keyword::SEQUENCES,
12167-
Keyword::IN,
12168-
Keyword::SCHEMA,
12169-
]) {
12170-
GrantObjects::AllSequencesInSchema {
12171-
schemas: self.parse_comma_separated(|p| p.parse_object_name(false))?,
12172-
}
12173-
} else {
12174-
let object_type = self.parse_one_of_keywords(&[
12175-
Keyword::SEQUENCE,
12176-
Keyword::DATABASE,
12153+
let objects = if self.parse_keyword(Keyword::ON) {
12154+
if self.parse_keywords(&[Keyword::ALL, Keyword::TABLES, Keyword::IN, Keyword::SCHEMA]) {
12155+
Some(GrantObjects::AllTablesInSchema {
12156+
schemas: self.parse_comma_separated(|p| p.parse_object_name(false))?,
12157+
})
12158+
} else if self.parse_keywords(&[
12159+
Keyword::ALL,
12160+
Keyword::SEQUENCES,
12161+
Keyword::IN,
1217712162
Keyword::SCHEMA,
12178-
Keyword::TABLE,
12179-
Keyword::VIEW,
12180-
Keyword::WAREHOUSE,
12181-
Keyword::INTEGRATION,
12182-
]);
12183-
let objects =
12184-
self.parse_comma_separated(|p| p.parse_object_name_with_wildcards(false, true));
12185-
match object_type {
12186-
Some(Keyword::DATABASE) => GrantObjects::Databases(objects?),
12187-
Some(Keyword::SCHEMA) => GrantObjects::Schemas(objects?),
12188-
Some(Keyword::SEQUENCE) => GrantObjects::Sequences(objects?),
12189-
Some(Keyword::WAREHOUSE) => GrantObjects::Warehouses(objects?),
12190-
Some(Keyword::INTEGRATION) => GrantObjects::Integrations(objects?),
12191-
Some(Keyword::VIEW) => GrantObjects::Views(objects?),
12192-
Some(Keyword::TABLE) | None => GrantObjects::Tables(objects?),
12193-
_ => unreachable!(),
12163+
]) {
12164+
Some(GrantObjects::AllSequencesInSchema {
12165+
schemas: self.parse_comma_separated(|p| p.parse_object_name(false))?,
12166+
})
12167+
} else {
12168+
let object_type = self.parse_one_of_keywords(&[
12169+
Keyword::SEQUENCE,
12170+
Keyword::DATABASE,
12171+
Keyword::DATABASE,
12172+
Keyword::SCHEMA,
12173+
Keyword::TABLE,
12174+
Keyword::VIEW,
12175+
Keyword::WAREHOUSE,
12176+
Keyword::INTEGRATION,
12177+
Keyword::VIEW,
12178+
Keyword::WAREHOUSE,
12179+
Keyword::INTEGRATION,
12180+
]);
12181+
let objects =
12182+
self.parse_comma_separated(|p| p.parse_object_name_with_wildcards(false, true));
12183+
match object_type {
12184+
Some(Keyword::DATABASE) => Some(GrantObjects::Databases(objects?)),
12185+
Some(Keyword::SCHEMA) => Some(GrantObjects::Schemas(objects?)),
12186+
Some(Keyword::SEQUENCE) => Some(GrantObjects::Sequences(objects?)),
12187+
Some(Keyword::WAREHOUSE) => Some(GrantObjects::Warehouses(objects?)),
12188+
Some(Keyword::INTEGRATION) => Some(GrantObjects::Integrations(objects?)),
12189+
Some(Keyword::VIEW) => Some(GrantObjects::Views(objects?)),
12190+
Some(Keyword::TABLE) | None => Some(GrantObjects::Tables(objects?)),
12191+
_ => unreachable!(),
12192+
}
1219412193
}
12194+
} else {
12195+
None
1219512196
};
1219612197

1219712198
Ok((privileges, objects))
@@ -12218,6 +12219,9 @@ impl<'a> Parser<'a> {
1221812219
Ok(Action::AttachPolicy)
1221912220
} else if self.parse_keywords(&[Keyword::BIND, Keyword::SERVICE, Keyword::ENDPOINT]) {
1222012221
Ok(Action::BindServiceEndpoint)
12222+
} else if self.parse_keywords(&[Keyword::DATABASE, Keyword::ROLE]) {
12223+
let role = self.parse_object_name(false)?;
12224+
Ok(Action::DatabaseRole { role })
1222112225
} else if self.parse_keywords(&[Keyword::EVOLVE, Keyword::SCHEMA]) {
1222212226
Ok(Action::EvolveSchema)
1222312227
} else if self.parse_keywords(&[Keyword::IMPORT, Keyword::SHARE]) {
@@ -12283,6 +12287,9 @@ impl<'a> Parser<'a> {
1228312287
Ok(Action::Read)
1228412288
} else if self.parse_keyword(Keyword::REPLICATE) {
1228512289
Ok(Action::Replicate)
12290+
} else if self.parse_keyword(Keyword::ROLE) {
12291+
let role = self.parse_identifier()?;
12292+
Ok(Action::Role { role })
1228612293
} else if self.parse_keyword(Keyword::SELECT) {
1228712294
Ok(Action::Select {
1228812295
columns: parse_columns(self)?,

tests/sqlparser_common.rs

+10-7
Original file line numberDiff line numberDiff line change
@@ -8638,7 +8638,7 @@ fn parse_grant() {
86388638
granted_by,
86398639
..
86408640
} => match (privileges, objects) {
8641-
(Privileges::Actions(actions), GrantObjects::Tables(objects)) => {
8641+
(Privileges::Actions(actions), Some(GrantObjects::Tables(objects))) => {
86428642
assert_eq!(
86438643
vec![
86448644
Action::Select { columns: None },
@@ -8688,7 +8688,7 @@ fn parse_grant() {
86888688
with_grant_option,
86898689
..
86908690
} => match (privileges, objects) {
8691-
(Privileges::Actions(actions), GrantObjects::AllTablesInSchema { schemas }) => {
8691+
(Privileges::Actions(actions), Some(GrantObjects::AllTablesInSchema { schemas })) => {
86928692
assert_eq!(vec![Action::Insert { columns: None }], actions);
86938693
assert_eq_vec(&["public"], &schemas);
86948694
assert_eq_vec(&["browser"], &grantees);
@@ -8708,7 +8708,7 @@ fn parse_grant() {
87088708
granted_by,
87098709
..
87108710
} => match (privileges, objects, granted_by) {
8711-
(Privileges::Actions(actions), GrantObjects::Sequences(objects), None) => {
8711+
(Privileges::Actions(actions), Some(GrantObjects::Sequences(objects)), None) => {
87128712
assert_eq!(
87138713
vec![Action::Usage, Action::Select { columns: None }],
87148714
actions
@@ -8745,7 +8745,7 @@ fn parse_grant() {
87458745
Privileges::All {
87468746
with_privileges_keyword,
87478747
},
8748-
GrantObjects::Schemas(schemas),
8748+
Some(GrantObjects::Schemas(schemas)),
87498749
) => {
87508750
assert!(!with_privileges_keyword);
87518751
assert_eq_vec(&["aa", "b"], &schemas);
@@ -8762,7 +8762,10 @@ fn parse_grant() {
87628762
objects,
87638763
..
87648764
} => match (privileges, objects) {
8765-
(Privileges::Actions(actions), GrantObjects::AllSequencesInSchema { schemas }) => {
8765+
(
8766+
Privileges::Actions(actions),
8767+
Some(GrantObjects::AllSequencesInSchema { schemas }),
8768+
) => {
87668769
assert_eq!(vec![Action::Usage], actions);
87678770
assert_eq_vec(&["bus"], &schemas);
87688771
}
@@ -8792,7 +8795,7 @@ fn test_revoke() {
87928795
match verified_stmt(sql) {
87938796
Statement::Revoke {
87948797
privileges,
8795-
objects: GrantObjects::Tables(tables),
8798+
objects: Some(GrantObjects::Tables(tables)),
87968799
grantees,
87978800
granted_by,
87988801
cascade,
@@ -8818,7 +8821,7 @@ fn test_revoke_with_cascade() {
88188821
match all_dialects_except(|d| d.is::<MySqlDialect>()).verified_stmt(sql) {
88198822
Statement::Revoke {
88208823
privileges,
8821-
objects: GrantObjects::Tables(tables),
8824+
objects: Some(GrantObjects::Tables(tables)),
88228825
grantees,
88238826
granted_by,
88248827
cascade,

tests/sqlparser_mysql.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -3046,7 +3046,10 @@ fn parse_grant() {
30463046
);
30473047
assert_eq!(
30483048
objects,
3049-
GrantObjects::Tables(vec![ObjectName::from(vec!["*".into(), "*".into()])])
3049+
Some(GrantObjects::Tables(vec![ObjectName::from(vec![
3050+
"*".into(),
3051+
"*".into()
3052+
])]))
30503053
);
30513054
assert!(!with_grant_option);
30523055
assert!(granted_by.is_none());
@@ -3087,7 +3090,10 @@ fn parse_revoke() {
30873090
);
30883091
assert_eq!(
30893092
objects,
3090-
GrantObjects::Tables(vec![ObjectName::from(vec!["db1".into(), "*".into()])])
3093+
Some(GrantObjects::Tables(vec![ObjectName::from(vec![
3094+
"db1".into(),
3095+
"*".into()
3096+
])]))
30913097
);
30923098
if let [Grantee {
30933099
grantee_type: GranteesType::None,

tests/sqlparser_snowflake.rs

+12
Original file line numberDiff line numberDiff line change
@@ -3270,3 +3270,15 @@ fn test_grant_account_privileges() {
32703270
}
32713271
}
32723272
}
3273+
3274+
#[test]
3275+
fn test_grant_role_to() {
3276+
snowflake_and_generic().verified_stmt("GRANT ROLE r1 TO ROLE r2");
3277+
snowflake_and_generic().verified_stmt("GRANT ROLE r1 TO USER u1");
3278+
}
3279+
3280+
#[test]
3281+
fn test_grant_database_role_to() {
3282+
snowflake_and_generic().verified_stmt("GRANT DATABASE ROLE r1 TO ROLE r2");
3283+
snowflake_and_generic().verified_stmt("GRANT DATABASE ROLE db1.sc1.r1 TO ROLE db1.sc1.r2");
3284+
}

0 commit comments

Comments
 (0)