"""Leichte In-Place-Migrationen für SQLite (kein Alembic). Wird beim App-Start nach create_all() ausgeführt. Idempotent. """ from __future__ import annotations import logging from sqlalchemy import text from sqlmodel import Session from app.core.db import engine log = logging.getLogger("voice-agent.migrate") def _existing_columns(conn, table: str) -> set[str]: rows = conn.execute(text(f"PRAGMA table_info({table})")).all() return {r[1] for r in rows} # row[1] = column name def run_migrations() -> None: with engine.begin() as conn: # 1) Job.owner_id Spalte nachrüsten, falls die Tabelle aus alter Version kommt. cols = _existing_columns(conn, "job") if "owner_id" not in cols: log.info("Migration: füge job.owner_id hinzu") conn.execute(text("ALTER TABLE job ADD COLUMN owner_id INTEGER")) conn.execute(text("CREATE INDEX IF NOT EXISTS ix_job_owner_id ON job(owner_id)")) def assign_orphan_jobs_to(user_id: int) -> int: """Weist alle Jobs ohne owner_id dem angegebenen User zu. Gibt Anzahl zurück.""" with Session(engine) as session: result = session.execute( text("UPDATE job SET owner_id = :uid WHERE owner_id IS NULL"), {"uid": user_id}, ) session.commit() n = result.rowcount or 0 if n: log.info("Migration: %d Bestand-Jobs an user_id=%d zugeordnet", n, user_id) return n