summaryrefslogtreecommitdiff
path: root/src/backend/optimizer/plan/setrefs.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer/plan/setrefs.c')
-rw-r--r--src/backend/optimizer/plan/setrefs.c73
1 files changed, 61 insertions, 12 deletions
diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c
index 5240a7283b..5c11d788e0 100644
--- a/src/backend/optimizer/plan/setrefs.c
+++ b/src/backend/optimizer/plan/setrefs.c
@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/plan/setrefs.c,v 1.132 2007/02/22 23:44:25 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/plan/setrefs.c,v 1.133 2007/02/23 21:59:44 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -73,6 +73,7 @@ static void set_join_references(Join *join, int rtoffset);
static void set_inner_join_references(Plan *inner_plan,
indexed_tlist *outer_itlist);
static void set_upper_references(Plan *plan, int rtoffset);
+static void set_dummy_tlist_references(Plan *plan, int rtoffset);
static indexed_tlist *build_tlist_index(List *tlist);
static Var *search_indexed_tlist_for_var(Var *var,
indexed_tlist *itlist,
@@ -315,8 +316,7 @@ set_plan_refs(PlannerGlobal *glob, Plan *plan, int rtoffset)
* executor, we fix it up for possible use by EXPLAIN (not to
* mention ease of debugging --- wrong varnos are very confusing).
*/
- plan->targetlist =
- fix_scan_list(plan->targetlist, rtoffset);
+ set_dummy_tlist_references(plan, rtoffset);
/*
* Since these plan types don't check quals either, we should not
* find any qual expression attached to them.
@@ -330,11 +330,12 @@ set_plan_refs(PlannerGlobal *glob, Plan *plan, int rtoffset)
/*
* Like the plan types above, Limit doesn't evaluate its tlist
* or quals. It does have live expressions for limit/offset,
- * however.
+ * however; and those cannot contain subplan variable refs,
+ * so fix_scan_expr works for them.
*/
- splan->plan.targetlist =
- fix_scan_list(splan->plan.targetlist, rtoffset);
+ set_dummy_tlist_references(plan, rtoffset);
Assert(splan->plan.qual == NIL);
+
splan->limitOffset =
fix_scan_expr(splan->limitOffset, rtoffset);
splan->limitCount =
@@ -375,8 +376,7 @@ set_plan_refs(PlannerGlobal *glob, Plan *plan, int rtoffset)
* Append, like Sort et al, doesn't actually evaluate its
* targetlist or check quals.
*/
- splan->plan.targetlist =
- fix_scan_list(splan->plan.targetlist, rtoffset);
+ set_dummy_tlist_references(plan, rtoffset);
Assert(splan->plan.qual == NIL);
foreach(l, splan->appendplans)
{
@@ -892,10 +892,7 @@ set_upper_references(Plan *plan, int rtoffset)
List *output_targetlist;
ListCell *l;
- if (subplan != NULL)
- subplan_itlist = build_tlist_index(subplan->targetlist);
- else
- subplan_itlist = build_tlist_index(NIL);
+ subplan_itlist = build_tlist_index(subplan->targetlist);
output_targetlist = NIL;
foreach(l, plan->targetlist)
@@ -921,6 +918,58 @@ set_upper_references(Plan *plan, int rtoffset)
}
/*
+ * set_dummy_tlist_references
+ * Replace the targetlist of an upper-level plan node with a simple
+ * list of OUTER references to its child.
+ *
+ * This is used for plan types like Sort and Append that don't evaluate
+ * their targetlists. Although the executor doesn't care at all what's in
+ * the tlist, EXPLAIN needs it to be realistic.
+ *
+ * Note: we could almost use set_upper_references() here, but it fails for
+ * Append for lack of a lefttree subplan. Single-purpose code is faster
+ * anyway.
+ */
+static void
+set_dummy_tlist_references(Plan *plan, int rtoffset)
+{
+ List *output_targetlist;
+ ListCell *l;
+
+ output_targetlist = NIL;
+ foreach(l, plan->targetlist)
+ {
+ TargetEntry *tle = (TargetEntry *) lfirst(l);
+ Var *oldvar = (Var *) tle->expr;
+ Var *newvar;
+
+ newvar = makeVar(OUTER,
+ tle->resno,
+ exprType((Node *) oldvar),
+ exprTypmod((Node *) oldvar),
+ 0);
+ if (IsA(oldvar, Var))
+ {
+ newvar->varnoold = oldvar->varno + rtoffset;
+ newvar->varoattno = oldvar->varattno;
+ }
+ else
+ {
+ newvar->varnoold = 0; /* wasn't ever a plain Var */
+ newvar->varoattno = 0;
+ }
+
+ tle = flatCopyTargetEntry(tle);
+ tle->expr = (Expr *) newvar;
+ output_targetlist = lappend(output_targetlist, tle);
+ }
+ plan->targetlist = output_targetlist;
+
+ /* We don't touch plan->qual here */
+}
+
+
+/*
* build_tlist_index --- build an index data structure for a child tlist
*
* In most cases, subplan tlists will be "flat" tlists with only Vars,