diff --git a/examples/custom_materializations/pyproject.toml b/examples/custom_materializations/pyproject.toml index 70eb2d7f9e..fd233a9986 100644 --- a/examples/custom_materializations/pyproject.toml +++ b/examples/custom_materializations/pyproject.toml @@ -14,3 +14,6 @@ custom_full_with_custom_kind = "custom_materializations.custom_kind:CustomFullWi [tool.setuptools.packages.find] include = ["custom_materializations"] + +[tool.setuptools_scm] +fallback_version = "0.0.0" diff --git a/sqlmesh/core/macros.py b/sqlmesh/core/macros.py index a72bf4605a..af891a5460 100644 --- a/sqlmesh/core/macros.py +++ b/sqlmesh/core/macros.py @@ -653,7 +653,13 @@ def substitute( if len(items) == 1: item = items[0] - expressions = item.expressions if isinstance(item, (exp.Array, exp.Tuple)) else item + expressions = ( + item.expressions + if isinstance(item, (exp.Array, exp.Tuple)) + else [item.this] + if isinstance(item, exp.Paren) + else item + ) else: expressions = items diff --git a/tests/core/test_context.py b/tests/core/test_context.py index 6b98bf5d25..0f14fd4a8b 100644 --- a/tests/core/test_context.py +++ b/tests/core/test_context.py @@ -2198,13 +2198,13 @@ def test_plan_audit_intervals(tmp_path: pathlib.Path, caplog): # Case 1: The timestamp audit should be in the inclusive range ['2025-02-01 00:00:00', '2025-02-01 23:59:59.999999'] assert ( - f"""SELECT COUNT(*) FROM (SELECT ("timestamp_id") AS "timestamp_id" FROM (SELECT * FROM "sqlmesh__sqlmesh_audit"."sqlmesh_audit__timestamp_example__{timestamp_snapshot.version}" AS "sqlmesh_audit__timestamp_example__{timestamp_snapshot.version}" WHERE "timestamp_id" BETWEEN CAST('2025-02-01 00:00:00' AS TIMESTAMP) AND CAST('2025-02-01 23:59:59.999999' AS TIMESTAMP)) AS "_q_0" WHERE TRUE GROUP BY ("timestamp_id") HAVING COUNT(*) > 1) AS "audit\"""" + f"""SELECT COUNT(*) FROM (SELECT "timestamp_id" AS "timestamp_id" FROM (SELECT * FROM "sqlmesh__sqlmesh_audit"."sqlmesh_audit__timestamp_example__{timestamp_snapshot.version}" AS "sqlmesh_audit__timestamp_example__{timestamp_snapshot.version}" WHERE "timestamp_id" BETWEEN CAST('2025-02-01 00:00:00' AS TIMESTAMP) AND CAST('2025-02-01 23:59:59.999999' AS TIMESTAMP)) AS "_q_0" WHERE TRUE GROUP BY "timestamp_id" HAVING COUNT(*) > 1) AS "audit\"""" in caplog.text ) # Case 2: The date audit should be in the inclusive range ['2025-02-01', '2025-02-01'] assert ( - f"""SELECT COUNT(*) FROM (SELECT ("date_id") AS "date_id" FROM (SELECT * FROM "sqlmesh__sqlmesh_audit"."sqlmesh_audit__date_example__{date_snapshot.version}" AS "sqlmesh_audit__date_example__{date_snapshot.version}" WHERE "date_id" BETWEEN CAST('2025-02-01' AS DATE) AND CAST('2025-02-01' AS DATE)) AS "_q_0" WHERE TRUE GROUP BY ("date_id") HAVING COUNT(*) > 1) AS "audit\"""" + f"""SELECT COUNT(*) FROM (SELECT "date_id" AS "date_id" FROM (SELECT * FROM "sqlmesh__sqlmesh_audit"."sqlmesh_audit__date_example__{date_snapshot.version}" AS "sqlmesh_audit__date_example__{date_snapshot.version}" WHERE "date_id" BETWEEN CAST('2025-02-01' AS DATE) AND CAST('2025-02-01' AS DATE)) AS "_q_0" WHERE TRUE GROUP BY "date_id" HAVING COUNT(*) > 1) AS "audit\"""" in caplog.text ) diff --git a/tests/core/test_model.py b/tests/core/test_model.py index 14c29165b7..1ba14a4aff 100644 --- a/tests/core/test_model.py +++ b/tests/core/test_model.py @@ -55,6 +55,7 @@ create_seed_model, create_sql_model, load_sql_based_model, + load_sql_based_models, model, ) from sqlmesh.core.model.common import parse_expression @@ -11096,3 +11097,61 @@ def test_render_query_optimize_query_false(assert_exp_eq, sushi_context): LIMIT 10 """, ) + + +def test_each_macro_with_paren_expression_arg(assert_exp_eq): + expressions = d.parse( + """ + MODEL ( + name dataset.@table_name, + kind VIEW, + blueprints ( + ( + table_name := model1, + event_columns := ( + 'value' AS property1, + 'value' AS property2 + ) + ), + ( + table_name := model2, + event_columns := ( + 'value' AS property1 + ) + ) + ), + ); + + SELECT @EACH(@event_columns, x -> x) + """ + ) + + models = load_sql_based_models(expressions, lambda _: {}) + + # Should generate 2 models from the blueprints + assert len(models) == 2 + + # Get the models sorted by name for consistent testing + model1 = next(m for m in models if "model1" in m.name) + model2 = next(m for m in models if "model2" in m.name) + + # Verify model names + assert model1.name == "dataset.model1" + assert model2.name == "dataset.model2" + + assert_exp_eq( + model1.render_query(), + """ + SELECT + 'value' AS "property1", + 'value' AS "property2" + """, + ) + + assert_exp_eq( + model2.render_query(), + """ + SELECT + 'value' AS "property1" + """, + )