Skip to content

Commit 53db794

Browse files
authored
Add missing options to duplicated FK constraints (#671)
The new options in FK constraints (on update action, match type, etc.) were missing from the duplication process. Thus, the options set in the constraint disappeared after modifying columns with foreign key constraints.
1 parent 5cff353 commit 53db794

File tree

3 files changed

+23
-15
lines changed

3 files changed

+23
-15
lines changed

pkg/migrations/duplicate.go

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ const (
4242

4343
cSetDefaultSQL = `ALTER TABLE %s ALTER COLUMN %s SET DEFAULT %s`
4444
cAlterTableAddCheckConstraintSQL = `ALTER TABLE %s ADD CONSTRAINT %s %s NOT VALID`
45-
cAlterTableAddForeignKeySQL = `ALTER TABLE %s ADD CONSTRAINT %s FOREIGN KEY (%s) REFERENCES %s (%s) ON DELETE %s`
4645
)
4746

4847
// NewColumnDuplicator creates a new Duplicator for a column.
@@ -190,14 +189,20 @@ func (d *duplicatorStmtBuilder) duplicateForeignKeyConstraints(withoutConstraint
190189
continue
191190
}
192191
if duplicatedMember, constraintColumns := d.allConstraintColumns(fk.Columns, colNames...); duplicatedMember {
193-
stmts = append(stmts, fmt.Sprintf(cAlterTableAddForeignKeySQL,
194-
pq.QuoteIdentifier(d.table.Name),
195-
pq.QuoteIdentifier(DuplicationName(fk.Name)),
196-
strings.Join(quoteColumnNames(constraintColumns), ", "),
197-
pq.QuoteIdentifier(fk.ReferencedTable),
198-
strings.Join(quoteColumnNames(fk.ReferencedColumns), ", "),
199-
fk.OnDelete,
200-
))
192+
sql := fmt.Sprintf("ALTER TABLE %s ADD ", pq.QuoteIdentifier(d.table.Name))
193+
writer := ConstraintSQLWriter{
194+
Name: DuplicationName(fk.Name),
195+
Columns: constraintColumns,
196+
}
197+
sql += writer.WriteForeignKey(
198+
fk.ReferencedTable,
199+
fk.ReferencedColumns,
200+
ForeignKeyAction(fk.OnDelete),
201+
ForeignKeyAction(fk.OnUpdate),
202+
fk.OnDeleteSetColumns,
203+
ForeignKeyMatchType(fk.MatchType),
204+
)
205+
stmts = append(stmts, sql)
201206
}
202207
}
203208
return stmts

pkg/migrations/duplicate_test.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ var table = &schema.Table{
3434
},
3535
ForeignKeys: map[string]*schema.ForeignKey{
3636
"fk_city": {Name: "fk_city", Columns: []string{"city"}, ReferencedTable: "cities", ReferencedColumns: []string{"id"}, OnDelete: "NO ACTION"},
37-
"fk_name_nick": {Name: "fk_name_nick", Columns: []string{"name", "nick"}, ReferencedTable: "users", ReferencedColumns: []string{"name", "nick"}, OnDelete: "CASCADE"},
37+
"fk_name_nick": {Name: "fk_name_nick", Columns: []string{"name", "nick"}, ReferencedTable: "users", ReferencedColumns: []string{"name", "nick"}, OnDelete: "CASCADE", OnUpdate: "CASCADE", MatchType: "FULL"},
3838
},
3939
Indexes: map[string]*schema.Index{
4040
"idx_no_kate": {
@@ -115,30 +115,30 @@ func TestDuplicateStmtBuilderForeignKeyConstraints(t *testing.T) {
115115
"single-column FK with single column duplicated": {
116116
columns: []string{"city"},
117117
expectedStmts: []string{
118-
`ALTER TABLE "test_table" ADD CONSTRAINT "_pgroll_dup_fk_city" FOREIGN KEY ("_pgroll_new_city") REFERENCES "cities" ("id") ON DELETE NO ACTION`,
118+
`ALTER TABLE "test_table" ADD CONSTRAINT "_pgroll_dup_fk_city" FOREIGN KEY ("_pgroll_new_city") REFERENCES "cities" ("id") MATCH SIMPLE ON DELETE NO ACTION ON UPDATE NO ACTION`,
119119
},
120120
},
121121
"single-column FK with multiple columns duplicated": {
122122
columns: []string{"city", "description"},
123123
expectedStmts: []string{
124-
`ALTER TABLE "test_table" ADD CONSTRAINT "_pgroll_dup_fk_city" FOREIGN KEY ("_pgroll_new_city") REFERENCES "cities" ("id") ON DELETE NO ACTION`,
124+
`ALTER TABLE "test_table" ADD CONSTRAINT "_pgroll_dup_fk_city" FOREIGN KEY ("_pgroll_new_city") REFERENCES "cities" ("id") MATCH SIMPLE ON DELETE NO ACTION ON UPDATE NO ACTION`,
125125
},
126126
},
127127
"multi-column FK with single column duplicated": {
128128
columns: []string{"name"},
129129
expectedStmts: []string{
130-
`ALTER TABLE "test_table" ADD CONSTRAINT "_pgroll_dup_fk_name_nick" FOREIGN KEY ("_pgroll_new_name", "nick") REFERENCES "users" ("name", "nick") ON DELETE CASCADE`,
130+
`ALTER TABLE "test_table" ADD CONSTRAINT "_pgroll_dup_fk_name_nick" FOREIGN KEY ("_pgroll_new_name", "nick") REFERENCES "users" ("name", "nick") MATCH FULL ON DELETE CASCADE ON UPDATE CASCADE`,
131131
},
132132
},
133133
"multi-column FK with multiple unrelated column duplicated": {
134134
columns: []string{"name", "description"},
135135
expectedStmts: []string{
136-
`ALTER TABLE "test_table" ADD CONSTRAINT "_pgroll_dup_fk_name_nick" FOREIGN KEY ("_pgroll_new_name", "nick") REFERENCES "users" ("name", "nick") ON DELETE CASCADE`,
136+
`ALTER TABLE "test_table" ADD CONSTRAINT "_pgroll_dup_fk_name_nick" FOREIGN KEY ("_pgroll_new_name", "nick") REFERENCES "users" ("name", "nick") MATCH FULL ON DELETE CASCADE ON UPDATE CASCADE`,
137137
},
138138
},
139139
"multi-column FK with multiple columns": {
140140
columns: []string{"name", "nick"},
141-
expectedStmts: []string{`ALTER TABLE "test_table" ADD CONSTRAINT "_pgroll_dup_fk_name_nick" FOREIGN KEY ("_pgroll_new_name", "_pgroll_new_nick") REFERENCES "users" ("name", "nick") ON DELETE CASCADE`},
141+
expectedStmts: []string{`ALTER TABLE "test_table" ADD CONSTRAINT "_pgroll_dup_fk_name_nick" FOREIGN KEY ("_pgroll_new_name", "_pgroll_new_nick") REFERENCES "users" ("name", "nick") MATCH FULL ON DELETE CASCADE ON UPDATE CASCADE`},
142142
},
143143
} {
144144
t.Run(name, func(t *testing.T) {

pkg/schema/schema.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,9 @@ type ForeignKey struct {
132132
// The ON DELETE behavior of the foreign key
133133
OnDelete string `json:"onDelete"`
134134

135+
// OnDeleteSetColumns is the list of columns to update ON DELETE
136+
OnDeleteSetColumns []string `json:"onDeleteSetColumns"`
137+
135138
// The ON UPDATE behavior of the foreign key
136139
OnUpdate string `json:"onUpdate"`
137140

0 commit comments

Comments
 (0)