Skip to content

Commit 1e3b21d

Browse files
committed
Change FK trigger naming convention to fix self-referential FKs.
Use names like "RI_ConstraintTrigger_a_NNNN" for FK action triggers and "RI_ConstraintTrigger_c_NNNN" for FK check triggers. This ensures the action trigger fires first in self-referential cases where the very same row update fires both an action and a check trigger. This change provides a non-probabilistic solution for bug #6268, at the risk that it could break client code that is making assumptions about the exact names assigned to auto-generated FK triggers. Hence, change this in HEAD only. No need for forced initdb since old triggers continue to work fine.
1 parent 5895872 commit 1e3b21d

File tree

1 file changed

+12
-14
lines changed

1 file changed

+12
-14
lines changed

src/backend/commands/tablecmds.c

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6467,8 +6467,17 @@ CreateFKCheckTrigger(RangeVar *myRel, Constraint *fkconstraint,
64676467
{
64686468
CreateTrigStmt *fk_trigger;
64696469

6470+
/*
6471+
* Note: for a self-referential FK (referencing and referenced tables are
6472+
* the same), it is important that the ON UPDATE action fires before the
6473+
* CHECK action, since both triggers will fire on the same row during an
6474+
* UPDATE event; otherwise the CHECK trigger will be checking a non-final
6475+
* state of the row. Triggers fire in name order, so we ensure this by
6476+
* using names like "RI_ConstraintTrigger_a_NNNN" for the action triggers
6477+
* and "RI_ConstraintTrigger_c_NNNN" for the check triggers.
6478+
*/
64706479
fk_trigger = makeNode(CreateTrigStmt);
6471-
fk_trigger->trigname = "RI_ConstraintTrigger";
6480+
fk_trigger->trigname = "RI_ConstraintTrigger_c";
64726481
fk_trigger->relation = myRel;
64736482
fk_trigger->row = true;
64746483
fk_trigger->timing = TRIGGER_TYPE_AFTER;
@@ -6524,7 +6533,7 @@ createForeignKeyTriggers(Relation rel, Constraint *fkconstraint,
65246533
* DELETE action on the referenced table.
65256534
*/
65266535
fk_trigger = makeNode(CreateTrigStmt);
6527-
fk_trigger->trigname = "RI_ConstraintTrigger";
6536+
fk_trigger->trigname = "RI_ConstraintTrigger_a";
65286537
fk_trigger->relation = fkconstraint->pktable;
65296538
fk_trigger->row = true;
65306539
fk_trigger->timing = TRIGGER_TYPE_AFTER;
@@ -6577,7 +6586,7 @@ createForeignKeyTriggers(Relation rel, Constraint *fkconstraint,
65776586
* UPDATE action on the referenced table.
65786587
*/
65796588
fk_trigger = makeNode(CreateTrigStmt);
6580-
fk_trigger->trigname = "RI_ConstraintTrigger";
6589+
fk_trigger->trigname = "RI_ConstraintTrigger_a";
65816590
fk_trigger->relation = fkconstraint->pktable;
65826591
fk_trigger->row = true;
65836592
fk_trigger->timing = TRIGGER_TYPE_AFTER;
@@ -6628,17 +6637,6 @@ createForeignKeyTriggers(Relation rel, Constraint *fkconstraint,
66286637
/*
66296638
* Build and execute CREATE CONSTRAINT TRIGGER statements for the CHECK
66306639
* action for both INSERTs and UPDATEs on the referencing table.
6631-
*
6632-
* Note: for a self-referential FK (referencing and referenced tables are
6633-
* the same), it is important that the ON UPDATE action fires before the
6634-
* CHECK action, since both triggers will fire on the same row during an
6635-
* UPDATE event; otherwise the CHECK trigger will be checking a non-final
6636-
* state of the row. Because triggers fire in name order, we are
6637-
* effectively relying on the OIDs of the triggers to sort correctly as
6638-
* text. This will work except when the OID counter wraps around or adds
6639-
* a digit, eg "99999" sorts after "100000". That is infrequent enough,
6640-
* and the use of self-referential FKs is rare enough, that we live with
6641-
* it for now. There will be a real fix in PG 9.2.
66426640
*/
66436641
CreateFKCheckTrigger(myRel, fkconstraint, constraintOid, indexOid, true);
66446642
CreateFKCheckTrigger(myRel, fkconstraint, constraintOid, indexOid, false);

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy