"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

Reply via email to