Skip to content

Commit 5cff353

Browse files
authored
Unify table level foreign key conversion in sql2pgroll (#628)
This PR unifies FK constraints in `sql2pgroll` package. The new function `convertFkConstraint` in is the unified way to process table level FK constraints of columns and tables.
1 parent ee84b88 commit 5cff353

File tree

7 files changed

+327
-210
lines changed

7 files changed

+327
-210
lines changed

pkg/sql2pgroll/alter_table.go

Lines changed: 10 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -185,83 +185,27 @@ func convertAlterTableAddForeignKeyConstraint(stmt *pgq.AlterTableStmt, constrai
185185
return nil, nil
186186
}
187187

188-
columns := make([]string, len(constraint.GetFkAttrs()))
189-
for i := range columns {
190-
columns[i] = constraint.GetFkAttrs()[i].GetString_().GetSval()
191-
}
192-
193-
foreignColumns := make([]string, len(constraint.GetPkAttrs()))
194-
for i := range columns {
195-
foreignColumns[i] = constraint.GetPkAttrs()[i].GetString_().GetSval()
196-
}
188+
tableName := getQualifiedRelationName(stmt.Relation)
189+
columns, references := convertFkConstraint(constraint)
197190

198191
migs := make(map[string]string)
199192
for _, column := range columns {
200193
migs[column] = PlaceHolderSQL
201194
}
202195

203-
onDelete, err := parseOnDeleteAction(constraint.GetFkDelAction())
204-
if err != nil {
205-
return nil, fmt.Errorf("failed to parse on delete action: %w", err)
206-
}
207-
208-
tableName := getQualifiedRelationName(stmt.Relation)
209-
foreignTable := getQualifiedRelationName(constraint.GetPktable())
210-
211196
return &migrations.OpCreateConstraint{
212-
Columns: columns,
213-
Up: migs,
214-
Down: migs,
215-
Name: constraint.GetConname(),
216-
References: &migrations.TableForeignKeyReference{
217-
Columns: foreignColumns,
218-
OnDelete: onDelete,
219-
Table: foreignTable,
220-
},
221-
Table: tableName,
222-
Type: migrations.OpCreateConstraintTypeForeignKey,
197+
Columns: columns,
198+
Up: migs,
199+
Down: migs,
200+
Name: constraint.GetConname(),
201+
References: references,
202+
Table: tableName,
203+
Type: migrations.OpCreateConstraintTypeForeignKey,
223204
}, nil
224205
}
225206

226-
func parseOnDeleteAction(action string) (migrations.ForeignKeyAction, error) {
227-
switch action {
228-
case "a":
229-
return migrations.ForeignKeyActionNOACTION, nil
230-
case "c":
231-
return migrations.ForeignKeyActionCASCADE, nil
232-
case "r":
233-
return migrations.ForeignKeyActionRESTRICT, nil
234-
case "d":
235-
return migrations.ForeignKeyActionSETDEFAULT, nil
236-
case "n":
237-
return migrations.ForeignKeyActionSETNULL, nil
238-
default:
239-
return migrations.ForeignKeyActionNOACTION, fmt.Errorf("unknown delete action: %q", action)
240-
}
241-
}
242-
243207
func canConvertForeignKeyConstraint(constraint *pgq.Constraint) bool {
244-
if constraint.SkipValidation {
245-
return false
246-
}
247-
248-
switch constraint.GetFkUpdAction() {
249-
case "r", "c", "n", "d":
250-
// RESTRICT, CASCADE, SET NULL, SET DEFAULT
251-
return false
252-
case "a":
253-
// NO ACTION, the default
254-
break
255-
}
256-
switch constraint.GetFkMatchtype() {
257-
case "f":
258-
// FULL
259-
return false
260-
case "s":
261-
// SIMPLE, the default
262-
break
263-
}
264-
return true
208+
return !constraint.SkipValidation
265209
}
266210

267211
// convertAlterTableAddCheckConstraint converts SQL statements like:

pkg/sql2pgroll/alter_table_test.go

Lines changed: 64 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -90,23 +90,35 @@ func TestConvertAlterTableStatements(t *testing.T) {
9090
},
9191
{
9292
sql: "ALTER TABLE foo ADD CONSTRAINT fk_bar_cd FOREIGN KEY (a, b) REFERENCES bar (c, d);",
93-
expectedOp: expect.AddForeignKeyOp1WithOnDelete(migrations.ForeignKeyActionNOACTION),
93+
expectedOp: expect.AddForeignKeyOp1WithParams(migrations.ForeignKeyMatchTypeSIMPLE, migrations.ForeignKeyActionNOACTION, migrations.ForeignKeyActionNOACTION),
9494
},
9595
{
9696
sql: "ALTER TABLE foo ADD CONSTRAINT fk_bar_cd FOREIGN KEY (a, b) REFERENCES bar (c, d) ON DELETE NO ACTION;",
97-
expectedOp: expect.AddForeignKeyOp1WithOnDelete(migrations.ForeignKeyActionNOACTION),
97+
expectedOp: expect.AddForeignKeyOp1WithParams(migrations.ForeignKeyMatchTypeSIMPLE, migrations.ForeignKeyActionNOACTION, migrations.ForeignKeyActionNOACTION),
9898
},
9999
{
100100
sql: "ALTER TABLE foo ADD CONSTRAINT fk_bar_cd FOREIGN KEY (a, b) REFERENCES bar (c, d) ON DELETE RESTRICT;",
101-
expectedOp: expect.AddForeignKeyOp1WithOnDelete(migrations.ForeignKeyActionRESTRICT),
101+
expectedOp: expect.AddForeignKeyOp1WithParams(migrations.ForeignKeyMatchTypeSIMPLE, migrations.ForeignKeyActionRESTRICT, migrations.ForeignKeyActionNOACTION),
102102
},
103103
{
104104
sql: "ALTER TABLE foo ADD CONSTRAINT fk_bar_cd FOREIGN KEY (a, b) REFERENCES bar (c, d) ON DELETE SET DEFAULT ;",
105-
expectedOp: expect.AddForeignKeyOp1WithOnDelete(migrations.ForeignKeyActionSETDEFAULT),
105+
expectedOp: expect.AddForeignKeyOp1WithParams(migrations.ForeignKeyMatchTypeSIMPLE, migrations.ForeignKeyActionSETDEFAULT, migrations.ForeignKeyActionNOACTION),
106106
},
107107
{
108108
sql: "ALTER TABLE foo ADD CONSTRAINT fk_bar_cd FOREIGN KEY (a, b) REFERENCES bar (c, d) ON DELETE SET NULL;",
109-
expectedOp: expect.AddForeignKeyOp1WithOnDelete(migrations.ForeignKeyActionSETNULL),
109+
expectedOp: expect.AddForeignKeyOp1WithParams(migrations.ForeignKeyMatchTypeSIMPLE, migrations.ForeignKeyActionSETNULL, migrations.ForeignKeyActionNOACTION),
110+
},
111+
{
112+
sql: "ALTER TABLE foo ADD CONSTRAINT fk_bar_cd FOREIGN KEY (a, b) REFERENCES bar (c, d) ON DELETE RESTRICT ON UPDATE SET DEFAULT;",
113+
expectedOp: expect.AddForeignKeyOp1WithParams(migrations.ForeignKeyMatchTypeSIMPLE, migrations.ForeignKeyActionRESTRICT, migrations.ForeignKeyActionSETDEFAULT),
114+
},
115+
{
116+
sql: "ALTER TABLE foo ADD CONSTRAINT fk_bar_cd FOREIGN KEY (a, b) REFERENCES bar (c, d) ON DELETE SET DEFAULT ON UPDATE RESTRICT;",
117+
expectedOp: expect.AddForeignKeyOp1WithParams(migrations.ForeignKeyMatchTypeSIMPLE, migrations.ForeignKeyActionSETDEFAULT, migrations.ForeignKeyActionRESTRICT),
118+
},
119+
{
120+
sql: "ALTER TABLE foo ADD CONSTRAINT fk_bar_cd FOREIGN KEY (a, b) REFERENCES bar (c, d) MATCH FULL ON UPDATE SET NULL;",
121+
expectedOp: expect.AddForeignKeyOp1WithParams(migrations.ForeignKeyMatchTypeFULL, migrations.ForeignKeyActionNOACTION, migrations.ForeignKeyActionSETNULL),
110122
},
111123
{
112124
sql: "ALTER TABLE foo ADD CONSTRAINT fk_bar_c FOREIGN KEY (a) REFERENCES bar (c);",
@@ -195,32 +207,68 @@ func TestConvertAlterTableStatements(t *testing.T) {
195207
expectedOp: expect.AddColumnOp7,
196208
},
197209
{
198-
sql: "ALTER TABLE foo ADD COLUMN bar int CONSTRAINT fk_baz REFERENCES baz (bar)",
199-
expectedOp: expect.AddColumnOp8WithOnDeleteAction(migrations.ForeignKeyActionNOACTION),
210+
sql: "ALTER TABLE foo ADD COLUMN bar int CONSTRAINT fk_baz REFERENCES baz (bar) MATCH FULL",
211+
expectedOp: expect.AddColumnOp8WithOnDeleteAction(migrations.ForeignKeyActionNOACTION, migrations.ForeignKeyActionNOACTION, migrations.ForeignKeyMatchTypeFULL),
200212
},
201213
{
202214
sql: "ALTER TABLE foo ADD COLUMN bar int CONSTRAINT fk_baz REFERENCES baz (bar) ON UPDATE NO ACTION",
203-
expectedOp: expect.AddColumnOp8WithOnDeleteAction(migrations.ForeignKeyActionNOACTION),
215+
expectedOp: expect.AddColumnOp8WithOnDeleteAction(migrations.ForeignKeyActionNOACTION, migrations.ForeignKeyActionNOACTION, migrations.ForeignKeyMatchTypeSIMPLE),
204216
},
205217
{
206218
sql: "ALTER TABLE foo ADD COLUMN bar int CONSTRAINT fk_baz REFERENCES baz (bar) ON DELETE NO ACTION",
207-
expectedOp: expect.AddColumnOp8WithOnDeleteAction(migrations.ForeignKeyActionNOACTION),
219+
expectedOp: expect.AddColumnOp8WithOnDeleteAction(migrations.ForeignKeyActionNOACTION, migrations.ForeignKeyActionNOACTION, migrations.ForeignKeyMatchTypeSIMPLE),
208220
},
209221
{
210222
sql: "ALTER TABLE foo ADD COLUMN bar int CONSTRAINT fk_baz REFERENCES baz (bar) ON DELETE RESTRICT",
211-
expectedOp: expect.AddColumnOp8WithOnDeleteAction(migrations.ForeignKeyActionRESTRICT),
223+
expectedOp: expect.AddColumnOp8WithOnDeleteAction(migrations.ForeignKeyActionRESTRICT, migrations.ForeignKeyActionNOACTION, migrations.ForeignKeyMatchTypeSIMPLE),
224+
},
225+
{
226+
sql: "ALTER TABLE foo ADD COLUMN bar int CONSTRAINT fk_baz REFERENCES baz (bar) MATCH SIMPLE ON DELETE SET NULL ",
227+
expectedOp: expect.AddColumnOp8WithOnDeleteAction(migrations.ForeignKeyActionSETNULL, migrations.ForeignKeyActionNOACTION, migrations.ForeignKeyMatchTypeSIMPLE),
228+
},
229+
{
230+
sql: "ALTER TABLE foo ADD COLUMN bar int CONSTRAINT fk_baz REFERENCES baz (bar) ON DELETE SET DEFAULT ON UPDATE NO ACTION",
231+
expectedOp: expect.AddColumnOp8WithOnDeleteAction(migrations.ForeignKeyActionSETDEFAULT, migrations.ForeignKeyActionNOACTION, migrations.ForeignKeyMatchTypeSIMPLE),
232+
},
233+
{
234+
sql: "ALTER TABLE foo ADD COLUMN bar int CONSTRAINT fk_baz REFERENCES baz (bar) MATCH FULL ON DELETE CASCADE ON UPDATE CASCADE",
235+
expectedOp: expect.AddColumnOp8WithOnDeleteAction(migrations.ForeignKeyActionCASCADE, migrations.ForeignKeyActionCASCADE, migrations.ForeignKeyMatchTypeFULL),
236+
},
237+
{
238+
sql: "ALTER TABLE foo ADD COLUMN bar int REFERENCES baz (bar) ON UPDATE RESTRICT",
239+
expectedOp: expect.AddColumnOp9WithOnDeleteActionUnnamed("foo_bar_fkey", migrations.ForeignKeyActionNOACTION, migrations.ForeignKeyActionRESTRICT, migrations.ForeignKeyMatchTypeSIMPLE),
240+
},
241+
{
242+
sql: "ALTER TABLE foo ADD COLUMN bar int REFERENCES baz (bar) ON UPDATE CASCADE",
243+
expectedOp: expect.AddColumnOp9WithOnDeleteActionUnnamed("foo_bar_fkey", migrations.ForeignKeyActionNOACTION, migrations.ForeignKeyActionCASCADE, migrations.ForeignKeyMatchTypeSIMPLE),
244+
},
245+
{
246+
sql: "ALTER TABLE foo ADD COLUMN bar int REFERENCES baz (bar) ON UPDATE SET NULL",
247+
expectedOp: expect.AddColumnOp9WithOnDeleteActionUnnamed("foo_bar_fkey", migrations.ForeignKeyActionNOACTION, migrations.ForeignKeyActionSETNULL, migrations.ForeignKeyMatchTypeSIMPLE),
248+
},
249+
{
250+
sql: "ALTER TABLE foo ADD COLUMN bar int REFERENCES baz (bar) ON UPDATE SET DEFAULT",
251+
expectedOp: expect.AddColumnOp9WithOnDeleteActionUnnamed("foo_bar_fkey", migrations.ForeignKeyActionNOACTION, migrations.ForeignKeyActionSETDEFAULT, migrations.ForeignKeyMatchTypeSIMPLE),
252+
},
253+
{
254+
sql: "ALTER TABLE foo ADD CONSTRAINT fk_baz FOREIGN KEY (a, b) REFERENCES bar (c, d) ON UPDATE RESTRICT",
255+
expectedOp: expect.AddConstraintOp10ForeignKey(migrations.ForeignKeyActionNOACTION, migrations.ForeignKeyActionRESTRICT, migrations.ForeignKeyMatchTypeSIMPLE),
256+
},
257+
{
258+
sql: "ALTER TABLE foo ADD CONSTRAINT fk_baz FOREIGN KEY (a, b) REFERENCES bar (c, d) ON UPDATE CASCADE",
259+
expectedOp: expect.AddConstraintOp10ForeignKey(migrations.ForeignKeyActionNOACTION, migrations.ForeignKeyActionCASCADE, migrations.ForeignKeyMatchTypeSIMPLE),
212260
},
213261
{
214-
sql: "ALTER TABLE foo ADD COLUMN bar int CONSTRAINT fk_baz REFERENCES baz (bar) ON DELETE SET NULL ",
215-
expectedOp: expect.AddColumnOp8WithOnDeleteAction(migrations.ForeignKeyActionSETNULL),
262+
sql: "ALTER TABLE foo ADD CONSTRAINT fk_baz FOREIGN KEY (a, b) REFERENCES bar (c, d) ON UPDATE SET NULL",
263+
expectedOp: expect.AddConstraintOp10ForeignKey(migrations.ForeignKeyActionNOACTION, migrations.ForeignKeyActionSETNULL, migrations.ForeignKeyMatchTypeSIMPLE),
216264
},
217265
{
218-
sql: "ALTER TABLE foo ADD COLUMN bar int CONSTRAINT fk_baz REFERENCES baz (bar) ON DELETE SET DEFAULT",
219-
expectedOp: expect.AddColumnOp8WithOnDeleteAction(migrations.ForeignKeyActionSETDEFAULT),
266+
sql: "ALTER TABLE foo ADD CONSTRAINT fk_baz FOREIGN KEY (a, b) REFERENCES bar (c, d) ON UPDATE SET DEFAULT",
267+
expectedOp: expect.AddConstraintOp10ForeignKey(migrations.ForeignKeyActionNOACTION, migrations.ForeignKeyActionSETDEFAULT, migrations.ForeignKeyMatchTypeSIMPLE),
220268
},
221269
{
222-
sql: "ALTER TABLE foo ADD COLUMN bar int CONSTRAINT fk_baz REFERENCES baz (bar) ON DELETE CASCADE",
223-
expectedOp: expect.AddColumnOp8WithOnDeleteAction(migrations.ForeignKeyActionCASCADE),
270+
sql: "ALTER TABLE foo ADD CONSTRAINT fk_baz FOREIGN KEY (a, b) REFERENCES bar (c, d) MATCH FULL",
271+
expectedOp: expect.AddConstraintOp10ForeignKey(migrations.ForeignKeyActionNOACTION, migrations.ForeignKeyActionNOACTION, migrations.ForeignKeyMatchTypeFULL),
224272
},
225273
{
226274
sql: "ALTER TABLE foo ADD COLUMN bar int GENERATED BY DEFAULT AS IDENTITY ",
@@ -265,11 +313,6 @@ func TestUnconvertableAlterTableStatements(t *testing.T) {
265313
"ALTER TABLE foo DROP COLUMN IF EXISTS bar",
266314

267315
// Unsupported foreign key statements
268-
"ALTER TABLE foo ADD CONSTRAINT fk_bar_cd FOREIGN KEY (a, b) REFERENCES bar (c, d) ON UPDATE RESTRICT;",
269-
"ALTER TABLE foo ADD CONSTRAINT fk_bar_cd FOREIGN KEY (a, b) REFERENCES bar (c, d) ON UPDATE CASCADE;",
270-
"ALTER TABLE foo ADD CONSTRAINT fk_bar_cd FOREIGN KEY (a, b) REFERENCES bar (c, d) ON UPDATE SET NULL;",
271-
"ALTER TABLE foo ADD CONSTRAINT fk_bar_cd FOREIGN KEY (a, b) REFERENCES bar (c, d) ON UPDATE SET DEFAULT;",
272-
"ALTER TABLE foo ADD CONSTRAINT fk_bar_cd FOREIGN KEY (a, b) REFERENCES bar (c, d) MATCH FULL;",
273316
"ALTER TABLE foo ADD CONSTRAINT fk_bar_cd FOREIGN KEY (a, b) REFERENCES bar (c, d) NOT VALID",
274317
// MATCH PARTIAL is not implemented in the actual parser yet
275318
//"ALTER TABLE foo ADD CONSTRAINT fk_bar_cd FOREIGN KEY (a, b) REFERENCES bar (c, d) MATCH PARTIAL;",
@@ -283,10 +326,6 @@ func TestUnconvertableAlterTableStatements(t *testing.T) {
283326
"ALTER TABLE foo ADD CONSTRAINT bar CHECK (age > 0) NOT VALID",
284327

285328
// ADD COLUMN cases not yet covered
286-
"ALTER TABLE foo ADD COLUMN bar int REFERENCES bar (c) ON UPDATE RESTRICT",
287-
"ALTER TABLE foo ADD COLUMN bar int REFERENCES bar (c) ON UPDATE CASCADE",
288-
"ALTER TABLE foo ADD COLUMN bar int REFERENCES bar (c) ON UPDATE SET NULL",
289-
"ALTER TABLE foo ADD COLUMN bar int REFERENCES bar (c) ON UPDATE SET DEFAULT",
290329
"ALTER TABLE foo ADD COLUMN IF NOT EXISTS bar int",
291330
"ALTER TABLE foo ADD COLUMN bar int UNIQUE DEFERRABLE",
292331
"ALTER TABLE foo ADD COLUMN bar int UNIQUE INITIALLY DEFERRED",

pkg/sql2pgroll/create_table.go

Lines changed: 72 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,12 @@ var referentialAction = map[string]migrations.ForeignKeyAction{
1919
"r": migrations.ForeignKeyActionRESTRICT,
2020
}
2121

22+
var matchTypes = map[string]migrations.ForeignKeyMatchType{
23+
"s": migrations.ForeignKeyMatchTypeSIMPLE,
24+
"p": migrations.ForeignKeyMatchTypePARTIAL,
25+
"f": migrations.ForeignKeyMatchTypeFULL,
26+
}
27+
2228
// convertCreateStmt converts a CREATE TABLE statement to a pgroll operation.
2329
func convertCreateStmt(stmt *pgq.CreateStmt) (migrations.Operations, error) {
2430
// Check if the statement can be converted
@@ -270,45 +276,7 @@ func convertConstraint(c *pgq.Constraint) (*migrations.Constraint, error) {
270276
constraintType = migrations.ConstraintTypePrimaryKey
271277
case pgq.ConstrType_CONSTR_FOREIGN:
272278
constraintType = migrations.ConstraintTypeForeignKey
273-
referencedTable := c.Pktable.Relname
274-
referencedColumns := make([]string, len(c.PkAttrs))
275-
for i, node := range c.PkAttrs {
276-
referencedColumns[i] = node.GetString_().Sval
277-
}
278-
matchType := migrations.ForeignKeyMatchTypeSIMPLE
279-
switch c.FkMatchtype {
280-
case "p":
281-
matchType = migrations.ForeignKeyMatchTypePARTIAL
282-
case "f":
283-
matchType = migrations.ForeignKeyMatchTypeFULL
284-
case "s":
285-
matchType = migrations.ForeignKeyMatchTypeSIMPLE
286-
}
287-
columnsToSet := make([]string, len(c.FkDelSetCols))
288-
onDelete := migrations.ForeignKeyActionNOACTION
289-
if c.FkDelAction != "" {
290-
onDelete = referentialAction[c.FkDelAction]
291-
for i, node := range c.FkDelSetCols {
292-
columnsToSet[i] = node.GetString_().Sval
293-
}
294-
}
295-
onUpdate := migrations.ForeignKeyActionNOACTION
296-
if c.FkUpdAction != "" {
297-
onUpdate = referentialAction[c.FkUpdAction]
298-
}
299-
columns = make([]string, len(c.FkAttrs))
300-
for i, node := range c.FkAttrs {
301-
columns[i] = node.GetString_().Sval
302-
}
303-
304-
references = &migrations.TableForeignKeyReference{
305-
Table: referencedTable,
306-
Columns: referencedColumns,
307-
MatchType: matchType,
308-
OnDelete: onDelete,
309-
OnDeleteSetColumns: columnsToSet,
310-
OnUpdate: onUpdate,
311-
}
279+
columns, references = convertFkConstraint(c)
312280
case pgq.ConstrType_CONSTR_EXCLUSION:
313281
constraintType = migrations.ConstraintTypeExclude
314282
exclude = &migrations.ConstraintExclude{
@@ -379,6 +347,50 @@ func convertConstraint(c *pgq.Constraint) (*migrations.Constraint, error) {
379347
}, nil
380348
}
381349

350+
// convertFkConstraint converts a foreign key constraint to a table level foreign key constraint.
351+
func convertFkConstraint(c *pgq.Constraint) ([]string, *migrations.TableForeignKeyReference) {
352+
referencedTable := getQualifiedRelationName(c.GetPktable())
353+
referencedColumns := make([]string, len(c.PkAttrs))
354+
for i, node := range c.PkAttrs {
355+
referencedColumns[i] = node.GetString_().Sval
356+
}
357+
matchType := migrations.ForeignKeyMatchTypeSIMPLE
358+
if c.GetFkMatchtype() != "" {
359+
matchType = matchTypes[c.FkMatchtype]
360+
}
361+
var columnsToSet []string
362+
onDelete := migrations.ForeignKeyActionNOACTION
363+
if c.GetFkDelAction() != "" {
364+
onDelete = referentialAction[c.GetFkDelAction()]
365+
if c.GetFkDelSetCols() != nil {
366+
columnsToSet = make([]string, len(c.FkDelSetCols))
367+
for i, node := range c.FkDelSetCols {
368+
columnsToSet[i] = node.GetString_().Sval
369+
}
370+
}
371+
}
372+
onUpdate := migrations.ForeignKeyActionNOACTION
373+
if c.GetFkUpdAction() != "" {
374+
onUpdate = referentialAction[c.GetFkUpdAction()]
375+
}
376+
var columns []string
377+
if c.GetFkAttrs() != nil {
378+
columns = make([]string, len(c.GetFkAttrs()))
379+
for i, node := range c.GetFkAttrs() {
380+
columns[i] = node.GetString_().Sval
381+
}
382+
}
383+
384+
return columns, &migrations.TableForeignKeyReference{
385+
Table: referencedTable,
386+
Columns: referencedColumns,
387+
MatchType: matchType,
388+
OnDelete: onDelete,
389+
OnDeleteSetColumns: columnsToSet,
390+
OnUpdate: onUpdate,
391+
}
392+
}
393+
382394
// canConvertColumnDef returns true iff `col` can be converted to a pgroll
383395
// `Column` definition.
384396
func canConvertColumnDef(col *pgq.ColumnDef) bool {
@@ -440,9 +452,19 @@ func convertInlineForeignKeyConstraint(tableName, columnName string, constraint
440452
return nil, nil
441453
}
442454

443-
onDelete, err := parseOnDeleteAction(constraint.GetFkDelAction())
444-
if err != nil {
445-
return nil, err
455+
onDelete := migrations.ForeignKeyActionNOACTION
456+
if constraint.GetFkDelAction() != "" {
457+
onDelete = referentialAction[constraint.FkDelAction]
458+
}
459+
460+
onUpdate := migrations.ForeignKeyActionNOACTION
461+
if constraint.GetFkUpdAction() != "" {
462+
onUpdate = referentialAction[constraint.FkUpdAction]
463+
}
464+
465+
matchType := migrations.ForeignKeyMatchTypeSIMPLE
466+
if constraint.GetFkMatchtype() != "" {
467+
matchType = matchTypes[constraint.FkMatchtype]
446468
}
447469

448470
name := fmt.Sprintf("%s_%s_fkey", tableName, columnName)
@@ -451,10 +473,14 @@ func convertInlineForeignKeyConstraint(tableName, columnName string, constraint
451473
}
452474

453475
return &migrations.ForeignKeyReference{
454-
Name: name,
455-
OnDelete: onDelete,
456-
Column: constraint.GetPkAttrs()[0].GetString_().GetSval(),
457-
Table: getQualifiedRelationName(constraint.GetPktable()),
476+
Name: name,
477+
OnDelete: onDelete,
478+
OnUpdate: onUpdate,
479+
MatchType: matchType,
480+
Column: constraint.GetPkAttrs()[0].GetString_().GetSval(),
481+
Table: getQualifiedRelationName(constraint.GetPktable()),
482+
Deferrable: constraint.GetDeferrable(),
483+
InitiallyDeferred: constraint.GetInitdeferred(),
458484
}, nil
459485
}
460486

0 commit comments

Comments
 (0)