PR #150 introduced a double brace `{ {` on handlers_shop.go:109 that
broke compilation. Migration tests were also hardcoded for 1 migration
but 3 now exist (0001–0003).
The ON CONFLICT upsert referenced unqualified "bought" which PostgreSQL
rejected as ambiguous, and the table lacked the UNIQUE constraint needed
for ON CONFLICT. Adds a unique index on (character_id, shop_item_id) via
migration 0003 and qualifies the column as shop_items_bought.bought.
The migration consolidation (27fb0fa) merged 33 incremental patches
into 0001_init.sql and marks the baseline as applied for any existing
database. Users who only ran some of the 33 patches have schema gaps
that cause runtime errors.
0002_catch_up_patches.sql replays all 33 patches (skipping 15 and 20,
which are destructive data resets) with idempotency guards so it is a
no-op on fresh or fully-patched databases and fills gaps otherwise.
Replace 4 independent schema management code paths (Docker shell
script, setup wizard pg_restore, test helpers, manual psql) with a
single migration runner embedded in the server binary.
The new server/migrations/ package uses Go embed to bundle all SQL
schemas. On startup, Migrate() creates a schema_version tracking
table, detects existing databases (auto-marks baseline as applied),
and runs pending migrations in transactions.
Key changes:
- Consolidated init.sql + 9.2-update + 33 patches into 0001_init.sql
- Setup wizard simplified to single "Apply schema" checkbox
- Test helpers use migrations.Migrate() instead of pg_restore
- Docker no longer needs schema volume mounts or init script
- Seed data (shops, events, gacha) embedded and applied via API
- Future migrations just add 0002_*.sql files — no manual steps