Repository: TobikoData/sqlmesh
Pull request #2880 (2024-07-08 21:39:25)

Fix: normalize excluded columns in STAR macro, fix except_ logging
Context: https://tobiko-data.slack.com/archives/C044BRE5W4S/p1720460653564549?thread_ts=1720454069.814999&cid=C044BRE5W4S


Patch:
diff --git a/sqlmesh/core/macros.py b/sqlmesh/core/macros.py
index b99b6ff1..dda8bc1f 100644
--- a/sqlmesh/core/macros.py
+++ b/sqlmesh/core/macros.py
@@ -17,6 +17,7 @@ from sqlglot import Generator, exp, parse_one
 from sqlglot.executor.env import ENV
 from sqlglot.executor.python import Python
 from sqlglot.helper import csv, ensure_collection
+from sqlglot.optimizer.normalize_identifiers import normalize_identifiers
 from sqlglot.schema import MappingSchema
 
 from sqlmesh.core import constants as c
@@ -799,11 +800,11 @@ def star(
     evaluator: MacroEvaluator,
     relation: exp.Table,
     alias: exp.Column = t.cast(exp.Column, exp.column("")),
-    exclude: t.Union[exp.Array, exp.Tuple] = exp.Tuple(this=[]),
+    exclude: t.Union[exp.Array, exp.Tuple] = exp.Tuple(expressions=[]),
     prefix: exp.Literal = exp.Literal.string(""),
     suffix: exp.Literal = exp.Literal.string(""),
     quote_identifiers: exp.Boolean = exp.true(),
-    except_: t.Union[exp.Array, exp.Tuple] = exp.Tuple(this=[]),
+    except_: t.Union[exp.Array, exp.Tuple] = exp.Tuple(expressions=[]),
 ) -> t.List[exp.Alias]:
     """Returns a list of projections for the given relation.
 
@@ -832,7 +833,7 @@ def star(
         raise SQLMeshError(f"Invalid alias '{alias}'. Expected an identifier.")
     if exclude and not isinstance(exclude, (exp.Array, exp.Tuple)):
         raise SQLMeshError(f"Invalid exclude '{exclude}'. Expected an array.")
-    if except_:
+    if except_ != exp.tuple_():
         logger.warning(
             "The 'except_' argument in @STAR will soon be deprecated. Use 'exclude' instead."
         )
@@ -845,7 +846,10 @@ def star(
     if not isinstance(quote_identifiers, exp.Boolean):
         raise SQLMeshError(f"Invalid quote_identifiers '{quote_identifiers}'. Expected a boolean.")
 
-    excluded_names = {e.name for e in exclude.expressions or except_.expressions}
+    excluded_names = {
+        normalize_identifiers(excluded, dialect=evaluator.dialect).name
+        for excluded in exclude.expressions or except_.expressions
+    }
     quoted = quote_identifiers.this
     table_identifier = alias.name or relation.name
 


Test patch:
diff --git a/tests/core/test_macros.py b/tests/core/test_macros.py
index c290ff76..72bde9ce 100644
--- a/tests/core/test_macros.py
+++ b/tests/core/test_macros.py
@@ -110,6 +110,24 @@ def test_star(assert_exp_eq) -> None:
     evaluator = MacroEvaluator(schema=schema, dialect="tsql")
     assert_exp_eq(evaluator.transform(parse_one(sql, read="tsql")), expected_sql, dialect="tsql")
 
+    sql = """SELECT @STAR(foo, exclude := [SomeColumn]) FROM foo"""
+    expected_sql = "SELECT CAST(`foo`.`a` AS STRING) AS `a` FROM foo"
+    schema = MappingSchema(
+        {
+            "foo": {
+                "a": exp.DataType.build("string"),
+                "somecolumn": "int",
+            },
+        },
+        dialect="databricks",
+    )
+    evaluator = MacroEvaluator(schema=schema, dialect="databricks")
+    assert_exp_eq(
+        evaluator.transform(parse_one(sql, read="databricks")),
+        expected_sql,
+        dialect="databricks",
+    )
+
 
 def test_start_no_column_types(assert_exp_eq) -> None:
     sql = """SELECT @STAR(foo) FROM foo"""