diff --git a/modules/system/databaseHealth.py b/modules/system/databaseHealth.py index ba369cf2..80a19ac9 100644 --- a/modules/system/databaseHealth.py +++ b/modules/system/databaseHealth.py @@ -799,12 +799,16 @@ def _jsonSafe(v): def _discoverLegacyTables(dbFilter: Optional[str] = None) -> List[dict]: """Find tables that exist in the DB but have no entry in MODEL_REGISTRY. + A table is legacy if its name does NOT match any PowerOnModel class. + Tables that exist in multiple DBs (shared-table pattern) are NOT flagged + as legacy -- the connector creates them wherever code writes that model. + Returns a list of dicts: {db, table, rowCount, sizeBytes}. """ from modules.datamodels.datamodelBase import MODEL_REGISTRY - from modules.shared.fkRegistry import _buildTableToDbMap + from modules.shared.fkRegistry import _ensureModelsLoaded - tableToDb = _buildTableToDbMap() + _ensureModelsLoaded() registeredDbs = getRegisteredDatabases() results: List[dict] = [] @@ -831,11 +835,7 @@ def _discoverLegacyTables(dbFilter: Optional[str] = None) -> List[dict]: """) for row in cur.fetchall(): tblName = row["table_name"] - inRegistry = ( - tblName in MODEL_REGISTRY - and tableToDb.get(tblName) == dbName - ) - if not inRegistry: + if tblName not in MODEL_REGISTRY: results.append({ "db": dbName, "table": tblName, @@ -855,14 +855,10 @@ def _dropLegacyTable(dbName: str, tableName: str) -> dict: Raises ValueError if the table is model-backed (safety guard). """ from modules.datamodels.datamodelBase import MODEL_REGISTRY - from modules.shared.fkRegistry import _buildTableToDbMap + from modules.shared.fkRegistry import _ensureModelsLoaded - tableToDb = _buildTableToDbMap() - inRegistry = ( - tableName in MODEL_REGISTRY - and tableToDb.get(tableName) == dbName - ) - if inRegistry: + _ensureModelsLoaded() + if tableName in MODEL_REGISTRY: raise ValueError( f"Table '{dbName}.{tableName}' is backed by a Pydantic model and cannot be dropped via legacy cleanup." ) diff --git a/modules/system/databaseMigration.py b/modules/system/databaseMigration.py index 8de28aba..4739b8ff 100644 --- a/modules/system/databaseMigration.py +++ b/modules/system/databaseMigration.py @@ -21,7 +21,7 @@ import psycopg2.extras from modules.shared.configuration import APP_CONFIG from modules.shared.dbRegistry import getRegisteredDatabases -from modules.shared.fkRegistry import _buildTableToDbMap, getFkRelationships +from modules.shared.fkRegistry import getFkRelationships from modules.datamodels.datamodelBase import MODEL_REGISTRY from modules.system.databaseHealth import _getConnection, _jsonSafe @@ -120,15 +120,18 @@ def _exportDatabases(databases: List[str]) -> dict: def _getModelTablesForDb(dbName: str, physicalTables: List[str]) -> List[str]: """Return only those physical tables that have a matching Pydantic model - registered in MODEL_REGISTRY and mapped to *dbName*. + registered in MODEL_REGISTRY. Tables without a Pydantic class (legacy / orphan tables) are excluded from export so the backup contains only model-backed data. + + Note: the same model can exist in multiple databases (shared-table + pattern), so we only check membership in MODEL_REGISTRY, not the + DB mapping. """ - tableToDb = _buildTableToDbMap() return sorted( t for t in physicalTables - if t in MODEL_REGISTRY and tableToDb.get(t) == dbName + if t in MODEL_REGISTRY )