diff options
Diffstat (limited to 'src/backend/optimizer')
-rw-r--r-- | src/backend/optimizer/plan/initsplan.c | 6 | ||||
-rw-r--r-- | src/backend/optimizer/plan/planner.c | 37 |
2 files changed, 27 insertions, 16 deletions
diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index 774b9d627dc..11d951cabea 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -861,11 +861,11 @@ make_outerjoininfo(PlannerInfo *root, Assert(jointype != JOIN_RIGHT); /* - * Presently the executor cannot support FOR UPDATE/SHARE marking of rels + * Presently the executor cannot support FOR [KEY] UPDATE/SHARE marking of rels * appearing on the nullable side of an outer join. (It's somewhat unclear * what that would mean, anyway: what should we mark when a result row is * generated from no element of the nullable relation?) So, complain if - * any nullable rel is FOR UPDATE/SHARE. + * any nullable rel is FOR [KEY] UPDATE/SHARE. * * You might be wondering why this test isn't made far upstream in the * parser. It's because the parser hasn't got enough info --- consider @@ -883,7 +883,7 @@ make_outerjoininfo(PlannerInfo *root, (jointype == JOIN_FULL && bms_is_member(rc->rti, left_rels))) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("SELECT FOR UPDATE/SHARE cannot be applied to the nullable side of an outer join"))); + errmsg("SELECT FOR UPDATE/SHARE/KEY UPDATE/KEY SHARE cannot be applied to the nullable side of an outer join"))); } sjinfo->syn_lefthand = left_rels; diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c index de975d8791d..3e75d3994cb 100644 --- a/src/backend/optimizer/plan/planner.c +++ b/src/backend/optimizer/plan/planner.c @@ -562,7 +562,7 @@ subquery_planner(PlannerGlobal *glob, Query *parse, returningLists = NIL; /* - * If there was a FOR UPDATE/SHARE clause, the LockRows node will + * If there was a FOR [KEY] UPDATE/SHARE clause, the LockRows node will * have dealt with fetching non-locked marked rows, else we need * to have ModifyTable do that. */ @@ -954,7 +954,7 @@ inheritance_planner(PlannerInfo *root) root->simple_rel_array = save_rel_array; /* - * If there was a FOR UPDATE/SHARE clause, the LockRows node will have + * If there was a FOR [KEY] UPDATE/SHARE clause, the LockRows node will have * dealt with fetching non-locked marked rows, else we need to have * ModifyTable do that. */ @@ -1065,13 +1065,13 @@ grouping_planner(PlannerInfo *root, double tuple_fraction) tlist); /* - * Can't handle FOR UPDATE/SHARE here (parser should have checked + * Can't handle FOR [KEY] UPDATE/SHARE here (parser should have checked * already, but let's make sure). */ if (parse->rowMarks) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("SELECT FOR UPDATE/SHARE is not allowed with UNION/INTERSECT/EXCEPT"))); + errmsg("SELECT FOR UPDATE/SHARE/KEY UPDATE/KEY SHARE is not allowed with UNION/INTERSECT/EXCEPT"))); /* * Calculate pathkeys that represent result ordering requirements @@ -1797,7 +1797,7 @@ grouping_planner(PlannerInfo *root, double tuple_fraction) } /* - * If there is a FOR UPDATE/SHARE clause, add the LockRows node. (Note: we + * If there is a FOR [KEY] UPDATE/SHARE clause, add the LockRows node. (Note: we * intentionally test parse->rowMarks not root->rowMarks here. If there * are only non-locking rowmarks, they should be handled by the * ModifyTable node instead.) @@ -1983,7 +1983,7 @@ preprocess_rowmarks(PlannerInfo *root) if (parse->rowMarks) { /* - * We've got trouble if FOR UPDATE/SHARE appears inside grouping, + * We've got trouble if FOR [KEY] UPDATE/SHARE appears inside grouping, * since grouping renders a reference to individual tuple CTIDs * invalid. This is also checked at parse time, but that's * insufficient because of rule substitution, query pullup, etc. @@ -1993,7 +1993,7 @@ preprocess_rowmarks(PlannerInfo *root) else { /* - * We only need rowmarks for UPDATE, DELETE, or FOR UPDATE/SHARE. + * We only need rowmarks for UPDATE, DELETE, or FOR [KEY] UPDATE/SHARE. */ if (parse->commandType != CMD_UPDATE && parse->commandType != CMD_DELETE) @@ -2003,7 +2003,7 @@ preprocess_rowmarks(PlannerInfo *root) /* * We need to have rowmarks for all base relations except the target. We * make a bitmapset of all base rels and then remove the items we don't - * need or have FOR UPDATE/SHARE marks for. + * need or have FOR [KEY] UPDATE/SHARE marks for. */ rels = get_base_rel_indexes((Node *) parse->jointree); if (parse->resultRelation) @@ -2020,7 +2020,7 @@ preprocess_rowmarks(PlannerInfo *root) PlanRowMark *newrc; /* - * Currently, it is syntactically impossible to have FOR UPDATE + * Currently, it is syntactically impossible to have FOR UPDATE et al * applied to an update/delete target rel. If that ever becomes * possible, we should drop the target from the PlanRowMark list. */ @@ -2040,10 +2040,21 @@ preprocess_rowmarks(PlannerInfo *root) newrc = makeNode(PlanRowMark); newrc->rti = newrc->prti = rc->rti; newrc->rowmarkId = ++(root->glob->lastRowMarkId); - if (rc->forUpdate) - newrc->markType = ROW_MARK_EXCLUSIVE; - else - newrc->markType = ROW_MARK_SHARE; + switch (rc->strength) + { + case LCS_FORUPDATE: + newrc->markType = ROW_MARK_EXCLUSIVE; + break; + case LCS_FORNOKEYUPDATE: + newrc->markType = ROW_MARK_NOKEYEXCLUSIVE; + break; + case LCS_FORSHARE: + newrc->markType = ROW_MARK_SHARE; + break; + case LCS_FORKEYSHARE: + newrc->markType = ROW_MARK_KEYSHARE; + break; + } newrc->noWait = rc->noWait; newrc->isParent = false; |