Skip to content

Commit aabafc9

Browse files
authored
feat: Support trailing commas (apache#557)
1 parent 8176561 commit aabafc9

File tree

2 files changed

+43
-1
lines changed

2 files changed

+43
-1
lines changed

src/parser.rs

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1639,6 +1639,33 @@ impl<'a> Parser<'a> {
16391639
}
16401640
}
16411641

1642+
/// Parse a comma-separated list of 1+ SelectItem
1643+
pub fn parse_projection(&mut self) -> Result<Vec<SelectItem>, ParserError> {
1644+
let mut values = vec![];
1645+
loop {
1646+
values.push(self.parse_select_item()?);
1647+
if !self.consume_token(&Token::Comma) {
1648+
break;
1649+
} else if dialect_of!(self is BigQueryDialect) {
1650+
// BigQuery allows trailing commas.
1651+
// e.g. `SELECT 1, 2, FROM t`
1652+
// https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical#trailing_commas
1653+
match self.peek_token() {
1654+
Token::Word(kw)
1655+
if keywords::RESERVED_FOR_COLUMN_ALIAS
1656+
.iter()
1657+
.any(|d| kw.keyword == *d) =>
1658+
{
1659+
break
1660+
}
1661+
Token::RParen | Token::EOF => break,
1662+
_ => continue,
1663+
}
1664+
}
1665+
}
1666+
Ok(values)
1667+
}
1668+
16421669
/// Parse a comma-separated list of 1+ items accepted by `F`
16431670
pub fn parse_comma_separated<T, F>(&mut self, mut f: F) -> Result<Vec<T>, ParserError>
16441671
where
@@ -3486,7 +3513,7 @@ impl<'a> Parser<'a> {
34863513
None
34873514
};
34883515

3489-
let projection = self.parse_comma_separated(Parser::parse_select_item)?;
3516+
let projection = self.parse_projection()?;
34903517

34913518
let into = if self.parse_keyword(Keyword::INTO) {
34923519
let temporary = self

tests/sqlparser_bigquery.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,21 @@ fn parse_table_identifiers() {
9494
test_table_ident("abc5.GROUP", vec![Ident::new("abc5"), Ident::new("GROUP")]);
9595
}
9696

97+
#[test]
98+
fn parse_trailing_comma() {
99+
for (sql, canonical) in [
100+
("SELECT a,", "SELECT a"),
101+
("SELECT a, b,", "SELECT a, b"),
102+
("SELECT a, b AS c,", "SELECT a, b AS c"),
103+
("SELECT a, b AS c, FROM t", "SELECT a, b AS c FROM t"),
104+
("SELECT a, b, FROM t", "SELECT a, b FROM t"),
105+
("SELECT a, b, LIMIT 1", "SELECT a, b LIMIT 1"),
106+
("SELECT a, (SELECT 1, )", "SELECT a, (SELECT 1)"),
107+
] {
108+
bigquery().one_statement_parses_to(sql, canonical);
109+
}
110+
}
111+
97112
#[test]
98113
fn parse_cast_type() {
99114
let sql = r#"SELECT SAFE_CAST(1 AS INT64)"#;

0 commit comments

Comments
 (0)