Skip to content

Commit a26c7e3

Browse files
committed
Support set-returning functions in the target lists of Agg and Group plan
nodes. This is a pretty ugly feature but since we don't yet have a plausible substitute, we'd better support it everywhere. Per gripe from Jeff Davis.
1 parent 8818f37 commit a26c7e3

File tree

2 files changed

+80
-14
lines changed

2 files changed

+80
-14
lines changed

src/backend/executor/nodeAgg.c

Lines changed: 42 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@
6161
* Portions Copyright (c) 1994, Regents of the University of California
6262
*
6363
* IDENTIFICATION
64-
* $PostgreSQL: pgsql/src/backend/executor/nodeAgg.c,v 1.160 2008/08/25 22:42:32 tgl Exp $
64+
* $PostgreSQL: pgsql/src/backend/executor/nodeAgg.c,v 1.161 2008/09/08 00:22:55 tgl Exp $
6565
*
6666
*-------------------------------------------------------------------------
6767
*/
@@ -805,6 +805,23 @@ ExecAgg(AggState *node)
805805
if (node->agg_done)
806806
return NULL;
807807

808+
/*
809+
* Check to see if we're still projecting out tuples from a previous agg
810+
* tuple (because there is a function-returning-set in the projection
811+
* expressions). If so, try to project another one.
812+
*/
813+
if (node->ss.ps.ps_TupFromTlist)
814+
{
815+
TupleTableSlot *result;
816+
ExprDoneCond isDone;
817+
818+
result = ExecProject(node->ss.ps.ps_ProjInfo, &isDone);
819+
if (isDone == ExprMultipleResult)
820+
return result;
821+
/* Done with that source tuple... */
822+
node->ss.ps.ps_TupFromTlist = false;
823+
}
824+
808825
if (((Agg *) node->ss.ps.plan)->aggstrategy == AGG_HASHED)
809826
{
810827
if (!node->table_filled)
@@ -825,7 +842,6 @@ agg_retrieve_direct(AggState *aggstate)
825842
PlanState *outerPlan;
826843
ExprContext *econtext;
827844
ExprContext *tmpcontext;
828-
ProjectionInfo *projInfo;
829845
Datum *aggvalues;
830846
bool *aggnulls;
831847
AggStatePerAgg peragg;
@@ -844,7 +860,6 @@ agg_retrieve_direct(AggState *aggstate)
844860
aggnulls = econtext->ecxt_aggnulls;
845861
/* tmpcontext is the per-input-tuple expression context */
846862
tmpcontext = aggstate->tmpcontext;
847-
projInfo = aggstate->ss.ps.ps_ProjInfo;
848863
peragg = aggstate->peragg;
849864
pergroup = aggstate->pergroup;
850865
firstSlot = aggstate->ss.ss_ScanTupleSlot;
@@ -982,10 +997,19 @@ agg_retrieve_direct(AggState *aggstate)
982997
{
983998
/*
984999
* Form and return a projection tuple using the aggregate results
985-
* and the representative input tuple. Note we do not support
986-
* aggregates returning sets ...
1000+
* and the representative input tuple.
9871001
*/
988-
return ExecProject(projInfo, NULL);
1002+
TupleTableSlot *result;
1003+
ExprDoneCond isDone;
1004+
1005+
result = ExecProject(aggstate->ss.ps.ps_ProjInfo, &isDone);
1006+
1007+
if (isDone != ExprEndResult)
1008+
{
1009+
aggstate->ss.ps.ps_TupFromTlist =
1010+
(isDone == ExprMultipleResult);
1011+
return result;
1012+
}
9891013
}
9901014
}
9911015

@@ -1045,7 +1069,6 @@ static TupleTableSlot *
10451069
agg_retrieve_hash_table(AggState *aggstate)
10461070
{
10471071
ExprContext *econtext;
1048-
ProjectionInfo *projInfo;
10491072
Datum *aggvalues;
10501073
bool *aggnulls;
10511074
AggStatePerAgg peragg;
@@ -1061,7 +1084,6 @@ agg_retrieve_hash_table(AggState *aggstate)
10611084
econtext = aggstate->ss.ps.ps_ExprContext;
10621085
aggvalues = econtext->ecxt_aggvalues;
10631086
aggnulls = econtext->ecxt_aggnulls;
1064-
projInfo = aggstate->ss.ps.ps_ProjInfo;
10651087
peragg = aggstate->peragg;
10661088
firstSlot = aggstate->ss.ss_ScanTupleSlot;
10671089

@@ -1125,10 +1147,19 @@ agg_retrieve_hash_table(AggState *aggstate)
11251147
{
11261148
/*
11271149
* Form and return a projection tuple using the aggregate results
1128-
* and the representative input tuple. Note we do not support
1129-
* aggregates returning sets ...
1150+
* and the representative input tuple.
11301151
*/
1131-
return ExecProject(projInfo, NULL);
1152+
TupleTableSlot *result;
1153+
ExprDoneCond isDone;
1154+
1155+
result = ExecProject(aggstate->ss.ps.ps_ProjInfo, &isDone);
1156+
1157+
if (isDone != ExprEndResult)
1158+
{
1159+
aggstate->ss.ps.ps_TupFromTlist =
1160+
(isDone == ExprMultipleResult);
1161+
return result;
1162+
}
11321163
}
11331164
}
11341165

src/backend/executor/nodeGroup.c

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
* locate group boundaries.
1616
*
1717
* IDENTIFICATION
18-
* $PostgreSQL: pgsql/src/backend/executor/nodeGroup.c,v 1.70 2008/01/01 19:45:49 momjian Exp $
18+
* $PostgreSQL: pgsql/src/backend/executor/nodeGroup.c,v 1.71 2008/09/08 00:22:56 tgl Exp $
1919
*
2020
*-------------------------------------------------------------------------
2121
*/
@@ -49,6 +49,23 @@ ExecGroup(GroupState *node)
4949
numCols = ((Group *) node->ss.ps.plan)->numCols;
5050
grpColIdx = ((Group *) node->ss.ps.plan)->grpColIdx;
5151

52+
/*
53+
* Check to see if we're still projecting out tuples from a previous group
54+
* tuple (because there is a function-returning-set in the projection
55+
* expressions). If so, try to project another one.
56+
*/
57+
if (node->ss.ps.ps_TupFromTlist)
58+
{
59+
TupleTableSlot *result;
60+
ExprDoneCond isDone;
61+
62+
result = ExecProject(node->ss.ps.ps_ProjInfo, &isDone);
63+
if (isDone == ExprMultipleResult)
64+
return result;
65+
/* Done with that source tuple... */
66+
node->ss.ps.ps_TupFromTlist = false;
67+
}
68+
5269
/*
5370
* The ScanTupleSlot holds the (copied) first tuple of each group.
5471
*/
@@ -90,7 +107,16 @@ ExecGroup(GroupState *node)
90107
/*
91108
* Form and return a projection tuple using the first input tuple.
92109
*/
93-
return ExecProject(node->ss.ps.ps_ProjInfo, NULL);
110+
TupleTableSlot *result;
111+
ExprDoneCond isDone;
112+
113+
result = ExecProject(node->ss.ps.ps_ProjInfo, &isDone);
114+
115+
if (isDone != ExprEndResult)
116+
{
117+
node->ss.ps.ps_TupFromTlist = (isDone == ExprMultipleResult);
118+
return result;
119+
}
94120
}
95121
}
96122

@@ -142,7 +168,16 @@ ExecGroup(GroupState *node)
142168
/*
143169
* Form and return a projection tuple using the first input tuple.
144170
*/
145-
return ExecProject(node->ss.ps.ps_ProjInfo, NULL);
171+
TupleTableSlot *result;
172+
ExprDoneCond isDone;
173+
174+
result = ExecProject(node->ss.ps.ps_ProjInfo, &isDone);
175+
176+
if (isDone != ExprEndResult)
177+
{
178+
node->ss.ps.ps_TupFromTlist = (isDone == ExprMultipleResult);
179+
return result;
180+
}
146181
}
147182
}
148183

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy