diff options
Diffstat (limited to 'src/backend/executor/execMain.c')
-rw-r--r-- | src/backend/executor/execMain.c | 32 |
1 files changed, 27 insertions, 5 deletions
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c index 1f70b2704ad..a0f9cfedd3f 100644 --- a/src/backend/executor/execMain.c +++ b/src/backend/executor/execMain.c @@ -26,7 +26,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.264 2006/01/11 08:43:12 neilc Exp $ + * $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.265 2006/01/12 21:48:53 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1213,7 +1213,8 @@ lnext: ; newSlot = EvalPlanQual(estate, erm->rti, &update_ctid, - update_xmax); + update_xmax, + estate->es_snapshot->curcid); if (!TupIsNull(newSlot)) { slot = newSlot; @@ -1521,7 +1522,8 @@ ldelete:; epqslot = EvalPlanQual(estate, resultRelInfo->ri_RangeTableIndex, &update_ctid, - update_xmax); + update_xmax, + estate->es_snapshot->curcid); if (!TupIsNull(epqslot)) { *tupleid = update_ctid; @@ -1673,7 +1675,8 @@ lreplace:; epqslot = EvalPlanQual(estate, resultRelInfo->ri_RangeTableIndex, &update_ctid, - update_xmax); + update_xmax, + estate->es_snapshot->curcid); if (!TupIsNull(epqslot)) { *tupleid = update_ctid; @@ -1820,6 +1823,7 @@ ExecConstraints(ResultRelInfo *resultRelInfo, * rti - rangetable index of table containing tuple * *tid - t_ctid from the outdated tuple (ie, next updated version) * priorXmax - t_xmax from the outdated tuple + * curCid - command ID of current command of my transaction * * *tid is also an output parameter: it's modified to hold the TID of the * latest version of the tuple (note this may be changed even on failure) @@ -1829,7 +1833,7 @@ ExecConstraints(ResultRelInfo *resultRelInfo, */ TupleTableSlot * EvalPlanQual(EState *estate, Index rti, - ItemPointer tid, TransactionId priorXmax) + ItemPointer tid, TransactionId priorXmax, CommandId curCid) { evalPlanQual *epq; EState *epqstate; @@ -1906,6 +1910,24 @@ EvalPlanQual(EState *estate, Index rti, } /* + * If tuple was inserted by our own transaction, we have to check + * cmin against curCid: cmin >= curCid means our command cannot + * see the tuple, so we should ignore it. Without this we are + * open to the "Halloween problem" of indefinitely re-updating + * the same tuple. (We need not check cmax because + * HeapTupleSatisfiesDirty will consider a tuple deleted by + * our transaction dead, regardless of cmax.) We just checked + * that priorXmax == xmin, so we can test that variable instead + * of doing HeapTupleHeaderGetXmin again. + */ + if (TransactionIdIsCurrentTransactionId(priorXmax) && + HeapTupleHeaderGetCmin(tuple.t_data) >= curCid) + { + ReleaseBuffer(buffer); + return NULL; + } + + /* * We got tuple - now copy it for use by recheck query. */ copyTuple = heap_copytuple(&tuple); |