aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer/plan/createplan.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2009-10-12 18:10:51 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2009-10-12 18:10:51 +0000
commit0adaf4cb312fe3eff83e786d6a0b53ae2cdc9302 (patch)
tree177cf2ea668d6fcabbafc37db4741813ea3f685d /src/backend/optimizer/plan/createplan.c
parent05d249717d652f0b16960d8a58611e222f1f907b (diff)
downloadpostgresql-0adaf4cb312fe3eff83e786d6a0b53ae2cdc9302.tar.gz
postgresql-0adaf4cb312fe3eff83e786d6a0b53ae2cdc9302.zip
Move the handling of SELECT FOR UPDATE locking and rechecking out of
execMain.c and into a new plan node type LockRows. Like the recent change to put table updating into a ModifyTable plan node, this increases planning flexibility by allowing the operations to occur below the top level of the plan tree. It's necessary in any case to restore the previous behavior of having FOR UPDATE locking occur before ModifyTable does. This partially refactors EvalPlanQual to allow multiple rows-under-test to be inserted into the EPQ machinery before starting an EPQ test query. That isn't sufficient to fix EPQ's general bogosity in the face of plans that return multiple rows per test row, though. Since this patch is mostly about getting some plan node infrastructure in place and not about fixing ten-year-old bugs, I will leave EPQ improvements for another day. Another behavioral change that we could now think about is doing FOR UPDATE before LIMIT, but that too seems like it should be treated as a followon patch.
Diffstat (limited to 'src/backend/optimizer/plan/createplan.c')
-rw-r--r--src/backend/optimizer/plan/createplan.c35
1 files changed, 32 insertions, 3 deletions
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index b29b0765919..1452bdd035c 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/plan/createplan.c,v 1.264 2009/10/10 01:43:49 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/plan/createplan.c,v 1.265 2009/10/12 18:10:45 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1336,7 +1336,8 @@ create_subqueryscan_plan(PlannerInfo *root, Path *best_path,
scan_clauses,
scan_relid,
best_path->parent->subplan,
- best_path->parent->subrtable);
+ best_path->parent->subrtable,
+ best_path->parent->subrowmark);
copy_path_costsize(&scan_plan->scan.plan, best_path);
@@ -2508,7 +2509,8 @@ make_subqueryscan(List *qptlist,
List *qpqual,
Index scanrelid,
Plan *subplan,
- List *subrtable)
+ List *subrtable,
+ List *subrowmark)
{
SubqueryScan *node = makeNode(SubqueryScan);
Plan *plan = &node->scan.plan;
@@ -2528,6 +2530,7 @@ make_subqueryscan(List *qptlist,
node->scan.scanrelid = scanrelid;
node->subplan = subplan;
node->subrtable = subrtable;
+ node->subrowmark = subrowmark;
return node;
}
@@ -3591,6 +3594,31 @@ make_setop(SetOpCmd cmd, SetOpStrategy strategy, Plan *lefttree,
}
/*
+ * make_lockrows
+ * Build a LockRows plan node
+ */
+LockRows *
+make_lockrows(Plan *lefttree, List *rowMarks)
+{
+ LockRows *node = makeNode(LockRows);
+ Plan *plan = &node->plan;
+
+ copy_plan_costsize(plan, lefttree);
+
+ /* charge cpu_tuple_cost to reflect locking costs (underestimate?) */
+ plan->total_cost += cpu_tuple_cost * plan->plan_rows;
+
+ plan->targetlist = lefttree->targetlist;
+ plan->qual = NIL;
+ plan->lefttree = lefttree;
+ plan->righttree = NULL;
+
+ node->rowMarks = rowMarks;
+
+ return node;
+}
+
+/*
* Note: offset_est and count_est are passed in to save having to repeat
* work already done to estimate the values of the limitOffset and limitCount
* expressions. Their values are as returned by preprocess_limit (0 means
@@ -3792,6 +3820,7 @@ is_projection_capable_plan(Plan *plan)
case T_Sort:
case T_Unique:
case T_SetOp:
+ case T_LockRows:
case T_Limit:
case T_ModifyTable:
case T_Append: