Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commita1fbd47

Browse files
committed
Fix GroupBy: enable functions over aggregates and GroupBy-ed fields
in target list.
1 parentf4279c4 commita1fbd47

File tree

3 files changed

+87
-66
lines changed

3 files changed

+87
-66
lines changed

‎src/backend/optimizer/plan/planmain.c

Lines changed: 45 additions & 26 deletions
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.3 1997/04/05 06:37:37 vadim Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planmain.c,v 1.4 1997/04/29 04:32:50 vadim Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -359,8 +359,9 @@ make_groupPlan(List **tlist,
359359
List*sort_tlist;
360360
List*sl,*gl;
361361
List*glc=listCopy (groupClause);
362-
List*aggvals=NIL;/* list of vars of aggregates */
363-
intaggvcnt;
362+
List*otles=NIL;/* list of removed non-GroupBy entries */
363+
List*otlvars=NIL;/* list of var in them */
364+
intotlvcnt;
364365
Sort*sortplan;
365366
Group*grpplan;
366367
intnumCols;
@@ -375,7 +376,8 @@ make_groupPlan(List **tlist,
375376

376377
/*
377378
* Make template TL for subplan, Sort & Group:
378-
* 1. Take away Aggregates and re-set resno-s accordantly.
379+
* 1. If there are aggregates (tuplePerGroup is true) then take
380+
* away non-GroupBy entries and re-set resno-s accordantly.
379381
* 2. Make grpColIdx
380382
*
381383
* Note: we assume that TLEs in *tlist are ordered in accordance
@@ -390,7 +392,7 @@ make_groupPlan(List **tlist,
390392
{
391393
GroupClause*grpcl= (GroupClause*)lfirst(gl);
392394

393-
if (grpcl->resdom->resno==te->resdom->resno )
395+
if (grpcl->entry->resdom->resno==te->resdom->resno )
394396
{
395397

396398
resdom=te->resdom;
@@ -403,15 +405,20 @@ make_groupPlan(List **tlist,
403405
break;
404406
}
405407
}
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);
408+
/*
409+
* Non-GroupBy entry: remove it from Group/Sort TL if there are
410+
* aggregates in query - it will be evaluated by Aggregate plan
411+
*/
412+
if (resdom==NULL )
413+
{
414+
if (tuplePerGroup )
415+
{
416+
otlvars=nconc (otlvars,pull_var_clause (te->expr));
417+
otles=lcons (te,otles);
418+
sort_tlist=lremove (te,sort_tlist);
412419
}
413420
else
414-
resdom->resno=last_resno++;/* re-set */
421+
te->resdom->resno=last_resno++;
415422
}
416423
}
417424

@@ -421,12 +428,12 @@ make_groupPlan(List **tlist,
421428
}
422429

423430
/*
424-
*Aggregateswere removed from TL - we are to add Vars forthem
425-
* to the end of TL if there are no such Vars in TL already.
431+
*If non-GroupBy entrieswere removed from TL - we are to add Vars for
432+
*themto the end of TL if there are no such Vars in TL already.
426433
*/
427434

428-
aggvcnt=length (aggvals);
429-
foreach (gl,aggvals)
435+
otlvcnt=length (otlvars);
436+
foreach (gl,otlvars)
430437
{
431438
Var*v= (Var*)lfirst (gl);
432439

@@ -437,9 +444,9 @@ make_groupPlan(List **tlist,
437444
last_resno++;
438445
}
439446
else/* already in TL */
440-
aggvcnt--;
447+
otlvcnt--;
441448
}
442-
/* Nowaggvcnt is number of Vars added in TL forAggregates */
449+
/* Nowotlvcnt is number of Vars added in TL fornon-GroupBy entries */
443450

444451
/* Make TL for subplan: substitute Vars from subplan TL into new TL */
445452
sl=flatten_tlist_vars (sort_tlist,subplan->targetlist);
@@ -489,17 +496,28 @@ make_groupPlan(List **tlist,
489496
grpColIdx,sortplan);
490497

491498
/*
492-
* Make TL for parent: "restore"Aggregates and
493-
* resno-s of others accordantly.
499+
* Make TL for parent: "restore"non-GroupBy entries (if they
500+
*were removed) and setresno-s of others accordantly.
494501
*/
495502
sl=sort_tlist;
496503
sort_tlist=NIL;/* to be new parent TL */
497504
foreach (gl,*tlist)
498505
{
506+
List*temp=NIL;
499507
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 */
508+
509+
foreach (temp,otles)/* Is it removed non-GroupBy entry ? */
510+
{
511+
TargetEntry*ote= (TargetEntry*)lfirst (temp);
512+
513+
if (ote->resdom->resno==te->resdom->resno )
514+
{
515+
otles=lremove (ote,otles);
516+
break;
517+
}
518+
}
519+
if (temp==NIL )/* It's "our" TLE - we're to return */
520+
{/* it from Sort/Group plans */
503521
TargetEntry*my= (TargetEntry*)lfirst (sl);/* get it */
504522

505523
sl=sl->next;/* prepare for the next "our" */
@@ -508,15 +526,16 @@ make_groupPlan(List **tlist,
508526
sort_tlist=lappend (sort_tlist,my);
509527
continue;
510528
}
511-
/* TLE of anaggregate */
529+
/*else - it'sTLE of annon-GroupBy entry */
512530
sort_tlist=lappend (sort_tlist,copyObject(te));
513531
}
514532
/*
515-
* Pureaggregates Vars were at the end of Group' TL.
533+
* Purenon-GroupBy entries Vars were at the end of Group' TL.
516534
* They shouldn't appear in parent TL, all others shouldn't
517535
* disappear.
518536
*/
519-
Assert (aggvcnt==length (sl) );
537+
Assert (otlvcnt==length (sl) );
538+
Assert (length (otles)==0 );
520539

521540
*tlist=sort_tlist;
522541

‎src/backend/parser/analyze.c

Lines changed: 40 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.26 1997/04/27 19:16:44 thomas Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.27 1997/04/29 04:32:26 vadim Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -1552,7 +1552,8 @@ transformGroupClause(ParseState *pstate, List *grouplist, List *targetlist)
15521552
if (restarget==NULL)
15531553
elog(WARN,"The field being grouped by must appear in the target list");
15541554

1555-
grpcl->resdom=resdom=restarget->resdom;
1555+
grpcl->entry=restarget;
1556+
resdom=restarget->resdom;
15561557
grpcl->grpOpoid=oprid(oper("<",
15571558
resdom->restype,
15581559
resdom->restype,false));
@@ -2359,6 +2360,39 @@ contain_agg_clause(Node *clause)
23592360
return FALSE;
23602361
}
23612362

2363+
/*
2364+
* exprIsAggOrGroupCol -
2365+
* returns true if the expression does not contain non-group columns.
2366+
*/
2367+
staticbool
2368+
exprIsAggOrGroupCol(Node*expr,List*groupClause)
2369+
{
2370+
List*gl;
2371+
2372+
if (expr==NULL||IsA (expr,Const)||IsA (expr,Aggreg) )
2373+
return TRUE;
2374+
2375+
foreach (gl,groupClause)
2376+
{
2377+
GroupClause*grpcl=lfirst(gl);
2378+
2379+
if (equal (expr,grpcl->entry->expr) )
2380+
return TRUE;
2381+
}
2382+
2383+
if (IsA (expr,Expr) )
2384+
{
2385+
List*temp;
2386+
2387+
foreach (temp, ((Expr*)expr)->args)
2388+
if (!exprIsAggOrGroupCol(lfirst(temp),groupClause))
2389+
return FALSE;
2390+
return TRUE;
2391+
}
2392+
2393+
return FALSE;
2394+
}
2395+
23622396
/*
23632397
* tleIsAggOrGroupCol -
23642398
* returns true if the TargetEntry is Agg or GroupCol.
@@ -2376,9 +2410,9 @@ tleIsAggOrGroupCol(TargetEntry *tle, List *groupClause)
23762410
{
23772411
GroupClause*grpcl=lfirst(gl);
23782412

2379-
if (tle->resdom->resno==grpcl->resdom->resno )
2413+
if (tle->resdom->resno==grpcl->entry->resdom->resno )
23802414
{
2381-
if (IsA (expr,Aggreg) )
2415+
if (contain_agg_clause ((Node*)expr) )
23822416
elog (WARN,"parser: aggregates not allowed in GROUP BY clause");
23832417
return TRUE;
23842418
}
@@ -2387,39 +2421,8 @@ tleIsAggOrGroupCol(TargetEntry *tle, List *groupClause)
23872421
if (IsA (expr,Aggreg) )
23882422
return TRUE;
23892423

2390-
return FALSE;
2391-
}
2392-
2393-
#if0/* Now GroupBy contains resdom to enable Group By func_results */
2394-
/*
2395-
* exprIsAggOrGroupCol -
2396-
* returns true if the expression does not contain non-group columns.
2397-
*/
2398-
staticbool
2399-
exprIsAggOrGroupCol(Node*expr,List*groupClause)
2400-
{
2401-
if (expr==NULL)
2402-
return TRUE;
2403-
elseif (IsA(expr,Const))
2404-
return TRUE;
2405-
elseif (IsA(expr,Var)) {
2406-
List*gl;
2407-
Var*var= (Var*)expr;
2408-
/*
2409-
* only group columns are legal
2410-
*/
2411-
foreach (gl,groupClause) {
2412-
GroupClause*grpcl=lfirst(gl);
2413-
if ((grpcl->grpAttr->varno==var->varno)&&
2414-
(grpcl->grpAttr->varattno==var->varattno))
2415-
return TRUE;
2416-
}
2417-
return FALSE;
2418-
}elseif (IsA(expr,Aggreg))
2419-
/* aggregates can take group column or non-group column as argument,
2420-
no further check necessary. */
2421-
return TRUE;
2422-
elseif (IsA(expr,Expr)) {
2424+
if (IsA (expr,Expr) )
2425+
{
24232426
List*temp;
24242427

24252428
foreach (temp, ((Expr*)expr)->args)
@@ -2430,7 +2433,6 @@ exprIsAggOrGroupCol(Node *expr, List *groupClause)
24302433

24312434
return FALSE;
24322435
}
2433-
#endif
24342436

24352437
/*
24362438
* parseCheckAggregates -

‎src/include/nodes/parsenodes.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
*
77
* Copyright (c) 1994, Regents of the University of California
88
*
9-
* $Id: parsenodes.h,v 1.14 1997/04/23 05:58:06 vadim Exp $
9+
* $Id: parsenodes.h,v 1.15 1997/04/29 04:28:59 vadim Exp $
1010
*
1111
*-------------------------------------------------------------------------
1212
*/
@@ -774,7 +774,7 @@ typedef struct SortClause {
774774
*/
775775
typedefstructGroupClause {
776776
NodeTagtype;
777-
Resdom*resdom;/* attributes to group on */
777+
TargetEntry*entry;/* attributes to group on */
778778
OidgrpOpoid;/* the sort operator to use */
779779
}GroupClause;
780780

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp