mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-08-23 07:24:10 +00:00
Re-enable trailing commas in DCL (#1318)
This commit is contained in:
parent
0884dd920d
commit
f77192d4ec
2 changed files with 41 additions and 10 deletions
|
@ -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,
|
||||||
|
|
|
@ -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,)")
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue