Skip to content

Commit 8c848cd

Browse files
committed
Fix GetForeignKey*Triggers for self-referential FKs
Because of inadequate filtering, the check triggers were confusing the search for action triggers in GetForeignKeyActionTriggers and vice-versa in GetForeignKeyCheckTriggers; this confusion results in seemingly random assertion failures, and can have real impact in non-asserting builds depending on catalog order. Change these functions so that they correctly ignore triggers that are not relevant to each side. To reduce the odds of further problems, do not break out of the searching loop in assertion builds. This break is likely to hide bugs; without it, we would have detected this bug immediately. This problem was introduced by f456634, so backpatch to 15 where that commit first appeared. Author: Amit Langote <amitlangote09@gmail.com> Discussion: https://postgr.es/m/20220908172029.sejft2ppckbo6oh5@awork3.anarazel.de Discussion: https://postgr.es/m/4104619.1662663056@sss.pgh.pa.us
1 parent 8b878bf commit 8c848cd

File tree

1 file changed

+12
-0
lines changed

1 file changed

+12
-0
lines changed

src/backend/commands/tablecmds.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10581,6 +10581,9 @@ GetForeignKeyActionTriggers(Relation trigrel,
1058110581
continue;
1058210582
if (trgform->tgrelid != confrelid)
1058310583
continue;
10584+
/* Only ever look at "action" triggers on the PK side. */
10585+
if (RI_FKey_trigger_type(trgform->tgfoid) != RI_TRIGGER_PK)
10586+
continue;
1058410587
if (TRIGGER_FOR_DELETE(trgform->tgtype))
1058510588
{
1058610589
Assert(*deleteTriggerOid == InvalidOid);
@@ -10591,8 +10594,11 @@ GetForeignKeyActionTriggers(Relation trigrel,
1059110594
Assert(*updateTriggerOid == InvalidOid);
1059210595
*updateTriggerOid = trgform->oid;
1059310596
}
10597+
#ifndef USE_ASSERT_CHECKING
10598+
/* In an assert-enabled build, continue looking to find duplicates */
1059410599
if (OidIsValid(*deleteTriggerOid) && OidIsValid(*updateTriggerOid))
1059510600
break;
10601+
#endif
1059610602
}
1059710603

1059810604
if (!OidIsValid(*deleteTriggerOid))
@@ -10636,6 +10642,9 @@ GetForeignKeyCheckTriggers(Relation trigrel,
1063610642
continue;
1063710643
if (trgform->tgrelid != conrelid)
1063810644
continue;
10645+
/* Only ever look at "check" triggers on the FK side. */
10646+
if (RI_FKey_trigger_type(trgform->tgfoid) != RI_TRIGGER_FK)
10647+
continue;
1063910648
if (TRIGGER_FOR_INSERT(trgform->tgtype))
1064010649
{
1064110650
Assert(*insertTriggerOid == InvalidOid);
@@ -10646,8 +10655,11 @@ GetForeignKeyCheckTriggers(Relation trigrel,
1064610655
Assert(*updateTriggerOid == InvalidOid);
1064710656
*updateTriggerOid = trgform->oid;
1064810657
}
10658+
#ifndef USE_ASSERT_CHECKING
10659+
/* In an assert-enabled build, continue looking to find duplicates. */
1064910660
if (OidIsValid(*insertTriggerOid) && OidIsValid(*updateTriggerOid))
1065010661
break;
10662+
#endif
1065110663
}
1065210664

1065310665
if (!OidIsValid(*insertTriggerOid))

0 commit comments

Comments
 (0)