summaryrefslogtreecommitdiff
path: root/src/backend/optimizer/plan/planner.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer/plan/planner.c')
-rw-r--r--src/backend/optimizer/plan/planner.c57
1 files changed, 37 insertions, 20 deletions
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index 0b396b29bcc..6b24098cdd3 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/plan/planner.c,v 1.260 2009/10/26 02:26:33 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/plan/planner.c,v 1.261 2009/10/28 14:55:38 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1638,19 +1638,7 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
}
/*
- * If there is a LIMIT/OFFSET clause, add the LIMIT node.
- */
- if (parse->limitCount || parse->limitOffset)
- {
- result_plan = (Plan *) make_limit(result_plan,
- parse->limitOffset,
- parse->limitCount,
- offset_est,
- count_est);
- }
-
- /*
- * Finally, if there is a FOR UPDATE/SHARE clause, add the LockRows node.
+ * If there is a FOR 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.)
@@ -1660,6 +1648,23 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
result_plan = (Plan *) make_lockrows(result_plan,
root->rowMarks,
SS_assign_special_param(root));
+ /*
+ * The result can no longer be assumed sorted, since locking might
+ * cause the sort key columns to be replaced with new values.
+ */
+ current_pathkeys = NIL;
+ }
+
+ /*
+ * Finally, if there is a LIMIT/OFFSET clause, add the LIMIT node.
+ */
+ if (parse->limitCount || parse->limitOffset)
+ {
+ result_plan = (Plan *) make_limit(result_plan,
+ parse->limitOffset,
+ parse->limitCount,
+ offset_est,
+ count_est);
}
/* Compute result-relations list if needed */
@@ -1795,20 +1800,33 @@ preprocess_rowmarks(PlannerInfo *root)
/*
* Convert RowMarkClauses to PlanRowMark representation.
- *
- * Note: currently, it is syntactically impossible to have FOR UPDATE
- * applied to an update/delete target rel. If that ever becomes
- * possible, we should drop the target from the PlanRowMark list.
*/
prowmarks = NIL;
foreach(l, parse->rowMarks)
{
RowMarkClause *rc = (RowMarkClause *) lfirst(l);
- PlanRowMark *newrc = makeNode(PlanRowMark);
+ RangeTblEntry *rte = rt_fetch(rc->rti, parse->rtable);
+ PlanRowMark *newrc;
+ /*
+ * Currently, it is syntactically impossible to have FOR UPDATE
+ * applied to an update/delete target rel. If that ever becomes
+ * possible, we should drop the target from the PlanRowMark list.
+ */
Assert(rc->rti != parse->resultRelation);
+
+ /*
+ * Ignore RowMarkClauses for subqueries; they aren't real tables
+ * and can't support true locking. Subqueries that got flattened
+ * into the main query should be ignored completely. Any that didn't
+ * will get ROW_MARK_COPY items in the next loop.
+ */
+ if (rte->rtekind != RTE_RELATION)
+ continue;
+
rels = bms_del_member(rels, rc->rti);
+ newrc = makeNode(PlanRowMark);
newrc->rti = newrc->prti = rc->rti;
if (rc->forUpdate)
newrc->markType = ROW_MARK_EXCLUSIVE;
@@ -1838,7 +1856,6 @@ preprocess_rowmarks(PlannerInfo *root)
continue;
newrc = makeNode(PlanRowMark);
-
newrc->rti = newrc->prti = i;
/* real tables support REFERENCE, anything else needs COPY */
if (rte->rtekind == RTE_RELATION)