db restore with create db if not exitst
This commit is contained in:
parent
59ad6f3849
commit
c4a9a66c60
1 changed files with 82 additions and 2 deletions
|
|
@ -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:
|
||||
|
|
|
|||
Loading…
Reference in a new issue