diff --git a/sqlglot/dialects/bigquery.py b/sqlglot/dialects/bigquery.py index 352da79093..7473d8f98e 100644 --- a/sqlglot/dialects/bigquery.py +++ b/sqlglot/dialects/bigquery.py @@ -1245,7 +1245,12 @@ def contains_sql(self, expression: exp.Contains) -> str: def cast_sql(self, expression: exp.Cast, safe_prefix: t.Optional[str] = None) -> str: this = expression.this + # This ensures that inline type-annotated ARRAY literals like ARRAY[1, 2, 3] + # are roundtripped unaffected. The inner check excludes ARRAY(SELECt ...) expressions, + # because they aren't literals and so the above syntax is invalid BigQuery. if isinstance(this, exp.Array): - return f"{self.sql(expression, 'to')}{self.sql(this)}" + elem = seq_get(this.expressions, 0) + if not (elem and elem.find(exp.Query)): + return f"{self.sql(expression, 'to')}{self.sql(this)}" return super().cast_sql(expression, safe_prefix=safe_prefix) diff --git a/tests/dialects/test_bigquery.py b/tests/dialects/test_bigquery.py index b4e4793249..1f36fe4f4f 100644 --- a/tests/dialects/test_bigquery.py +++ b/tests/dialects/test_bigquery.py @@ -234,6 +234,10 @@ def test_bigquery(self): self.validate_identity( "CREATE OR REPLACE VIEW test (tenant_id OPTIONS (description='Test description on table creation')) AS SELECT 1 AS tenant_id, 1 AS customer_id", ) + self.validate_identity( + "ARRAY(SELECT AS STRUCT e.x AS y, e.z AS bla FROM UNNEST(bob))::ARRAY>", + "CAST(ARRAY(SELECT AS STRUCT e.x AS y, e.z AS bla FROM UNNEST(bob)) AS ARRAY>)", + ) self.validate_identity( "SELECT * FROM `proj.dataset.INFORMATION_SCHEMA.SOME_VIEW`", "SELECT * FROM `proj.dataset.INFORMATION_SCHEMA.SOME_VIEW` AS `proj.dataset.INFORMATION_SCHEMA.SOME_VIEW`",