11"""SQLite reference SQL profile for the strict OpenStatSpec wide-table contract."""
22
3+ import json
34import re
45from collections .abc import Iterable , Mapping
56from typing import Any
@@ -46,6 +47,35 @@ def catalog(metadata: MetaData) -> tuple[Table, Table]:
4647 return datasets , variables
4748
4849
50+
51+ def multiple_response_set_catalog (metadata : MetaData ) -> Table :
52+ return Table (
53+ "multiple_response_set_catalog" , metadata ,
54+ Column ("dataset_id" , String (255 ), primary_key = True ),
55+ Column ("set_name" , String (255 ), primary_key = True ),
56+ Column ("member_ordinal" , Integer , primary_key = True ),
57+ Column ("kind" , String (16 )), Column ("label" , Text ),
58+ Column ("counted_value" , Text ), Column ("variable_name" , String (255 )),
59+ Column ("definition" , Text , nullable = False ),
60+ )
61+
62+ def multiple_response_set_rows (dataset_id : str , definitions : str ) -> list [dict [str , Any ]]:
63+ sets = json .loads (definitions )
64+ rows = []
65+ for set_name , definition in sets .items ():
66+ members = definition .get ("variable_list" , definition .get ("variables" , []))
67+ if isinstance (members , str ):
68+ members = members .split ()
69+ for ordinal , variable_name in enumerate (members or [None ], start = 1 ):
70+ rows .append ({
71+ "dataset_id" : dataset_id , "set_name" : set_name , "member_ordinal" : ordinal ,
72+ "kind" : definition .get ("set_type" , definition .get ("type" )),
73+ "label" : definition .get ("label" ),
74+ "counted_value" : str (definition .get ("counted_value" , definition .get ("countedvalue" , "" ))),
75+ "variable_name" : variable_name , "definition" : json .dumps (definition , default = str , sort_keys = True ),
76+ })
77+ return rows
78+
4979def physical_name (source_name : str , used : set [str ]) -> str :
5080 stem = _IDENTIFIER .sub ("_" , source_name ).strip ("_" ).lower () or "variable"
5181 stem = stem [:54 ]
@@ -76,14 +106,15 @@ def create_wide_dataset(
76106 engine = create_engine (database_url )
77107 metadata = MetaData ()
78108 datasets , variable_catalog = catalog (metadata )
109+ multiple_response_catalog = multiple_response_set_catalog (metadata )
79110 data_table = Table (
80111 data_table_name (dataset_id ), metadata ,
81112 Column ("__case_ordinal" , BigInteger , primary_key = True , nullable = False ),
82113 * (Column (item ["physical_name" ], Float () if item ["storage_kind" ] == "numeric" else Text (),
83114 nullable = item ["storage_kind" ] == "numeric" ) for item in variables ),
84115 )
85116 with engine .begin () as connection :
86- metadata .create_all (connection , tables = [datasets , variable_catalog ])
117+ metadata .create_all (connection , tables = [datasets , variable_catalog , multiple_response_catalog ])
87118 if connection .execute (select (datasets .c .dataset_id ).where (datasets .c .dataset_id == dataset_id )).first ():
88119 raise ValueError (f"Dataset { dataset_id !r} already exists; imports never overwrite a dataset." )
89120 data_table .create (connection )
@@ -98,6 +129,9 @@ def create_wide_dataset(
98129 multiple_response_sets = multiple_response_sets ,
99130 ))
100131 connection .execute (insert (variable_catalog ), [dict (dataset_id = dataset_id , ** item ) for item in variables ])
132+ mrset_rows = multiple_response_set_rows (dataset_id , multiple_response_sets )
133+ if mrset_rows :
134+ connection .execute (insert (multiple_response_catalog ), mrset_rows )
101135 if materialized :
102136 connection .execute (insert (data_table ), materialized )
103137 return {"dataset_id" : dataset_id , "data_table" : data_table .name , "case_count" : len (materialized )}
0 commit comments