Skip to content

Commit 68b0da6

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 0a7c9ee commit 68b0da6

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
@@ -10615,6 +10615,9 @@ GetForeignKeyActionTriggers(Relation trigrel,
1061510615
continue;
1061610616
if (trgform->tgrelid != confrelid)
1061710617
continue;
10618+
/* Only ever look at "action" triggers on the PK side. */
10619+
if (RI_FKey_trigger_type(trgform->tgfoid) != RI_TRIGGER_PK)
10620+
continue;
1061810621
if (TRIGGER_FOR_DELETE(trgform->tgtype))
1061910622
{
1062010623
Assert(*deleteTriggerOid == InvalidOid);
@@ -10625,8 +10628,11 @@ GetForeignKeyActionTriggers(Relation trigrel,
1062510628
Assert(*updateTriggerOid == InvalidOid);
1062610629
*updateTriggerOid = trgform->oid;
1062710630
}
10631+
#ifndef USE_ASSERT_CHECKING
10632+
/* In an assert-enabled build, continue looking to find duplicates */
1062810633
if (OidIsValid(*deleteTriggerOid) && OidIsValid(*updateTriggerOid))
1062910634
break;
10635+
#endif
1063010636
}
1063110637

1063210638
if (!OidIsValid(*deleteTriggerOid))
@@ -10670,6 +10676,9 @@ GetForeignKeyCheckTriggers(Relation trigrel,
1067010676
continue;
1067110677
if (trgform->tgrelid != conrelid)
1067210678
continue;
10679+
/* Only ever look at "check" triggers on the FK side. */
10680+
if (RI_FKey_trigger_type(trgform->tgfoid) != RI_TRIGGER_FK)
10681+
continue;
1067310682
if (TRIGGER_FOR_INSERT(trgform->tgtype))
1067410683
{
1067510684
Assert(*insertTriggerOid == InvalidOid);
@@ -10680,8 +10689,11 @@ GetForeignKeyCheckTriggers(Relation trigrel,
1068010689
Assert(*updateTriggerOid == InvalidOid);
1068110690
*updateTriggerOid = trgform->oid;
1068210691
}
10692+
#ifndef USE_ASSERT_CHECKING
10693+
/* In an assert-enabled build, continue looking to find duplicates. */
1068310694
if (OidIsValid(*insertTriggerOid) && OidIsValid(*updateTriggerOid))
1068410695
break;
10696+
#endif
1068510697
}
1068610698

1068710699
if (!OidIsValid(*insertTriggerOid))

0 commit comments

Comments
 (0)