- if ((junkfilter = estate->es_junkFilter) != NULL)
- {
- Datum datum;
- bool isNull;
-
- /*
- * extract the 'ctid' junk attribute.
- */
- if (operation == CMD_UPDATE || operation == CMD_DELETE)
- {
- if (!ExecGetJunkAttribute(junkfilter,
- slot,
- "ctid",
- &datum,
- &isNull))
- elog(ERROR, "could not find junk ctid column");
-
- /* shouldn't ever get a null result... */
- if (isNull)
- elog(ERROR, "ctid is NULL");
-
- tupleid = (ItemPointer) DatumGetPointer(datum);
- tuple_ctid = *tupleid; /* make sure we don't free the ctid!! */
- tupleid = &tuple_ctid;
- }
-
- /*
- * Process any FOR UPDATE or FOR SHARE locking requested.
- */
- else if (estate->es_rowMarks != NIL)
- {
- ListCell *l;
-
- lmark: ;
- foreach(l, estate->es_rowMarks)
- {
- ExecRowMark *erm = lfirst(l);
- HeapTupleData tuple;
- Buffer buffer;
- ItemPointerData update_ctid;
- TransactionId update_xmax;
- TupleTableSlot *newSlot;
- LockTupleMode lockmode;
- HTSU_Result test;
-
- if (!ExecGetJunkAttribute(junkfilter,
- slot,
- erm->resname,
- &datum,
- &isNull))
- elog(ERROR, "could not find junk \"%s\" column",
- erm->resname);
-
- /* shouldn't ever get a null result... */
- if (isNull)
- elog(ERROR, "\"%s\" is NULL", erm->resname);
-
- tuple.t_self = *((ItemPointer) DatumGetPointer(datum));
-
- if (erm->forUpdate)
- lockmode = LockTupleExclusive;
- else
- lockmode = LockTupleShared;
-
- test = heap_lock_tuple(erm->relation, &tuple, &buffer,
- &update_ctid, &update_xmax,
- estate->es_snapshot->curcid,
- lockmode, erm->noWait);
- ReleaseBuffer(buffer);
- switch (test)
- {
- case HeapTupleSelfUpdated:
- /* treat it as deleted; do not process */
- goto lnext;
-
- case HeapTupleMayBeUpdated:
- break;
-
- case HeapTupleUpdated:
- if (IsXactIsoLevelSerializable)
- ereport(ERROR,
- (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
- errmsg("could not serialize access due to concurrent update")));
- if (!ItemPointerEquals(&update_ctid,
- &tuple.t_self))
- {
- /* updated, so look at updated version */
- newSlot = EvalPlanQual(estate,
- erm->rti,
- &update_ctid,
- update_xmax,
- estate->es_snapshot->curcid);
- if (!TupIsNull(newSlot))
- {
- slot = newSlot;
- estate->es_useEvalPlan = true;
- goto lmark;
- }
- }
-
- /*
- * if tuple was deleted or PlanQual failed for
- * updated tuple - we must not return this tuple!
- */
- goto lnext;
-
- default:
- elog(ERROR, "unrecognized heap_lock_tuple status: %u",
- test);
- return NULL;
- }
- }
- }
-
- /*
- * Finally create a new "clean" tuple with all junk attributes
- * removed
- */
- slot = ExecFilterJunk(junkfilter, slot);
- }