From cade580f4e0e0177112b84e855d1fe0e371f8fc5 Mon Sep 17 00:00:00 2001 From: aamoghS Date: Thu, 1 Oct 2026 16:00:06 -0400 Subject: [PATCH] fix(db): make bootcamp session uniqueness a unique index drizzle-kit introspects unique constraint columns with no ORDER BY. On Neon it read unique_bootcamp_session as (term, week), diffed it against the schema's (week, term), and tried to re-add it. Adding a unique constraint to a non-empty table opens a TTY prompt, which killed the App Hosting build before withdrawn_by_admin_at was pushed. Index columns are introspected by position, so a unique index with the same columns and null semantics diffs cleanly. Verified on a restored prod dump: push applies without a prompt, a second push is clean, and db:check passes. --- packages/db/src/schemas/events.ts | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/packages/db/src/schemas/events.ts b/packages/db/src/schemas/events.ts index d8faf932..f7ec73b8 100644 --- a/packages/db/src/schemas/events.ts +++ b/packages/db/src/schemas/events.ts @@ -7,6 +7,7 @@ import { integer, index, unique, + uniqueIndex, } from "drizzle-orm/pg-core"; import { relations } from "drizzle-orm"; import { users } from "./auth"; @@ -46,10 +47,14 @@ export const events = pgTable( }, (table) => [ // One event per week per bootcamp. Nulls count as distinct in Postgres, so - // ordinary events all carry (null, null) and never collide. Table order, not - // readability order: push introspects it this way and a reversed spelling - // diffs against itself forever. - unique("unique_bootcamp_session").on(table.bootcampWeek, table.bootcampTerm), + // ordinary events all carry (null, null) and never collide. A unique index, + // not a unique constraint: drizzle-kit reads a constraint's columns with no + // ORDER BY, so on Neon it saw them reversed, tried to re-add it, and push + // stopped at a TTY prompt mid-deploy. Index columns are read in order. + uniqueIndex("event_bootcamp_session_idx").on( + table.bootcampWeek, + table.bootcampTerm, + ), // Both bootcamp pages read every session of one term. index("event_bootcamp_term_idx").on(table.bootcampTerm), ],