"Kevin Grittner" <[email protected]> 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 ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers