7
7
*
8
8
*
9
9
* 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 $
11
11
*
12
12
*-------------------------------------------------------------------------
13
13
*/
19
19
#include "nodes/plannodes.h"
20
20
#include "nodes/parsenodes.h"
21
21
#include "nodes/relation.h"
22
+ #include "nodes/makefuncs.h"
22
23
23
24
#include "optimizer/planmain.h"
24
25
#include "optimizer/internal.h"
25
26
#include "optimizer/paths.h"
26
27
#include "optimizer/clauses.h"
27
28
#include "optimizer/keys.h"
28
29
#include "optimizer/tlist.h"
30
+ #include "optimizer/var.h"
29
31
#include "optimizer/xfunc.h"
30
32
#include "optimizer/cost.h"
31
33
39
41
static Plan * subplanner (Query * root , List * flat_tlist , List * qual );
40
42
static Result * make_result (List * tlist , Node * resconstantqual , Plan * subplan );
41
43
42
- static Plan * make_groupPlan (List * tlist , bool tuplePerGroup ,
44
+ static Plan * make_groupPlan (List * * tlist , bool tuplePerGroup ,
43
45
List * groupClause , Plan * subplan );
44
46
45
47
/*
@@ -110,20 +112,6 @@ query_planner(Query *root,
110
112
level_tlist = tlist ;
111
113
}
112
114
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
-
127
115
/*
128
116
* A query may have a non-variable target list and a non-variable
129
117
* qualification only under certain conditions:
@@ -170,7 +158,7 @@ query_planner(Query *root,
170
158
subplan = subplanner (root , level_tlist , qual );
171
159
172
160
set_tlist_references (subplan );
173
-
161
+
174
162
/*
175
163
* If we have a GROUP BY clause, insert a group node (with the appropriate
176
164
* sort node.)
@@ -184,32 +172,31 @@ query_planner(Query *root,
184
172
* present. Otherwise, need every tuple from the group to do the
185
173
* aggregation.)
186
174
*/
187
- tuplePerGroup = (aggplan == NULL ) ? FALSE : TRUE ;
175
+ tuplePerGroup = ( root -> qry_aggs ) ? TRUE : FALSE ;
188
176
189
177
subplan =
190
- make_groupPlan (tlist , tuplePerGroup , root -> groupClause , subplan );
178
+ make_groupPlan (& tlist , tuplePerGroup , root -> groupClause , subplan );
191
179
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 );
195
180
}
196
181
197
182
/*
198
183
* If aggregate is present, insert the agg node
199
184
*/
200
- if (aggplan != NULL ) {
185
+ if ( root -> qry_aggs )
186
+ {
187
+ aggplan = make_agg (tlist , root -> qry_numAgg , root -> qry_aggs );
201
188
aggplan -> plan .lefttree = subplan ;
202
- subplan = (Plan * )aggplan ;
203
-
204
189
/*
205
190
* set the varno/attno entries to the appropriate references to
206
191
* the result tuple of the subplans. (We need to set those in the
207
192
* array of aggreg's in the Agg node also. Even though they're
208
193
* pointers, after a few dozen's of copying, they're not the same as
209
194
* those in the target list.)
210
195
*/
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 ;
213
200
214
201
tlist = aggplan -> plan .targetlist ;
215
202
}
@@ -238,9 +225,17 @@ query_planner(Query *root,
238
225
* the very last stage of query execution. this could be bad.
239
226
* but it is joey's responsibility to optimally push these
240
227
* 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
241
233
*/
242
- subplan -> targetlist = flatten_tlist_vars (tlist ,
234
+ if ( root -> groupClause == NULL && aggplan == NULL )
235
+ {
236
+ subplan -> targetlist = flatten_tlist_vars (tlist ,
243
237
subplan -> targetlist );
238
+ }
244
239
245
240
/*
246
241
* Destructively modify the query plan's targetlist to add fjoin
@@ -356,58 +351,130 @@ make_result(List *tlist,
356
351
*****************************************************************************/
357
352
358
353
static Plan *
359
- make_groupPlan (List * tlist ,
354
+ make_groupPlan (List * * tlist ,
360
355
bool tuplePerGroup ,
361
356
List * groupClause ,
362
357
Plan * subplan )
363
358
{
364
359
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 ;
367
364
Sort * sortplan ;
368
365
Group * grpplan ;
369
366
int numCols ;
370
367
AttrNumber * grpColIdx ;
368
+ int keyno = 1 ;
369
+ int last_resno = 1 ;
371
370
372
371
numCols = length (groupClause );
373
372
grpColIdx = (AttrNumber * )palloc (sizeof (AttrNumber )* numCols );
374
373
374
+ sort_tlist = new_unsorted_tlist (* tlist ); /* it's copy */
375
+
375
376
/*
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.
378
383
*/
379
- keyno = 1 ;
380
- sort_tlist = new_unsorted_tlist (subplan -> targetlist );
381
-
384
+ foreach (sl , sort_tlist )
382
385
{
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 */
389
415
}
390
416
}
417
+
418
+ if ( length (glc ) != 0 )
419
+ {
420
+ elog (WARN , "group attribute disappeared from target list" );
421
+ }
391
422
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
+ */
395
427
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 ++ ;
404
438
}
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 */
407
448
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 );
410
476
}
477
+
411
478
sortplan = make_sort (sort_tlist ,
412
479
_TEMP_RELATION_ID_ ,
413
480
subplan ,
@@ -417,8 +484,41 @@ make_groupPlan(List *tlist,
417
484
/*
418
485
* make the Group node
419
486
*/
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 ;
422
522
423
523
return (Plan * )grpplan ;
424
524
}
0 commit comments