Skip to content

Commit 9f318eb

Browse files
authored
feat(snowflake): Transpile BQ's ARRAY(SELECT AS STRUCT ...) (#5140)
* feat(snowflake): Transpile ARRAY(SELECT AS STRUCT ...) * Reuse existing selection
1 parent c484ca3 commit 9f318eb

File tree

2 files changed

+59
-1
lines changed

2 files changed

+59
-1
lines changed

sqlglot/dialects/snowflake.py

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1017,7 +1017,6 @@ class Generator(generator.Generator):
10171017
exp.ApproxDistinct: rename_func("APPROX_COUNT_DISTINCT"),
10181018
exp.ArgMax: rename_func("MAX_BY"),
10191019
exp.ArgMin: rename_func("MIN_BY"),
1020-
exp.Array: inline_array_sql,
10211020
exp.ArrayConcat: lambda self, e: self.arrayconcat_sql(e, name="ARRAY_CAT"),
10221021
exp.ArrayContains: lambda self, e: self.func("ARRAY_CONTAINS", e.expression, e.this),
10231022
exp.AtTimeZone: lambda self, e: self.func(
@@ -1427,3 +1426,29 @@ def arrayagg_sql(self, expression: exp.ArrayAgg) -> str:
14271426
expr_sql = self.sql(exp.WithinGroup(this=expr_sql, expression=order))
14281427

14291428
return expr_sql
1429+
1430+
def array_sql(self, expression: exp.Array) -> str:
1431+
expressions = expression.expressions
1432+
1433+
first_expr = seq_get(expressions, 0)
1434+
if isinstance(first_expr, exp.Select):
1435+
# SELECT AS STRUCT foo AS alias_foo -> ARRAY_AGG(OBJECT_CONSTRUCT('alias_foo', foo))
1436+
if first_expr.text("kind").upper() == "STRUCT":
1437+
object_construct_args = []
1438+
for expr in first_expr.expressions:
1439+
# Alias case: SELECT AS STRUCT foo AS alias_foo -> OBJECT_CONSTRUCT('alias_foo', foo)
1440+
# Column case: SELECT AS STRUCT foo -> OBJECT_CONSTRUCT('foo', foo)
1441+
name = expr.this if isinstance(expr, exp.Alias) else expr
1442+
1443+
object_construct_args.extend([exp.Literal.string(expr.alias_or_name), name])
1444+
1445+
array_agg = exp.ArrayAgg(
1446+
this=_build_object_construct(args=object_construct_args)
1447+
)
1448+
1449+
first_expr.set("kind", None)
1450+
first_expr.set("expressions", [array_agg])
1451+
1452+
return self.sql(first_expr.subquery())
1453+
1454+
return inline_array_sql(self, expression)

tests/dialects/test_bigquery.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2583,3 +2583,36 @@ def test_array_agg(self):
25832583
"snowflake": "SELECT ARRAY_AGG(x) WITHIN GROUP (ORDER BY col1 ASC NULLS FIRST, col2 DESC NULLS LAST)",
25842584
},
25852585
)
2586+
2587+
def test_select_as_struct(self):
2588+
self.validate_all(
2589+
"SELECT ARRAY(SELECT AS STRUCT x1 AS x1, x2 AS x2 FROM t) AS array_col",
2590+
write={
2591+
"bigquery": "SELECT ARRAY(SELECT AS STRUCT x1 AS x1, x2 AS x2 FROM t) AS array_col",
2592+
"snowflake": "SELECT (SELECT ARRAY_AGG(OBJECT_CONSTRUCT('x1', x1, 'x2', x2)) FROM t) AS array_col",
2593+
},
2594+
)
2595+
2596+
self.validate_all(
2597+
"WITH t1 AS (SELECT ARRAY(SELECT AS STRUCT x1 AS alias_x1, x2 /* test */ FROM t2) AS array_col) SELECT array_col[0].alias_x1, array_col[0].x2 FROM t1",
2598+
write={
2599+
"bigquery": "WITH t1 AS (SELECT ARRAY(SELECT AS STRUCT x1 AS alias_x1, x2 /* test */ FROM t2) AS array_col) SELECT array_col[0].alias_x1, array_col[0].x2 FROM t1",
2600+
"snowflake": "WITH t1 AS (SELECT (SELECT ARRAY_AGG(OBJECT_CONSTRUCT('alias_x1', x1, 'x2', x2 /* test */)) FROM t2) AS array_col) SELECT array_col[0].alias_x1, array_col[0].x2 FROM t1",
2601+
},
2602+
)
2603+
2604+
self.validate_all(
2605+
"WITH t1 AS (SELECT ARRAY(SELECT AS STRUCT 1 AS a, 2 AS b) AS array_col) SELECT array_col[0].a, array_col[0].b FROM t1",
2606+
write={
2607+
"bigquery": "WITH t1 AS (SELECT ARRAY(SELECT AS STRUCT 1 AS a, 2 AS b) AS array_col) SELECT array_col[0].a, array_col[0].b FROM t1",
2608+
"snowflake": "WITH t1 AS (SELECT (SELECT ARRAY_AGG(OBJECT_CONSTRUCT('a', 1, 'b', 2))) AS array_col) SELECT array_col[0].a, array_col[0].b FROM t1",
2609+
},
2610+
)
2611+
2612+
self.validate_all(
2613+
"WITH t1 AS (SELECT ARRAY(SELECT AS STRUCT x1 AS alias_x1, x2 /* test */ FROM t2 WHERE x2 = 4) AS array_col) SELECT array_col[0].alias_x1, array_col[0].x2 FROM t1",
2614+
write={
2615+
"bigquery": "WITH t1 AS (SELECT ARRAY(SELECT AS STRUCT x1 AS alias_x1, x2 /* test */ FROM t2 WHERE x2 = 4) AS array_col) SELECT array_col[0].alias_x1, array_col[0].x2 FROM t1",
2616+
"snowflake": "WITH t1 AS (SELECT (SELECT ARRAY_AGG(OBJECT_CONSTRUCT('alias_x1', x1, 'x2', x2 /* test */)) FROM t2 WHERE x2 = 4) AS array_col) SELECT array_col[0].alias_x1, array_col[0].x2 FROM t1",
2617+
},
2618+
)

0 commit comments

Comments
 (0)