db restore with create db if not exitst
All checks were successful
Deploy Plattform-Core / test (push) Successful in 39s
Deploy Plattform-Core / deploy (push) Successful in 4s

This commit is contained in:
ValueOn AG 2026-05-24 09:18:59 +02:00
parent 59ad6f3849
commit c4a9a66c60

View file

@ -545,6 +545,74 @@ def _prepareImport(payload: dict) -> dict:
}
def _ensureDatabaseExists(dbName: str) -> bool:
"""Create the PostgreSQL database if it does not yet exist.
Connects to the ``postgres`` admin database using the same credentials
as the target DB. Returns True if the database was created, False if
it already existed.
"""
registeredDbs = getRegisteredDatabases()
configPrefix = registeredDbs.get(dbName)
if configPrefix is None:
return False
hostKey = f"{configPrefix}_HOST" if configPrefix != "DB" else "DB_HOST"
portKey = f"{configPrefix}_PORT" if configPrefix != "DB" else "DB_PORT"
userKey = f"{configPrefix}_USER" if configPrefix != "DB" else "DB_USER"
passwordKey = f"{configPrefix}_PASSWORD_SECRET" if configPrefix != "DB" else "DB_PASSWORD_SECRET"
adminConn = psycopg2.connect(
host=APP_CONFIG.get(hostKey, "localhost"),
port=int(APP_CONFIG.get(portKey, 5432)),
database="postgres",
user=APP_CONFIG.get(userKey),
password=APP_CONFIG.get(passwordKey),
client_encoding="utf8",
)
try:
adminConn.autocommit = True
with adminConn.cursor() as cur:
cur.execute("SELECT 1 FROM pg_database WHERE datname = %s", (dbName,))
if cur.fetchone():
return False
cur.execute(f'CREATE DATABASE "{dbName}"')
logger.info("Created missing database: %s", dbName)
return True
finally:
adminConn.close()
def _createTableFromExport(conn, tableName: str, rows: List[dict]) -> None:
"""Create a table based on the column structure found in the export data.
Uses TEXT for all columns since we don't have the original DDL.
The ``id`` column gets a PRIMARY KEY constraint.
"""
allKeys: List[str] = []
seen: set = set()
for row in rows:
for k in row.keys():
if k not in seen:
allKeys.append(k)
seen.add(k)
if not allKeys:
return
colDefs = []
for col in allKeys:
if col == "id":
colDefs.append(f'"{col}" TEXT PRIMARY KEY')
else:
colDefs.append(f'"{col}" TEXT')
ddl = f'CREATE TABLE IF NOT EXISTS "{tableName}" ({", ".join(colDefs)})'
with conn.cursor() as cur:
cur.execute(ddl)
logger.info("Created table %s with %d columns", tableName, len(allKeys))
def _importSingleDb(payload: dict, dbName: str, mode: str, protectedIds: List[str]) -> dict:
"""Import a single database from the (already remapped) payload.
@ -563,11 +631,21 @@ def _importSingleDb(payload: dict, dbName: str, mode: str, protectedIds: List[st
return {"database": dbName, "tables": {}, "recordCount": 0,
"warnings": [f"Keine Daten fuer '{dbName}' im Payload"]}
try:
dbCreated = _ensureDatabaseExists(dbName)
except Exception as e:
logger.error("Failed to ensure database %s exists: %s", dbName, e)
return {"database": dbName, "tables": {}, "recordCount": 0,
"warnings": [f"Datenbank '{dbName}' konnte nicht erstellt werden: {e}"]}
protectedIdSet = set(protectedIds)
tables = dbData.get("tables", {})
warnings: List[str] = []
dbResult: Dict[str, int] = {}
if dbCreated:
warnings.append(f"Datenbank '{dbName}' wurde neu erstellt")
conn = _getConnection(dbName)
try:
conn.autocommit = False
@ -576,9 +654,11 @@ def _importSingleDb(payload: dict, dbName: str, mode: str, protectedIds: List[st
for tableName, rows in tables.items():
if not isinstance(rows, list):
continue
if tableName not in existingTables:
warnings.append(f"Tabelle '{dbName}.{tableName}' existiert nicht, uebersprungen")
continue
_createTableFromExport(conn, tableName, rows)
conn.commit()
conn.autocommit = False
physicalCols = _getPhysicalColumns(conn, tableName)
if not physicalCols: