From 9d642412300deae2e599f48b40c60f0b6faf789a Mon Sep 17 00:00:00 2001 From: Lukas Date: Wed, 3 Jun 2026 20:22:59 +0200 Subject: [PATCH] fix(db): add missing legacy_key_cleanup_completed column migration Add migrate_schema_if_needed() to handle adding missing columns to existing tables for backward compatibility. Automatically adds legacy_key_cleanup_completed BOOLEAN column to system_settings table if missing, preventing 'no such column' errors on startup for existing databases. --- src/server/database/init.py | 65 +++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/src/server/database/init.py b/src/server/database/init.py index e65c372..347df36 100644 --- a/src/server/database/init.py +++ b/src/server/database/init.py @@ -119,6 +119,11 @@ async def initialize_database( result["tables_created"] = tables logger.info("Created %s tables", len(tables)) + # Migrate schema if needed (add missing columns to existing tables) + migrations = await migrate_schema_if_needed(engine) + if migrations: + logger.info("Applied %s schema migrations", len(migrations)) + # Validate schema if requested if validate_schema: validation = await validate_database_schema(engine) @@ -305,6 +310,66 @@ async def validate_database_schema( } +# ============================================================================= +# Schema Migration +# ============================================================================= + + +async def migrate_schema_if_needed( + engine: Optional[AsyncEngine] = None +) -> List[str]: + """Migrate database schema to current version if needed. + + Handles adding missing columns to existing tables for backward + compatibility with older database schemas. + + Args: + engine: Optional database engine (uses default if not provided) + + Returns: + List of migration operations performed + """ + if engine is None: + engine = get_engine() + + migrations_applied = [] + + try: + async with engine.connect() as conn: + # Get existing columns in system_settings table + existing_columns = await conn.run_sync( + lambda sync_conn: [ + col["name"] + for col in inspect(sync_conn).get_columns("system_settings") + ] + ) + + # Migration: Add legacy_key_cleanup_completed column if missing + if "legacy_key_cleanup_completed" not in existing_columns: + logger.info( + "Migrating system_settings table: " + "adding legacy_key_cleanup_completed column" + ) + await conn.execute( + text(""" + ALTER TABLE system_settings + ADD COLUMN legacy_key_cleanup_completed BOOLEAN + NOT NULL DEFAULT 0 + """) + ) + migrations_applied.append("added legacy_key_cleanup_completed") + logger.info( + "Migration complete: added legacy_key_cleanup_completed column" + ) + + except Exception as e: + logger.error("Schema migration failed: %s", e) + # Don't raise - migration failures shouldn't block startup + # The missing column will be handled gracefully by the application + + return migrations_applied + + # ============================================================================= # Schema Version Management # =============================================================================