Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 07c741e

Browse files
committed
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.
1 parent 4cb0950 commit 07c741e

File tree

4 files changed

+67
-12
lines changed

4 files changed

+67
-12
lines changed

src/backend/optimizer/plan/setrefs.c

Lines changed: 60 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,15 @@
99
*
1010
*
1111
* IDENTIFICATION
12-
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.68 2000/10/26 21:36:09 tgl Exp $
12+
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.69 2001/01/09 03:48:51 tgl Exp $
1313
*
1414
*-------------------------------------------------------------------------
1515
*/
1616
#include <sys/types.h>
1717

1818
#include "postgres.h"
1919

20+
#include "nodes/makefuncs.h"
2021
#include "nodes/nodeFuncs.h"
2122
#include "optimizer/clauses.h"
2223
#include "optimizer/planmain.h"
@@ -270,22 +271,75 @@ set_join_references(Join *join)
270271
* to refer to the tuples returned by its lefttree subplan.
271272
*
272273
* This is used for single-input plan types like Agg, Group, Result.
274+
*
275+
* In most cases, we have to match up individual Vars in the tlist and
276+
* qual expressions with elements of the subplan's tlist (which was
277+
* generated by flatten_tlist() from these selfsame expressions, so it
278+
* should have all the required variables). There is an important exception,
279+
* however: a GROUP BY expression that is also an output expression will
280+
* have been pushed into the subplan tlist unflattened. We want to detect
281+
* this case and reference the subplan output directly. Therefore, check
282+
* for equality of the whole tlist expression to any subplan element before
283+
* we resort to picking the expression apart for individual Vars.
273284
*/
274285
static void
275286
set_uppernode_references(Plan *plan, Index subvarno)
276287
{
277288
Plan *subplan = plan->lefttree;
278-
List *subplanTargetList;
289+
List *subplanTargetList,
290+
*outputTargetList,
291+
*l;
279292

280293
if (subplan != NULL)
281294
subplanTargetList = subplan->targetlist;
282295
else
283296
subplanTargetList = NIL;
284297

285-
plan->targetlist = (List *)
286-
replace_vars_with_subplan_refs((Node *) plan->targetlist,
287-
subvarno,
288-
subplanTargetList);
298+
outputTargetList = NIL;
299+
foreach (l, plan->targetlist)
300+
{
301+
TargetEntry *tle = (TargetEntry *) lfirst(l);
302+
TargetEntry *subplantle;
303+
Node *newexpr;
304+
305+
subplantle = tlistentry_member(tle->expr, subplanTargetList);
306+
if (subplantle)
307+
{
308+
/* Found a matching subplan output expression */
309+
Resdom *resdom = subplantle->resdom;
310+
Var *newvar;
311+
312+
newvar = makeVar(subvarno,
313+
resdom->resno,
314+
resdom->restype,
315+
resdom->restypmod,
316+
0);
317+
/* If we're just copying a simple Var, copy up original info */
318+
if (subplantle->expr && IsA(subplantle->expr, Var))
319+
{
320+
Var *subvar = (Var *) subplantle->expr;
321+
322+
newvar->varnoold = subvar->varnoold;
323+
newvar->varoattno = subvar->varoattno;
324+
}
325+
else
326+
{
327+
newvar->varnoold = 0;
328+
newvar->varoattno = 0;
329+
}
330+
newexpr = (Node *) newvar;
331+
}
332+
else
333+
{
334+
/* No matching expression, so replace individual Vars */
335+
newexpr = replace_vars_with_subplan_refs(tle->expr,
336+
subvarno,
337+
subplanTargetList);
338+
}
339+
outputTargetList = lappend(outputTargetList,
340+
makeTargetEntry(tle->resdom, newexpr));
341+
}
342+
plan->targetlist = outputTargetList;
289343

290344
plan->qual = (List *)
291345
replace_vars_with_subplan_refs((Node *) plan->qual,

src/backend/optimizer/plan/subselect.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1994, Regents of the University of California
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/subselect.c,v 1.46 2000/11/21 00:17:59 tgl Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/subselect.c,v 1.47 2001/01/09 03:48:51 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -125,6 +125,7 @@ make_subplan(SubLink *slink)
125125
{
126126
SubPlan *node = makeNode(SubPlan);
127127
Query *subquery = (Query *) (slink->subselect);
128+
Oid result_type = exprType((Node *) slink);
128129
double tuple_fraction;
129130
Plan *plan;
130131
List *lst;
@@ -368,7 +369,7 @@ make_subplan(SubLink *slink)
368369
/*
369370
* Make expression of SUBPLAN type
370371
*/
371-
expr->typeOid = BOOLOID;/* bogus, but we don't really care */
372+
expr->typeOid = result_type;
372373
expr->opType = SUBPLAN_EXPR;
373374
expr->oper = (Node *) node;
374375

src/backend/optimizer/util/tlist.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/tlist.c,v 1.47 2000/08/08 15:41:53 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/tlist.c,v 1.48 2001/01/09 03:48:50 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -18,7 +18,6 @@
1818
#include "optimizer/tlist.h"
1919
#include "optimizer/var.h"
2020

21-
static TargetEntry *tlistentry_member(Node *node, List *targetlist);
2221

2322
/*****************************************************************************
2423
* ---------- RELATION node target list routines ----------
@@ -29,7 +28,7 @@ static TargetEntry *tlistentry_member(Node *node, List *targetlist);
2928
* Finds the (first) member of the given tlist whose expression is
3029
* equal() to the given expression. Result is NULL if no such member.
3130
*/
32-
static TargetEntry *
31+
TargetEntry *
3332
tlistentry_member(Node *node, List *targetlist)
3433
{
3534
List *temp;

src/include/optimizer/tlist.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $Id: tlist.h,v 1.26 2000/06/08 22:37:51 momjian Exp $
10+
* $Id: tlist.h,v 1.27 2001/01/09 03:48:50 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -16,6 +16,7 @@
1616

1717
#include "nodes/relation.h"
1818

19+
extern TargetEntry *tlistentry_member(Node *node, List *targetlist);
1920
extern Resdom *tlist_member(Node *node, List *targetlist);
2021

2122
extern void add_var_to_tlist(RelOptInfo *rel, Var *var);

0 commit comments

Comments
 (0)