drizzle-team / drizzle-team/drizzle-orm
[BUG]: drizzle-kit pull generates many() instead of one() for one-to-one relations (unique FK columns)
- Dominant language
- TypeScript
- Stars
- 35.8k
- Forks
- 1.6k
- Avg merge
- 2d 7h
- Merged PRs (30d)
- 4
Description
### Report hasn't been filed before.
- [x] I have verified that the bug I'm about to report hasn't been filed before.
### What version of `drizzle-orm` are you using?
1.0.0-beta.16
### What version of `drizzle-kit` are you using?
1.0.0-beta.16
### Other packages
_No response_
### Describe the Bug
**What is the undesired behavior?**
`drizzle-kit pull` generates `many()` for the reverse side of a one-to-one relationship. When a foreign key column has a `UNIQUE` constraint, the reverse relation should be `one()`, not `many()`.
**Steps to reproduce:**
Given this PostgreSQL schema:
```sql
CREATE TABLE users (
id uuid PRIMARY KEY DEFAULT gen_random_uuid()
);
CREATE TABLE profiles (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
user_id uuid UNIQUE NOT NULL REFERENCES users(id)
);
```
`user_id` is `UNIQUE`, so `users → profiles` is a one-to-one relationship.
Run `drizzle-kit pull`.
**Actual result:**
```typescript
export const usersRelations = relations(users, ({ many }) => ({
profiles: many(profiles), // incorrect — should be one()
}));
export const profilesRelations = relations(profiles, ({ one }) => ({
user: one(users, { fields: [profiles.userId], references: [users.id] }),
}));
```
**Desired result:**
```typescript
export const usersRelations = relations(users, ({ one }) => ({
profile: one(profiles), // one-to-one reverse
}));
export const profilesRelations = relations(profiles, ({ one }) => ({
user: one(users, { fields: [profiles.userId], references: [users.id] }),
}));
```
**Root cause:**
In `relationsToTypeScript`, the code checks `table.uniques` for a matching constraint on `columnsFrom`, but the comparison uses the **cased column names** (post-`withCasing`) against the raw unique constraint column names. When casing is applied (e.g., `camelCase` mode), `columnsFrom` becomes `["userId"]` while the unique constraint stores `["user_id"]`, so the `.every((col, i) => col === columnsFrom[i])` check always fails.
**Database:** PostgreSQL 18.3
Contributor guide
Assessment
This issue has not been assessed yet.