brackt/docs/agents/database.md
2026-04-15 19:50:39 -07:00

2.1 KiB

Database

Schema Changes Workflow

  1. Edit database/schema.ts
  2. npm run db:generate — generates migration SQL + snapshot
  3. Verify the SQL in drizzle/ looks correct
  4. Verify a snapshot was created in drizzle/meta/ (e.g. 0070_snapshot.json)
  5. npm run db:migrate — applies migration
  6. Add model functions in app/models/ for new queries

Drizzle Migration Rules

NEVER manually create migration SQL files or edit drizzle/meta/_journal.json. The journal and snapshots must stay in sync — drizzle-kit manages both. Missing snapshots cause drizzle-kit generate to fail with "data is malformed".

  • Always use drizzle-kit generate (or drizzle-kit generate --custom for interactive rename prompts)
  • Snapshot JSON must only contain PostgreSQL-valid fields — do not add "autoincrement" (Postgres uses sequences, and invalid fields cause Zod validation failures)
  • After generating, run drizzle-kit generate again to confirm "No schema changes" — validates the snapshot chain
  • For destructive migrations (drop/rename), use IF EXISTS / IF NOT EXISTS guards

Scoring Event Dates (Non-Obvious Gotcha)

Event dates are stored in two different columns depending on event type. Any date-range query must account for both:

  1. scoringEvents.eventDate (date column, YYYY-MM-DD) — used for non-bracket events (majors, final standings) and sometimes bracket events when the admin sets one date for an entire round.

  2. playoffMatchGames.scheduledAt (timestamp) — used for individual games within a bracket match. Bracket events often have eventDate = null on the scoring event itself.

Pattern for date-range queries: Two-step approach:

  1. selectDistinct event IDs via left joins through playoffMatches → playoffMatchGames, filtering: eventDate IN [dates] OR (scheduledAt >= dayStart AND scheduledAt <= dayEnd)
  2. findMany on the matched IDs to load full event data with relations

All timestamp bounds use UTC (T00:00:00.000Z / T23:59:59.999Z).

Reference implementation: getEventsForDates and getUpcomingEventsForDraftedParticipants in app/models/scoring-event.ts.