Commit cc77005d authored by Tom Lane's avatar Tom Lane

Change Agg and Group nodes so that Vars contained in their targetlists

and quals have varno OUTER, rather than zero, to indicate a reference to
an output of their lefttree subplan.  This is consistent with the way
that every other upper-level node type does it, and allows some simplifications
in setrefs.c and EXPLAIN.
parent 3c5985b4
......@@ -7,7 +7,7 @@
* 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 $
*
*-------------------------------------------------------------------------
*/
......@@ -52,8 +52,8 @@ static void show_scan_qual(List *qual, const char *qlabel,
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,
......@@ -783,55 +783,55 @@ explain_outNode(StringInfo str,
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:
......@@ -844,13 +844,13 @@ explain_outNode(StringInfo str,
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:
......@@ -1088,13 +1088,15 @@ show_scan_qual(List *qual, const char *qlabel,
*/
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;
......@@ -1105,15 +1107,27 @@ show_upper_qual(List *qual, const char *qlabel,
/* 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);
......
......@@ -61,7 +61,7 @@
* 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 $
*
*-------------------------------------------------------------------------
*/
......@@ -420,7 +420,7 @@ advance_transition_function(AggState *aggstate,
/*
* 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).
*
......@@ -643,8 +643,8 @@ find_unaggregated_cols_walker(Node *node, Bitmapset **colnos)
{
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;
......@@ -905,7 +905,7 @@ agg_retrieve_direct(AggState *aggstate)
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,
......@@ -926,7 +926,7 @@ agg_retrieve_direct(AggState *aggstate)
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
......@@ -973,7 +973,7 @@ agg_retrieve_direct(AggState *aggstate)
* 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
......@@ -1022,7 +1022,7 @@ agg_fill_hash_table(AggState *aggstate)
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);
......@@ -1116,7 +1116,7 @@ agg_retrieve_hash_table(AggState *aggstate)
* 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
......
......@@ -15,7 +15,7 @@
* 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 $
*
*-------------------------------------------------------------------------
*/
......@@ -72,9 +72,14 @@ ExecGroup(GroupState *node)
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
......@@ -126,7 +131,7 @@ ExecGroup(GroupState *node)
*/
/* 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
......
......@@ -38,7 +38,7 @@
* 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 $
*
*-------------------------------------------------------------------------
*/
......@@ -132,13 +132,11 @@ ExecResult(ResultState *node)
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
{
......
......@@ -9,7 +9,7 @@
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
......@@ -56,7 +56,6 @@ typedef struct
typedef struct
{
indexed_tlist *subplan_itlist;
Index subvarno;
int rtoffset;
} fix_upper_expr_context;
......@@ -73,7 +72,7 @@ static Node *fix_scan_expr_mutator(Node *node, fix_scan_expr_context *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,
......@@ -90,7 +89,6 @@ static Node *fix_join_expr_mutator(Node *node,
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);
......@@ -345,7 +343,7 @@ set_plan_refs(PlannerGlobal *glob, Plan *plan, int rtoffset)
break;
case T_Agg:
case T_Group:
set_upper_references(plan, (Index) 0, rtoffset);
set_upper_references(plan, rtoffset);
break;
case T_Result:
{
......@@ -354,11 +352,9 @@ set_plan_refs(PlannerGlobal *glob, Plan *plan, int rtoffset)
/*
* 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 =
......@@ -889,7 +885,7 @@ set_inner_join_references(Plan *inner_plan, indexed_tlist *outer_itlist)
* 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;
......@@ -909,7 +905,6 @@ set_upper_references(Plan *plan, Index subvarno, int rtoffset)
newexpr = fix_upper_expr((Node *) tle->expr,
subplan_itlist,
subvarno,
rtoffset);
tle = flatCopyTargetEntry(tle);
tle->expr = (Expr *) newexpr;
......@@ -920,7 +915,6 @@ set_upper_references(Plan *plan, Index subvarno, int rtoffset)
plan->qual = (List *)
fix_upper_expr((Node *) plan->qual,
subplan_itlist,
subvarno,
rtoffset);
pfree(subplan_itlist);
......@@ -1233,23 +1227,20 @@ fix_join_expr_mutator(Node *node, fix_join_expr_context *context)
*
* '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);
}
......@@ -1267,7 +1258,7 @@ fix_upper_expr_mutator(Node *node, fix_upper_expr_context *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");
......@@ -1278,7 +1269,7 @@ fix_upper_expr_mutator(Node *node, fix_upper_expr_context *context)
{
newvar = search_indexed_tlist_for_non_var(node,
context->subplan_itlist,
context->subvarno);
OUTER);
if (newvar)
return (Node *) newvar;
}
......
......@@ -9,7 +9,7 @@
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
......@@ -2626,7 +2626,7 @@ get_rte_for_var(Var *var, int levelsup, deparse_context *context,
/*
* 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.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment