"Kevin Grittner" <kevin.gritt...@wicourts.gov> wrote: > I believe that we can get DELETE behavior which is every bit as > sensible as INSERT behavior with a very small change. > I think the right thing is to throw an error if the old row for a > BEFORE UPDATE is updated by the same transaction and the trigger > function ultimately returns a non-NULL value. And to make this a bit less hand-wavy, a rough patch attached. I expect the error message could use some word-smithing, and it could use comments; but it seemed like something concrete might speed things along. -Kevin
*** a/src/backend/executor/execMain.c --- b/src/backend/executor/execMain.c *************** *** 1847,1854 **** EvalPlanQualFetch(EState *estate, Relation relation, int lockmode, switch (test) { case HeapTupleSelfUpdated: - /* treat it as deleted; do not process */ ReleaseBuffer(buffer); return NULL; case HeapTupleMayBeUpdated: --- 1847,1862 ---- switch (test) { case HeapTupleSelfUpdated: ReleaseBuffer(buffer); + if (!ItemPointerEquals(&update_ctid, &tuple.t_self)) + { + /* it was updated, so look at the updated version */ + tuple.t_self = update_ctid; + /* updated row should have xmin matching this xmax */ + priorXmax = update_xmax; + continue; + } + /* treat it as deleted; do not process */ return NULL; case HeapTupleMayBeUpdated: *** a/src/backend/executor/nodeModifyTable.c --- b/src/backend/executor/nodeModifyTable.c *************** *** 354,359 **** ldelete:; --- 354,375 ---- switch (result) { case HeapTupleSelfUpdated: + if (!ItemPointerEquals(tupleid, &update_ctid)) + { + HeapTuple copyTuple; + + estate->es_output_cid = GetCurrentCommandId(false); + copyTuple = EvalPlanQualFetch(estate, + resultRelationDesc, + LockTupleExclusive, + &update_ctid, + update_xmax); + if (copyTuple != NULL) + { + *tupleid = update_ctid = copyTuple->t_self; + goto ldelete; + } + } /* already deleted by self; nothing to do */ return NULL; *************** *** 570,575 **** lreplace:; --- 586,595 ---- switch (result) { case HeapTupleSelfUpdated: + if (!ItemPointerEquals(tupleid, &update_ctid)) + ereport(ERROR, + (errcode(ERRCODE_TRIGGERED_ACTION_EXCEPTION), + errmsg("row modified by same transaction during trigger execution"))); /* already deleted by self; nothing to do */ return NULL;
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers