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 <noreply@anthropic.com>
This commit is contained in:
2026-04-03 10:41:36 -04:00
parent f1a05a68a8
commit 7402f18bcf
2 changed files with 11 additions and 0 deletions

View File

@@ -258,6 +258,16 @@ Admin endpoints use `game_service.py` functions which handle both database updat
3. Return JSON responses with appropriate status codes 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 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 ## Important Notes
- **Port 5000 conflict**: macOS AirPlay Receiver uses port 5000 by default. Use `PORT=5001` when running the backend. - **Port 5000 conflict**: macOS AirPlay Receiver uses port 5000 by default. Use `PORT=5001` when running the backend.

View File

@@ -100,6 +100,7 @@ def run_migrations_online():
context.configure( context.configure(
connection=connection, connection=connection,
target_metadata=get_metadata(), target_metadata=get_metadata(),
render_as_batch=True,
**conf_args **conf_args
) )