@@ -32,6 +32,80 @@ def test_failed_row_insert_leaves_no_catalog_or_data_table(tmp_path) -> None:
3232 assert connection .execute ("select count(*) from dataset" ).fetchone () == (0 ,)
3333 assert connection .execute ("select count(*) from variable" ).fetchone () == (0 ,)
3434
35+ def test_failed_create_does_not_drop_a_concurrently_created_table (
36+ tmp_path , monkeypatch ,
37+ ) -> None :
38+ database_path = tmp_path / "race.sqlite"
39+ database = f"sqlite:///{ database_path } "
40+ variables = [{
41+ "ordinal" : 1 , "source_name" : "name" , "physical_name" : "name" ,
42+ "storage_kind" : "string" , "string_width" : 8 , "label" : "" ,
43+ "format" : "A8" , "measure" : "nominal" , "alignment" : "left" ,
44+ "display_width" : 8 , "value_labels" : "{}" , "missing_ranges" : "[]" ,
45+ }]
46+ real_inspect = wide .inspect
47+ inspected_data_table = 0
48+
49+ def inspect_with_concurrent_table (bind ):
50+ actual = real_inspect (bind )
51+
52+ class Inspector :
53+ def has_table (self , table_name ):
54+ nonlocal inspected_data_table
55+ if table_name == "data_race" :
56+ inspected_data_table += 1
57+ return inspected_data_table > 1
58+ return actual .has_table (table_name )
59+
60+ return Inspector ()
61+
62+ real_create = wide .Table .create
63+ real_drop = wide .Table .drop
64+ dropped = []
65+
66+ def fail_data_table_create (table , bind , ** kwargs ):
67+ if table .name == "data_race" :
68+ raise RuntimeError ("concurrent create won" )
69+ return real_create (table , bind , ** kwargs )
70+
71+ def observe_drop (table , bind , ** kwargs ):
72+ if table .name == "data_race" :
73+ dropped .append (table .name )
74+ return real_drop (table , bind , ** kwargs )
75+
76+ monkeypatch .setattr (wide , "inspect" , inspect_with_concurrent_table )
77+ monkeypatch .setattr (wide .Table , "create" , fail_data_table_create )
78+ monkeypatch .setattr (wide .Table , "drop" , observe_drop )
79+
80+ with pytest .raises (RuntimeError , match = "concurrent create won" ):
81+ create_wide_dataset (
82+ database_url = database , dataset_id = "race" , source_name = "race.sav" ,
83+ source_format = "SAV" , rows = [{"name" : "ok" }], variables = variables ,
84+ )
85+
86+ assert inspected_data_table == 1
87+ assert dropped == []
88+
89+
90+ def test_dataset_name_cannot_equal_an_existing_normative_uuid (tmp_path ) -> None :
91+ database = f"sqlite:///{ tmp_path / 'namespace.sqlite' } "
92+ variables = [{
93+ "ordinal" : 1 , "source_name" : "name" , "physical_name" : "name" ,
94+ "storage_kind" : "string" , "string_width" : 8 , "label" : "" ,
95+ "format" : "A8" , "measure" : "nominal" , "alignment" : "left" ,
96+ "display_width" : 8 , "value_labels" : "{}" , "missing_ranges" : "[]" ,
97+ }]
98+ first = create_wide_dataset (
99+ database_url = database , dataset_id = "first" , source_name = "first.sav" ,
100+ source_format = "SAV" , rows = [{"name" : "first" }], variables = variables ,
101+ )
102+
103+ with pytest .raises (ValueError , match = "already exists" ):
104+ create_wide_dataset (
105+ database_url = database , dataset_id = first ["dataset_id" ],
106+ source_name = "second.sav" , source_format = "SAV" ,
107+ rows = [{"name" : "second" }], variables = variables ,
108+ )
35109
36110def test_failed_preflight_persists_operation_without_creating_dataset (tmp_path ) -> None :
37111 database_path = tmp_path / "preflight.sqlite"
0 commit comments