Re-enable trailing commas in DCL (#1318)

This commit is contained in:
Mohamed Abdeen 2024-07-08 13:31:33 +03:00 committed by GitHub
parent 0884dd920d
commit f77192d4ec
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 41 additions and 10 deletions

View file

@ -46,6 +46,9 @@ pub enum ParserError {
RecursionLimitExceeded,
}
// avoid clippy type_complexity warnings
type ParsedAction = (Keyword, Option<Vec<Ident>>);
// Use `Parser::expected` instead, if possible
macro_rules! parser_err {
($MSG:expr, $loc:expr) => {
@ -3334,6 +3337,29 @@ impl<'a> Parser<'a> {
ret
}
pub fn parse_actions_list(&mut self) -> Result<Vec<ParsedAction>, ParserError> {
let mut values = vec![];
loop {
values.push(self.parse_grant_permission()?);
if !self.consume_token(&Token::Comma) {
break;
} else if self.options.trailing_commas {
match self.peek_token().token {
Token::Word(kw) if kw.keyword == Keyword::ON => {
break;
}
Token::RParen
| Token::SemiColon
| Token::EOF
| Token::RBracket
| Token::RBrace => break,
_ => continue,
}
}
}
Ok(values)
}
/// Parse a comma-separated list of 1+ items accepted by `F`
pub fn parse_comma_separated<T, F>(&mut self, mut f: F) -> Result<Vec<T>, ParserError>
where
@ -3347,9 +3373,7 @@ impl<'a> Parser<'a> {
} else if self.options.trailing_commas {
match self.peek_token().token {
Token::Word(kw)
if keywords::RESERVED_FOR_COLUMN_ALIAS
.iter()
.any(|d| kw.keyword == *d) =>
if keywords::RESERVED_FOR_COLUMN_ALIAS.contains(&kw.keyword) =>
{
break;
}
@ -9680,11 +9704,8 @@ impl<'a> Parser<'a> {
with_privileges_keyword: self.parse_keyword(Keyword::PRIVILEGES),
}
} else {
let old_value = self.options.trailing_commas;
self.options.trailing_commas = false;
let (actions, err): (Vec<_>, Vec<_>) = self
.parse_comma_separated(Parser::parse_grant_permission)?
.parse_actions_list()?
.into_iter()
.map(|(kw, columns)| match kw {
Keyword::DELETE => Ok(Action::Delete),
@ -9706,8 +9727,6 @@ impl<'a> Parser<'a> {
})
.partition(Result::is_ok);
self.options.trailing_commas = old_value;
if !err.is_empty() {
let errors: Vec<Keyword> = err.into_iter().filter_map(|x| x.err()).collect();
return Err(ParserError::ParserError(format!(
@ -9753,7 +9772,7 @@ impl<'a> Parser<'a> {
Ok((privileges, objects))
}
pub fn parse_grant_permission(&mut self) -> Result<(Keyword, Option<Vec<Ident>>), ParserError> {
pub fn parse_grant_permission(&mut self) -> Result<ParsedAction, ParserError> {
if let Some(kw) = self.parse_one_of_keywords(&[
Keyword::CONNECT,
Keyword::CREATE,

View file

@ -8942,6 +8942,11 @@ fn parse_trailing_comma() {
"CREATE TABLE employees (name TEXT, age INT)",
);
trailing_commas.one_statement_parses_to(
"GRANT USAGE, SELECT, INSERT, ON p TO u",
"GRANT USAGE, SELECT, INSERT ON p TO u",
);
trailing_commas.verified_stmt("SELECT album_id, name FROM track");
trailing_commas.verified_stmt("SELECT * FROM track ORDER BY milliseconds");
@ -8961,6 +8966,13 @@ fn parse_trailing_comma() {
ParserError::ParserError("Expected an expression, found: from".to_string())
);
assert_eq!(
trailing_commas
.parse_sql_statements("REVOKE USAGE, SELECT, ON p TO u")
.unwrap_err(),
ParserError::ParserError("Expected a privilege keyword, found: ON".to_string())
);
assert_eq!(
trailing_commas
.parse_sql_statements("CREATE TABLE employees (name text, age int,)")