Deferred RI trigger for non-key UPDATEs and subxacts - Mailing list pgsql-patches
From | Affan Salman |
---|---|
Subject | Deferred RI trigger for non-key UPDATEs and subxacts |
Date | |
Msg-id | 469806F7.40502@enterprisedb.com Whole thread Raw |
Responses |
Re: Deferred RI trigger for non-key UPDATEs and subxacts
Re: Deferred RI trigger for non-key UPDATEs and subxacts |
List | pgsql-patches |
With some time to spare, I thought I'd submit a quick-fix patch to the issue I reported here: http://archives.postgresql.org/pgsql-hackers/2007-07/msg00339.php This should preclude optimizing away a deferred RI trigger if the UPDATEd row (in the FK table) was inserted by "current" transaction (i.e. defined by TransactionIdIsCurrentTransactionId()) and not necessarily "by our own transaction" as the code currently says. ________________________________________________________________________ backend/commands/trigger.c | 17 !!!!!!!!!!!!!!!!! test/regress/expected/foreign_key.out | 15 +++++++++++++++ test/regress/sql/foreign_key.sql | 19 +++++++++++++++++++ 3 files changed, 34 insertions(+), 17 modifications(!) ________________________________________________________________________ -- Affan Salman EnterpriseDB Corporation http://www.enterprisedb.com Index: src/backend/commands/trigger.c =================================================================== RCS file: /home/affan/repos/cvs/pgsql/pgsql/src/backend/commands/trigger.c,v retrieving revision 1.215 diff -p -c -b -r1.215 trigger.c *** src/backend/commands/trigger.c 1 Jul 2007 17:45:42 -0000 1.215 --- src/backend/commands/trigger.c 13 Jul 2007 20:13:13 -0000 *************** AfterTriggerSaveEvent(ResultRelInfo *rel *** 3389,3403 **** * Update on FK table * * There is one exception when updating FK tables: if the ! * updated row was inserted by our own transaction and the ! * FK is deferred, we still need to fire the trigger. This ! * is because our UPDATE will invalidate the INSERT so the ! * end-of-transaction INSERT RI trigger will not do ! * anything, so we have to do the check for the UPDATE ! * anyway. */ ! if (HeapTupleHeaderGetXmin(oldtup->t_data) != ! GetCurrentTransactionId() && RI_FKey_keyequal_upd_fk(trigger, rel, oldtup, newtup)) { continue; --- 3389,3404 ---- * Update on FK table * * There is one exception when updating FK tables: if the ! * updated row was inserted by "current" transaction (any ! * active or sub-committed xact from the local transaction ! * tree) and the FK is deferred, we still need to fire the ! * trigger. This is because our UPDATE will invalidate the ! * INSERT so the end-of-transaction INSERT RI trigger will ! * not do anything, so we have to do the check for the ! * UPDATE anyway. */ ! if (!TransactionIdIsCurrentTransactionId( ! HeapTupleHeaderGetXmin(oldtup->t_data)) && RI_FKey_keyequal_upd_fk(trigger, rel, oldtup, newtup)) { continue; Index: src/test/regress/sql/foreign_key.sql =================================================================== RCS file: /home/affan/repos/cvs/pgsql/pgsql/src/test/regress/sql/foreign_key.sql,v retrieving revision 1.19 diff -p -c -b -r1.19 foreign_key.sql *** src/test/regress/sql/foreign_key.sql 5 Jun 2007 21:31:09 -0000 1.19 --- src/test/regress/sql/foreign_key.sql 13 Jul 2007 21:22:56 -0000 *************** UPDATE fktable SET id = id + 1; *** 830,832 **** --- 830,851 ---- -- should catch error from initial INSERT COMMIT; + + -- Now test the same UPDATE from a SAVEPOINT to validate that we do + -- not optimize away the FK RI trigger when the transaction that + -- created the being-UPDATEd row isn't the same as the transaction + -- UPDATing the row; but is a "current" transaction. + + BEGIN; + + -- doesn't match PK, but no error yet + INSERT INTO fktable VALUES (0, 20); + + -- subxact for this SAVEPOINT will be active now + SAVEPOINT updSavept; + + -- don't change FK + UPDATE fktable SET id = id + 1; + + -- should catch error from initial INSERT + COMMIT; Index: src/test/regress/expected/foreign_key.out =================================================================== RCS file: /home/affan/repos/cvs/pgsql/pgsql/src/test/regress/expected/foreign_key.out,v retrieving revision 1.43 diff -p -c -b -r1.43 foreign_key.out *** src/test/regress/expected/foreign_key.out 5 Jun 2007 21:31:09 -0000 1.43 --- src/test/regress/expected/foreign_key.out 13 Jul 2007 21:23:12 -0000 *************** UPDATE fktable SET id = id + 1; *** 1193,1195 **** --- 1193,1210 ---- COMMIT; ERROR: insert or update on table "fktable" violates foreign key constraint "fktable_fk_fkey" DETAIL: Key (fk)=(20) is not present in table "pktable". + -- Now test the same UPDATE from a SAVEPOINT to validate that we do + -- not optimize away the FK RI trigger when the transaction that + -- created the being-UPDATEd row isn't the same as the transaction + -- UPDATing the row; but is a "current" transaction. + BEGIN; + -- doesn't match PK, but no error yet + INSERT INTO fktable VALUES (0, 20); + -- subxact for this SAVEPOINT will be active now + SAVEPOINT updSavept; + -- don't change FK + UPDATE fktable SET id = id + 1; + -- should catch error from initial INSERT + COMMIT; + ERROR: insert or update on table "fktable" violates foreign key constraint "fktable_fk_fkey" + DETAIL: Key (fk)=(20) is not present in table "pktable".
pgsql-patches by date: