@@ -103,6 +103,7 @@ def test_plan_applies_to_same_dataset_and_physical_table_without_copy(
103103 actor = "test-agent" ,
104104 database_profile = "sqlite" ,
105105 allow_schema_change = True ,
106+ allow_delete_variable = True ,
106107 dolt_branch = None ,
107108 dolt_head = None ,
108109 )
@@ -153,6 +154,56 @@ def test_plan_applies_to_same_dataset_and_physical_table_without_copy(
153154 )
154155
155156
157+ def test_string_declaration_creates_column_and_catalog_variable (catalog ) -> None :
158+ url , path , dataset_id , table_name = catalog
159+
160+ openstatspec .apply_spss_in_place (
161+ database_url = url ,
162+ dataset_id = dataset_id ,
163+ source_text = "STRING note (A8)." ,
164+ actor = "test-agent" ,
165+ )
166+
167+ connection = sqlite3 .connect (path )
168+ assert connection .execute (
169+ "select source_name, storage_kind, declared_string_width from variable "
170+ "where dataset_id = ? order by source_ordinal" ,
171+ (dataset_id ,),
172+ ).fetchall () == [("score" , "numeric" , None ), ("note" , "string" , 8 )]
173+ assert connection .execute (
174+ f'SELECT note FROM "{ table_name } " ORDER BY __case_ordinal'
175+ ).fetchall () == [(None ,), (None ,), (None ,)]
176+ connection .close ()
177+
178+
179+ def test_delete_then_recreate_same_name_resolves_operations_in_order (catalog ) -> None :
180+ url , path , dataset_id , table_name = catalog
181+
182+ openstatspec .apply_spss_in_place (
183+ database_url = url ,
184+ dataset_id = dataset_id ,
185+ source_text = (
186+ "COMPUTE other = score. DELETE VARIABLES score. "
187+ "RECODE other (2 = 9) (ELSE = COPY) INTO score."
188+ ),
189+ actor = "test-agent" ,
190+ )
191+
192+ connection = sqlite3 .connect (path )
193+ variables = connection .execute (
194+ "select source_name, physical_name from variable where dataset_id = ? "
195+ "order by source_ordinal" ,
196+ (dataset_id ,),
197+ ).fetchall ()
198+ assert [row [0 ] for row in variables ] == ["other" , "score" ]
199+ physical = dict (variables )
200+ assert connection .execute (
201+ f'SELECT "{ physical ["other" ]} ", "{ physical ["score" ]} " '
202+ f'FROM "{ table_name } " ORDER BY __case_ordinal'
203+ ).fetchall () == [(1.0 , 1.0 ), (2.0 , 9.0 ), (3.0 , 3.0 )]
204+ connection .close ()
205+
206+
156207def test_public_apply_supports_non_dolt_without_building_undo (catalog ) -> None :
157208 url , path , dataset_id , table_name = catalog
158209 plan = _plan ("RECODE score (1 = 0)." )
@@ -364,6 +415,38 @@ def test_missing_audit_schema_fails_before_mutation(catalog) -> None:
364415 ).fetchall () == [(1.0 ,), (2.0 ,), (3.0 ,)]
365416
366417
418+ def test_delete_is_rejected_when_drop_column_is_unavailable (
419+ catalog , monkeypatch ,
420+ ) -> None :
421+ url , path , dataset_id , table_name = catalog
422+ monkeypatch .setattr (
423+ inplace_transform ,
424+ "effective_profile" ,
425+ lambda _url , ** _kwargs : (
426+ SimpleNamespace (name = "sqlite" ),
427+ {"server_version" : "3.34.0" },
428+ ),
429+ )
430+
431+ with pytest .raises (openstatspec .TransformationError ) as caught :
432+ openstatspec .apply_spss_in_place (
433+ database_url = url ,
434+ dataset_id = dataset_id ,
435+ source_text = "COMPUTE other = score. DELETE VARIABLES score." ,
436+ actor = "test-agent" ,
437+ )
438+
439+ assert caught .value .code == "delete_variable_not_supported"
440+ connection = sqlite3 .connect (path )
441+ assert connection .execute (
442+ f'SELECT score FROM "{ table_name } " ORDER BY __case_ordinal'
443+ ).fetchall () == [(1.0 ,), (2.0 ,), (3.0 ,)]
444+ assert [
445+ row [1 ] for row in connection .execute (f'PRAGMA table_info("{ table_name } ")' )
446+ ] == ["__case_ordinal" , "score" ]
447+ connection .close ()
448+
449+
367450def test_nontransactional_ddl_profile_rejects_create_before_mutation (
368451 catalog ,
369452) -> None :
@@ -381,6 +464,7 @@ def test_nontransactional_ddl_profile_rejects_create_before_mutation(
381464 actor = "test-agent" ,
382465 database_profile = "mysql" ,
383466 allow_schema_change = False ,
467+ allow_delete_variable = True ,
384468 dolt_branch = None ,
385469 dolt_head = None ,
386470 )
@@ -692,7 +776,10 @@ def test_transactional_ddl_rollback_skips_unlocked_compensation(
692776 monkeypatch .setattr (
693777 inplace_transform ,
694778 "effective_profile" ,
695- lambda _url , ** _kwargs : (SimpleNamespace (name = profile_name ), {}),
779+ lambda _url , ** _kwargs : (
780+ SimpleNamespace (name = profile_name ),
781+ {"server_version" : "3.35.0" },
782+ ),
696783 )
697784
698785 def fail_after_schema_change (
0 commit comments