From 07c741e61c8cb1fd945907a225d15467a08aca70 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Tue, 9 Jan 2001 03:48:51 +0000 Subject: [PATCH] Fix oversight in planning of GROUP queries: when an expression is used as both a GROUP BY item and an output expression, the top-level Group node should just copy up the evaluated expression value from its input, rather than re-evaluating the expression. Aside from any performance benefit this might offer, this avoids a crash when there is a sub-SELECT in said expression. --- src/backend/optimizer/plan/setrefs.c | 66 +++++++++++++++++++++++--- src/backend/optimizer/plan/subselect.c | 5 +- src/backend/optimizer/util/tlist.c | 5 +- src/include/optimizer/tlist.h | 3 +- 4 files changed, 67 insertions(+), 12 deletions(-) diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c index deb020e256..5a54c95691 100644 --- a/src/backend/optimizer/plan/setrefs.c +++ b/src/backend/optimizer/plan/setrefs.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.68 2000/10/26 21:36:09 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.69 2001/01/09 03:48:51 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -17,6 +17,7 @@ #include "postgres.h" +#include "nodes/makefuncs.h" #include "nodes/nodeFuncs.h" #include "optimizer/clauses.h" #include "optimizer/planmain.h" @@ -270,22 +271,75 @@ set_join_references(Join *join) * to refer to the tuples returned by its lefttree subplan. * * This is used for single-input plan types like Agg, Group, Result. + * + * In most cases, we have to match up individual Vars in the tlist and + * qual expressions with elements of the subplan's tlist (which was + * generated by flatten_tlist() from these selfsame expressions, so it + * should have all the required variables). There is an important exception, + * however: a GROUP BY expression that is also an output expression will + * have been pushed into the subplan tlist unflattened. We want to detect + * this case and reference the subplan output directly. Therefore, check + * for equality of the whole tlist expression to any subplan element before + * we resort to picking the expression apart for individual Vars. */ static void set_uppernode_references(Plan *plan, Index subvarno) { Plan *subplan = plan->lefttree; - List *subplanTargetList; + List *subplanTargetList, + *outputTargetList, + *l; if (subplan != NULL) subplanTargetList = subplan->targetlist; else subplanTargetList = NIL; - plan->targetlist = (List *) - replace_vars_with_subplan_refs((Node *) plan->targetlist, - subvarno, - subplanTargetList); + outputTargetList = NIL; + foreach (l, plan->targetlist) + { + TargetEntry *tle = (TargetEntry *) lfirst(l); + TargetEntry *subplantle; + Node *newexpr; + + subplantle = tlistentry_member(tle->expr, subplanTargetList); + if (subplantle) + { + /* Found a matching subplan output expression */ + Resdom *resdom = subplantle->resdom; + Var *newvar; + + newvar = makeVar(subvarno, + resdom->resno, + resdom->restype, + resdom->restypmod, + 0); + /* If we're just copying a simple Var, copy up original info */ + if (subplantle->expr && IsA(subplantle->expr, Var)) + { + Var *subvar = (Var *) subplantle->expr; + + newvar->varnoold = subvar->varnoold; + newvar->varoattno = subvar->varoattno; + } + else + { + newvar->varnoold = 0; + newvar->varoattno = 0; + } + newexpr = (Node *) newvar; + } + else + { + /* No matching expression, so replace individual Vars */ + newexpr = replace_vars_with_subplan_refs(tle->expr, + subvarno, + subplanTargetList); + } + outputTargetList = lappend(outputTargetList, + makeTargetEntry(tle->resdom, newexpr)); + } + plan->targetlist = outputTargetList; plan->qual = (List *) replace_vars_with_subplan_refs((Node *) plan->qual, diff --git a/src/backend/optimizer/plan/subselect.c b/src/backend/optimizer/plan/subselect.c index 4ebabc1e87..61dd2baa7f 100644 --- a/src/backend/optimizer/plan/subselect.c +++ b/src/backend/optimizer/plan/subselect.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/subselect.c,v 1.46 2000/11/21 00:17:59 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/subselect.c,v 1.47 2001/01/09 03:48:51 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -125,6 +125,7 @@ make_subplan(SubLink *slink) { SubPlan *node = makeNode(SubPlan); Query *subquery = (Query *) (slink->subselect); + Oid result_type = exprType((Node *) slink); double tuple_fraction; Plan *plan; List *lst; @@ -368,7 +369,7 @@ make_subplan(SubLink *slink) /* * Make expression of SUBPLAN type */ - expr->typeOid = BOOLOID;/* bogus, but we don't really care */ + expr->typeOid = result_type; expr->opType = SUBPLAN_EXPR; expr->oper = (Node *) node; diff --git a/src/backend/optimizer/util/tlist.c b/src/backend/optimizer/util/tlist.c index 93b3fc6f56..fa542a8828 100644 --- a/src/backend/optimizer/util/tlist.c +++ b/src/backend/optimizer/util/tlist.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/util/tlist.c,v 1.47 2000/08/08 15:41:53 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/util/tlist.c,v 1.48 2001/01/09 03:48:50 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -18,7 +18,6 @@ #include "optimizer/tlist.h" #include "optimizer/var.h" -static TargetEntry *tlistentry_member(Node *node, List *targetlist); /***************************************************************************** * ---------- RELATION node target list routines ---------- @@ -29,7 +28,7 @@ static TargetEntry *tlistentry_member(Node *node, List *targetlist); * Finds the (first) member of the given tlist whose expression is * equal() to the given expression. Result is NULL if no such member. */ -static TargetEntry * +TargetEntry * tlistentry_member(Node *node, List *targetlist) { List *temp; diff --git a/src/include/optimizer/tlist.h b/src/include/optimizer/tlist.h index 8d3eb20d02..2159cbe2b8 100644 --- a/src/include/optimizer/tlist.h +++ b/src/include/optimizer/tlist.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: tlist.h,v 1.26 2000/06/08 22:37:51 momjian Exp $ + * $Id: tlist.h,v 1.27 2001/01/09 03:48:50 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -16,6 +16,7 @@ #include "nodes/relation.h" +extern TargetEntry *tlistentry_member(Node *node, List *targetlist); extern Resdom *tlist_member(Node *node, List *targetlist); extern void add_var_to_tlist(RelOptInfo *rel, Var *var); -- 2.40.0