mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-08-19 05:30:19 +00:00
Add basic support for GRANT and REVOKE (#365)
* Add basic support for GRANT privileges on tables and sequences * Cargo fmt * Make enum for granted privileges * Implement and use Display for GrantObjects * Simplify Display for GrantPrivileges * Add column privileges * Add second column privilege to test * Add REVOKE privileges and reformat * Fix some clippy warnings * Fix more clippy Co-authored-by: Andrew Lamb <andrew@nerdnetworks.org>
This commit is contained in:
parent
d33bacf679
commit
d7e84be3e1
4 changed files with 528 additions and 0 deletions
144
src/parser.rs
144
src/parser.rs
|
@ -156,6 +156,8 @@ impl<'a> Parser<'a> {
|
|||
Keyword::COPY => Ok(self.parse_copy()?),
|
||||
Keyword::SET => Ok(self.parse_set()?),
|
||||
Keyword::SHOW => Ok(self.parse_show()?),
|
||||
Keyword::GRANT => Ok(self.parse_grant()?),
|
||||
Keyword::REVOKE => Ok(self.parse_revoke()?),
|
||||
Keyword::START => Ok(self.parse_start_transaction()?),
|
||||
// `BEGIN` is a nonstandard but common alias for the
|
||||
// standard `START TRANSACTION` statement. It is supported
|
||||
|
@ -2882,6 +2884,148 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Parse a GRANT statement.
|
||||
pub fn parse_grant(&mut self) -> Result<Statement, ParserError> {
|
||||
let (privileges, objects) = self.parse_grant_revoke_privileges_objects()?;
|
||||
|
||||
self.expect_keyword(Keyword::TO)?;
|
||||
let grantees = self.parse_comma_separated(Parser::parse_identifier)?;
|
||||
|
||||
let with_grant_option =
|
||||
self.parse_keywords(&[Keyword::WITH, Keyword::GRANT, Keyword::OPTION]);
|
||||
|
||||
let granted_by = self
|
||||
.parse_keywords(&[Keyword::GRANTED, Keyword::BY])
|
||||
.then(|| self.parse_identifier().unwrap());
|
||||
|
||||
Ok(Statement::Grant {
|
||||
privileges,
|
||||
objects,
|
||||
grantees,
|
||||
with_grant_option,
|
||||
granted_by,
|
||||
})
|
||||
}
|
||||
|
||||
fn parse_grant_revoke_privileges_objects(
|
||||
&mut self,
|
||||
) -> Result<(Privileges, GrantObjects), ParserError> {
|
||||
let privileges = if self.parse_keyword(Keyword::ALL) {
|
||||
Privileges::All {
|
||||
with_privileges_keyword: self.parse_keyword(Keyword::PRIVILEGES),
|
||||
}
|
||||
} else {
|
||||
Privileges::Actions(
|
||||
self.parse_comma_separated(Parser::parse_grant_permission)?
|
||||
.into_iter()
|
||||
.map(|(kw, columns)| match kw {
|
||||
Keyword::DELETE => Action::Delete,
|
||||
Keyword::INSERT => Action::Insert { columns },
|
||||
Keyword::REFERENCES => Action::References { columns },
|
||||
Keyword::SELECT => Action::Select { columns },
|
||||
Keyword::TRIGGER => Action::Trigger,
|
||||
Keyword::TRUNCATE => Action::Truncate,
|
||||
Keyword::UPDATE => Action::Update { columns },
|
||||
Keyword::USAGE => Action::Usage,
|
||||
_ => unreachable!(),
|
||||
})
|
||||
.collect(),
|
||||
)
|
||||
};
|
||||
|
||||
self.expect_keyword(Keyword::ON)?;
|
||||
|
||||
let objects = if self.parse_keywords(&[
|
||||
Keyword::ALL,
|
||||
Keyword::TABLES,
|
||||
Keyword::IN,
|
||||
Keyword::SCHEMA,
|
||||
]) {
|
||||
GrantObjects::AllTablesInSchema {
|
||||
schemas: self.parse_comma_separated(Parser::parse_object_name)?,
|
||||
}
|
||||
} else if self.parse_keywords(&[
|
||||
Keyword::ALL,
|
||||
Keyword::SEQUENCES,
|
||||
Keyword::IN,
|
||||
Keyword::SCHEMA,
|
||||
]) {
|
||||
GrantObjects::AllSequencesInSchema {
|
||||
schemas: self.parse_comma_separated(Parser::parse_object_name)?,
|
||||
}
|
||||
} else {
|
||||
let object_type =
|
||||
self.parse_one_of_keywords(&[Keyword::SEQUENCE, Keyword::SCHEMA, Keyword::TABLE]);
|
||||
let objects = self.parse_comma_separated(Parser::parse_object_name);
|
||||
match object_type {
|
||||
Some(Keyword::SCHEMA) => GrantObjects::Schemas(objects?),
|
||||
Some(Keyword::SEQUENCE) => GrantObjects::Sequences(objects?),
|
||||
Some(Keyword::TABLE) | None => GrantObjects::Tables(objects?),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
};
|
||||
|
||||
Ok((privileges, objects))
|
||||
}
|
||||
|
||||
fn parse_grant_permission(&mut self) -> Result<(Keyword, Option<Vec<Ident>>), ParserError> {
|
||||
if let Some(kw) = self.parse_one_of_keywords(&[
|
||||
Keyword::CONNECT,
|
||||
Keyword::CREATE,
|
||||
Keyword::DELETE,
|
||||
Keyword::EXECUTE,
|
||||
Keyword::INSERT,
|
||||
Keyword::REFERENCES,
|
||||
Keyword::SELECT,
|
||||
Keyword::TEMPORARY,
|
||||
Keyword::TRIGGER,
|
||||
Keyword::TRUNCATE,
|
||||
Keyword::UPDATE,
|
||||
Keyword::USAGE,
|
||||
]) {
|
||||
let columns = match kw {
|
||||
Keyword::INSERT | Keyword::REFERENCES | Keyword::SELECT | Keyword::UPDATE => {
|
||||
let columns = self.parse_parenthesized_column_list(Optional)?;
|
||||
if columns.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(columns)
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
Ok((kw, columns))
|
||||
} else {
|
||||
self.expected("a privilege keyword", self.peek_token())?
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse a REVOKE statement
|
||||
pub fn parse_revoke(&mut self) -> Result<Statement, ParserError> {
|
||||
let (privileges, objects) = self.parse_grant_revoke_privileges_objects()?;
|
||||
|
||||
self.expect_keyword(Keyword::FROM)?;
|
||||
let grantees = self.parse_comma_separated(Parser::parse_identifier)?;
|
||||
|
||||
let granted_by = self
|
||||
.parse_keywords(&[Keyword::GRANTED, Keyword::BY])
|
||||
.then(|| self.parse_identifier().unwrap());
|
||||
|
||||
let cascade = self.parse_keyword(Keyword::CASCADE);
|
||||
let restrict = self.parse_keyword(Keyword::RESTRICT);
|
||||
if cascade && restrict {
|
||||
return parser_err!("Cannot specify both CASCADE and RESTRICT in REVOKE");
|
||||
}
|
||||
|
||||
Ok(Statement::Revoke {
|
||||
privileges,
|
||||
objects,
|
||||
grantees,
|
||||
granted_by,
|
||||
cascade,
|
||||
})
|
||||
}
|
||||
|
||||
/// Parse an INSERT statement
|
||||
pub fn parse_insert(&mut self) -> Result<Statement, ParserError> {
|
||||
let or = if !dialect_of!(self is SQLiteDialect) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue