You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@datafusion.apache.org by al...@apache.org on 2025/01/25 15:01:38 UTC
(datafusion-sqlparser-rs) branch main updated: BigQuery: Support trailing commas in column definitions list (#1682)
This is an automated email from the ASF dual-hosted git repository.
alamb pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/datafusion-sqlparser-rs.git
The following commit(s) were added to refs/heads/main by this push:
new fd6c98e9 BigQuery: Support trailing commas in column definitions list (#1682)
fd6c98e9 is described below
commit fd6c98e9332cfe80f44acbe3a994309065c70946
Author: Ifeanyi Ubah <if...@validio.io>
AuthorDate: Sat Jan 25 16:01:33 2025 +0100
BigQuery: Support trailing commas in column definitions list (#1682)
---
src/dialect/bigquery.rs | 5 ++++
src/dialect/mod.rs | 9 +++++++-
src/parser/mod.rs | 12 ++++++++--
tests/sqlparser_common.rs | 59 +++++++++++++++++++++++++++++++++--------------
4 files changed, 65 insertions(+), 20 deletions(-)
diff --git a/src/dialect/bigquery.rs b/src/dialect/bigquery.rs
index e92169a3..71617439 100644
--- a/src/dialect/bigquery.rs
+++ b/src/dialect/bigquery.rs
@@ -31,6 +31,11 @@ impl Dialect for BigQueryDialect {
true
}
+ /// See <https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_table_statement>
+ fn supports_column_definition_trailing_commas(&self) -> bool {
+ true
+ }
+
fn is_identifier_start(&self, ch: char) -> bool {
ch.is_ascii_lowercase() || ch.is_ascii_uppercase() || ch == '_'
}
diff --git a/src/dialect/mod.rs b/src/dialect/mod.rs
index 79260326..9fc16cd5 100644
--- a/src/dialect/mod.rs
+++ b/src/dialect/mod.rs
@@ -405,11 +405,18 @@ pub trait Dialect: Debug + Any {
}
/// Returns true if the dialect supports trailing commas in the `FROM` clause of a `SELECT` statement.
- /// /// Example: `SELECT 1 FROM T, U, LIMIT 1`
+ /// Example: `SELECT 1 FROM T, U, LIMIT 1`
fn supports_from_trailing_commas(&self) -> bool {
false
}
+ /// Returns true if the dialect supports trailing commas in the
+ /// column definitions list of a `CREATE` statement.
+ /// Example: `CREATE TABLE T (x INT, y TEXT,)`
+ fn supports_column_definition_trailing_commas(&self) -> bool {
+ false
+ }
+
/// Returns true if the dialect supports double dot notation for object names
///
/// Example
diff --git a/src/parser/mod.rs b/src/parser/mod.rs
index 355e520a..c5b222ac 100644
--- a/src/parser/mod.rs
+++ b/src/parser/mod.rs
@@ -6718,7 +6718,11 @@ impl<'a> Parser<'a> {
return self.expected("',' or ')' after column definition", self.peek_token());
};
- if rparen && (!comma || self.options.trailing_commas) {
+ if rparen
+ && (!comma
+ || self.dialect.supports_column_definition_trailing_commas()
+ || self.options.trailing_commas)
+ {
let _ = self.consume_token(&Token::RParen);
break;
}
@@ -9298,7 +9302,11 @@ impl<'a> Parser<'a> {
self.next_token();
Ok(vec![])
} else {
- let cols = self.parse_comma_separated(Parser::parse_view_column)?;
+ let cols = self.parse_comma_separated_with_trailing_commas(
+ Parser::parse_view_column,
+ self.dialect.supports_column_definition_trailing_commas(),
+ None,
+ )?;
self.expect_token(&Token::RParen)?;
Ok(cols)
}
diff --git a/tests/sqlparser_common.rs b/tests/sqlparser_common.rs
index ebd6bef0..e1ef2f90 100644
--- a/tests/sqlparser_common.rs
+++ b/tests/sqlparser_common.rs
@@ -10189,15 +10189,19 @@ fn parse_trailing_comma() {
"Expected: column name or constraint definition, found: )".to_string()
)
);
+
+ let unsupported_dialects = all_dialects_where(|d| !d.supports_trailing_commas());
+ assert_eq!(
+ unsupported_dialects
+ .parse_sql_statements("SELECT * FROM track ORDER BY milliseconds,")
+ .unwrap_err(),
+ ParserError::ParserError("Expected: an expression, found: EOF".to_string())
+ );
}
#[test]
fn parse_projection_trailing_comma() {
- // Some dialects allow trailing commas only in the projection
- let trailing_commas = TestedDialects::new(vec![
- Box::new(SnowflakeDialect {}),
- Box::new(BigQueryDialect {}),
- ]);
+ let trailing_commas = all_dialects_where(|d| d.supports_projection_trailing_commas());
trailing_commas.one_statement_parses_to(
"SELECT album_id, name, FROM track",
@@ -10210,20 +10214,14 @@ fn parse_projection_trailing_comma() {
trailing_commas.verified_stmt("SELECT DISTINCT ON (album_id) name FROM track");
+ let unsupported_dialects = all_dialects_where(|d| {
+ !d.supports_projection_trailing_commas() && !d.supports_trailing_commas()
+ });
assert_eq!(
- trailing_commas
- .parse_sql_statements("SELECT * FROM track ORDER BY milliseconds,")
+ unsupported_dialects
+ .parse_sql_statements("SELECT album_id, name, FROM track")
.unwrap_err(),
- ParserError::ParserError("Expected: an expression, found: EOF".to_string())
- );
-
- assert_eq!(
- trailing_commas
- .parse_sql_statements("CREATE TABLE employees (name text, age int,)")
- .unwrap_err(),
- ParserError::ParserError(
- "Expected: column name or constraint definition, found: )".to_string()
- ),
+ ParserError::ParserError("Expected an expression, found: FROM".to_string())
);
}
@@ -13061,6 +13059,33 @@ fn parse_overlaps() {
verified_stmt("SELECT (DATE '2016-01-10', DATE '2016-02-01') OVERLAPS (DATE '2016-01-20', DATE '2016-02-10')");
}
+#[test]
+fn parse_column_definition_trailing_commas() {
+ let dialects = all_dialects_where(|d| d.supports_column_definition_trailing_commas());
+
+ dialects.one_statement_parses_to("CREATE TABLE T (x INT64,)", "CREATE TABLE T (x INT64)");
+ dialects.one_statement_parses_to(
+ "CREATE TABLE T (x INT64, y INT64, )",
+ "CREATE TABLE T (x INT64, y INT64)",
+ );
+ dialects.one_statement_parses_to(
+ "CREATE VIEW T (x, y, ) AS SELECT 1",
+ "CREATE VIEW T (x, y) AS SELECT 1",
+ );
+
+ let unsupported_dialects = all_dialects_where(|d| {
+ !d.supports_projection_trailing_commas() && !d.supports_trailing_commas()
+ });
+ assert_eq!(
+ unsupported_dialects
+ .parse_sql_statements("CREATE TABLE employees (name text, age int,)")
+ .unwrap_err(),
+ ParserError::ParserError(
+ "Expected: column name or constraint definition, found: )".to_string()
+ ),
+ );
+}
+
#[test]
fn test_trailing_commas_in_from() {
let dialects = all_dialects_where(|d| d.supports_from_trailing_commas());
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@datafusion.apache.org
For additional commands, e-mail: commits-help@datafusion.apache.org