@@ -2203,6 +2203,90 @@ fn parse_big_query_declare() {
22032203 ) ;
22042204}
22052205
2206+ #[ test]
2207+ fn parse_bigquery_create_external_table_with_connection_and_options ( ) {
2208+ let sql = concat ! (
2209+ "CREATE OR REPLACE EXTERNAL TABLE `proj.ds.tbl` " ,
2210+ "WITH CONNECTION `projects/proj/locations/us/connections/c` " ,
2211+ r#"OPTIONS(format = "ICEBERG", uris = ["gs://b/m.json"])"# ,
2212+ ) ;
2213+ let stmts = bigquery ( ) . parse_sql_statements ( sql) . unwrap ( ) ;
2214+ assert_eq ! ( stmts. len( ) , 1 ) ;
2215+ let Statement :: CreateTable ( ct) = & stmts[ 0 ] else {
2216+ panic ! ( "expected CreateTable, got {:?}" , stmts[ 0 ] ) ;
2217+ } ;
2218+ assert ! ( ct. external) ;
2219+ assert ! ( ct. or_replace) ;
2220+ assert ! ( ct. columns. is_empty( ) ) ;
2221+ let with_connection = ct. with_connection . as_ref ( ) . expect ( "with_connection set" ) ;
2222+ assert_eq ! (
2223+ with_connection. to_string( ) ,
2224+ "`projects/proj/locations/us/connections/c`"
2225+ ) ;
2226+ let CreateTableOptions :: Options ( opts) = & ct. table_options else {
2227+ panic ! ( "expected OPTIONS, got {:?}" , ct. table_options) ;
2228+ } ;
2229+ assert_eq ! ( opts. len( ) , 2 ) ;
2230+ }
2231+
2232+ #[ test]
2233+ fn parse_bigquery_create_external_table_with_connection_variants ( ) {
2234+ // WITH CONNECTION alone — no OPTIONS, no explicit column list.
2235+ // Display normalizes the bare form by adding an empty column list, so
2236+ // use `one_statement_parses_to` to assert the normalized output.
2237+ let stmt = bigquery ( ) . one_statement_parses_to (
2238+ "CREATE EXTERNAL TABLE t WITH CONNECTION c" ,
2239+ "CREATE EXTERNAL TABLE t () WITH CONNECTION c" ,
2240+ ) ;
2241+ let Statement :: CreateTable ( ct) = stmt else {
2242+ panic ! ( "expected CreateTable" ) ;
2243+ } ;
2244+ assert ! ( ct. external) ;
2245+ assert ! ( !ct. or_replace) ;
2246+ assert ! ( ct. columns. is_empty( ) ) ;
2247+ assert_eq ! (
2248+ ct. with_connection
2249+ . as_ref( )
2250+ . expect( "with_connection set" )
2251+ . to_string( ) ,
2252+ "c"
2253+ ) ;
2254+ assert ! ( matches!( ct. table_options, CreateTableOptions :: None ) ) ;
2255+
2256+ // With explicit columns + OPTIONS. Exercises the Display round-trip of
2257+ // the `(columns) WITH CONNECTION <name> OPTIONS(...)` ordering so a
2258+ // future refactor that reshuffles clause order will fail this test.
2259+ let sql = concat ! (
2260+ "CREATE EXTERNAL TABLE t (a INT64, b STRING) " ,
2261+ r#"WITH CONNECTION c OPTIONS(uris = ["gs://x"])"# ,
2262+ ) ;
2263+ let stmt = bigquery ( ) . verified_stmt ( sql) ;
2264+ let Statement :: CreateTable ( ct) = stmt else {
2265+ panic ! ( "expected CreateTable" ) ;
2266+ } ;
2267+ assert_eq ! ( ct. columns. len( ) , 2 ) ;
2268+ assert_eq ! (
2269+ ct. with_connection
2270+ . as_ref( )
2271+ . expect( "with_connection set" )
2272+ . to_string( ) ,
2273+ "c"
2274+ ) ;
2275+ let CreateTableOptions :: Options ( opts) = & ct. table_options else {
2276+ panic ! ( "expected OPTIONS, got {:?}" , ct. table_options) ;
2277+ } ;
2278+ assert_eq ! ( opts. len( ) , 1 ) ;
2279+
2280+ // Baseline: no WITH CONNECTION. The new parser branch must not produce
2281+ // a spurious with_connection when the keyword pair is absent.
2282+ let stmt =
2283+ bigquery ( ) . verified_stmt ( "CREATE EXTERNAL TABLE t (a INT64) OPTIONS(uris = [\" gs://x\" ])" ) ;
2284+ let Statement :: CreateTable ( ct) = stmt else {
2285+ panic ! ( "expected CreateTable" ) ;
2286+ } ;
2287+ assert ! ( ct. with_connection. is_none( ) ) ;
2288+ }
2289+
22062290fn bigquery ( ) -> TestedDialects {
22072291 TestedDialects :: new ( vec ! [ Box :: new( BigQueryDialect { } ) ] )
22082292}
0 commit comments