diff options
Diffstat (limited to 'src/backend/executor/execMain.c')
-rw-r--r-- | src/backend/executor/execMain.c | 45 |
1 files changed, 30 insertions, 15 deletions
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c index a546292da6e..a753b207008 100644 --- a/src/backend/executor/execMain.c +++ b/src/backend/executor/execMain.c @@ -836,7 +836,7 @@ InitPlan(QueryDesc *queryDesc, int eflags) erm->prti = rc->prti; erm->rowmarkId = rc->rowmarkId; erm->markType = rc->markType; - erm->noWait = rc->noWait; + erm->waitPolicy = rc->waitPolicy; ItemPointerSetInvalid(&(erm->curCtid)); estate->es_rowMarks = lappend(estate->es_rowMarks, erm); } @@ -1871,7 +1871,7 @@ EvalPlanQual(EState *estate, EPQState *epqstate, /* * Get and lock the updated version of the row; if fail, return NULL. */ - copyTuple = EvalPlanQualFetch(estate, relation, lockmode, false /* wait */, + copyTuple = EvalPlanQualFetch(estate, relation, lockmode, LockWaitBlock, tid, priorXmax); if (copyTuple == NULL) @@ -1930,12 +1930,15 @@ EvalPlanQual(EState *estate, EPQState *epqstate, * estate - executor state data * relation - table containing tuple * lockmode - requested tuple lock mode - * noWait - wait mode to pass to heap_lock_tuple + * wait_policy - requested lock wait policy * *tid - t_ctid from the outdated tuple (ie, next updated version) * priorXmax - t_xmax from the outdated tuple * * Returns a palloc'd copy of the newest tuple version, or NULL if we find * that there is no newest version (ie, the row was deleted not updated). + * We also return NULL if the tuple is locked and the wait policy is to skip + * such tuples. + * * If successful, we have locked the newest tuple version, so caller does not * need to worry about it changing anymore. * @@ -1943,7 +1946,8 @@ EvalPlanQual(EState *estate, EPQState *epqstate, * but we use "int" to avoid having to include heapam.h in executor.h. */ HeapTuple -EvalPlanQualFetch(EState *estate, Relation relation, int lockmode, bool noWait, +EvalPlanQualFetch(EState *estate, Relation relation, int lockmode, + LockWaitPolicy wait_policy, ItemPointer tid, TransactionId priorXmax) { HeapTuple copyTuple = NULL; @@ -1992,18 +1996,25 @@ EvalPlanQualFetch(EState *estate, Relation relation, int lockmode, bool noWait, if (TransactionIdIsValid(SnapshotDirty.xmax)) { ReleaseBuffer(buffer); - if (noWait) + switch (wait_policy) { - if (!ConditionalXactLockTableWait(SnapshotDirty.xmax)) - ereport(ERROR, - (errcode(ERRCODE_LOCK_NOT_AVAILABLE), - errmsg("could not obtain lock on row in relation \"%s\"", - RelationGetRelationName(relation)))); + case LockWaitBlock: + XactLockTableWait(SnapshotDirty.xmax, + relation, &tuple.t_data->t_ctid, + XLTW_FetchUpdated); + break; + case LockWaitSkip: + if (!ConditionalXactLockTableWait(SnapshotDirty.xmax)) + return NULL; /* skip instead of waiting */ + break; + case LockWaitError: + if (!ConditionalXactLockTableWait(SnapshotDirty.xmax)) + ereport(ERROR, + (errcode(ERRCODE_LOCK_NOT_AVAILABLE), + errmsg("could not obtain lock on row in relation \"%s\"", + RelationGetRelationName(relation)))); + break; } - else - XactLockTableWait(SnapshotDirty.xmax, - relation, &tuple.t_data->t_ctid, - XLTW_FetchUpdated); continue; /* loop back to repeat heap_fetch */ } @@ -2030,7 +2041,7 @@ EvalPlanQualFetch(EState *estate, Relation relation, int lockmode, bool noWait, */ test = heap_lock_tuple(relation, &tuple, estate->es_output_cid, - lockmode, noWait, + lockmode, wait_policy, false, &buffer, &hufd); /* We now have two pins on the buffer, get rid of one */ ReleaseBuffer(buffer); @@ -2076,6 +2087,10 @@ EvalPlanQualFetch(EState *estate, Relation relation, int lockmode, bool noWait, /* tuple was deleted, so give up */ return NULL; + case HeapTupleWouldBlock: + ReleaseBuffer(buffer); + return NULL; + default: ReleaseBuffer(buffer); elog(ERROR, "unrecognized heap_lock_tuple status: %u", |