Repository navigation
Conversation
Generator.struct_sql passed every PropertyEQ key to exp.alias_, which only accepts a string or an Identifier, so generating a struct whose keys are expressions raised ValueError. Snowflake allows arbitrary OBJECT_CONSTRUCT key expressions and sqlglot itself emits OBJECT_CONSTRUCT(1, 2) for MAP(ARRAY(1), ARRAY(2)), which then failed to transpile to bigquery, postgres, spark and the default dialect. Other keys now become the field name through exp.to_identifier(self.sql(key)), as the DuckDB generator already does. [DEEPSEEK]
|
PR motivating claim "Snowflake allows arbitrary expressions as OBJECT_CONSTRUCT keys" is not correct https://docs.snowflake.com/en/sql-reference/functions/object_construct |
|
You are right, and thanks for the correction - Snowflake keys are VARCHAR values, so The one part that still reproduces from valid input is on sqlglot's own side: |
Generator.struct_sqlhands every struct key toexp.alias_, which only accepts a string or anIdentifier, so generating a struct whose keys are expressions raises:Snowflake allows arbitrary expressions as
OBJECT_CONSTRUCTkeys, and sqlglot itself produces thatinput:
MAP(ARRAY(1), ARRAY(2))in snowflake round-trips toOBJECT_CONSTRUCT(1, 2), which thencannot be transpiled to bigquery, postgres, spark or the default dialect. It reproduces on 30.24.0
too, so this is long-standing rather than a new regression. The DuckDB generator already handles such
keys, which is where the shape of the fix comes from.
The fix keeps the existing string-literal and identifier branches and uses
exp.to_identifier(self.sql(key))as the field name for any other key:OBJECT_CONSTRUCT(1, 2)becomes
STRUCT(2 AS `1`)for bigquery/spark andSTRUCT(2 AS "1")for postgres/default, withduckdb and snowflake output unchanged.
Tests:
tests/dialects/test_snowflake.pygains twovalidate_allcases (a literal key and a columnkey across bigquery/duckdb/postgres/spark/snowflake/default) next to the existing
OBJECT_CONSTRUCT(a, b, c, d)test — 8 failures in that file before the fix, 107 passed / 1641subtests after, and the full suite is 1416 passed / 22121 subtests.
ruff check,ruff format --checkandmypy sqlglot/generator.pyare clean.Disclosure: prepared with an AI coding agent (DeepSeek); the repro, the red/green runs and the final
diff were reviewed before opening this.