aboutsummaryrefslogtreecommitdiff
path: root/src/backend/parser/analyze.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/parser/analyze.c')
-rw-r--r--src/backend/parser/analyze.c40
1 files changed, 22 insertions, 18 deletions
diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c
index fb6c44c11c8..bd78e949853 100644
--- a/src/backend/parser/analyze.c
+++ b/src/backend/parser/analyze.c
@@ -2358,7 +2358,7 @@ transformLockingClause(ParseState *pstate, Query *qry, LockingClause *lc,
allrels = makeNode(LockingClause);
allrels->lockedRels = NIL; /* indicates all rels */
allrels->strength = lc->strength;
- allrels->noWait = lc->noWait;
+ allrels->waitPolicy = lc->waitPolicy;
if (lockedRels == NIL)
{
@@ -2372,13 +2372,13 @@ transformLockingClause(ParseState *pstate, Query *qry, LockingClause *lc,
switch (rte->rtekind)
{
case RTE_RELATION:
- applyLockingClause(qry, i,
- lc->strength, lc->noWait, pushedDown);
+ applyLockingClause(qry, i, lc->strength, lc->waitPolicy,
+ pushedDown);
rte->requiredPerms |= ACL_SELECT_FOR_UPDATE;
break;
case RTE_SUBQUERY:
- applyLockingClause(qry, i,
- lc->strength, lc->noWait, pushedDown);
+ applyLockingClause(qry, i, lc->strength, lc->waitPolicy,
+ pushedDown);
/*
* FOR UPDATE/SHARE of subquery is propagated to all of
@@ -2424,15 +2424,13 @@ transformLockingClause(ParseState *pstate, Query *qry, LockingClause *lc,
switch (rte->rtekind)
{
case RTE_RELATION:
- applyLockingClause(qry, i,
- lc->strength, lc->noWait,
- pushedDown);
+ applyLockingClause(qry, i, lc->strength,
+ lc->waitPolicy, pushedDown);
rte->requiredPerms |= ACL_SELECT_FOR_UPDATE;
break;
case RTE_SUBQUERY:
- applyLockingClause(qry, i,
- lc->strength, lc->noWait,
- pushedDown);
+ applyLockingClause(qry, i, lc->strength,
+ lc->waitPolicy, pushedDown);
/* see comment above */
transformLockingClause(pstate, rte->subquery,
allrels, true);
@@ -2499,7 +2497,8 @@ transformLockingClause(ParseState *pstate, Query *qry, LockingClause *lc,
*/
void
applyLockingClause(Query *qry, Index rtindex,
- LockClauseStrength strength, bool noWait, bool pushedDown)
+ LockClauseStrength strength, LockWaitPolicy waitPolicy,
+ bool pushedDown)
{
RowMarkClause *rc;
@@ -2516,15 +2515,20 @@ applyLockingClause(Query *qry, Index rtindex,
* a shared and exclusive lock at the same time; it'll end up being
* exclusive anyway.)
*
- * We also consider that NOWAIT wins if it's specified both ways. This
- * is a bit more debatable but raising an error doesn't seem helpful.
- * (Consider for instance SELECT FOR UPDATE NOWAIT from a view that
- * internally contains a plain FOR UPDATE spec.)
+ * Similarly, if the same RTE is specified with more than one lock wait
+ * policy, consider that NOWAIT wins over SKIP LOCKED, which in turn
+ * wins over waiting for the lock (the default). This is a bit more
+ * debatable but raising an error doesn't seem helpful. (Consider for
+ * instance SELECT FOR UPDATE NOWAIT from a view that internally
+ * contains a plain FOR UPDATE spec.) Having NOWAIT win over SKIP
+ * LOCKED is reasonable since the former throws an error in case of
+ * coming across a locked tuple, which may be undesirable in some cases
+ * but it seems better than silently returning inconsistent results.
*
* And of course pushedDown becomes false if any clause is explicit.
*/
rc->strength = Max(rc->strength, strength);
- rc->noWait |= noWait;
+ rc->waitPolicy = Max(rc->waitPolicy, waitPolicy);
rc->pushedDown &= pushedDown;
return;
}
@@ -2533,7 +2537,7 @@ applyLockingClause(Query *qry, Index rtindex,
rc = makeNode(RowMarkClause);
rc->rti = rtindex;
rc->strength = strength;
- rc->noWait = noWait;
+ rc->waitPolicy = waitPolicy;
rc->pushedDown = pushedDown;
qry->rowMarks = lappend(qry->rowMarks, rc);
}