drizzle-team / drizzle-team/drizzle-orm
[BUG]: drizzle-kit pull generates invalid through relations for composite foreign keys
- 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.15-859cf75
Also reproduced with `drizzle-orm@1.0.0-rc.4`.
### What version of `drizzle-kit` are you using?
1.0.0-beta.15-859cf75
Also reproduced by running `drizzle-kit@1.0.0-rc.4` against the same isolated PostgreSQL database.
### Other packages
_No response_
### Describe the Bug
`drizzle-kit pull` generates an invalid `relations.ts` when a table has exactly two foreign keys and one of them is composite.
The generated through relation has two problems:
1. It uses the through-table column names as columns on the referenced table.
2. It omits the `r.` prefix from the through-table references in the composite-key code path.
Consequently, importing the generated `relations.ts` throws at runtime.
#### Minimal reproduction
Using PostgreSQL, create these tables:
```sql
CREATE TABLE organizations (
id bigint NOT NULL,
tenant_id bigint NOT NULL,
PRIMARY KEY (id, tenant_id)
);
CREATE TABLE users (
id bigint PRIMARY KEY
);
CREATE TABLE assignments (
organization_id bigint NOT NULL,
organization_tenant_id bigint NOT NULL,
user_id bigint NOT NULL,
CONSTRAINT assignments_organization_fk
FOREIGN KEY (organization_id, organization_tenant_id)
REFERENCES organizations (id, tenant_id),
CONSTRAINT assignments_user_fk
FOREIGN KEY (user_id)
REFERENCES users (id)
);
```
Run:
```sh
drizzle-kit pull
```
Both beta.15 and RC.4 generate:
```typescript
organizations: {
users: r.many.users({
from: [
r.organizations.organizationId.through(assignments.organizationId),
r.organizations.organizationTenantId.through(assignments.organizationTenantId)
],
to: r.users.id.through(r.assignments.userId)
}),
},
```
This output is invalid because:
- `organizations.organizationId` does not exist; the referenced column is `organizations.id`.
- `organizations.organizationTenantId` does not exist; the referenced column is `organizations.tenantId`.
- `assignments.organizationId` and `assignments.organizationTenantId` are emitted without the required `r.` prefix.
Importing the generated file fails with:
```text
TypeError: undefined is not an object
(evaluating 'r.organizations.organizationId.through')
```
#### Expected output
```typescript
organizations: {
users: r.many.users({
from: [
r.organizations.id.through(r.assignments.organizationId),
r.organizations.tenantId.through(r.assignments.organizationTenantId)
],
to: r.users.id.through(r.assignments.userId)
}),
},
```
#### Apparent cause
The composite-key branches in `relationsToTypeScript` iterate over `columnsThroughFrom` / `columnsThroughTo` and use each through-column name on both tables:
```typescript
relation.columnsThroughFrom.map(
(it) => `r.${relation.tableFrom}.${it}.through(${relation.tableThrough}.${it})`
)
```
The generator needs to zip the referenced columns with the through columns and include `r.` before the through table, conceptually:
```typescript
relation.columnsThroughFrom.map(
(throughColumn, index) =>
`r.${relation.tableFrom}.${relation.columnsFrom[index]}.through(r.${relation.tableThrough}.${throughColumn})`
)
```
The same correction is needed for `columnsTo` / `columnsThroughTo`.
This is related to #5493 because both go through the inferred junction-table relation generator, but it is not the same bug. #5493 concerned reverse-relation alias matching and was fixed in beta.19; this composite-key template still produces the invalid output above in RC.4.
Contributor guide
Research direction
Start in relationsToTypeScript, focusing on the composite-key branches that process columnsThroughFrom and columnsThroughTo. Reproduce the issue with the PostgreSQL schema in the report, run drizzle-kit pull, and verify that the generated relations.ts uses the referenced columns and imports successfully for both relation directions.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- postgresql, typescript
- Domain
- backend-api-design, databases
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 75/100