Skip to content

Commit 30882da

Browse files
committed
Fix: Always force recreation of materialized views
1 parent 31763bf commit 30882da

File tree

3 files changed

+58
-52
lines changed

3 files changed

+58
-52
lines changed

sqlmesh/core/snapshot/evaluator.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2087,11 +2087,7 @@ def insert(
20872087
render_kwargs: t.Dict[str, t.Any],
20882088
**kwargs: t.Any,
20892089
) -> None:
2090-
deployability_index = (
2091-
kwargs.get("deployability_index") or DeployabilityIndex.all_deployable()
2092-
)
20932090
snapshot = kwargs["snapshot"]
2094-
snapshots = kwargs["snapshots"]
20952091

20962092
if (
20972093
not snapshot.is_materialized_view
@@ -2106,7 +2102,7 @@ def insert(
21062102
table_name,
21072103
query_or_df,
21082104
model.columns_to_types,
2109-
replace=not self.adapter.HAS_VIEW_BINDING,
2105+
replace=snapshot.is_materialized_view or not self.adapter.HAS_VIEW_BINDING,
21102106
materialized=self._is_materialized_view(model),
21112107
view_properties=kwargs.get("physical_properties", model.physical_properties),
21122108
table_description=model.description,

tests/core/engine_adapter/integration/test_integration.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3550,3 +3550,60 @@ def test_identifier_length_limit(ctx: TestContext):
35503550
match=re.escape(match),
35513551
):
35523552
adapter.create_table(long_table_name, {"col": exp.DataType.build("int")})
3553+
3554+
3555+
def test_materialized_view_evaluation(ctx: TestContext):
3556+
adapter = ctx.engine_adapter
3557+
dialect = ctx.dialect
3558+
if not adapter.SUPPORTS_MATERIALIZED_VIEWS:
3559+
pytest.skip(f"Skipping engine {dialect} as it does not support materialized views")
3560+
3561+
elif dialect == "snowflake":
3562+
pytest.skip(
3563+
f"Skipping Snowflake as it requires an enterprise account for materialized views"
3564+
)
3565+
3566+
model_name = ctx.table("test_tbl")
3567+
mview_name = ctx.table("test_mview")
3568+
3569+
sqlmesh = ctx.create_context()
3570+
3571+
sqlmesh.upsert_model(
3572+
load_sql_based_model(
3573+
d.parse(
3574+
f"""
3575+
MODEL (name {model_name}, kind FULL);
3576+
3577+
SELECT 1 AS col
3578+
"""
3579+
)
3580+
)
3581+
)
3582+
3583+
sqlmesh.upsert_model(
3584+
load_sql_based_model(
3585+
d.parse(
3586+
f"""
3587+
MODEL (name {mview_name}, kind VIEW (materialized true));
3588+
3589+
SELECT * FROM {model_name}
3590+
"""
3591+
)
3592+
)
3593+
)
3594+
3595+
# Case 1: Ensure that plan is successful and we can query the materialized view
3596+
sqlmesh.plan(auto_apply=True, no_prompts=True)
3597+
3598+
df = adapter.fetchdf(f"SELECT * FROM {mview_name.sql(dialect=dialect)}")
3599+
assert df["col"][0] == 1
3600+
3601+
# Case 2: Ensure that we can change the underlying table and the materialized view is recreated
3602+
sqlmesh.upsert_model(
3603+
load_sql_based_model(d.parse(f"""MODEL (name {model_name}, kind FULL); SELECT 2 AS col"""))
3604+
)
3605+
3606+
sqlmesh.plan(auto_apply=True, no_prompts=True)
3607+
3608+
df = adapter.fetchdf(f"SELECT * FROM {mview_name.sql(dialect=dialect)}")
3609+
assert df["col"][0] == 2

tests/core/engine_adapter/integration/test_integration_bigquery.py

Lines changed: 0 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -436,53 +436,6 @@ def test_table_diff_table_name_matches_column_name(ctx: TestContext):
436436
assert row_diff.full_match_count == 1
437437

438438

439-
def test_materialized_view_evaluation(ctx: TestContext, engine_adapter: BigQueryEngineAdapter):
440-
model_name = ctx.table("test_tbl")
441-
mview_name = ctx.table("test_mview")
442-
443-
sqlmesh = ctx.create_context()
444-
445-
sqlmesh.upsert_model(
446-
load_sql_based_model(
447-
d.parse(
448-
f"""
449-
MODEL (name {model_name}, kind FULL);
450-
451-
SELECT 1 AS col
452-
"""
453-
)
454-
)
455-
)
456-
457-
sqlmesh.upsert_model(
458-
load_sql_based_model(
459-
d.parse(
460-
f"""
461-
MODEL (name {mview_name}, kind VIEW (materialized true));
462-
463-
SELECT * FROM {model_name}
464-
"""
465-
)
466-
)
467-
)
468-
469-
# Case 1: Ensure that plan is successful and we can query the materialized view
470-
sqlmesh.plan(auto_apply=True, no_prompts=True)
471-
472-
df = engine_adapter.fetchdf(f"SELECT * FROM {mview_name.sql(dialect=ctx.dialect)}")
473-
assert df["col"][0] == 1
474-
475-
# Case 2: Ensure that we can change the underlying table and the materialized view is recreated
476-
sqlmesh.upsert_model(
477-
load_sql_based_model(d.parse(f"""MODEL (name {model_name}, kind FULL); SELECT 2 AS col"""))
478-
)
479-
480-
sqlmesh.plan(auto_apply=True, no_prompts=True)
481-
482-
df = engine_adapter.fetchdf(f"SELECT * FROM {mview_name.sql(dialect=ctx.dialect)}")
483-
assert df["col"][0] == 2
484-
485-
486439
def test_correlation_id_in_job_labels(ctx: TestContext):
487440
model_name = ctx.table("test")
488441

0 commit comments

Comments
 (0)