@@ -3532,16 +3532,11 @@ impl<'a> Parser<'a> {
3532
3532
// e.g. `SELECT 1, 2, FROM t`
3533
3533
// https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical#trailing_commas
3534
3534
// https://docs.snowflake.com/en/release-notes/2024/8_11#select-supports-trailing-commas
3535
- //
3536
- // This pattern could be captured better with RAII type semantics, but it's quite a bit of
3537
- // code to add for just one case, so we'll just do it manually here.
3538
- let old_value = self.options.trailing_commas;
3539
- self.options.trailing_commas |= self.dialect.supports_projection_trailing_commas();
3540
3535
3541
- let ret = self.parse_comma_separated(|p| p.parse_select_item());
3542
- self.options.trailing_commas = old_value ;
3536
+ let trailing_commas =
3537
+ self.options.trailing_commas | self.dialect.supports_projection_trailing_commas() ;
3543
3538
3544
- ret
3539
+ self.parse_comma_separated_with_trailing_commas(|p| p.parse_select_item(), trailing_commas)
3545
3540
}
3546
3541
3547
3542
pub fn parse_actions_list(&mut self) -> Result<Vec<ParsedAction>, ParserError> {
@@ -3568,11 +3563,12 @@ impl<'a> Parser<'a> {
3568
3563
}
3569
3564
3570
3565
/// Parse the comma of a comma-separated syntax element.
3566
+ /// Allows for control over trailing commas
3571
3567
/// Returns true if there is a next element
3572
- fn is_parse_comma_separated_end (&mut self) -> bool {
3568
+ fn is_parse_comma_separated_end_with_trailing_commas (&mut self, trailing_commas: bool ) -> bool {
3573
3569
if !self.consume_token(&Token::Comma) {
3574
3570
true
3575
- } else if self.options. trailing_commas {
3571
+ } else if trailing_commas {
3576
3572
let token = self.peek_token().token;
3577
3573
match token {
3578
3574
Token::Word(ref kw)
@@ -3590,15 +3586,34 @@ impl<'a> Parser<'a> {
3590
3586
}
3591
3587
}
3592
3588
3589
+ /// Parse the comma of a comma-separated syntax element.
3590
+ /// Returns true if there is a next element
3591
+ fn is_parse_comma_separated_end(&mut self) -> bool {
3592
+ self.is_parse_comma_separated_end_with_trailing_commas(self.options.trailing_commas)
3593
+ }
3594
+
3593
3595
/// Parse a comma-separated list of 1+ items accepted by `F`
3594
- pub fn parse_comma_separated<T, F>(&mut self, mut f: F) -> Result<Vec<T>, ParserError>
3596
+ pub fn parse_comma_separated<T, F>(&mut self, f: F) -> Result<Vec<T>, ParserError>
3597
+ where
3598
+ F: FnMut(&mut Parser<'a>) -> Result<T, ParserError>,
3599
+ {
3600
+ self.parse_comma_separated_with_trailing_commas(f, self.options.trailing_commas)
3601
+ }
3602
+
3603
+ /// Parse a comma-separated list of 1+ items accepted by `F`
3604
+ /// Allows for control over trailing commas
3605
+ fn parse_comma_separated_with_trailing_commas<T, F>(
3606
+ &mut self,
3607
+ mut f: F,
3608
+ trailing_commas: bool,
3609
+ ) -> Result<Vec<T>, ParserError>
3595
3610
where
3596
3611
F: FnMut(&mut Parser<'a>) -> Result<T, ParserError>,
3597
3612
{
3598
3613
let mut values = vec![];
3599
3614
loop {
3600
3615
values.push(f(self)?);
3601
- if self.is_parse_comma_separated_end( ) {
3616
+ if self.is_parse_comma_separated_end_with_trailing_commas(trailing_commas ) {
3602
3617
break;
3603
3618
}
3604
3619
}
0 commit comments