@@ -2918,6 +2918,81 @@ def test_virtual_environment_mode_dev_only_model_kind_change_manual_categorizati
29182918 ]
29192919
29202920
2921+ @time_machine .travel ("2023-01-08 15:00:00 UTC" )
2922+ def test_virtual_environment_mode_dev_only_seed_model_change (
2923+ init_and_plan_context : t .Callable ,
2924+ ):
2925+ context , _ = init_and_plan_context (
2926+ "examples/sushi" , config = "test_config_virtual_environment_mode_dev_only"
2927+ )
2928+ context .load ()
2929+ context .plan ("prod" , auto_apply = True , no_prompts = True )
2930+
2931+ seed_model = context .get_model ("sushi.waiter_names" )
2932+ with open (seed_model .seed_path , "a" ) as fd :
2933+ fd .write ("\n 123,New Test Name" )
2934+
2935+ context .load ()
2936+ seed_model_snapshot = context .get_snapshot ("sushi.waiter_names" )
2937+ plan = context .plan_builder ("dev" ).build ()
2938+ assert plan .directly_modified == {seed_model_snapshot .snapshot_id }
2939+ assert len (plan .missing_intervals ) == 2
2940+ context .apply (plan )
2941+
2942+ actual_seed_df_in_dev = context .fetchdf ("SELECT * FROM sushi__dev.waiter_names WHERE id = 123" )
2943+ assert actual_seed_df_in_dev .to_dict ("records" ) == [{"id" : 123 , "name" : "New Test Name" }]
2944+ actual_seed_df_in_prod = context .fetchdf ("SELECT * FROM sushi.waiter_names WHERE id = 123" )
2945+ assert actual_seed_df_in_prod .empty
2946+
2947+ plan = context .plan_builder ("prod" ).build ()
2948+ assert plan .directly_modified == {seed_model_snapshot .snapshot_id }
2949+ assert len (plan .missing_intervals ) == 1
2950+ assert plan .missing_intervals [0 ].snapshot_id == seed_model_snapshot .snapshot_id
2951+ context .apply (plan )
2952+
2953+ actual_seed_df_in_prod = context .fetchdf ("SELECT * FROM sushi.waiter_names WHERE id = 123" )
2954+ assert actual_seed_df_in_prod .to_dict ("records" ) == [{"id" : 123 , "name" : "New Test Name" }]
2955+
2956+
2957+ @time_machine .travel ("2023-01-08 15:00:00 UTC" )
2958+ def test_virtual_environment_mode_dev_only_model_change_downstream_of_seed (
2959+ init_and_plan_context : t .Callable ,
2960+ ):
2961+ """This test covers a scenario when a model downstream of a seed model is modified and explicitly selected
2962+ causing an (unhydrated) seed model to sourced from the state. If SQLMesh attempts to create
2963+ a table for the unchanged seed model, it will fail because the seed model is not hydrated.
2964+ """
2965+ context , _ = init_and_plan_context (
2966+ "examples/sushi" , config = "test_config_virtual_environment_mode_dev_only"
2967+ )
2968+ context .load ()
2969+ context .plan ("prod" , auto_apply = True , no_prompts = True )
2970+
2971+ # Make sure that a different version of the seed model is loaded
2972+ seed_model = context .get_model ("sushi.waiter_names" )
2973+ seed_model = seed_model .copy (update = {"stamp" : "force new version" })
2974+ context .upsert_model (seed_model )
2975+
2976+ # Make a change to the downstream model
2977+ model = context .get_model ("sushi.waiter_as_customer_by_day" )
2978+ model = model .copy (update = {"stamp" : "force new version" })
2979+ context .upsert_model (model )
2980+
2981+ # It is important to clear the cache so that the hydrated seed model is not sourced from the cache
2982+ context .clear_caches ()
2983+
2984+ # Make sure to use the selector so that the seed model is sourced from the state
2985+ plan = context .plan_builder ("dev" , select_models = [model .name ]).build ()
2986+ assert len (plan .directly_modified ) == 1
2987+ assert list (plan .directly_modified )[0 ].name == model .fqn
2988+ assert len (plan .missing_intervals ) == 1
2989+ assert plan .missing_intervals [0 ].snapshot_id .name == model .fqn
2990+
2991+ # Make sure there's no error when applying the plan
2992+ context .apply (plan )
2993+ context .plan ("prod" , auto_apply = True , no_prompts = True )
2994+
2995+
29212996@time_machine .travel ("2023-01-08 15:00:00 UTC" )
29222997def test_restatement_plan_ignores_changes (init_and_plan_context : t .Callable ):
29232998 context , plan = init_and_plan_context ("examples/sushi" )
0 commit comments