From cc77005df7177d9af1c23b7af1cac08102fcbca9 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Thu, 22 Feb 2007 23:44:25 +0000 Subject: [PATCH] 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. --- src/backend/commands/explain.c | 68 +++++++++++++++++----------- src/backend/executor/nodeAgg.c | 18 ++++---- src/backend/executor/nodeGroup.c | 13 ++++-- src/backend/executor/nodeResult.c | 8 ++-- src/backend/optimizer/plan/setrefs.c | 25 ++++------ src/backend/utils/adt/ruleutils.c | 4 +- 6 files changed, 72 insertions(+), 64 deletions(-) diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c index 34784eb078..6a97b01ec3 100644 --- a/src/backend/commands/explain.c +++ b/src/backend/commands/explain.c @@ -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); diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c index f6ee9b275e..58e59c60c5 100644 --- a/src/backend/executor/nodeAgg.c +++ b/src/backend/executor/nodeAgg.c @@ -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 diff --git a/src/backend/executor/nodeGroup.c b/src/backend/executor/nodeGroup.c index 0b636aa01e..ce03f94e2e 100644 --- a/src/backend/executor/nodeGroup.c +++ b/src/backend/executor/nodeGroup.c @@ -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 diff --git a/src/backend/executor/nodeResult.c b/src/backend/executor/nodeResult.c index 98e9d21972..5ea5132dd2 100644 --- a/src/backend/executor/nodeResult.c +++ b/src/backend/executor/nodeResult.c @@ -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 { diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c index aaa383742e..5240a7283b 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.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; } diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index 064b8e07f7..2f61b4a9fc 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -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. -- 2.40.0