aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlvaro Herrera <alvherre@alvh.no-ip.org>2022-09-09 12:22:20 +0200
committerAlvaro Herrera <alvherre@alvh.no-ip.org>2022-09-09 12:22:20 +0200
commit68b0da67794e62df53d07956482770cbfbc5e786 (patch)
treeb68912103ca76687daa7d0f381b556a5b897938c /src
parent0a7c9ee50062e0f48cdd89b9c0e166ff59caabc8 (diff)
downloadpostgresql-68b0da67794e62df53d07956482770cbfbc5e786.tar.gz
postgresql-68b0da67794e62df53d07956482770cbfbc5e786.zip
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 f4566345cf40, 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
Diffstat (limited to 'src')
-rw-r--r--src/backend/commands/tablecmds.c12
1 files changed, 12 insertions, 0 deletions
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index f687a98bcc9..bc748f8e1ac 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -10615,6 +10615,9 @@ GetForeignKeyActionTriggers(Relation trigrel,
continue;
if (trgform->tgrelid != confrelid)
continue;
+ /* Only ever look at "action" triggers on the PK side. */
+ if (RI_FKey_trigger_type(trgform->tgfoid) != RI_TRIGGER_PK)
+ continue;
if (TRIGGER_FOR_DELETE(trgform->tgtype))
{
Assert(*deleteTriggerOid == InvalidOid);
@@ -10625,8 +10628,11 @@ GetForeignKeyActionTriggers(Relation trigrel,
Assert(*updateTriggerOid == InvalidOid);
*updateTriggerOid = trgform->oid;
}
+#ifndef USE_ASSERT_CHECKING
+ /* In an assert-enabled build, continue looking to find duplicates */
if (OidIsValid(*deleteTriggerOid) && OidIsValid(*updateTriggerOid))
break;
+#endif
}
if (!OidIsValid(*deleteTriggerOid))
@@ -10670,6 +10676,9 @@ GetForeignKeyCheckTriggers(Relation trigrel,
continue;
if (trgform->tgrelid != conrelid)
continue;
+ /* Only ever look at "check" triggers on the FK side. */
+ if (RI_FKey_trigger_type(trgform->tgfoid) != RI_TRIGGER_FK)
+ continue;
if (TRIGGER_FOR_INSERT(trgform->tgtype))
{
Assert(*insertTriggerOid == InvalidOid);
@@ -10680,8 +10689,11 @@ GetForeignKeyCheckTriggers(Relation trigrel,
Assert(*updateTriggerOid == InvalidOid);
*updateTriggerOid = trgform->oid;
}
+#ifndef USE_ASSERT_CHECKING
+ /* In an assert-enabled build, continue looking to find duplicates. */
if (OidIsValid(*insertTriggerOid) && OidIsValid(*updateTriggerOid))
break;
+#endif
}
if (!OidIsValid(*insertTriggerOid))