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:
@@ -273,6 +273,13 @@ func (w *Writer) constraintToDBML(c *models.Constraint, t *models.Table) string
|
||||
actions = append(actions, fmt.Sprintf("update: %s", c.OnUpdate))
|
||||
}
|
||||
|
||||
if c.Deferrable != nil && *c.Deferrable {
|
||||
actions = append(actions, "deferrable")
|
||||
}
|
||||
if c.InitiallyDeferred != nil && *c.InitiallyDeferred {
|
||||
actions = append(actions, "initially deferred")
|
||||
}
|
||||
|
||||
refLine := fmt.Sprintf("Ref: %s %s %s", fromRef, relationship, toRef)
|
||||
if len(actions) > 0 {
|
||||
refLine += fmt.Sprintf(" [%s]", strings.Join(actions, ", "))
|
||||
|
||||
@@ -171,3 +171,31 @@ func TestWriter_WriteDatabase_OneToOneRelationship(t *testing.T) {
|
||||
|
||||
assert.Contains(t, output, "Ref: public.profiles.user_id - public.users.id")
|
||||
}
|
||||
|
||||
func TestWriter_WriteDatabase_ForeignKeyDeferral(t *testing.T) {
|
||||
yes := true
|
||||
db := models.InitDatabase("test_db")
|
||||
schema := models.InitSchema("public")
|
||||
users := models.InitTable("users", "public")
|
||||
users.Columns["id"] = models.InitColumn("id", "users", "public")
|
||||
users.Columns["id"].Type = "bigint"
|
||||
posts := models.InitTable("posts", "public")
|
||||
posts.Columns["user_id"] = models.InitColumn("user_id", "posts", "public")
|
||||
posts.Columns["user_id"].Type = "bigint"
|
||||
fk := models.InitConstraint("fk_posts_user", models.ForeignKeyConstraint)
|
||||
fk.Table, fk.Schema = "posts", "public"
|
||||
fk.Columns = []string{"user_id"}
|
||||
fk.ReferencedTable, fk.ReferencedSchema = "users", "public"
|
||||
fk.ReferencedColumns = []string{"id"}
|
||||
fk.Deferrable = &yes
|
||||
fk.InitiallyDeferred = &yes
|
||||
posts.Constraints[fk.Name] = fk
|
||||
schema.Tables = append(schema.Tables, users, posts)
|
||||
db.Schemas = append(db.Schemas, schema)
|
||||
|
||||
outputPath := filepath.Join(t.TempDir(), "test.dbml")
|
||||
assert.NoError(t, NewWriter(&writers.WriterOptions{OutputPath: outputPath}).WriteDatabase(db))
|
||||
content, err := os.ReadFile(outputPath)
|
||||
assert.NoError(t, err)
|
||||
assert.Contains(t, string(content), "Ref: public.posts.user_id > public.users.id [deferrable, initially deferred]")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user