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

View file

@ -8942,6 +8942,11 @@ fn parse_trailing_comma() {
"CREATE TABLE employees (name TEXT, age INT)", "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 album_id, name FROM track");
trailing_commas.verified_stmt("SELECT * FROM track ORDER BY milliseconds"); 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()) 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!( assert_eq!(
trailing_commas trailing_commas
.parse_sql_statements("CREATE TABLE employees (name text, age int,)") .parse_sql_statements("CREATE TABLE employees (name text, age int,)")