* Portions Copyright (c) 1994-5, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.157 2007/02/22 22:00:22 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.158 2007/02/22 23:44:24 tgl Exp $
*
*-------------------------------------------------------------------------
*/
int scanrelid, Plan *outer_plan,
StringInfo str, int indent, ExplainState *es);
static void show_upper_qual(List *qual, const char *qlabel,
- const char *outer_name, int outer_varno, Plan *outer_plan,
- const char *inner_name, int inner_varno, Plan *inner_plan,
+ const char *outer_name, Plan *outer_plan,
+ const char *inner_name, Plan *inner_plan,
StringInfo str, int indent, ExplainState *es);
static void show_sort_keys(Plan *sortplan, int nkeys, AttrNumber *keycols,
const char *qlabel,
case T_NestLoop:
show_upper_qual(((NestLoop *) plan)->join.joinqual,
"Join Filter",
- "outer", OUTER, outerPlan(plan),
- "inner", INNER, innerPlan(plan),
+ "outer", outerPlan(plan),
+ "inner", innerPlan(plan),
str, indent, es);
show_upper_qual(plan->qual,
"Filter",
- "outer", OUTER, outerPlan(plan),
- "inner", INNER, innerPlan(plan),
+ "outer", outerPlan(plan),
+ "inner", innerPlan(plan),
str, indent, es);
break;
case T_MergeJoin:
show_upper_qual(((MergeJoin *) plan)->mergeclauses,
"Merge Cond",
- "outer", OUTER, outerPlan(plan),
- "inner", INNER, innerPlan(plan),
+ "outer", outerPlan(plan),
+ "inner", innerPlan(plan),
str, indent, es);
show_upper_qual(((MergeJoin *) plan)->join.joinqual,
"Join Filter",
- "outer", OUTER, outerPlan(plan),
- "inner", INNER, innerPlan(plan),
+ "outer", outerPlan(plan),
+ "inner", innerPlan(plan),
str, indent, es);
show_upper_qual(plan->qual,
"Filter",
- "outer", OUTER, outerPlan(plan),
- "inner", INNER, innerPlan(plan),
+ "outer", outerPlan(plan),
+ "inner", innerPlan(plan),
str, indent, es);
break;
case T_HashJoin:
show_upper_qual(((HashJoin *) plan)->hashclauses,
"Hash Cond",
- "outer", OUTER, outerPlan(plan),
- "inner", INNER, innerPlan(plan),
+ "outer", outerPlan(plan),
+ "inner", innerPlan(plan),
str, indent, es);
show_upper_qual(((HashJoin *) plan)->join.joinqual,
"Join Filter",
- "outer", OUTER, outerPlan(plan),
- "inner", INNER, innerPlan(plan),
+ "outer", outerPlan(plan),
+ "inner", innerPlan(plan),
str, indent, es);
show_upper_qual(plan->qual,
"Filter",
- "outer", OUTER, outerPlan(plan),
- "inner", INNER, innerPlan(plan),
+ "outer", outerPlan(plan),
+ "inner", innerPlan(plan),
str, indent, es);
break;
case T_Agg:
case T_Group:
show_upper_qual(plan->qual,
"Filter",
- "subplan", 0, outerPlan(plan),
- "", 0, NULL,
+ "subplan", outerPlan(plan),
+ "", NULL,
str, indent, es);
break;
case T_Sort:
case T_Result:
show_upper_qual((List *) ((Result *) plan)->resconstantqual,
"One-Time Filter",
- "subplan", OUTER, outerPlan(plan),
- "", 0, NULL,
+ "subplan", outerPlan(plan),
+ "", NULL,
str, indent, es);
show_upper_qual(plan->qual,
"Filter",
- "subplan", OUTER, outerPlan(plan),
- "", 0, NULL,
+ "subplan", outerPlan(plan),
+ "", NULL,
str, indent, es);
break;
default:
*/
static void
show_upper_qual(List *qual, const char *qlabel,
- const char *outer_name, int outer_varno, Plan *outer_plan,
- const char *inner_name, int inner_varno, Plan *inner_plan,
+ const char *outer_name, Plan *outer_plan,
+ const char *inner_name, Plan *inner_plan,
StringInfo str, int indent, ExplainState *es)
{
List *context;
Node *outercontext;
Node *innercontext;
+ int outer_varno;
+ int inner_varno;
Node *node;
char *exprstr;
int i;
/* Generate deparse context */
if (outer_plan)
+ {
outercontext = deparse_context_for_subplan(outer_name,
(Node *) outer_plan);
+ outer_varno = OUTER;
+ }
else
+ {
outercontext = NULL;
+ outer_varno = 0;
+ }
if (inner_plan)
+ {
innercontext = deparse_context_for_subplan(inner_name,
(Node *) inner_plan);
+ inner_varno = INNER;
+ }
else
+ {
innercontext = NULL;
+ inner_varno = 0;
+ }
context = deparse_context_for_plan(outer_varno, outercontext,
inner_varno, innercontext,
es->rtable);
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/nodeAgg.c,v 1.150 2007/02/02 00:07:03 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/nodeAgg.c,v 1.151 2007/02/22 23:44:24 tgl Exp $
*
*-------------------------------------------------------------------------
*/
/*
* Advance all the aggregates for one input tuple. The input tuple
- * has been stored in tmpcontext->ecxt_scantuple, so that it is accessible
+ * has been stored in tmpcontext->ecxt_outertuple, so that it is accessible
* to ExecEvalExpr. pergroup is the array of per-group structs to use
* (this might be in a hashtable entry).
*
{
Var *var = (Var *) node;
- /* setrefs.c should have set the varno to 0 */
- Assert(var->varno == 0);
+ /* setrefs.c should have set the varno to OUTER */
+ Assert(var->varno == OUTER);
Assert(var->varlevelsup == 0);
*colnos = bms_add_member(*colnos, var->varattno);
return false;
aggstate->grp_firstTuple = NULL; /* don't keep two pointers */
/* set up for first advance_aggregates call */
- tmpcontext->ecxt_scantuple = firstSlot;
+ tmpcontext->ecxt_outertuple = firstSlot;
/*
* Process each outer-plan tuple, and then fetch the next one,
break;
}
/* set up for next advance_aggregates call */
- tmpcontext->ecxt_scantuple = outerslot;
+ tmpcontext->ecxt_outertuple = outerslot;
/*
* If we are grouping, check whether we've crossed a group
* with an empty firstSlot ... but if not grouping, there can't be any
* references to non-aggregated input columns, so no problem.)
*/
- econtext->ecxt_scantuple = firstSlot;
+ econtext->ecxt_outertuple = firstSlot;
/*
* Check the qual (HAVING clause); if the group does not match, ignore
if (TupIsNull(outerslot))
break;
/* set up for advance_aggregates call */
- tmpcontext->ecxt_scantuple = outerslot;
+ tmpcontext->ecxt_outertuple = outerslot;
/* Find or build hashtable entry for this tuple's group */
entry = lookup_hash_entry(aggstate, outerslot);
* Use the representative input tuple for any references to
* non-aggregated input columns in the qual and tlist.
*/
- econtext->ecxt_scantuple = firstSlot;
+ econtext->ecxt_outertuple = firstSlot;
/*
* Check the qual (HAVING clause); if the group does not match, ignore
* locate group boundaries.
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/nodeGroup.c,v 1.68 2007/02/02 00:07:03 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/nodeGroup.c,v 1.69 2007/02/22 23:44:24 tgl Exp $
*
*-------------------------------------------------------------------------
*/
node->grp_done = TRUE;
return NULL;
}
- /* Copy tuple, set up as input for qual test and projection */
+ /* Copy tuple into firsttupleslot */
ExecCopySlot(firsttupleslot, outerslot);
- econtext->ecxt_scantuple = firsttupleslot;
+
+ /*
+ * Set it up as input for qual test and projection. The expressions
+ * will access the input tuple as varno OUTER.
+ */
+ econtext->ecxt_outertuple = firsttupleslot;
/*
* Check the qual (HAVING clause); if the group does not match, ignore
*/
/* Copy tuple, set up as input for qual test and projection */
ExecCopySlot(firsttupleslot, outerslot);
- econtext->ecxt_scantuple = firsttupleslot;
+ econtext->ecxt_outertuple = firsttupleslot;
/*
* Check the qual (HAVING clause); if the group does not match, ignore
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/nodeResult.c,v 1.39 2007/02/16 03:49:04 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/nodeResult.c,v 1.40 2007/02/22 23:44:25 tgl Exp $
*
*-------------------------------------------------------------------------
*/
if (TupIsNull(outerTupleSlot))
return NULL;
- node->ps.ps_OuterTupleSlot = outerTupleSlot;
-
/*
- * XXX gross hack. use outer tuple as scan tuple for projection
+ * prepare to compute projection expressions, which will expect
+ * to access the input tuples as varno OUTER.
*/
econtext->ecxt_outertuple = outerTupleSlot;
- econtext->ecxt_scantuple = outerTupleSlot;
}
else
{
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/plan/setrefs.c,v 1.131 2007/02/22 22:00:24 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/plan/setrefs.c,v 1.132 2007/02/22 23:44:25 tgl Exp $
*
*-------------------------------------------------------------------------
*/
typedef struct
{
indexed_tlist *subplan_itlist;
- Index subvarno;
int rtoffset;
} fix_upper_expr_context;
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, Index subvarno, int rtoffset);
+static void set_upper_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,
fix_join_expr_context *context);
static Node *fix_upper_expr(Node *node,
indexed_tlist *subplan_itlist,
- Index subvarno,
int rtoffset);
static Node *fix_upper_expr_mutator(Node *node,
fix_upper_expr_context *context);
break;
case T_Agg:
case T_Group:
- set_upper_references(plan, (Index) 0, rtoffset);
+ set_upper_references(plan, rtoffset);
break;
case T_Result:
{
/*
* Result may or may not have a subplan; if not, it's more
* like a scan node than an upper node.
- *
- * XXX why does Result use a different subvarno from Agg/Group?
*/
if (splan->plan.lefttree != NULL)
- set_upper_references(plan, (Index) OUTER, rtoffset);
+ set_upper_references(plan, rtoffset);
else
{
splan->plan.targetlist =
* the expression.
*/
static void
-set_upper_references(Plan *plan, Index subvarno, int rtoffset)
+set_upper_references(Plan *plan, int rtoffset)
{
Plan *subplan = plan->lefttree;
indexed_tlist *subplan_itlist;
newexpr = fix_upper_expr((Node *) tle->expr,
subplan_itlist,
- subvarno,
rtoffset);
tle = flatCopyTargetEntry(tle);
tle->expr = (Expr *) newexpr;
plan->qual = (List *)
fix_upper_expr((Node *) plan->qual,
subplan_itlist,
- subvarno,
rtoffset);
pfree(subplan_itlist);
*
* 'node': the tree to be fixed (a target item or qual)
* 'subplan_itlist': indexed target list for subplan
- * 'subvarno': varno to be assigned to all Vars
* 'rtoffset': how much to increment varnoold by
*
* The resulting tree is a copy of the original in which all Var nodes have
- * varno = subvarno, varattno = resno of corresponding subplan target.
+ * varno = OUTER, varattno = resno of corresponding subplan target.
* The original tree is not modified.
*/
static Node *
fix_upper_expr(Node *node,
indexed_tlist *subplan_itlist,
- Index subvarno,
int rtoffset)
{
fix_upper_expr_context context;
context.subplan_itlist = subplan_itlist;
- context.subvarno = subvarno;
context.rtoffset = rtoffset;
return fix_upper_expr_mutator(node, &context);
}
newvar = search_indexed_tlist_for_var(var,
context->subplan_itlist,
- context->subvarno,
+ OUTER,
context->rtoffset);
if (!newvar)
elog(ERROR, "variable not found in subplan target list");
{
newvar = search_indexed_tlist_for_non_var(node,
context->subplan_itlist,
- context->subvarno);
+ OUTER);
if (newvar)
return (Node *) newvar;
}
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.249 2007/02/14 01:58:57 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.250 2007/02/22 23:44:25 tgl Exp $
*
*-------------------------------------------------------------------------
*/
/*
* Try to find the relevant RTE in this rtable. In a plan tree, it's
- * likely that varno is OUTER, INNER, or 0, in which case we try to use
+ * likely that varno is OUTER or INNER, in which case we try to use
* varnoold instead. If the Var references an expression computed by a
* subplan, varnoold will be 0, and we fall back to looking at the special
* subplan RTEs.