diff --git a/sqlmesh/core/model/meta.py b/sqlmesh/core/model/meta.py index 94956dff99..67ea32f9d9 100644 --- a/sqlmesh/core/model/meta.py +++ b/sqlmesh/core/model/meta.py @@ -321,17 +321,19 @@ def _column_descriptions_validator( if isinstance(vs, (exp.Tuple, exp.Array)): vs = vs.expressions - raw_col_descriptions = ( - vs + # Normalize each part while it is still an identifier, so that a quoted + # column keeps its case on dialects where quoting makes it significant. + col_descriptions = ( + {normalize_identifiers(k, dialect=dialect).name: v for k, v in vs.items()} if isinstance(vs, dict) - else {".".join([part.this for part in v.this.parts]): v.expression.name for v in vs} + else { + ".".join( + normalize_identifiers(part, dialect=dialect).name for part in v.this.parts + ): v.expression.name + for v in vs + } ) - col_descriptions = { - normalize_identifiers(k, dialect=dialect).name: v - for k, v in raw_col_descriptions.items() - } - columns_to_types = data.get("columns_to_types_") if columns_to_types: from sqlmesh.core.console import get_console diff --git a/tests/core/test_model.py b/tests/core/test_model.py index 1f3cde265b..3de4ff2ebc 100644 --- a/tests/core/test_model.py +++ b/tests/core/test_model.py @@ -1000,6 +1000,32 @@ def test_column_descriptions(sushi_context, assert_exp_eq): assert model.column_descriptions == {"id": "primary key", "foo": "bar"} +def test_column_descriptions_quoted_identifier(): + expressions = d.parse( + """ + MODEL ( + name db.table, + kind FULL, + dialect snowflake, + column_descriptions ( + "myColumn" = 'a case-sensitive column', + other_column = 'an unquoted column' + ) + ); + + SELECT 1 AS "myColumn", 2 AS other_column + """ + ) + model = load_sql_based_model(expressions, dialect="snowflake") + + # A quoted key keeps its case, an unquoted one is still normalized. + assert model.column_descriptions == { + "myColumn": "a case-sensitive column", + "OTHER_COLUMN": "an unquoted column", + } + assert set(model.column_descriptions) <= set(model.columns_to_types) + + def test_model_jinja_macro_reference_extraction(): @macro() def test_macro(**kwargs) -> None: