From 46527a52db2758864ff38a9638ddbdcf52b458ea Mon Sep 17 00:00:00 2001 From: ngoiyaeric <1.15367894e+08+ngoiyaeric@users.noreply.github.com> Date: Thu, 9 Jul 2026 20:08:21 +0000 Subject: [PATCH 1/2] fix: redirect all user_id FKs from auth.users to public.users for Clerk auth support Root cause: Clerk-authenticated users exist in public.users (with clerk_user_id mapping) but NOT in auth.users. The FK constraints on chats, messages, system_prompts, locations, visualizations, chat_participants, and prompt_generation_jobs pointed to auth.users.id, causing foreign key violations (23503) when inserting records for Clerk-authenticated users. Fix: All user_id FK constraints now reference public.users.id as the canonical identity table. This normalizes the schema so that public.users serves as the unified identity store for both Clerk and Supabase Auth users. Also adds performance indexes on all user_id columns. Note: The Supabase migration has already been applied to the production database via the Supabase MCP tool. This migration file is for schema tracking and drizzle-kit consistency. --- .../0005_fix_chat_db_fk_normalization.sql | 73 +++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 drizzle/migrations/0005_fix_chat_db_fk_normalization.sql diff --git a/drizzle/migrations/0005_fix_chat_db_fk_normalization.sql b/drizzle/migrations/0005_fix_chat_db_fk_normalization.sql new file mode 100644 index 00000000..0c4b5945 --- /dev/null +++ b/drizzle/migrations/0005_fix_chat_db_fk_normalization.sql @@ -0,0 +1,73 @@ +-- Migration: fix_chat_db_fk_normalization +-- Description: Redirect all user_id foreign keys from auth.users to public.users +-- to support Clerk-authenticated users who exist only in public.users. +-- This normalizes the schema so public.users is the canonical identity table. +-- Root cause: Clerk users authenticate via Clerk (not Supabase Auth), so their +-- user IDs exist in public.users but NOT in auth.users. The FK constraint +-- chats_user_id_fkey pointed to auth.users.id, causing foreign key violations +-- when inserting chats for Clerk-authenticated users. +-- +-- Note: The 0001_sync_schema_full.sql migration creates the tables with +-- correct public.users FKs, but pre-existing FKs from the original schema +-- (pointing to auth.users) may still exist in some deployments. +-- This migration ensures all FKs are corrected. + +-- Step 1: Drop all affected foreign key constraints referencing auth.users +ALTER TABLE public.chats + DROP CONSTRAINT IF EXISTS chats_user_id_fkey; + +ALTER TABLE public.messages + DROP CONSTRAINT IF EXISTS messages_user_id_fkey; + +ALTER TABLE public.system_prompts + DROP CONSTRAINT IF EXISTS system_prompts_user_id_fkey; + +ALTER TABLE public.locations + DROP CONSTRAINT IF EXISTS locations_user_id_fkey; + +ALTER TABLE public.visualizations + DROP CONSTRAINT IF EXISTS visualizations_user_id_fkey; + +ALTER TABLE public.chat_participants + DROP CONSTRAINT IF EXISTS chat_participants_user_id_fkey; + +ALTER TABLE public.prompt_generation_jobs + DROP CONSTRAINT IF EXISTS prompt_generation_jobs_user_id_fkey; + +-- Step 2: Add new foreign key constraints referencing public.users.id +ALTER TABLE public.chats + ADD CONSTRAINT chats_user_id_fkey + FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; + +ALTER TABLE public.messages + ADD CONSTRAINT messages_user_id_fkey + FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; + +ALTER TABLE public.system_prompts + ADD CONSTRAINT system_prompts_user_id_fkey + FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; + +ALTER TABLE public.locations + ADD CONSTRAINT locations_user_id_fkey + FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; + +ALTER TABLE public.visualizations + ADD CONSTRAINT visualizations_user_id_fkey + FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; + +ALTER TABLE public.chat_participants + ADD CONSTRAINT chat_participants_user_id_fkey + FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; + +ALTER TABLE public.prompt_generation_jobs + ADD CONSTRAINT prompt_generation_jobs_user_id_fkey + FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; + +-- Step 3: Add indexes on user_id columns for query performance +CREATE INDEX IF NOT EXISTS idx_chats_user_id ON public.chats(user_id); +CREATE INDEX IF NOT EXISTS idx_messages_user_id ON public.messages(user_id); +CREATE INDEX IF NOT EXISTS idx_system_prompts_user_id ON public.system_prompts(user_id); +CREATE INDEX IF NOT EXISTS idx_locations_user_id ON public.locations(user_id); +CREATE INDEX IF NOT EXISTS idx_visualizations_user_id ON public.visualizations(user_id); +CREATE INDEX IF NOT EXISTS idx_chat_participants_user_id ON public.chat_participants(user_id); +CREATE INDEX IF NOT EXISTS idx_prompt_generation_jobs_user_id ON public.prompt_generation_jobs(user_id); From cdb8fdd11af5c46d858c1ac33fb10ad9a049223c Mon Sep 17 00:00:00 2001 From: ngoiyaeric <1.15367894e+08+ngoiyaeric@users.noreply.github.com> Date: Thu, 9 Jul 2026 20:25:37 +0000 Subject: [PATCH 2/2] fix: use NOT VALID + VALIDATE for FK constraints, separate CONCURRENTLY indexes - Migration 0005: Drop old auth.users FKs, create new public.users FKs with NOT VALID to avoid blocking writes during creation, then VALIDATE CONSTRAINT to enforce. - Migration 0006: Separate file for CREATE INDEX CONCURRENTLY on user_id columns. Must run outside a transaction (drizzle-kit wraps in transaction). Includes manual execution instructions. Both changes reduce lock contention and prevent write-blocking during deployment. --- .../0005_fix_chat_db_fk_normalization.sql | 51 ++++++++++++------- .../migrations/0006_add_user_id_indexes.sql | 17 +++++++ 2 files changed, 51 insertions(+), 17 deletions(-) create mode 100644 drizzle/migrations/0006_add_user_id_indexes.sql diff --git a/drizzle/migrations/0005_fix_chat_db_fk_normalization.sql b/drizzle/migrations/0005_fix_chat_db_fk_normalization.sql index 0c4b5945..d7204b23 100644 --- a/drizzle/migrations/0005_fix_chat_db_fk_normalization.sql +++ b/drizzle/migrations/0005_fix_chat_db_fk_normalization.sql @@ -11,6 +11,10 @@ -- correct public.users FKs, but pre-existing FKs from the original schema -- (pointing to auth.users) may still exist in some deployments. -- This migration ensures all FKs are corrected. +-- +-- FK creation uses NOT VALID to avoid blocking writes during creation, +-- then VALIDATE CONSTRAINT is called separately to enforce the constraint +-- only after existing data is verified. See migration 0006 for index creation. -- Step 1: Drop all affected foreign key constraints referencing auth.users ALTER TABLE public.chats @@ -34,40 +38,53 @@ ALTER TABLE public.chat_participants ALTER TABLE public.prompt_generation_jobs DROP CONSTRAINT IF EXISTS prompt_generation_jobs_user_id_fkey; --- Step 2: Add new foreign key constraints referencing public.users.id +-- Step 2: Add new foreign key constraints referencing public.users.id (NOT VALID) ALTER TABLE public.chats ADD CONSTRAINT chats_user_id_fkey - FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; + FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE NOT VALID; ALTER TABLE public.messages ADD CONSTRAINT messages_user_id_fkey - FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; + FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE NOT VALID; ALTER TABLE public.system_prompts ADD CONSTRAINT system_prompts_user_id_fkey - FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; + FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE NOT VALID; ALTER TABLE public.locations ADD CONSTRAINT locations_user_id_fkey - FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; + FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE NOT VALID; ALTER TABLE public.visualizations ADD CONSTRAINT visualizations_user_id_fkey - FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; + FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE NOT VALID; ALTER TABLE public.chat_participants ADD CONSTRAINT chat_participants_user_id_fkey - FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; + FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE NOT VALID; ALTER TABLE public.prompt_generation_jobs ADD CONSTRAINT prompt_generation_jobs_user_id_fkey - FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; - --- Step 3: Add indexes on user_id columns for query performance -CREATE INDEX IF NOT EXISTS idx_chats_user_id ON public.chats(user_id); -CREATE INDEX IF NOT EXISTS idx_messages_user_id ON public.messages(user_id); -CREATE INDEX IF NOT EXISTS idx_system_prompts_user_id ON public.system_prompts(user_id); -CREATE INDEX IF NOT EXISTS idx_locations_user_id ON public.locations(user_id); -CREATE INDEX IF NOT EXISTS idx_visualizations_user_id ON public.visualizations(user_id); -CREATE INDEX IF NOT EXISTS idx_chat_participants_user_id ON public.chat_participants(user_id); -CREATE INDEX IF NOT EXISTS idx_prompt_generation_jobs_user_id ON public.prompt_generation_jobs(user_id); + FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE NOT VALID; + +-- Step 3: Validate all constraints (safe to run after data is verified) +ALTER TABLE public.chats + VALIDATE CONSTRAINT chats_user_id_fkey; + +ALTER TABLE public.messages + VALIDATE CONSTRAINT messages_user_id_fkey; + +ALTER TABLE public.system_prompts + VALIDATE CONSTRAINT system_prompts_user_id_fkey; + +ALTER TABLE public.locations + VALIDATE CONSTRAINT locations_user_id_fkey; + +ALTER TABLE public.visualizations + VALIDATE CONSTRAINT visualizations_user_id_fkey; + +ALTER TABLE public.chat_participants + VALIDATE CONSTRAINT chat_participants_user_id_fkey; + +ALTER TABLE public.prompt_generation_jobs + VALIDATE CONSTRAINT prompt_generation_jobs_user_id_fkey; diff --git a/drizzle/migrations/0006_add_user_id_indexes.sql b/drizzle/migrations/0006_add_user_id_indexes.sql new file mode 100644 index 00000000..a67ec00b --- /dev/null +++ b/drizzle/migrations/0006_add_user_id_indexes.sql @@ -0,0 +1,17 @@ +-- Migration: add_user_id_indexes +-- Description: Add performance indexes on user_id columns. +-- These use CREATE INDEX CONCURRENTLY to avoid blocking writes. +-- IMPORTANT: This migration MUST run outside a transaction. +-- CREATE INDEX CONCURRENTLY cannot execute inside a transaction block. +-- Run this file manually against the database: +-- psql $POSTGRES_URL -f 0006_add_user_id_indexes.sql +-- Or use the Supabase dashboard SQL editor (which does not wrap in transactions). +-- Do NOT use drizzle-kit migrate for this file; it wraps in a transaction. + +CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_chats_user_id ON public.chats(user_id); +CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_messages_user_id ON public.messages(user_id); +CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_system_prompts_user_id ON public.system_prompts(user_id); +CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_locations_user_id ON public.locations(user_id); +CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_visualizations_user_id ON public.visualizations(user_id); +CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_chat_participants_user_id ON public.chat_participants(user_id); +CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_prompt_generation_jobs_user_id ON public.prompt_generation_jobs(user_id);