@@ -2172,6 +2172,118 @@ def _dates_in_table(table_name: str) -> t.List[str]:
21722172 ], f"Table { tbl } wasnt cleared"
21732173
21742174
2175+ def test_restatement_plan_respects_disable_restatements (tmp_path : Path ):
2176+ model_a = """
2177+ MODEL (
2178+ name test.a,
2179+ kind INCREMENTAL_BY_TIME_RANGE (
2180+ time_column "ts"
2181+ ),
2182+ start '2024-01-01',
2183+ cron '@daily'
2184+ );
2185+
2186+ select account_id, ts from test.external_table;
2187+ """
2188+
2189+ model_b = """
2190+ MODEL (
2191+ name test.b,
2192+ kind INCREMENTAL_BY_TIME_RANGE (
2193+ time_column "ts",
2194+ disable_restatement true,
2195+ ),
2196+ start '2024-01-01',
2197+ cron '@daily'
2198+ );
2199+
2200+ select account_id, ts from test.a;
2201+ """
2202+
2203+ models_dir = tmp_path / "models"
2204+ models_dir .mkdir ()
2205+
2206+ for path , defn in {"a.sql" : model_a , "b.sql" : model_b }.items ():
2207+ with open (models_dir / path , "w" ) as f :
2208+ f .write (defn )
2209+
2210+ config = Config (model_defaults = ModelDefaultsConfig (dialect = "duckdb" ))
2211+ ctx = Context (paths = [tmp_path ], config = config )
2212+
2213+ engine_adapter = ctx .engine_adapter
2214+ engine_adapter .create_schema ("test" )
2215+
2216+ # source data
2217+ df = pd .DataFrame (
2218+ {
2219+ "account_id" : [1001 , 1002 , 1003 , 1004 ],
2220+ "ts" : [
2221+ "2024-01-01 00:30:00" ,
2222+ "2024-01-01 01:30:00" ,
2223+ "2024-01-01 02:30:00" ,
2224+ "2024-01-02 00:30:00" ,
2225+ ],
2226+ }
2227+ )
2228+ columns_to_types = {
2229+ "account_id" : exp .DataType .build ("int" ),
2230+ "ts" : exp .DataType .build ("timestamp" ),
2231+ }
2232+ external_table = exp .table_ (table = "external_table" , db = "test" , quoted = True )
2233+ engine_adapter .create_table (table_name = external_table , columns_to_types = columns_to_types )
2234+ engine_adapter .insert_append (
2235+ table_name = external_table , query_or_df = df , columns_to_types = columns_to_types
2236+ )
2237+
2238+ # plan + apply
2239+ ctx .plan (auto_apply = True , no_prompts = True )
2240+
2241+ def _dates_in_table (table_name : str ) -> t .List [str ]:
2242+ return [
2243+ str (r [0 ]) for r in engine_adapter .fetchall (f"select ts from { table_name } order by ts" )
2244+ ]
2245+
2246+ def get_snapshot_intervals (snapshot_id ):
2247+ return list (ctx .state_sync .get_snapshots ([snapshot_id ]).values ())[0 ].intervals
2248+
2249+ # verify initial state
2250+ for tbl in ["test.a" , "test.b" ]:
2251+ assert _dates_in_table (tbl ) == [
2252+ "2024-01-01 00:30:00" ,
2253+ "2024-01-01 01:30:00" ,
2254+ "2024-01-01 02:30:00" ,
2255+ "2024-01-02 00:30:00" ,
2256+ ]
2257+
2258+ # restate A and expect b to be ignored
2259+ starting_b_intervals = get_snapshot_intervals (ctx .snapshots ['"memory"."test"."b"' ].snapshot_id )
2260+ engine_adapter .execute ("delete from test.external_table where ts = '2024-01-01 01:30:00'" )
2261+ ctx .plan (
2262+ restate_models = ["test.a" ],
2263+ start = "2024-01-01" ,
2264+ end = "2024-01-02" ,
2265+ auto_apply = True ,
2266+ no_prompts = True ,
2267+ )
2268+
2269+ # verify A was changed and not b
2270+ assert _dates_in_table ("test.a" ) == [
2271+ "2024-01-01 00:30:00" ,
2272+ "2024-01-01 02:30:00" ,
2273+ "2024-01-02 00:30:00" ,
2274+ ]
2275+ assert _dates_in_table ("test.b" ) == [
2276+ "2024-01-01 00:30:00" ,
2277+ "2024-01-01 01:30:00" ,
2278+ "2024-01-01 02:30:00" ,
2279+ "2024-01-02 00:30:00" ,
2280+ ]
2281+
2282+ # Verify B intervals were not touched
2283+ b_intervals = get_snapshot_intervals (ctx .snapshots ['"memory"."test"."b"' ].snapshot_id )
2284+ assert starting_b_intervals == b_intervals
2285+
2286+
21752287def test_restatement_plan_clears_correct_intervals_across_environments (tmp_path : Path ):
21762288 model1 = """
21772289 MODEL (
0 commit comments