@@ -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
0 commit comments