Skip to content

Commit e46caec

Browse files
authored
Fix: Create empty physical tables for fully annotated self-referential models (#5391)
1 parent d26c779 commit e46caec

File tree

2 files changed

+32
-2
lines changed

2 files changed

+32
-2
lines changed

sqlmesh/core/snapshot/evaluator.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -746,11 +746,15 @@ def _evaluate_snapshot(
746746
adapter.execute(model.render_pre_statements(**render_statements_kwargs))
747747

748748
if not target_table_exists or (model.is_seed and not snapshot.intervals):
749-
columns_to_types_provided = (
749+
# Only create the empty table if the columns were provided explicitly by the user
750+
should_create_empty_table = (
750751
model.kind.is_materialized
751752
and model.columns_to_types_
752753
and columns_to_types_all_known(model.columns_to_types_)
753754
)
755+
if not should_create_empty_table:
756+
# Or if the model is self-referential and its query is fully annotated with types
757+
should_create_empty_table = model.depends_on_self and model.annotated
754758
if self._can_clone(snapshot, deployability_index):
755759
self._clone_snapshot_in_dev(
756760
snapshot=snapshot,
@@ -763,7 +767,7 @@ def _evaluate_snapshot(
763767
)
764768
runtime_stage = RuntimeStage.EVALUATING
765769
target_table_exists = True
766-
elif columns_to_types_provided or model.is_seed or model.kind.is_scd_type_2:
770+
elif should_create_empty_table or model.is_seed or model.kind.is_scd_type_2:
767771
self._execute_create(
768772
snapshot=snapshot,
769773
table_name=target_table_name,

tests/core/test_integration.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -980,6 +980,32 @@ def test_new_forward_only_model(init_and_plan_context: t.Callable):
980980
assert context.engine_adapter.table_exists(snapshot.table_name(is_deployable=False))
981981

982982

983+
@time_machine.travel("2023-01-08 00:00:00 UTC")
984+
def test_annotated_self_referential_model(init_and_plan_context: t.Callable):
985+
context, _ = init_and_plan_context("examples/sushi")
986+
987+
# Projections are fully annotated in the query but columns were not specified explicitly
988+
expressions = d.parse(
989+
f"""
990+
MODEL (
991+
name memory.sushi.test_self_ref,
992+
kind FULL,
993+
start '2023-01-01',
994+
);
995+
996+
SELECT 1::INT AS one FROM memory.sushi.test_self_ref;
997+
"""
998+
)
999+
model = load_sql_based_model(expressions)
1000+
assert model.depends_on_self
1001+
context.upsert_model(model)
1002+
1003+
context.plan("prod", skip_tests=True, no_prompts=True, auto_apply=True)
1004+
1005+
df = context.fetchdf("SELECT one FROM memory.sushi.test_self_ref")
1006+
assert len(df) == 0
1007+
1008+
9831009
@time_machine.travel("2023-01-08 15:00:00 UTC")
9841010
def test_plan_set_choice_is_reflected_in_missing_intervals(init_and_plan_context: t.Callable):
9851011
context, _ = init_and_plan_context("examples/sushi")

0 commit comments

Comments
 (0)