@@ -1356,6 +1356,52 @@ def _catalog_dataset_bijection_state(
13561356 return "valid" if set (legacy_rows ) == set (normative_rows ) else "unverified"
13571357
13581358
1359+ def _catalog_variable_bijection_state (
1360+ connection : Any , * , normative : Any , legacy : Iterable [Table ],
1361+ ) -> str :
1362+ """Require exact legacy-to-normative variable identity mappings."""
1363+ variables = tuple (legacy )[1 ]
1364+ legacy_rows = [
1365+ (
1366+ row ["dataset_id" ], row ["ordinal" ], row ["source_name" ],
1367+ row ["physical_name" ],
1368+ )
1369+ for row in connection .execute (select (
1370+ variables .c .dataset_id , variables .c .ordinal ,
1371+ variables .c .source_name , variables .c .physical_name ,
1372+ )).mappings ()
1373+ ]
1374+ normative_rows = [
1375+ (
1376+ row ["dataset_name" ], row ["source_ordinal" ], row ["source_name" ],
1377+ row ["physical_name" ],
1378+ )
1379+ for row in connection .execute (
1380+ select (
1381+ normative .dataset .c .dataset_name ,
1382+ normative .variable .c .source_ordinal ,
1383+ normative .variable .c .source_name ,
1384+ normative .variable .c .physical_name ,
1385+ ).join (
1386+ normative .variable ,
1387+ normative .variable .c .dataset_id == normative .dataset .c .dataset_id ,
1388+ )
1389+ ).mappings ()
1390+ ]
1391+ for rows in (legacy_rows , normative_rows ):
1392+ if any (
1393+ not isinstance (dataset_name , str ) or not dataset_name .strip ()
1394+ or not isinstance (ordinal , int ) or ordinal < 1
1395+ or not isinstance (source_name , str ) or not source_name .strip ()
1396+ or not isinstance (physical_name , str ) or not physical_name .strip ()
1397+ for dataset_name , ordinal , source_name , physical_name in rows
1398+ ):
1399+ return "unverified"
1400+ if len (set (rows )) != len (rows ):
1401+ return "ambiguous"
1402+ return "valid" if set (legacy_rows ) == set (normative_rows ) else "unverified"
1403+
1404+
13591405def _catalog_state (
13601406 connection : Any , normative : Any , legacy : Iterable [Table ],
13611407 * , allowed_migrations : Mapping [str , set [str ]] | None = None ,
@@ -1424,6 +1470,11 @@ def _catalog_state(
14241470 )
14251471 if mapping_state != "valid" :
14261472 return mapping_state
1473+ variable_mapping_state = _catalog_variable_bijection_state (
1474+ connection , normative = normative , legacy = legacy ,
1475+ )
1476+ if variable_mapping_state != "valid" :
1477+ return variable_mapping_state
14271478 return "verified"
14281479
14291480
@@ -1472,9 +1523,12 @@ def _catalog_snapshot(
14721523
14731524def _compensate_catalog_initialization (
14741525 connection : Any , * , metadata : MetaData , before_tables : set [str ],
1475- before_columns : Mapping [str , set [str ]],
1526+ before_columns : Mapping [str , set [str ]], normative : Any ,
1527+ legacy : Iterable [Table ],
14761528) -> None :
1477- """Restore the pre-initialization relation/column inventory after DDL failure."""
1529+ """Restore only when no concurrent initializer completed the catalog."""
1530+ if _catalog_state (connection , normative , legacy ) == "verified" :
1531+ return
14781532 current_tables = set (inspect (connection ).get_table_names ())
14791533 for table in reversed (metadata .sorted_tables ):
14801534 if table .name in current_tables and table .name not in before_tables :
@@ -1626,7 +1680,8 @@ def initialize_wide_catalog(
16261680 with connection .begin ():
16271681 _compensate_catalog_initialization (
16281682 connection , metadata = metadata , before_tables = before_tables ,
1629- before_columns = before_columns ,
1683+ before_columns = before_columns , normative = normative ,
1684+ legacy = legacy ,
16301685 )
16311686 except Exception as cleanup_error :
16321687 inventory = _catalog_residual_inventory (
0 commit comments