mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-07-07 17:04:59 +00:00
Add parsing for GRANT ROLE and GRANT DATABASE ROLE in Snowflake dialect (#1689)
This commit is contained in:
parent
257da5a82c
commit
ec948eaf6e
5 changed files with 94 additions and 54 deletions
|
@ -3230,7 +3230,7 @@ pub enum Statement {
|
|||
/// ```
|
||||
Grant {
|
||||
privileges: Privileges,
|
||||
objects: GrantObjects,
|
||||
objects: Option<GrantObjects>,
|
||||
grantees: Vec<Grantee>,
|
||||
with_grant_option: bool,
|
||||
granted_by: Option<Ident>,
|
||||
|
@ -3240,7 +3240,7 @@ pub enum Statement {
|
|||
/// ```
|
||||
Revoke {
|
||||
privileges: Privileges,
|
||||
objects: GrantObjects,
|
||||
objects: Option<GrantObjects>,
|
||||
grantees: Vec<Grantee>,
|
||||
granted_by: Option<Ident>,
|
||||
cascade: Option<CascadeOption>,
|
||||
|
@ -4785,7 +4785,9 @@ impl fmt::Display for Statement {
|
|||
granted_by,
|
||||
} => {
|
||||
write!(f, "GRANT {privileges} ")?;
|
||||
write!(f, "ON {objects} ")?;
|
||||
if let Some(objects) = objects {
|
||||
write!(f, "ON {objects} ")?;
|
||||
}
|
||||
write!(f, "TO {}", display_comma_separated(grantees))?;
|
||||
if *with_grant_option {
|
||||
write!(f, " WITH GRANT OPTION")?;
|
||||
|
@ -4803,7 +4805,9 @@ impl fmt::Display for Statement {
|
|||
cascade,
|
||||
} => {
|
||||
write!(f, "REVOKE {privileges} ")?;
|
||||
write!(f, "ON {objects} ")?;
|
||||
if let Some(objects) = objects {
|
||||
write!(f, "ON {objects} ")?;
|
||||
}
|
||||
write!(f, "FROM {}", display_comma_separated(grantees))?;
|
||||
if let Some(grantor) = granted_by {
|
||||
write!(f, " GRANTED BY {grantor}")?;
|
||||
|
@ -5503,6 +5507,9 @@ pub enum Action {
|
|||
Create {
|
||||
obj_type: Option<ActionCreateObjectType>,
|
||||
},
|
||||
DatabaseRole {
|
||||
role: ObjectName,
|
||||
},
|
||||
Delete,
|
||||
EvolveSchema,
|
||||
Execute {
|
||||
|
@ -5536,6 +5543,9 @@ pub enum Action {
|
|||
},
|
||||
Replicate,
|
||||
ResolveAll,
|
||||
Role {
|
||||
role: Ident,
|
||||
},
|
||||
Select {
|
||||
columns: Option<Vec<Ident>>,
|
||||
},
|
||||
|
@ -5565,6 +5575,7 @@ impl fmt::Display for Action {
|
|||
write!(f, " {obj_type}")?
|
||||
}
|
||||
}
|
||||
Action::DatabaseRole { role } => write!(f, "DATABASE ROLE {role}")?,
|
||||
Action::Delete => f.write_str("DELETE")?,
|
||||
Action::EvolveSchema => f.write_str("EVOLVE SCHEMA")?,
|
||||
Action::Execute { obj_type } => {
|
||||
|
@ -5591,6 +5602,7 @@ impl fmt::Display for Action {
|
|||
Action::References { .. } => f.write_str("REFERENCES")?,
|
||||
Action::Replicate => f.write_str("REPLICATE")?,
|
||||
Action::ResolveAll => f.write_str("RESOLVE ALL")?,
|
||||
Action::Role { role } => write!(f, "ROLE {role}")?,
|
||||
Action::Select { .. } => f.write_str("SELECT")?,
|
||||
Action::Temporary => f.write_str("TEMPORARY")?,
|
||||
Action::Trigger => f.write_str("TRIGGER")?,
|
||||
|
|
|
@ -12130,7 +12130,7 @@ impl<'a> Parser<'a> {
|
|||
|
||||
pub fn parse_grant_revoke_privileges_objects(
|
||||
&mut self,
|
||||
) -> Result<(Privileges, GrantObjects), ParserError> {
|
||||
) -> Result<(Privileges, Option<GrantObjects>), ParserError> {
|
||||
let privileges = if self.parse_keyword(Keyword::ALL) {
|
||||
Privileges::All {
|
||||
with_privileges_keyword: self.parse_keyword(Keyword::PRIVILEGES),
|
||||
|
@ -12140,48 +12140,49 @@ impl<'a> Parser<'a> {
|
|||
Privileges::Actions(actions)
|
||||
};
|
||||
|
||||
self.expect_keyword_is(Keyword::ON)?;
|
||||
|
||||
let objects = if self.parse_keywords(&[
|
||||
Keyword::ALL,
|
||||
Keyword::TABLES,
|
||||
Keyword::IN,
|
||||
Keyword::SCHEMA,
|
||||
]) {
|
||||
GrantObjects::AllTablesInSchema {
|
||||
schemas: self.parse_comma_separated(|p| p.parse_object_name(false))?,
|
||||
}
|
||||
} else if self.parse_keywords(&[
|
||||
Keyword::ALL,
|
||||
Keyword::SEQUENCES,
|
||||
Keyword::IN,
|
||||
Keyword::SCHEMA,
|
||||
]) {
|
||||
GrantObjects::AllSequencesInSchema {
|
||||
schemas: self.parse_comma_separated(|p| p.parse_object_name(false))?,
|
||||
let objects = if self.parse_keyword(Keyword::ON) {
|
||||
if self.parse_keywords(&[Keyword::ALL, Keyword::TABLES, Keyword::IN, Keyword::SCHEMA]) {
|
||||
Some(GrantObjects::AllTablesInSchema {
|
||||
schemas: self.parse_comma_separated(|p| p.parse_object_name(false))?,
|
||||
})
|
||||
} else if self.parse_keywords(&[
|
||||
Keyword::ALL,
|
||||
Keyword::SEQUENCES,
|
||||
Keyword::IN,
|
||||
Keyword::SCHEMA,
|
||||
]) {
|
||||
Some(GrantObjects::AllSequencesInSchema {
|
||||
schemas: self.parse_comma_separated(|p| p.parse_object_name(false))?,
|
||||
})
|
||||
} else {
|
||||
let object_type = self.parse_one_of_keywords(&[
|
||||
Keyword::SEQUENCE,
|
||||
Keyword::DATABASE,
|
||||
Keyword::DATABASE,
|
||||
Keyword::SCHEMA,
|
||||
Keyword::TABLE,
|
||||
Keyword::VIEW,
|
||||
Keyword::WAREHOUSE,
|
||||
Keyword::INTEGRATION,
|
||||
Keyword::VIEW,
|
||||
Keyword::WAREHOUSE,
|
||||
Keyword::INTEGRATION,
|
||||
]);
|
||||
let objects =
|
||||
self.parse_comma_separated(|p| p.parse_object_name_with_wildcards(false, true));
|
||||
match object_type {
|
||||
Some(Keyword::DATABASE) => Some(GrantObjects::Databases(objects?)),
|
||||
Some(Keyword::SCHEMA) => Some(GrantObjects::Schemas(objects?)),
|
||||
Some(Keyword::SEQUENCE) => Some(GrantObjects::Sequences(objects?)),
|
||||
Some(Keyword::WAREHOUSE) => Some(GrantObjects::Warehouses(objects?)),
|
||||
Some(Keyword::INTEGRATION) => Some(GrantObjects::Integrations(objects?)),
|
||||
Some(Keyword::VIEW) => Some(GrantObjects::Views(objects?)),
|
||||
Some(Keyword::TABLE) | None => Some(GrantObjects::Tables(objects?)),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let object_type = self.parse_one_of_keywords(&[
|
||||
Keyword::SEQUENCE,
|
||||
Keyword::DATABASE,
|
||||
Keyword::SCHEMA,
|
||||
Keyword::TABLE,
|
||||
Keyword::VIEW,
|
||||
Keyword::WAREHOUSE,
|
||||
Keyword::INTEGRATION,
|
||||
]);
|
||||
let objects =
|
||||
self.parse_comma_separated(|p| p.parse_object_name_with_wildcards(false, true));
|
||||
match object_type {
|
||||
Some(Keyword::DATABASE) => GrantObjects::Databases(objects?),
|
||||
Some(Keyword::SCHEMA) => GrantObjects::Schemas(objects?),
|
||||
Some(Keyword::SEQUENCE) => GrantObjects::Sequences(objects?),
|
||||
Some(Keyword::WAREHOUSE) => GrantObjects::Warehouses(objects?),
|
||||
Some(Keyword::INTEGRATION) => GrantObjects::Integrations(objects?),
|
||||
Some(Keyword::VIEW) => GrantObjects::Views(objects?),
|
||||
Some(Keyword::TABLE) | None => GrantObjects::Tables(objects?),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
None
|
||||
};
|
||||
|
||||
Ok((privileges, objects))
|
||||
|
@ -12208,6 +12209,9 @@ impl<'a> Parser<'a> {
|
|||
Ok(Action::AttachPolicy)
|
||||
} else if self.parse_keywords(&[Keyword::BIND, Keyword::SERVICE, Keyword::ENDPOINT]) {
|
||||
Ok(Action::BindServiceEndpoint)
|
||||
} else if self.parse_keywords(&[Keyword::DATABASE, Keyword::ROLE]) {
|
||||
let role = self.parse_object_name(false)?;
|
||||
Ok(Action::DatabaseRole { role })
|
||||
} else if self.parse_keywords(&[Keyword::EVOLVE, Keyword::SCHEMA]) {
|
||||
Ok(Action::EvolveSchema)
|
||||
} else if self.parse_keywords(&[Keyword::IMPORT, Keyword::SHARE]) {
|
||||
|
@ -12273,6 +12277,9 @@ impl<'a> Parser<'a> {
|
|||
Ok(Action::Read)
|
||||
} else if self.parse_keyword(Keyword::REPLICATE) {
|
||||
Ok(Action::Replicate)
|
||||
} else if self.parse_keyword(Keyword::ROLE) {
|
||||
let role = self.parse_identifier()?;
|
||||
Ok(Action::Role { role })
|
||||
} else if self.parse_keyword(Keyword::SELECT) {
|
||||
Ok(Action::Select {
|
||||
columns: parse_columns(self)?,
|
||||
|
|
|
@ -8637,7 +8637,7 @@ fn parse_grant() {
|
|||
granted_by,
|
||||
..
|
||||
} => match (privileges, objects) {
|
||||
(Privileges::Actions(actions), GrantObjects::Tables(objects)) => {
|
||||
(Privileges::Actions(actions), Some(GrantObjects::Tables(objects))) => {
|
||||
assert_eq!(
|
||||
vec![
|
||||
Action::Select { columns: None },
|
||||
|
@ -8687,7 +8687,7 @@ fn parse_grant() {
|
|||
with_grant_option,
|
||||
..
|
||||
} => match (privileges, objects) {
|
||||
(Privileges::Actions(actions), GrantObjects::AllTablesInSchema { schemas }) => {
|
||||
(Privileges::Actions(actions), Some(GrantObjects::AllTablesInSchema { schemas })) => {
|
||||
assert_eq!(vec![Action::Insert { columns: None }], actions);
|
||||
assert_eq_vec(&["public"], &schemas);
|
||||
assert_eq_vec(&["browser"], &grantees);
|
||||
|
@ -8707,7 +8707,7 @@ fn parse_grant() {
|
|||
granted_by,
|
||||
..
|
||||
} => match (privileges, objects, granted_by) {
|
||||
(Privileges::Actions(actions), GrantObjects::Sequences(objects), None) => {
|
||||
(Privileges::Actions(actions), Some(GrantObjects::Sequences(objects)), None) => {
|
||||
assert_eq!(
|
||||
vec![Action::Usage, Action::Select { columns: None }],
|
||||
actions
|
||||
|
@ -8744,7 +8744,7 @@ fn parse_grant() {
|
|||
Privileges::All {
|
||||
with_privileges_keyword,
|
||||
},
|
||||
GrantObjects::Schemas(schemas),
|
||||
Some(GrantObjects::Schemas(schemas)),
|
||||
) => {
|
||||
assert!(!with_privileges_keyword);
|
||||
assert_eq_vec(&["aa", "b"], &schemas);
|
||||
|
@ -8761,7 +8761,10 @@ fn parse_grant() {
|
|||
objects,
|
||||
..
|
||||
} => match (privileges, objects) {
|
||||
(Privileges::Actions(actions), GrantObjects::AllSequencesInSchema { schemas }) => {
|
||||
(
|
||||
Privileges::Actions(actions),
|
||||
Some(GrantObjects::AllSequencesInSchema { schemas }),
|
||||
) => {
|
||||
assert_eq!(vec![Action::Usage], actions);
|
||||
assert_eq_vec(&["bus"], &schemas);
|
||||
}
|
||||
|
@ -8791,7 +8794,7 @@ fn test_revoke() {
|
|||
match verified_stmt(sql) {
|
||||
Statement::Revoke {
|
||||
privileges,
|
||||
objects: GrantObjects::Tables(tables),
|
||||
objects: Some(GrantObjects::Tables(tables)),
|
||||
grantees,
|
||||
granted_by,
|
||||
cascade,
|
||||
|
@ -8817,7 +8820,7 @@ fn test_revoke_with_cascade() {
|
|||
match all_dialects_except(|d| d.is::<MySqlDialect>()).verified_stmt(sql) {
|
||||
Statement::Revoke {
|
||||
privileges,
|
||||
objects: GrantObjects::Tables(tables),
|
||||
objects: Some(GrantObjects::Tables(tables)),
|
||||
grantees,
|
||||
granted_by,
|
||||
cascade,
|
||||
|
|
|
@ -3046,7 +3046,10 @@ fn parse_grant() {
|
|||
);
|
||||
assert_eq!(
|
||||
objects,
|
||||
GrantObjects::Tables(vec![ObjectName::from(vec!["*".into(), "*".into()])])
|
||||
Some(GrantObjects::Tables(vec![ObjectName::from(vec![
|
||||
"*".into(),
|
||||
"*".into()
|
||||
])]))
|
||||
);
|
||||
assert!(!with_grant_option);
|
||||
assert!(granted_by.is_none());
|
||||
|
@ -3087,7 +3090,10 @@ fn parse_revoke() {
|
|||
);
|
||||
assert_eq!(
|
||||
objects,
|
||||
GrantObjects::Tables(vec![ObjectName::from(vec!["db1".into(), "*".into()])])
|
||||
Some(GrantObjects::Tables(vec![ObjectName::from(vec![
|
||||
"db1".into(),
|
||||
"*".into()
|
||||
])]))
|
||||
);
|
||||
if let [Grantee {
|
||||
grantee_type: GranteesType::None,
|
||||
|
|
|
@ -3263,3 +3263,15 @@ fn test_grant_account_privileges() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_grant_role_to() {
|
||||
snowflake_and_generic().verified_stmt("GRANT ROLE r1 TO ROLE r2");
|
||||
snowflake_and_generic().verified_stmt("GRANT ROLE r1 TO USER u1");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_grant_database_role_to() {
|
||||
snowflake_and_generic().verified_stmt("GRANT DATABASE ROLE r1 TO ROLE r2");
|
||||
snowflake_and_generic().verified_stmt("GRANT DATABASE ROLE db1.sc1.r1 TO ROLE db1.sc1.r2");
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue