diff --git a/modules/system/databaseMigration.py b/modules/system/databaseMigration.py index 4739b8ff..d255bde2 100644 --- a/modules/system/databaseMigration.py +++ b/modules/system/databaseMigration.py @@ -742,18 +742,18 @@ def _importSingleDb(payload: dict, dbName: str, mode: str, protectedIds: List[st conn = _getConnection(dbName) try: - conn.autocommit = False existingTables = set(_listTables(conn)) - # Pre-create missing tables so FK ordering can discover them + # Ensure all import tables exist (create missing ones from export schema) for tableName, rows in tables.items(): - if tableName in excluded or not isinstance(rows, list): + if tableName in excluded or not isinstance(rows, list) or not rows: continue if tableName not in existingTables: + conn.autocommit = True _createTableFromExport(conn, tableName, rows) - conn.commit() conn.autocommit = False existingTables.add(tableName) + logger.info("Pre-created missing table %s.%s", dbName, tableName) # Build importable table list and sort by FK dependencies importable = [t for t in tables @@ -771,29 +771,40 @@ def _importSingleDb(payload: dict, dbName: str, mode: str, protectedIds: List[st # Phase 1 (replace only): DELETE children first (reverse topological order) if mode == "replace": for tableName in reversed(importOrder): - _deleteNonProtected(conn, tableName, protectedIdSet) + try: + conn.autocommit = False + _deleteNonProtected(conn, tableName, protectedIdSet) + conn.commit() + except Exception as e: + conn.rollback() + warnings.append(f"DELETE from {dbName}.{tableName} failed: {e}") + logger.warning("DELETE from %s.%s failed: %s", dbName, tableName, e) # Phase 2: INSERT parents first (topological order) for tableName in importOrder: - rows = tables[tableName] - physicalCols = _getPhysicalColumns(conn, tableName) - if not physicalCols: - continue - - filteredRows = [] - for row in rows: - if _isProtectedRow(tableName, row): + try: + conn.autocommit = False + rows = tables[tableName] + physicalCols = _getPhysicalColumns(conn, tableName) + if not physicalCols: continue - if row.get("id") and str(row["id"]) in protectedIdSet: - continue - filteredRows.append(row) - insertedCount = _insertRows(conn, tableName, filteredRows, physicalCols, mode) - dbResult[tableName] = insertedCount + filteredRows = [] + for row in rows: + if _isProtectedRow(tableName, row): + continue + if row.get("id") and str(row["id"]) in protectedIdSet: + continue + filteredRows.append(row) - conn.commit() + insertedCount = _insertRows(conn, tableName, filteredRows, physicalCols, mode) + conn.commit() + dbResult[tableName] = insertedCount + except Exception as e: + conn.rollback() + warnings.append(f"INSERT into {dbName}.{tableName} failed: {e}") + logger.warning("INSERT into %s.%s failed: %s", dbName, tableName, e) except Exception as e: - conn.rollback() logger.error("Import failed for database %s: %s", dbName, e) return {"database": dbName, "tables": {}, "recordCount": 0, "warnings": [f"Import fuer '{dbName}' fehlgeschlagen: {e}"]}