/* clear any leftover test tuple for this rel */
markSlot = EvalPlanQualSlot(&node->lr_epqstate, erm->relation, erm->rti);
ExecClearTuple(markSlot);
/* if child rel, must check whether it produced this row */ if (erm->rti != erm->prti)
{
Oid tableoid;
datum = ExecGetJunkAttribute(slot,
aerm->toidAttNo,
&isNull); /* shouldn't ever get a null result... */ if (isNull)
elog(ERROR, "tableoid is NULL");
tableoid = DatumGetObjectId(datum);
Assert(OidIsValid(erm->relid)); if (tableoid != erm->relid)
{ /* this child is inactive right now */
erm->ermActive = false;
ItemPointerSetInvalid(&(erm->curCtid)); continue;
}
}
erm->ermActive = true;
/* fetch the tuple's ctid */
datum = ExecGetJunkAttribute(slot,
aerm->ctidAttNo,
&isNull); /* shouldn't ever get a null result... */ if (isNull)
elog(ERROR, "ctid is NULL");
/* requests for foreign tables must be passed to their FDW */ if (erm->relation->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
{
FdwRoutine *fdwroutine; bool updated = false;
fdwroutine = GetFdwRoutineForRelation(erm->relation, false); /* this should have been checked already, but let's be safe */ if (fdwroutine->RefetchForeignRow == NULL)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("cannot lock rows in foreign table \"%s\"",
RelationGetRelationName(erm->relation))));
fdwroutine->RefetchForeignRow(estate,
erm,
datum,
markSlot,
&updated); if (TupIsNull(markSlot))
{ /* couldn't get the lock, so skip this row */ goto lnext;
}
/* *ifFDWsaystuplewasupdatedbeforegettinglocked,weneedto *performEPQtestingtoseeifqualsarestillsatisfied
*/ if (updated)
epq_needed = true;
continue;
}
/* okay, try to lock (and fetch) the tuple */
tid = *((ItemPointer) DatumGetPointer(datum)); switch (erm->markType)
{ case ROW_MARK_EXCLUSIVE:
lockmode = LockTupleExclusive; break; case ROW_MARK_NOKEYEXCLUSIVE:
lockmode = LockTupleNoKeyExclusive; break; case ROW_MARK_SHARE:
lockmode = LockTupleShare; break; case ROW_MARK_KEYSHARE:
lockmode = LockTupleKeyShare; break; default:
elog(ERROR, "unsupported rowmark type");
lockmode = LockTupleNoKeyExclusive; /* keep compiler quiet */ break;
}
lockflags = TUPLE_LOCK_FLAG_LOCK_UPDATE_IN_PROGRESS; if (!IsolationUsesXactSnapshot())
lockflags |= TUPLE_LOCK_FLAG_FIND_LAST_VERSION;
/* *Gotthelocksuccessfully,thelockedtuplesavedin *markSlotfor,ifneeded,EvalPlanQualtestingbelow.
*/ if (tmfd.traversed)
epq_needed = true; break;
case TM_Updated: if (IsolationUsesXactSnapshot())
ereport(ERROR,
(errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
errmsg("could not serialize access due to concurrent update")));
elog(ERROR, "unexpected table_tuple_lock status: %u",
test); break;
case TM_Deleted: if (IsolationUsesXactSnapshot())
ereport(ERROR,
(errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
errmsg("could not serialize access due to concurrent update"))); /* tuple was deleted so don't return it */ goto lnext;
case TM_Invisible:
elog(ERROR, "attempted to lock invisible tuple"); break;
/* *Andfinallywecanre-evaluatethetuple.
*/
slot = EvalPlanQualNext(&node->lr_epqstate); if (TupIsNull(slot))
{ /* Updated tuple fails qual, so ignore it and go on */ goto lnext;
}
}
/* Got all locks, so return the current tuple */ return slot;
}
/* ---------------------------------------------------------------- *ExecInitLockRows * *ThisinitializestheLockRowsnodestatestructuresand *thenode'ssubplan. *----------------------------------------------------------------
*/
LockRowsState *
ExecInitLockRows(LockRows *node, EState *estate, int eflags)
{
LockRowsState *lrstate;
Plan *outerPlan = outerPlan(node);
List *epq_arowmarks;
ListCell *lc;
/* check for unsupported flags */
Assert(!(eflags & EXEC_FLAG_MARK));
/* Now we have the info needed to set up EPQ state */
EvalPlanQualInit(&lrstate->lr_epqstate, estate,
outerPlan, epq_arowmarks, node->epqParam, NIL);
return lrstate;
}
/* ---------------------------------------------------------------- *ExecEndLockRows * *Thisshutsdownthesubplanandfreesresourcesallocated *tothisnode. *----------------------------------------------------------------
*/ void
ExecEndLockRows(LockRowsState *node)
{ /* We may have shut down EPQ already, but no harm in another call */
EvalPlanQualEnd(&node->lr_epqstate);
ExecEndNode(outerPlanState(node));
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.