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

Commit c50d847

Browse files
committed
Changes for GROUP BY func_results.
1 parent cc11cfd commit c50d847

File tree

1 file changed

+159
-59
lines changed

1 file changed

+159
-59
lines changed

src/backend/optimizer/plan/planmain.c

+159-59
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planmain.c,v 1.2 1996/10/31 10:59:14 scrappy Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planmain.c,v 1.3 1997/04/05 06:37:37 vadim Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -19,13 +19,15 @@
1919
#include "nodes/plannodes.h"
2020
#include "nodes/parsenodes.h"
2121
#include "nodes/relation.h"
22+
#include "nodes/makefuncs.h"
2223

2324
#include "optimizer/planmain.h"
2425
#include "optimizer/internal.h"
2526
#include "optimizer/paths.h"
2627
#include "optimizer/clauses.h"
2728
#include "optimizer/keys.h"
2829
#include "optimizer/tlist.h"
30+
#include "optimizer/var.h"
2931
#include "optimizer/xfunc.h"
3032
#include "optimizer/cost.h"
3133

@@ -39,7 +41,7 @@
3941
static Plan *subplanner(Query *root, List *flat_tlist, List *qual);
4042
static Result *make_result(List *tlist, Node *resconstantqual, Plan *subplan);
4143

42-
static Plan *make_groupPlan(List *tlist, bool tuplePerGroup,
44+
static Plan *make_groupPlan(List **tlist, bool tuplePerGroup,
4345
List *groupClause, Plan *subplan);
4446

4547
/*
@@ -110,20 +112,6 @@ query_planner(Query *root,
110112
level_tlist = tlist;
111113
}
112114

113-
/*
114-
* Needs to add the group attribute(s) to the target list so that they
115-
* are available to either the Group node or the Agg node. (The target
116-
* list may not contain the group attribute(s).)
117-
*/
118-
if (root->groupClause) {
119-
AddGroupAttrToTlist(level_tlist, root->groupClause);
120-
}
121-
122-
if (root->qry_aggs) {
123-
aggplan = make_agg(tlist, root->qry_numAgg, root->qry_aggs);
124-
tlist = level_tlist;
125-
}
126-
127115
/*
128116
* A query may have a non-variable target list and a non-variable
129117
* qualification only under certain conditions:
@@ -170,7 +158,7 @@ query_planner(Query *root,
170158
subplan = subplanner(root, level_tlist, qual);
171159

172160
set_tlist_references(subplan);
173-
161+
174162
/*
175163
* If we have a GROUP BY clause, insert a group node (with the appropriate
176164
* sort node.)
@@ -184,32 +172,31 @@ query_planner(Query *root,
184172
* present. Otherwise, need every tuple from the group to do the
185173
* aggregation.)
186174
*/
187-
tuplePerGroup = (aggplan == NULL) ? FALSE : TRUE;
175+
tuplePerGroup = ( root->qry_aggs ) ? TRUE : FALSE;
188176

189177
subplan =
190-
make_groupPlan(tlist, tuplePerGroup, root->groupClause, subplan);
178+
make_groupPlan(&tlist, tuplePerGroup, root->groupClause, subplan);
191179

192-
/* XXX fake it: this works for the Group node too! very very ugly,
193-
please change me -ay 2/95 */
194-
set_agg_tlist_references((Agg*)subplan);
195180
}
196181

197182
/*
198183
* If aggregate is present, insert the agg node
199184
*/
200-
if (aggplan != NULL) {
185+
if ( root->qry_aggs )
186+
{
187+
aggplan = make_agg(tlist, root->qry_numAgg, root->qry_aggs);
201188
aggplan->plan.lefttree = subplan;
202-
subplan = (Plan*)aggplan;
203-
204189
/*
205190
* set the varno/attno entries to the appropriate references to
206191
* the result tuple of the subplans. (We need to set those in the
207192
* array of aggreg's in the Agg node also. Even though they're
208193
* pointers, after a few dozen's of copying, they're not the same as
209194
* those in the target list.)
210195
*/
211-
set_agg_tlist_references((Agg*)subplan);
212-
set_agg_agglist_references((Agg*)subplan);
196+
set_agg_tlist_references (aggplan);
197+
set_agg_agglist_references (aggplan);
198+
199+
subplan = (Plan*)aggplan;
213200

214201
tlist = aggplan->plan.targetlist;
215202
}
@@ -238,9 +225,17 @@ query_planner(Query *root,
238225
* the very last stage of query execution. this could be bad.
239226
* but it is joey's responsibility to optimally push these
240227
* expressions down the plan tree. -- Wei
228+
*
229+
* But now nothing to do if there are GroupBy and/or Aggregates:
230+
* 1. make_groupPlan fixes tlist; 2. flatten_tlist_vars does nothing
231+
* with aggregates fixing only other entries (i.e. - GroupBy-ed and
232+
* so fixed by make_groupPlan). - vadim 04/05/97
241233
*/
242-
subplan->targetlist = flatten_tlist_vars(tlist,
234+
if ( root->groupClause == NULL && aggplan == NULL )
235+
{
236+
subplan->targetlist = flatten_tlist_vars(tlist,
243237
subplan->targetlist);
238+
}
244239

245240
/*
246241
* Destructively modify the query plan's targetlist to add fjoin
@@ -356,58 +351,130 @@ make_result(List *tlist,
356351
*****************************************************************************/
357352

358353
static Plan *
359-
make_groupPlan(List *tlist,
354+
make_groupPlan(List **tlist,
360355
bool tuplePerGroup,
361356
List *groupClause,
362357
Plan *subplan)
363358
{
364359
List *sort_tlist;
365-
List *gl;
366-
int keyno;
360+
List *sl, *gl;
361+
List *glc = listCopy (groupClause);
362+
List *aggvals = NIL; /* list of vars of aggregates */
363+
int aggvcnt;
367364
Sort *sortplan;
368365
Group *grpplan;
369366
int numCols;
370367
AttrNumber *grpColIdx;
368+
int keyno = 1;
369+
int last_resno = 1;
371370

372371
numCols = length(groupClause);
373372
grpColIdx = (AttrNumber *)palloc(sizeof(AttrNumber)*numCols);
374373

374+
sort_tlist = new_unsorted_tlist(*tlist); /* it's copy */
375+
375376
/*
376-
* first, make a sort node. Group node expects the tuples it gets
377-
* from the subplan is in the order as specified by the group columns.
377+
* Make template TL for subplan, Sort & Group:
378+
* 1. Take away Aggregates and re-set resno-s accordantly.
379+
* 2. Make grpColIdx
380+
*
381+
* Note: we assume that TLEs in *tlist are ordered in accordance
382+
* with their resdom->resno.
378383
*/
379-
keyno = 1;
380-
sort_tlist = new_unsorted_tlist(subplan->targetlist);
381-
384+
foreach (sl, sort_tlist)
382385
{
383-
/* if this is a mergejoin node, varno could be OUTER/INNER */
384-
List *l;
385-
foreach(l, sort_tlist) {
386-
TargetEntry *tle;
387-
tle = lfirst(l);
388-
((Var*)tle->expr)->varno = 1;
386+
Resdom *resdom = NULL;
387+
TargetEntry *te = (TargetEntry *) lfirst (sl);
388+
389+
foreach (gl, glc)
390+
{
391+
GroupClause *grpcl = (GroupClause*)lfirst(gl);
392+
393+
if ( grpcl->resdom->resno == te->resdom->resno )
394+
{
395+
396+
resdom = te->resdom;
397+
resdom->reskey = keyno;
398+
resdom->reskeyop = get_opcode (grpcl->grpOpoid);
399+
resdom->resno = last_resno; /* re-set */
400+
grpColIdx[keyno-1] = last_resno++;
401+
keyno++;
402+
glc = lremove (lfirst (gl), glc); /* TLE found for it */
403+
break;
404+
}
405+
}
406+
if ( resdom == NULL ) /* Not GroupBy-ed entry: remove */
407+
{ /* aggregate(s) from Group/Sort TL */
408+
if ( IsA (te->expr, Aggreg) )
409+
{ /* save Aggregate' Vars */
410+
aggvals = nconc (aggvals, pull_var_clause (te->expr));
411+
sort_tlist = lremove (lfirst (sl), sort_tlist);
412+
}
413+
else
414+
resdom->resno = last_resno++; /* re-set */
389415
}
390416
}
417+
418+
if ( length (glc) != 0 )
419+
{
420+
elog(WARN, "group attribute disappeared from target list");
421+
}
391422

392-
foreach (gl, groupClause) {
393-
GroupClause *grpcl = (GroupClause*)lfirst(gl);
394-
TargetEntry *tle;
423+
/*
424+
* Aggregates were removed from TL - we are to add Vars for them
425+
* to the end of TL if there are no such Vars in TL already.
426+
*/
395427

396-
tle = match_varid(grpcl->grpAttr, sort_tlist);
397-
/*
398-
* the parser should have checked to make sure the group attribute
399-
* is valid but the optimizer might have screwed up and hence we
400-
* check again.
401-
*/
402-
if (tle==NULL) {
403-
elog(WARN, "group attribute disappeared from target list");
428+
aggvcnt = length (aggvals);
429+
foreach (gl, aggvals)
430+
{
431+
Var *v = (Var*)lfirst (gl);
432+
433+
if ( tlist_member (v, sort_tlist) == NULL )
434+
{
435+
sort_tlist = lappend (sort_tlist,
436+
create_tl_element (v, last_resno));
437+
last_resno++;
404438
}
405-
tle->resdom->reskey = keyno;
406-
tle->resdom->reskeyop = get_opcode(grpcl->grpOpoid);
439+
else /* already in TL */
440+
aggvcnt--;
441+
}
442+
/* Now aggvcnt is number of Vars added in TL for Aggregates */
443+
444+
/* Make TL for subplan: substitute Vars from subplan TL into new TL */
445+
sl = flatten_tlist_vars (sort_tlist, subplan->targetlist);
446+
447+
subplan->targetlist = new_unsorted_tlist (sl); /* there */
407448

408-
grpColIdx[keyno-1] = tle->resdom->resno;
409-
keyno++;
449+
/*
450+
* Make Sort/Group TL :
451+
* 1. make Var nodes (with varno = 1 and varnoold = -1) for all
452+
* functions, 'couse they will be evaluated by subplan;
453+
* 2. for real Vars: set varno = 1 and varattno to its resno in subplan
454+
*/
455+
foreach (sl, sort_tlist)
456+
{
457+
TargetEntry *te = (TargetEntry *) lfirst (sl);
458+
Resdom *resdom = te->resdom;
459+
Node *expr = te->expr;
460+
461+
if ( IsA (expr, Var) )
462+
{
463+
#if 0 /* subplanVar->resdom->resno expected to be = te->resdom->resno */
464+
TargetEntry *subplanVar;
465+
466+
subplanVar = match_varid ((Var*)expr, subplan->targetlist);
467+
((Var*)expr)->varattno = subplanVar->resdom->resno;
468+
#endif
469+
((Var*)expr)->varattno = te->resdom->resno;
470+
((Var*)expr)->varno = 1;
471+
}
472+
else
473+
te->expr = (Node*) makeVar (1, resdom->resno,
474+
resdom->restype,
475+
-1, resdom->resno);
410476
}
477+
411478
sortplan = make_sort(sort_tlist,
412479
_TEMP_RELATION_ID_,
413480
subplan,
@@ -417,8 +484,41 @@ make_groupPlan(List *tlist,
417484
/*
418485
* make the Group node
419486
*/
420-
tlist = copyObject(tlist); /* make a copy */
421-
grpplan = make_group(tlist, tuplePerGroup, numCols, grpColIdx, sortplan);
487+
sort_tlist = copyObject (sort_tlist);
488+
grpplan = make_group(sort_tlist, tuplePerGroup, numCols,
489+
grpColIdx, sortplan);
490+
491+
/*
492+
* Make TL for parent: "restore" Aggregates and
493+
* resno-s of others accordantly.
494+
*/
495+
sl = sort_tlist;
496+
sort_tlist = NIL; /* to be new parent TL */
497+
foreach (gl, *tlist)
498+
{
499+
TargetEntry *te = (TargetEntry *) lfirst (gl);
500+
501+
if ( !IsA (te->expr, Aggreg) ) /* It's "our" TLE - we're to return */
502+
{ /* it from Sort/Group plans */
503+
TargetEntry *my = (TargetEntry *) lfirst (sl); /* get it */
504+
505+
sl = sl->next; /* prepare for the next "our" */
506+
my = copyObject (my);
507+
my->resdom->resno = te->resdom->resno; /* order of parent TL */
508+
sort_tlist = lappend (sort_tlist, my);
509+
continue;
510+
}
511+
/* TLE of an aggregate */
512+
sort_tlist = lappend (sort_tlist, copyObject(te));
513+
}
514+
/*
515+
* Pure aggregates Vars were at the end of Group' TL.
516+
* They shouldn't appear in parent TL, all others shouldn't
517+
* disappear.
518+
*/
519+
Assert ( aggvcnt == length (sl) );
520+
521+
*tlist = sort_tlist;
422522

423523
return (Plan*)grpplan;
424524
}

0 commit comments

Comments
 (0)