From ac85c8e3dc37b2cca25be526f1a6eb19a93657b8 Mon Sep 17 00:00:00 2001
From: ValueOn AG
Date: Mon, 25 May 2026 15:28:38 +0200
Subject: [PATCH] fix identification legacy table
---
modules/system/databaseHealth.py | 24 ++++++++++--------------
modules/system/databaseMigration.py | 11 +++++++----
2 files changed, 17 insertions(+), 18 deletions(-)
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
)