feat(pgsql): unique constraints on apply, matching unique index names, FK deferral

- migration writer now emits unique constraints (direct apply and live diff
  previously dropped them); idempotent via the existing DO block
- unique constraint adopts a same-named model unique index with
  ADD CONSTRAINT ... UNIQUE USING INDEX instead of building a second index
- dbml reader names unnamed unique indexes ukey_<table>_<cols> to match the
  unique constraint naming
- foreign key deferral: Constraint.Deferrable/InitiallyDeferred are *bool
  (nil = unspecified, never diffed); writers emit DEFERRABLE, DEFERRABLE
  INITIALLY DEFERRED and NOT DEFERRABLE; live reader reads condeferrable and
  condeferred; dbml reader/writer support deferrable and initially deferred
- tests and README/naming docs updated
This commit is contained in:
2026-10-08 00:07:49 +02:00
parent 20f8dd82b6
commit b4f18f088b
20 changed files with 756 additions and 36 deletions
+25 -1
View File
@@ -86,16 +86,40 @@ Ref: posts.user_id > users.id [delete: cascade]
- Table definitions with columns
- Primary keys (`pk`)
- Not null constraints (`not null`)
- Unique constraints (`unique`)
- Unique constraints (`unique`) → constraint `ukey_<table>_<col>`
- Default values (`default`)
- Inline references (`ref`)
- Standalone `Ref` blocks
- FK deferral: `deferrable`, `initially deferred` (see below)
- Commented cross-file refs (`// Ref:` — see below)
- Indexes and composite indexes
- Table notes and column notes
- Enums
- Dialect directives (`@postgres:` / `@sqlite:` — see below)
## Naming
| Source | Generated name |
| ------ | -------------- |
| Column `[unique]` | constraint `ukey_<table>_<col>` |
| Unnamed unique index | index `ukey_<table>_<cols>` (same name as the constraint on the same columns) |
| Unnamed index | `idx_<table>_<cols>` |
Explicit `name:` is never changed. Leading `_` in the table name is stripped.
## FK deferral
```
col int [ref: > t.id, deferrable, initially deferred]
Ref: a.x > b.id [delete: cascade, deferrable]
```
| Setting | SQL |
| ------- | --- |
| `deferrable` | `DEFERRABLE` |
| `initially deferred` | `DEFERRABLE INITIALLY DEFERRED` |
| neither | unspecified (existing FK left as is) |
## Commented cross-file refs
`// Ref:` / `// ref:` lines (ignored by dbdiagram) become FKs + relationships once both ends are loaded.