You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@datafusion.apache.org by gi...@apache.org on 2026/05/06 14:57:55 UTC
(datafusion-sqlparser-rs) branch main updated: BigQuery: Parse WITH CONNECTION on CREATE EXTERNAL TABLE (#2326)
This is an automated email from the ASF dual-hosted git repository.
github-merge-queue[bot] 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 7c78d138 BigQuery: Parse WITH CONNECTION on CREATE EXTERNAL TABLE (#2326)
7c78d138 is described below
commit 7c78d138ae4b69359ad38b0996eda7de5e1a356b
Author: Corey Fritz <cf...@montecarlodata.com>
AuthorDate: Wed May 6 08:39:38 2026 -0600
BigQuery: Parse WITH CONNECTION on CREATE EXTERNAL TABLE (#2326)
---
src/ast/ddl.rs | 6 ++++++
src/ast/helpers/stmt_create_table.rs | 11 +++++++++++
src/ast/spans.rs | 1 +
src/parser/mod.rs | 7 +++++++
tests/sqlparser_bigquery.rs | 25 +++++++++++++++++++++++++
tests/sqlparser_duckdb.rs | 1 +
tests/sqlparser_mssql.rs | 2 ++
tests/sqlparser_postgres.rs | 1 +
8 files changed, 54 insertions(+)
diff --git a/src/ast/ddl.rs b/src/ast/ddl.rs
index 62a8a71a..0a93f5b7 100644
--- a/src/ast/ddl.rs
+++ b/src/ast/ddl.rs
@@ -3020,6 +3020,9 @@ pub struct CreateTable {
/// Snowflake "EXTERNAL_VOLUME" clause for Iceberg tables
/// <https://docs.snowflake.com/en/sql-reference/sql/create-iceberg-table>
pub external_volume: Option<String>,
+ /// `WITH CONNECTION` clause.
+ /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_external_table_statement)
+ pub with_connection: Option<ObjectName>,
/// Snowflake "BASE_LOCATION" clause for Iceberg tables
/// <https://docs.snowflake.com/en/sql-reference/sql/create-iceberg-table>
pub base_location: Option<String>,
@@ -3269,6 +3272,9 @@ impl fmt::Display for CreateTable {
if let Some(cluster_by) = self.cluster_by.as_ref() {
write!(f, " CLUSTER BY {cluster_by}")?;
}
+ if let Some(with_connection) = &self.with_connection {
+ write!(f, " WITH CONNECTION {with_connection}")?;
+ }
if let options @ CreateTableOptions::Options(_) = &self.table_options {
write!(f, " {options}")?;
}
diff --git a/src/ast/helpers/stmt_create_table.rs b/src/ast/helpers/stmt_create_table.rs
index fc81d3b8..9ec9ab28 100644
--- a/src/ast/helpers/stmt_create_table.rs
+++ b/src/ast/helpers/stmt_create_table.rs
@@ -157,6 +157,9 @@ pub struct CreateTableBuilder {
pub base_location: Option<String>,
/// Optional external volume identifier.
pub external_volume: Option<String>,
+ /// `WITH CONNECTION` clause.
+ /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_external_table_statement)
+ pub with_connection: Option<ObjectName>,
/// Optional catalog name.
pub catalog: Option<String>,
/// Optional catalog synchronization option.
@@ -241,6 +244,7 @@ impl CreateTableBuilder {
with_tags: None,
base_location: None,
external_volume: None,
+ with_connection: None,
catalog: None,
catalog_sync: None,
storage_serialization_policy: None,
@@ -497,6 +501,11 @@ impl CreateTableBuilder {
self.external_volume = external_volume;
self
}
+ /// Set the `WITH CONNECTION` clause.
+ pub fn with_connection(mut self, with_connection: Option<ObjectName>) -> Self {
+ self.with_connection = with_connection;
+ self
+ }
/// Set the catalog name for the table.
pub fn catalog(mut self, catalog: Option<String>) -> Self {
self.catalog = catalog;
@@ -630,6 +639,7 @@ impl CreateTableBuilder {
with_tags: self.with_tags,
base_location: self.base_location,
external_volume: self.external_volume,
+ with_connection: self.with_connection,
catalog: self.catalog,
catalog_sync: self.catalog_sync,
storage_serialization_policy: self.storage_serialization_policy,
@@ -714,6 +724,7 @@ impl From<CreateTable> for CreateTableBuilder {
with_tags: table.with_tags,
base_location: table.base_location,
external_volume: table.external_volume,
+ with_connection: table.with_connection,
catalog: table.catalog,
catalog_sync: table.catalog_sync,
storage_serialization_policy: table.storage_serialization_policy,
diff --git a/src/ast/spans.rs b/src/ast/spans.rs
index 343d99e7..f6ba8954 100644
--- a/src/ast/spans.rs
+++ b/src/ast/spans.rs
@@ -589,6 +589,7 @@ impl Spanned for CreateTable {
with_storage_lifecycle_policy: _, // todo, Snowflake specific
with_tags: _, // todo, Snowflake specific
external_volume: _, // todo, Snowflake specific
+ with_connection: _, // todo, BigQuery external table connection
base_location: _, // todo, Snowflake specific
catalog: _, // todo, Snowflake specific
catalog_sync: _, // todo, Snowflake specific
diff --git a/src/parser/mod.rs b/src/parser/mod.rs
index 3d4b3095..07497b04 100644
--- a/src/parser/mod.rs
+++ b/src/parser/mod.rs
@@ -6418,6 +6418,12 @@ impl<'a> Parser<'a> {
None
};
let location = hive_formats.as_ref().and_then(|hf| hf.location.clone());
+
+ let with_connection = if self.parse_keywords(&[Keyword::WITH, Keyword::CONNECTION]) {
+ Some(self.parse_object_name(false)?)
+ } else {
+ None
+ };
let table_properties = self.parse_options(Keyword::TBLPROPERTIES)?;
let table_options = if !table_properties.is_empty() {
CreateTableOptions::TableProperties(table_properties)
@@ -6432,6 +6438,7 @@ impl<'a> Parser<'a> {
.hive_distribution(hive_distribution)
.hive_formats(hive_formats)
.table_options(table_options)
+ .with_connection(with_connection)
.or_replace(or_replace)
.if_not_exists(if_not_exists)
.external(true)
diff --git a/tests/sqlparser_bigquery.rs b/tests/sqlparser_bigquery.rs
index 212607e0..f6d4483c 100644
--- a/tests/sqlparser_bigquery.rs
+++ b/tests/sqlparser_bigquery.rs
@@ -2203,6 +2203,31 @@ fn parse_big_query_declare() {
);
}
+#[test]
+fn parse_bigquery_create_external_table_with_connection() {
+ bigquery().one_statement_parses_to(
+ concat!(
+ "CREATE OR REPLACE EXTERNAL TABLE `proj.ds.tbl` ",
+ "WITH CONNECTION `projects/proj/locations/us/connections/c` ",
+ r#"OPTIONS(format = "ICEBERG", uris = ["gs://b/m.json"])"#,
+ ),
+ concat!(
+ "CREATE OR REPLACE EXTERNAL TABLE `proj`.`ds`.`tbl` () ",
+ "WITH CONNECTION `projects/proj/locations/us/connections/c` ",
+ r#"OPTIONS(format = "ICEBERG", uris = ["gs://b/m.json"])"#,
+ ),
+ );
+ bigquery().one_statement_parses_to(
+ "CREATE EXTERNAL TABLE t WITH CONNECTION c",
+ "CREATE EXTERNAL TABLE t () WITH CONNECTION c",
+ );
+ bigquery().verified_stmt(concat!(
+ "CREATE EXTERNAL TABLE t (a INT64, b STRING) ",
+ r#"WITH CONNECTION c OPTIONS(uris = ["gs://x"])"#,
+ ));
+ bigquery().verified_stmt(r#"CREATE EXTERNAL TABLE t (a INT64) OPTIONS(uris = ["gs://x"])"#);
+}
+
fn bigquery() -> TestedDialects {
TestedDialects::new(vec![Box::new(BigQueryDialect {})])
}
diff --git a/tests/sqlparser_duckdb.rs b/tests/sqlparser_duckdb.rs
index 548ad27c..86c76581 100644
--- a/tests/sqlparser_duckdb.rs
+++ b/tests/sqlparser_duckdb.rs
@@ -780,6 +780,7 @@ fn test_duckdb_union_datatype() {
with_tags: Default::default(),
base_location: Default::default(),
external_volume: Default::default(),
+ with_connection: Default::default(),
catalog: Default::default(),
catalog_sync: Default::default(),
storage_serialization_policy: Default::default(),
diff --git a/tests/sqlparser_mssql.rs b/tests/sqlparser_mssql.rs
index d784c74a..6e866746 100644
--- a/tests/sqlparser_mssql.rs
+++ b/tests/sqlparser_mssql.rs
@@ -1999,6 +1999,7 @@ fn parse_create_table_with_valid_options() {
with_tags: None,
base_location: None,
external_volume: None,
+ with_connection: None,
catalog: None,
catalog_sync: None,
storage_serialization_policy: None,
@@ -2176,6 +2177,7 @@ fn parse_create_table_with_identity_column() {
with_tags: None,
base_location: None,
external_volume: None,
+ with_connection: None,
catalog: None,
catalog_sync: None,
storage_serialization_policy: None,
diff --git a/tests/sqlparser_postgres.rs b/tests/sqlparser_postgres.rs
index 369e7fc5..11e76dbc 100644
--- a/tests/sqlparser_postgres.rs
+++ b/tests/sqlparser_postgres.rs
@@ -6702,6 +6702,7 @@ fn parse_trigger_related_functions() {
with_tags: None,
base_location: None,
external_volume: None,
+ with_connection: None,
catalog: None,
catalog_sync: None,
storage_serialization_policy: None,
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@datafusion.apache.org
For additional commands, e-mail: commits-help@datafusion.apache.org