Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
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)