2.1 KiB
Database
Schema Changes Workflow
- Edit
database/schema.ts npm run db:generate— generates migration SQL + snapshot- Verify the SQL in
drizzle/looks correct - Verify a snapshot was created in
drizzle/meta/(e.g.0070_snapshot.json) npm run db:migrate— applies migration- 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(ordrizzle-kit generate --customfor 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 generateagain to confirm "No schema changes" — validates the snapshot chain - For destructive migrations (drop/rename), use
IF EXISTS/IF NOT EXISTSguards
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:
-
scoringEvents.eventDate(datecolumn,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. -
playoffMatchGames.scheduledAt(timestamp) — used for individual games within a bracket match. Bracket events often haveeventDate = nullon the scoring event itself.
Pattern for date-range queries: Two-step approach:
selectDistinctevent IDs via left joins throughplayoffMatches → playoffMatchGames, filtering:eventDate IN [dates] OR (scheduledAt >= dayStart AND scheduledAt <= dayEnd)findManyon 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.