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

Commit82f755e

Browse files
committed
Test HAVING condition before computing targetlist of an Aggregate node.
This is required by SQL spec to avoid failures in cases like SELECT sum(win)/sum(lose) FROM ... GROUP BY ... HAVING sum(lose) > 0;AFAICT we have gotten this wrong since day one. Kudos to Holger Jakobsfor being the first to notice.
1 parentafa035c commit82f755e

File tree

1 file changed

+34
-30
lines changed

1 file changed

+34
-30
lines changed

‎src/backend/executor/nodeAgg.c

Lines changed: 34 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
* Portions Copyright (c) 1994, Regents of the University of California
4646
*
4747
* IDENTIFICATION
48-
* $PostgreSQL: pgsql/src/backend/executor/nodeAgg.c,v 1.122 2004/06/06 00:41:26 tgl Exp $
48+
* $PostgreSQL: pgsql/src/backend/executor/nodeAgg.c,v 1.123 2004/07/10 18:39:23 tgl Exp $
4949
*
5050
*-------------------------------------------------------------------------
5151
*/
@@ -674,7 +674,6 @@ agg_retrieve_direct(AggState *aggstate)
674674
AggStatePerGrouppergroup;
675675
TupleTableSlot*outerslot;
676676
TupleTableSlot*firstSlot;
677-
TupleTableSlot*resultSlot;
678677
intaggno;
679678

680679
/*
@@ -696,11 +695,8 @@ agg_retrieve_direct(AggState *aggstate)
696695
* We loop retrieving groups until we find one matching
697696
* aggstate->ss.ps.qual
698697
*/
699-
do
698+
while (!aggstate->agg_done)
700699
{
701-
if (aggstate->agg_done)
702-
returnNULL;
703-
704700
/*
705701
* If we don't already have the first tuple of the new group,
706702
* fetch it from the outer plan.
@@ -815,7 +811,7 @@ agg_retrieve_direct(AggState *aggstate)
815811
/*
816812
* If we have no first tuple (ie, the outerPlan didn't return
817813
* anything), create a dummy all-nulls input tuple for use by
818-
* ExecProject. 99.44% of the time this is a waste of cycles,
814+
*ExecQual/ExecProject. 99.44% of the time this is a waste of cycles,
819815
* because ordinarily the projected output tuple's targetlist
820816
* cannot contain any direct (non-aggregated) references to input
821817
* columns, so the dummy tuple will not be referenced. However
@@ -857,22 +853,28 @@ agg_retrieve_direct(AggState *aggstate)
857853
}
858854

859855
/*
860-
* Form a projection tuple using the aggregate results and the
861-
* representative input tuple.Store it in the result tuple slot.
862-
* Note we do not support aggregates returning sets ...
856+
* Use the representative input tuple for any references to
857+
* non-aggregated input columns in the qual and tlist.
863858
*/
864859
econtext->ecxt_scantuple=firstSlot;
865-
resultSlot=ExecProject(projInfo,NULL);
866860

867861
/*
868-
* If the completed tuple does not match the qualifications, it is
869-
* ignored and we loop back to try to process another group.
870-
* Otherwise, return the tuple.
862+
* Check the qual (HAVING clause); if the group does not match,
863+
* ignore it and loop back to try to process another group.
871864
*/
865+
if (ExecQual(aggstate->ss.ps.qual,econtext, false))
866+
{
867+
/*
868+
* Form and return a projection tuple using the aggregate results
869+
* and the representative input tuple. Note we do not support
870+
* aggregates returning sets ...
871+
*/
872+
returnExecProject(projInfo,NULL);
873+
}
872874
}
873-
while (!ExecQual(aggstate->ss.ps.qual,econtext, false));
874875

875-
returnresultSlot;
876+
/* No more groups */
877+
returnNULL;
876878
}
877879

878880
/*
@@ -934,7 +936,6 @@ agg_retrieve_hash_table(AggState *aggstate)
934936
AggStatePerGrouppergroup;
935937
AggHashEntryentry;
936938
TupleTableSlot*firstSlot;
937-
TupleTableSlot*resultSlot;
938939
intaggno;
939940

940941
/*
@@ -952,11 +953,8 @@ agg_retrieve_hash_table(AggState *aggstate)
952953
* We loop retrieving groups until we find one satisfying
953954
* aggstate->ss.ps.qual
954955
*/
955-
do
956+
while (!aggstate->agg_done)
956957
{
957-
if (aggstate->agg_done)
958-
returnNULL;
959-
960958
/*
961959
* Find the next entry in the hash table
962960
*/
@@ -999,22 +997,28 @@ agg_retrieve_hash_table(AggState *aggstate)
999997
}
1000998

1001999
/*
1002-
* Form a projection tuple using the aggregate results and the
1003-
* representative input tuple.Store it in the result tuple slot.
1004-
* Note we do not support aggregates returning sets ...
1000+
* Use the representative input tuple for any references to
1001+
* non-aggregated input columns in the qual and tlist.
10051002
*/
10061003
econtext->ecxt_scantuple=firstSlot;
1007-
resultSlot=ExecProject(projInfo,NULL);
10081004

10091005
/*
1010-
* If the completed tuple does not match the qualifications, it is
1011-
* ignored and we loop back to try to process another group.
1012-
* Otherwise, return the tuple.
1006+
* Check the qual (HAVING clause); if the group does not match,
1007+
* ignore it and loop back to try to process another group.
10131008
*/
1009+
if (ExecQual(aggstate->ss.ps.qual,econtext, false))
1010+
{
1011+
/*
1012+
* Form and return a projection tuple using the aggregate results
1013+
* and the representative input tuple. Note we do not support
1014+
* aggregates returning sets ...
1015+
*/
1016+
returnExecProject(projInfo,NULL);
1017+
}
10141018
}
1015-
while (!ExecQual(aggstate->ss.ps.qual,econtext, false));
10161019

1017-
returnresultSlot;
1020+
/* No more groups */
1021+
returnNULL;
10181022
}
10191023

10201024
/* -----------------

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp