Skip to content

Commit 1f2c642

Browse files
fix(schema): make agent_threads/messages migration work on fresh DBs
Wrap the migration with CREATE TABLE IF NOT EXISTS for both agent_threads and agent_messages so it runs cleanly on new deployments, not just databases where the Go API had already created the tables. Also drop any threads left without a user after backfill so the NOT NULL constraint can be enforced when the user table is empty. Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 0604aef commit 1f2c642

1 file changed

Lines changed: 31 additions & 6 deletions

File tree

drizzle/0044_agent_threads_messages.sql

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,39 @@
1-
-- Add user_id column to existing agent_threads table (created by Go API)
2-
-- For existing rows, we set a placeholder that must be backfilled
1+
-- Create agent_threads if it does not exist (fresh deployments).
2+
-- On existing deployments where the Go API already created the table,
3+
-- this is a no-op and the user_id column is added by the ALTER below.
4+
CREATE TABLE IF NOT EXISTS "agent_threads" (
5+
"id" text PRIMARY KEY NOT NULL,
6+
"title" text DEFAULT '' NOT NULL,
7+
"metadata" text DEFAULT '{}',
8+
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
9+
"updated_at" timestamp with time zone DEFAULT now() NOT NULL
10+
);
11+
--> statement-breakpoint
12+
-- Create agent_messages if it does not exist (fresh deployments).
13+
CREATE TABLE IF NOT EXISTS "agent_messages" (
14+
"id" text PRIMARY KEY NOT NULL,
15+
"thread_id" text NOT NULL,
16+
"role" text NOT NULL,
17+
"content" text DEFAULT '' NOT NULL,
18+
"tool_calls" text DEFAULT '[]',
19+
"tool_call_id" text DEFAULT '',
20+
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
21+
"seq" integer NOT NULL
22+
);
23+
--> statement-breakpoint
24+
-- Add user_id column to agent_threads (existing Go-API tables won't have it).
325
ALTER TABLE "agent_threads" ADD COLUMN IF NOT EXISTS "user_id" uuid;
426
--> statement-breakpoint
5-
-- Backfill existing threads: assign to the first user in the org from metadata
27+
-- Backfill existing threads: assign to the first user available.
28+
-- No-op on fresh deployments where the table is empty.
629
UPDATE "agent_threads" SET "user_id" = (
730
SELECT u.id FROM "user" u LIMIT 1
831
) WHERE "user_id" IS NULL;
932
--> statement-breakpoint
10-
-- Now make it NOT NULL
33+
-- If backfill could not find a user (e.g. fresh DB with empty user table),
34+
-- delete any orphaned threads so we can enforce NOT NULL.
35+
DELETE FROM "agent_threads" WHERE "user_id" IS NULL;
36+
--> statement-breakpoint
1137
ALTER TABLE "agent_threads" ALTER COLUMN "user_id" SET NOT NULL;
1238
--> statement-breakpoint
1339
DO $$ BEGIN
@@ -18,10 +44,9 @@ END $$;
1844
--> statement-breakpoint
1945
CREATE INDEX IF NOT EXISTS "idx_agent_threads_user" ON "agent_threads" USING btree ("user_id");
2046
--> statement-breakpoint
21-
-- Clean orphaned messages whose thread no longer exists
47+
-- Clean orphaned messages whose thread no longer exists.
2248
DELETE FROM "agent_messages" WHERE "thread_id" NOT IN (SELECT "id" FROM "agent_threads");
2349
--> statement-breakpoint
24-
-- Ensure agent_messages has FK to agent_threads
2550
DO $$ BEGIN
2651
ALTER TABLE "agent_messages" ADD CONSTRAINT "agent_messages_thread_id_agent_threads_id_fk" FOREIGN KEY ("thread_id") REFERENCES "public"."agent_threads"("id") ON DELETE cascade ON UPDATE no action;
2752
EXCEPTION

0 commit comments

Comments
 (0)