Skip to content

Conversation

@kevin-courbet
Copy link

Description

Fixes a critical bug in PostgreSQL unique constraint introspection that causes drizzle-kit push to falsely detect missing constraints even when they exist in the database.

Problem

The current introspection query at pgSerializer.ts:1230-1236 uses information_schema.constraint_column_usage which creates a Cartesian product when joined with the columns table:

JOIN information_schema.constraint_column_usage AS ccu USING (constraint_schema, constraint_name)
JOIN information_schema.columns AS c ON c.table_schema = tc.constraint_schema
  AND tc.table_name = c.table_name AND ccu.column_name = c.column_name

This returns zero rows for multi-column unique constraints, causing drizzle-kit push to prompt users to add constraints that already exist.

Solution

Replace constraint_column_usage with key_column_usage (the standard PostgreSQL information_schema table for PRIMARY KEY and UNIQUE constraints) and properly join on:

  • constraint_name
  • constraint_schema
  • table_name

Added ORDER BY kcu.ordinal_position to preserve column order in multi-column constraints.

Testing

Before Fix

-- Returns 0 rows for multi-column unique constraint
SELECT c.column_name FROM information_schema.table_constraints tc
JOIN information_schema.constraint_column_usage AS ccu USING (constraint_schema, constraint_name)
JOIN information_schema.columns AS c ON c.table_schema = tc.constraint_schema
  AND tc.table_name = c.table_name AND ccu.column_name = c.column_name
WHERE tc.table_name = 'address' AND tc.constraint_type = 'UNIQUE';
-- Result: 0 rows

After Fix

-- Returns all columns in the constraint
SELECT kcu.column_name FROM information_schema.table_constraints tc
JOIN information_schema.key_column_usage kcu
  ON tc.constraint_name = kcu.constraint_name
  AND tc.constraint_schema = kcu.constraint_schema
  AND tc.table_name = kcu.table_name
WHERE tc.table_name = 'address' AND tc.constraint_type = 'UNIQUE'
ORDER BY kcu.ordinal_position;
-- Result: 5 rows (all columns in the unique constraint)

Impact

  • ✅ Fixes constraint detection for ALL multi-column unique constraints
  • ✅ Eliminates false "add constraint" prompts in drizzle-kit push
  • ✅ No breaking changes - only fixes broken introspection
  • ✅ Compatible with all PostgreSQL versions

Related Issues

Closes #4490
Closes #4531
Closes #4921

Checklist

  • Bug fix in drizzle-kit introspection
  • Tested with real PostgreSQL database
  • No breaking changes
  • Commit signed

Disclaimer: This PR was created with assistance from AI tools for bug diagnosis and documentation.

@kevin-courbet kevin-courbet force-pushed the fix/pg-unique-constraint-introspection branch 2 times, most recently from a5f9911 to a9ecb8f Compare November 15, 2025 00:39
The current query uses constraint_column_usage which creates a Cartesian
product when joined with the columns table, returning zero rows for
multi-column unique constraints.

This fix replaces constraint_column_usage with key_column_usage (the
standard table for PRIMARY KEY and UNIQUE constraints) and properly
joins on constraint_name, constraint_schema, and table_name.

Fixes drizzle-team#4490, drizzle-team#4531, drizzle-team#4921
@kevin-courbet kevin-courbet force-pushed the fix/pg-unique-constraint-introspection branch from a9ecb8f to 0d5330c Compare November 15, 2025 00:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant