""" Migrations de schéma SQLite. Ajouter une migration : append un tuple (id, sql) à _MIGRATIONS. L'id doit être unique et croissant (convention : NNNN_description). apply_pending() est idempotent ; elle peut être appelée à chaque démarrage. """ import sqlite3 from datetime import datetime, timezone from src.auth.db import get_conn _MIGRATIONS: list[tuple[str, str]] = [ ( "0001_add_prix_ht_to_subscriptions", "ALTER TABLE subscriptions ADD COLUMN prix_ht REAL", ), ( "0002_add_siret_to_users", "ALTER TABLE users ADD COLUMN siret TEXT", ), ( "0003_add_votes_balance_to_subscriptions", "ALTER TABLE subscriptions ADD COLUMN votes_balance INTEGER NOT NULL DEFAULT 0", ), ( "0004_add_votes_last_credited_at_to_subscriptions", "ALTER TABLE subscriptions ADD COLUMN votes_last_credited_at TEXT", ), ( "0005_rename_votes_credited_until_to_votes_last_credited_at", "ALTER TABLE subscriptions RENAME COLUMN votes_credited_until TO votes_last_credited_at", ), ] def apply_pending() -> None: conn = get_conn() conn.execute( "CREATE TABLE IF NOT EXISTS schema_migrations " "(id TEXT PRIMARY KEY, applied_at TEXT NOT NULL)" ) applied = { row[0] for row in conn.execute("SELECT id FROM schema_migrations").fetchall() } now = datetime.now(timezone.utc).isoformat() for migration_id, sql in _MIGRATIONS: if migration_id not in applied: try: conn.execute(sql) except sqlite3.OperationalError as exc: # Sur une DB fraîche (schéma déjà à jour), certaines migrations # sont sans effet : ADD COLUMN → "duplicate column name", # RENAME COLUMN → "no such column". On les ignore. err = str(exc) if "duplicate column name" not in err and "no such column" not in err: raise conn.execute( "INSERT INTO schema_migrations (id, applied_at) VALUES (?, ?)", (migration_id, now), ) conn.commit()