Skip to content

Commit 7c78d13

Browse files
authored
BigQuery: Parse WITH CONNECTION on CREATE EXTERNAL TABLE (apache#2326)
1 parent 79f06bd commit 7c78d13

8 files changed

Lines changed: 54 additions & 0 deletions

File tree

src/ast/ddl.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3020,6 +3020,9 @@ pub struct CreateTable {
30203020
/// Snowflake "EXTERNAL_VOLUME" clause for Iceberg tables
30213021
/// <https://docs.snowflake.com/en/sql-reference/sql/create-iceberg-table>
30223022
pub external_volume: Option<String>,
3023+
/// `WITH CONNECTION` clause.
3024+
/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_external_table_statement)
3025+
pub with_connection: Option<ObjectName>,
30233026
/// Snowflake "BASE_LOCATION" clause for Iceberg tables
30243027
/// <https://docs.snowflake.com/en/sql-reference/sql/create-iceberg-table>
30253028
pub base_location: Option<String>,
@@ -3269,6 +3272,9 @@ impl fmt::Display for CreateTable {
32693272
if let Some(cluster_by) = self.cluster_by.as_ref() {
32703273
write!(f, " CLUSTER BY {cluster_by}")?;
32713274
}
3275+
if let Some(with_connection) = &self.with_connection {
3276+
write!(f, " WITH CONNECTION {with_connection}")?;
3277+
}
32723278
if let options @ CreateTableOptions::Options(_) = &self.table_options {
32733279
write!(f, " {options}")?;
32743280
}

src/ast/helpers/stmt_create_table.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,9 @@ pub struct CreateTableBuilder {
157157
pub base_location: Option<String>,
158158
/// Optional external volume identifier.
159159
pub external_volume: Option<String>,
160+
/// `WITH CONNECTION` clause.
161+
/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_external_table_statement)
162+
pub with_connection: Option<ObjectName>,
160163
/// Optional catalog name.
161164
pub catalog: Option<String>,
162165
/// Optional catalog synchronization option.
@@ -241,6 +244,7 @@ impl CreateTableBuilder {
241244
with_tags: None,
242245
base_location: None,
243246
external_volume: None,
247+
with_connection: None,
244248
catalog: None,
245249
catalog_sync: None,
246250
storage_serialization_policy: None,
@@ -497,6 +501,11 @@ impl CreateTableBuilder {
497501
self.external_volume = external_volume;
498502
self
499503
}
504+
/// Set the `WITH CONNECTION` clause.
505+
pub fn with_connection(mut self, with_connection: Option<ObjectName>) -> Self {
506+
self.with_connection = with_connection;
507+
self
508+
}
500509
/// Set the catalog name for the table.
501510
pub fn catalog(mut self, catalog: Option<String>) -> Self {
502511
self.catalog = catalog;
@@ -630,6 +639,7 @@ impl CreateTableBuilder {
630639
with_tags: self.with_tags,
631640
base_location: self.base_location,
632641
external_volume: self.external_volume,
642+
with_connection: self.with_connection,
633643
catalog: self.catalog,
634644
catalog_sync: self.catalog_sync,
635645
storage_serialization_policy: self.storage_serialization_policy,
@@ -714,6 +724,7 @@ impl From<CreateTable> for CreateTableBuilder {
714724
with_tags: table.with_tags,
715725
base_location: table.base_location,
716726
external_volume: table.external_volume,
727+
with_connection: table.with_connection,
717728
catalog: table.catalog,
718729
catalog_sync: table.catalog_sync,
719730
storage_serialization_policy: table.storage_serialization_policy,

src/ast/spans.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -589,6 +589,7 @@ impl Spanned for CreateTable {
589589
with_storage_lifecycle_policy: _, // todo, Snowflake specific
590590
with_tags: _, // todo, Snowflake specific
591591
external_volume: _, // todo, Snowflake specific
592+
with_connection: _, // todo, BigQuery external table connection
592593
base_location: _, // todo, Snowflake specific
593594
catalog: _, // todo, Snowflake specific
594595
catalog_sync: _, // todo, Snowflake specific

src/parser/mod.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6418,6 +6418,12 @@ impl<'a> Parser<'a> {
64186418
None
64196419
};
64206420
let location = hive_formats.as_ref().and_then(|hf| hf.location.clone());
6421+
6422+
let with_connection = if self.parse_keywords(&[Keyword::WITH, Keyword::CONNECTION]) {
6423+
Some(self.parse_object_name(false)?)
6424+
} else {
6425+
None
6426+
};
64216427
let table_properties = self.parse_options(Keyword::TBLPROPERTIES)?;
64226428
let table_options = if !table_properties.is_empty() {
64236429
CreateTableOptions::TableProperties(table_properties)
@@ -6432,6 +6438,7 @@ impl<'a> Parser<'a> {
64326438
.hive_distribution(hive_distribution)
64336439
.hive_formats(hive_formats)
64346440
.table_options(table_options)
6441+
.with_connection(with_connection)
64356442
.or_replace(or_replace)
64366443
.if_not_exists(if_not_exists)
64376444
.external(true)

tests/sqlparser_bigquery.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2203,6 +2203,31 @@ fn parse_big_query_declare() {
22032203
);
22042204
}
22052205

2206+
#[test]
2207+
fn parse_bigquery_create_external_table_with_connection() {
2208+
bigquery().one_statement_parses_to(
2209+
concat!(
2210+
"CREATE OR REPLACE EXTERNAL TABLE `proj.ds.tbl` ",
2211+
"WITH CONNECTION `projects/proj/locations/us/connections/c` ",
2212+
r#"OPTIONS(format = "ICEBERG", uris = ["gs://b/m.json"])"#,
2213+
),
2214+
concat!(
2215+
"CREATE OR REPLACE EXTERNAL TABLE `proj`.`ds`.`tbl` () ",
2216+
"WITH CONNECTION `projects/proj/locations/us/connections/c` ",
2217+
r#"OPTIONS(format = "ICEBERG", uris = ["gs://b/m.json"])"#,
2218+
),
2219+
);
2220+
bigquery().one_statement_parses_to(
2221+
"CREATE EXTERNAL TABLE t WITH CONNECTION c",
2222+
"CREATE EXTERNAL TABLE t () WITH CONNECTION c",
2223+
);
2224+
bigquery().verified_stmt(concat!(
2225+
"CREATE EXTERNAL TABLE t (a INT64, b STRING) ",
2226+
r#"WITH CONNECTION c OPTIONS(uris = ["gs://x"])"#,
2227+
));
2228+
bigquery().verified_stmt(r#"CREATE EXTERNAL TABLE t (a INT64) OPTIONS(uris = ["gs://x"])"#);
2229+
}
2230+
22062231
fn bigquery() -> TestedDialects {
22072232
TestedDialects::new(vec![Box::new(BigQueryDialect {})])
22082233
}

tests/sqlparser_duckdb.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -780,6 +780,7 @@ fn test_duckdb_union_datatype() {
780780
with_tags: Default::default(),
781781
base_location: Default::default(),
782782
external_volume: Default::default(),
783+
with_connection: Default::default(),
783784
catalog: Default::default(),
784785
catalog_sync: Default::default(),
785786
storage_serialization_policy: Default::default(),

tests/sqlparser_mssql.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1999,6 +1999,7 @@ fn parse_create_table_with_valid_options() {
19991999
with_tags: None,
20002000
base_location: None,
20012001
external_volume: None,
2002+
with_connection: None,
20022003
catalog: None,
20032004
catalog_sync: None,
20042005
storage_serialization_policy: None,
@@ -2176,6 +2177,7 @@ fn parse_create_table_with_identity_column() {
21762177
with_tags: None,
21772178
base_location: None,
21782179
external_volume: None,
2180+
with_connection: None,
21792181
catalog: None,
21802182
catalog_sync: None,
21812183
storage_serialization_policy: None,

tests/sqlparser_postgres.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6702,6 +6702,7 @@ fn parse_trigger_related_functions() {
67026702
with_tags: None,
67036703
base_location: None,
67046704
external_volume: None,
6705+
with_connection: None,
67056706
catalog: None,
67066707
catalog_sync: None,
67076708
storage_serialization_policy: None,

0 commit comments

Comments
 (0)