Skip to content

Commit ec948ea

Browse files
authored
Add parsing for GRANT ROLE and GRANT DATABASE ROLE in Snowflake dialect (#1689)
1 parent 257da5a commit ec948ea

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
@@ -3230,7 +3230,7 @@ pub enum Statement {
32303230
/// ```
32313231
Grant {
32323232
privileges: Privileges,
3233-
objects: GrantObjects,
3233+
objects: Option<GrantObjects>,
32343234
grantees: Vec<Grantee>,
32353235
with_grant_option: bool,
32363236
granted_by: Option<Ident>,
@@ -3240,7 +3240,7 @@ pub enum Statement {
32403240
/// ```
32413241
Revoke {
32423242
privileges: Privileges,
3243-
objects: GrantObjects,
3243+
objects: Option<GrantObjects>,
32443244
grantees: Vec<Grantee>,
32453245
granted_by: Option<Ident>,
32463246
cascade: Option<CascadeOption>,
@@ -4785,7 +4785,9 @@ impl fmt::Display for Statement {
47854785
granted_by,
47864786
} => {
47874787
write!(f, "GRANT {privileges} ")?;
4788-
write!(f, "ON {objects} ")?;
4788+
if let Some(objects) = objects {
4789+
write!(f, "ON {objects} ")?;
4790+
}
47894791
write!(f, "TO {}", display_comma_separated(grantees))?;
47904792
if *with_grant_option {
47914793
write!(f, " WITH GRANT OPTION")?;
@@ -4803,7 +4805,9 @@ impl fmt::Display for Statement {
48034805
cascade,
48044806
} => {
48054807
write!(f, "REVOKE {privileges} ")?;
4806-
write!(f, "ON {objects} ")?;
4808+
if let Some(objects) = objects {
4809+
write!(f, "ON {objects} ")?;
4810+
}
48074811
write!(f, "FROM {}", display_comma_separated(grantees))?;
48084812
if let Some(grantor) = granted_by {
48094813
write!(f, " GRANTED BY {grantor}")?;
@@ -5503,6 +5507,9 @@ pub enum Action {
55035507
Create {
55045508
obj_type: Option<ActionCreateObjectType>,
55055509
},
5510+
DatabaseRole {
5511+
role: ObjectName,
5512+
},
55065513
Delete,
55075514
EvolveSchema,
55085515
Execute {
@@ -5536,6 +5543,9 @@ pub enum Action {
55365543
},
55375544
Replicate,
55385545
ResolveAll,
5546+
Role {
5547+
role: Ident,
5548+
},
55395549
Select {
55405550
columns: Option<Vec<Ident>>,
55415551
},
@@ -5565,6 +5575,7 @@ impl fmt::Display for Action {
55655575
write!(f, " {obj_type}")?
55665576
}
55675577
}
5578+
Action::DatabaseRole { role } => write!(f, "DATABASE ROLE {role}")?,
55685579
Action::Delete => f.write_str("DELETE")?,
55695580
Action::EvolveSchema => f.write_str("EVOLVE SCHEMA")?,
55705581
Action::Execute { obj_type } => {
@@ -5591,6 +5602,7 @@ impl fmt::Display for Action {
55915602
Action::References { .. } => f.write_str("REFERENCES")?,
55925603
Action::Replicate => f.write_str("REPLICATE")?,
55935604
Action::ResolveAll => f.write_str("RESOLVE ALL")?,
5605+
Action::Role { role } => write!(f, "ROLE {role}")?,
55945606
Action::Select { .. } => f.write_str("SELECT")?,
55955607
Action::Temporary => f.write_str("TEMPORARY")?,
55965608
Action::Trigger => f.write_str("TRIGGER")?,

src/parser/mod.rs

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

1213112131
pub fn parse_grant_revoke_privileges_objects(
1213212132
&mut self,
12133-
) -> Result<(Privileges, GrantObjects), ParserError> {
12133+
) -> Result<(Privileges, Option<GrantObjects>), ParserError> {
1213412134
let privileges = if self.parse_keyword(Keyword::ALL) {
1213512135
Privileges::All {
1213612136
with_privileges_keyword: self.parse_keyword(Keyword::PRIVILEGES),
@@ -12140,48 +12140,49 @@ impl<'a> Parser<'a> {
1214012140
Privileges::Actions(actions)
1214112141
};
1214212142

12143-
self.expect_keyword_is(Keyword::ON)?;
12144-
12145-
let objects = if self.parse_keywords(&[
12146-
Keyword::ALL,
12147-
Keyword::TABLES,
12148-
Keyword::IN,
12149-
Keyword::SCHEMA,
12150-
]) {
12151-
GrantObjects::AllTablesInSchema {
12152-
schemas: self.parse_comma_separated(|p| p.parse_object_name(false))?,
12153-
}
12154-
} else if self.parse_keywords(&[
12155-
Keyword::ALL,
12156-
Keyword::SEQUENCES,
12157-
Keyword::IN,
12158-
Keyword::SCHEMA,
12159-
]) {
12160-
GrantObjects::AllSequencesInSchema {
12161-
schemas: self.parse_comma_separated(|p| p.parse_object_name(false))?,
12162-
}
12163-
} else {
12164-
let object_type = self.parse_one_of_keywords(&[
12165-
Keyword::SEQUENCE,
12166-
Keyword::DATABASE,
12143+
let objects = if self.parse_keyword(Keyword::ON) {
12144+
if self.parse_keywords(&[Keyword::ALL, Keyword::TABLES, Keyword::IN, Keyword::SCHEMA]) {
12145+
Some(GrantObjects::AllTablesInSchema {
12146+
schemas: self.parse_comma_separated(|p| p.parse_object_name(false))?,
12147+
})
12148+
} else if self.parse_keywords(&[
12149+
Keyword::ALL,
12150+
Keyword::SEQUENCES,
12151+
Keyword::IN,
1216712152
Keyword::SCHEMA,
12168-
Keyword::TABLE,
12169-
Keyword::VIEW,
12170-
Keyword::WAREHOUSE,
12171-
Keyword::INTEGRATION,
12172-
]);
12173-
let objects =
12174-
self.parse_comma_separated(|p| p.parse_object_name_with_wildcards(false, true));
12175-
match object_type {
12176-
Some(Keyword::DATABASE) => GrantObjects::Databases(objects?),
12177-
Some(Keyword::SCHEMA) => GrantObjects::Schemas(objects?),
12178-
Some(Keyword::SEQUENCE) => GrantObjects::Sequences(objects?),
12179-
Some(Keyword::WAREHOUSE) => GrantObjects::Warehouses(objects?),
12180-
Some(Keyword::INTEGRATION) => GrantObjects::Integrations(objects?),
12181-
Some(Keyword::VIEW) => GrantObjects::Views(objects?),
12182-
Some(Keyword::TABLE) | None => GrantObjects::Tables(objects?),
12183-
_ => unreachable!(),
12153+
]) {
12154+
Some(GrantObjects::AllSequencesInSchema {
12155+
schemas: self.parse_comma_separated(|p| p.parse_object_name(false))?,
12156+
})
12157+
} else {
12158+
let object_type = self.parse_one_of_keywords(&[
12159+
Keyword::SEQUENCE,
12160+
Keyword::DATABASE,
12161+
Keyword::DATABASE,
12162+
Keyword::SCHEMA,
12163+
Keyword::TABLE,
12164+
Keyword::VIEW,
12165+
Keyword::WAREHOUSE,
12166+
Keyword::INTEGRATION,
12167+
Keyword::VIEW,
12168+
Keyword::WAREHOUSE,
12169+
Keyword::INTEGRATION,
12170+
]);
12171+
let objects =
12172+
self.parse_comma_separated(|p| p.parse_object_name_with_wildcards(false, true));
12173+
match object_type {
12174+
Some(Keyword::DATABASE) => Some(GrantObjects::Databases(objects?)),
12175+
Some(Keyword::SCHEMA) => Some(GrantObjects::Schemas(objects?)),
12176+
Some(Keyword::SEQUENCE) => Some(GrantObjects::Sequences(objects?)),
12177+
Some(Keyword::WAREHOUSE) => Some(GrantObjects::Warehouses(objects?)),
12178+
Some(Keyword::INTEGRATION) => Some(GrantObjects::Integrations(objects?)),
12179+
Some(Keyword::VIEW) => Some(GrantObjects::Views(objects?)),
12180+
Some(Keyword::TABLE) | None => Some(GrantObjects::Tables(objects?)),
12181+
_ => unreachable!(),
12182+
}
1218412183
}
12184+
} else {
12185+
None
1218512186
};
1218612187

1218712188
Ok((privileges, objects))
@@ -12208,6 +12209,9 @@ impl<'a> Parser<'a> {
1220812209
Ok(Action::AttachPolicy)
1220912210
} else if self.parse_keywords(&[Keyword::BIND, Keyword::SERVICE, Keyword::ENDPOINT]) {
1221012211
Ok(Action::BindServiceEndpoint)
12212+
} else if self.parse_keywords(&[Keyword::DATABASE, Keyword::ROLE]) {
12213+
let role = self.parse_object_name(false)?;
12214+
Ok(Action::DatabaseRole { role })
1221112215
} else if self.parse_keywords(&[Keyword::EVOLVE, Keyword::SCHEMA]) {
1221212216
Ok(Action::EvolveSchema)
1221312217
} else if self.parse_keywords(&[Keyword::IMPORT, Keyword::SHARE]) {
@@ -12273,6 +12277,9 @@ impl<'a> Parser<'a> {
1227312277
Ok(Action::Read)
1227412278
} else if self.parse_keyword(Keyword::REPLICATE) {
1227512279
Ok(Action::Replicate)
12280+
} else if self.parse_keyword(Keyword::ROLE) {
12281+
let role = self.parse_identifier()?;
12282+
Ok(Action::Role { role })
1227612283
} else if self.parse_keyword(Keyword::SELECT) {
1227712284
Ok(Action::Select {
1227812285
columns: parse_columns(self)?,

tests/sqlparser_common.rs

+10-7
Original file line numberDiff line numberDiff line change
@@ -8637,7 +8637,7 @@ fn parse_grant() {
86378637
granted_by,
86388638
..
86398639
} => match (privileges, objects) {
8640-
(Privileges::Actions(actions), GrantObjects::Tables(objects)) => {
8640+
(Privileges::Actions(actions), Some(GrantObjects::Tables(objects))) => {
86418641
assert_eq!(
86428642
vec![
86438643
Action::Select { columns: None },
@@ -8687,7 +8687,7 @@ fn parse_grant() {
86878687
with_grant_option,
86888688
..
86898689
} => match (privileges, objects) {
8690-
(Privileges::Actions(actions), GrantObjects::AllTablesInSchema { schemas }) => {
8690+
(Privileges::Actions(actions), Some(GrantObjects::AllTablesInSchema { schemas })) => {
86918691
assert_eq!(vec![Action::Insert { columns: None }], actions);
86928692
assert_eq_vec(&["public"], &schemas);
86938693
assert_eq_vec(&["browser"], &grantees);
@@ -8707,7 +8707,7 @@ fn parse_grant() {
87078707
granted_by,
87088708
..
87098709
} => match (privileges, objects, granted_by) {
8710-
(Privileges::Actions(actions), GrantObjects::Sequences(objects), None) => {
8710+
(Privileges::Actions(actions), Some(GrantObjects::Sequences(objects)), None) => {
87118711
assert_eq!(
87128712
vec![Action::Usage, Action::Select { columns: None }],
87138713
actions
@@ -8744,7 +8744,7 @@ fn parse_grant() {
87448744
Privileges::All {
87458745
with_privileges_keyword,
87468746
},
8747-
GrantObjects::Schemas(schemas),
8747+
Some(GrantObjects::Schemas(schemas)),
87488748
) => {
87498749
assert!(!with_privileges_keyword);
87508750
assert_eq_vec(&["aa", "b"], &schemas);
@@ -8761,7 +8761,10 @@ fn parse_grant() {
87618761
objects,
87628762
..
87638763
} => match (privileges, objects) {
8764-
(Privileges::Actions(actions), GrantObjects::AllSequencesInSchema { schemas }) => {
8764+
(
8765+
Privileges::Actions(actions),
8766+
Some(GrantObjects::AllSequencesInSchema { schemas }),
8767+
) => {
87658768
assert_eq!(vec![Action::Usage], actions);
87668769
assert_eq_vec(&["bus"], &schemas);
87678770
}
@@ -8791,7 +8794,7 @@ fn test_revoke() {
87918794
match verified_stmt(sql) {
87928795
Statement::Revoke {
87938796
privileges,
8794-
objects: GrantObjects::Tables(tables),
8797+
objects: Some(GrantObjects::Tables(tables)),
87958798
grantees,
87968799
granted_by,
87978800
cascade,
@@ -8817,7 +8820,7 @@ fn test_revoke_with_cascade() {
88178820
match all_dialects_except(|d| d.is::<MySqlDialect>()).verified_stmt(sql) {
88188821
Statement::Revoke {
88198822
privileges,
8820-
objects: GrantObjects::Tables(tables),
8823+
objects: Some(GrantObjects::Tables(tables)),
88218824
grantees,
88228825
granted_by,
88238826
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
@@ -3263,3 +3263,15 @@ fn test_grant_account_privileges() {
32633263
}
32643264
}
32653265
}
3266+
3267+
#[test]
3268+
fn test_grant_role_to() {
3269+
snowflake_and_generic().verified_stmt("GRANT ROLE r1 TO ROLE r2");
3270+
snowflake_and_generic().verified_stmt("GRANT ROLE r1 TO USER u1");
3271+
}
3272+
3273+
#[test]
3274+
fn test_grant_database_role_to() {
3275+
snowflake_and_generic().verified_stmt("GRANT DATABASE ROLE r1 TO ROLE r2");
3276+
snowflake_and_generic().verified_stmt("GRANT DATABASE ROLE db1.sc1.r1 TO ROLE db1.sc1.r2");
3277+
}

0 commit comments

Comments
 (0)