From 7402f18bcf11e9950908d58348b87655e56528cb Mon Sep 17 00:00:00 2001 From: Ryan Chen Date: Fri, 3 Apr 2026 10:41:36 -0400 Subject: [PATCH] Add render_as_batch for SQLite and document migration rules - Set render_as_batch=True in Alembic env.py so autogenerated migrations use batch mode for SQLite compatibility - Add SQLite + Alembic section to CLAUDE.md with rules for avoiding circular dependency and idempotency issues Co-Authored-By: Claude Opus 4.6 --- CLAUDE.md | 10 ++++++++++ migrations/env.py | 1 + 2 files changed, 11 insertions(+) diff --git a/CLAUDE.md b/CLAUDE.md index 7cd9a11..0d9082d 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -258,6 +258,16 @@ Admin endpoints use `game_service.py` functions which handle both database updat 3. Return JSON responses with appropriate status codes 4. For admin actions affecting game state, use functions from `game_service.py` to ensure WebSocket broadcasts +## SQLite + Alembic Migrations + +This project uses **SQLite** as its database. SQLite has limited ALTER TABLE support, so Alembic uses **batch mode** (`render_as_batch=True` in `migrations/env.py`) to handle schema changes by recreating tables behind the scenes. + +**When writing or generating migrations, you MUST:** +- **Always test migrations can actually run** against SQLite — don't just generate and commit blindly. +- **Watch for circular dependency errors** in batch mode. If a table has foreign keys (especially self-referential or mutual FKs like `games` ↔ `teams`), splitting a single `batch_alter_table` into multiple calls (e.g., one for column adds, one for FK creation) avoids `CircularDependencyError`. +- **Make migrations idempotent when possible** — check if columns/tables already exist before adding them, especially if production DB state may have drifted from Alembic history. Use `PRAGMA table_info('table_name')` to inspect existing columns. +- **Never combine column adds/drops with FK changes** in a single `batch_alter_table` block on tables that have existing foreign keys. + ## Important Notes - **Port 5000 conflict**: macOS AirPlay Receiver uses port 5000 by default. Use `PORT=5001` when running the backend. diff --git a/migrations/env.py b/migrations/env.py index 4c97092..9ee8a6c 100644 --- a/migrations/env.py +++ b/migrations/env.py @@ -100,6 +100,7 @@ def run_migrations_online(): context.configure( connection=connection, target_metadata=get_metadata(), + render_as_batch=True, **conf_args )