aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/executor')
-rw-r--r--src/backend/executor/nodeAgg.c53
-rw-r--r--src/backend/executor/nodeGroup.c41
2 files changed, 80 insertions, 14 deletions
diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c
index fa49862912e..80263d174c2 100644
--- a/src/backend/executor/nodeAgg.c
+++ b/src/backend/executor/nodeAgg.c
@@ -61,7 +61,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/nodeAgg.c,v 1.160 2008/08/25 22:42:32 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/nodeAgg.c,v 1.161 2008/09/08 00:22:55 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -805,6 +805,23 @@ ExecAgg(AggState *node)
if (node->agg_done)
return NULL;
+ /*
+ * Check to see if we're still projecting out tuples from a previous agg
+ * tuple (because there is a function-returning-set in the projection
+ * expressions). If so, try to project another one.
+ */
+ if (node->ss.ps.ps_TupFromTlist)
+ {
+ TupleTableSlot *result;
+ ExprDoneCond isDone;
+
+ result = ExecProject(node->ss.ps.ps_ProjInfo, &isDone);
+ if (isDone == ExprMultipleResult)
+ return result;
+ /* Done with that source tuple... */
+ node->ss.ps.ps_TupFromTlist = false;
+ }
+
if (((Agg *) node->ss.ps.plan)->aggstrategy == AGG_HASHED)
{
if (!node->table_filled)
@@ -825,7 +842,6 @@ agg_retrieve_direct(AggState *aggstate)
PlanState *outerPlan;
ExprContext *econtext;
ExprContext *tmpcontext;
- ProjectionInfo *projInfo;
Datum *aggvalues;
bool *aggnulls;
AggStatePerAgg peragg;
@@ -844,7 +860,6 @@ agg_retrieve_direct(AggState *aggstate)
aggnulls = econtext->ecxt_aggnulls;
/* tmpcontext is the per-input-tuple expression context */
tmpcontext = aggstate->tmpcontext;
- projInfo = aggstate->ss.ps.ps_ProjInfo;
peragg = aggstate->peragg;
pergroup = aggstate->pergroup;
firstSlot = aggstate->ss.ss_ScanTupleSlot;
@@ -982,10 +997,19 @@ agg_retrieve_direct(AggState *aggstate)
{
/*
* Form and return a projection tuple using the aggregate results
- * and the representative input tuple. Note we do not support
- * aggregates returning sets ...
+ * and the representative input tuple.
*/
- return ExecProject(projInfo, NULL);
+ TupleTableSlot *result;
+ ExprDoneCond isDone;
+
+ result = ExecProject(aggstate->ss.ps.ps_ProjInfo, &isDone);
+
+ if (isDone != ExprEndResult)
+ {
+ aggstate->ss.ps.ps_TupFromTlist =
+ (isDone == ExprMultipleResult);
+ return result;
+ }
}
}
@@ -1045,7 +1069,6 @@ static TupleTableSlot *
agg_retrieve_hash_table(AggState *aggstate)
{
ExprContext *econtext;
- ProjectionInfo *projInfo;
Datum *aggvalues;
bool *aggnulls;
AggStatePerAgg peragg;
@@ -1061,7 +1084,6 @@ agg_retrieve_hash_table(AggState *aggstate)
econtext = aggstate->ss.ps.ps_ExprContext;
aggvalues = econtext->ecxt_aggvalues;
aggnulls = econtext->ecxt_aggnulls;
- projInfo = aggstate->ss.ps.ps_ProjInfo;
peragg = aggstate->peragg;
firstSlot = aggstate->ss.ss_ScanTupleSlot;
@@ -1125,10 +1147,19 @@ agg_retrieve_hash_table(AggState *aggstate)
{
/*
* Form and return a projection tuple using the aggregate results
- * and the representative input tuple. Note we do not support
- * aggregates returning sets ...
+ * and the representative input tuple.
*/
- return ExecProject(projInfo, NULL);
+ TupleTableSlot *result;
+ ExprDoneCond isDone;
+
+ result = ExecProject(aggstate->ss.ps.ps_ProjInfo, &isDone);
+
+ if (isDone != ExprEndResult)
+ {
+ aggstate->ss.ps.ps_TupFromTlist =
+ (isDone == ExprMultipleResult);
+ return result;
+ }
}
}
diff --git a/src/backend/executor/nodeGroup.c b/src/backend/executor/nodeGroup.c
index 414e0b93f70..31566f1fb52 100644
--- a/src/backend/executor/nodeGroup.c
+++ b/src/backend/executor/nodeGroup.c
@@ -15,7 +15,7 @@
* locate group boundaries.
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/nodeGroup.c,v 1.70 2008/01/01 19:45:49 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/nodeGroup.c,v 1.71 2008/09/08 00:22:56 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -50,6 +50,23 @@ ExecGroup(GroupState *node)
grpColIdx = ((Group *) node->ss.ps.plan)->grpColIdx;
/*
+ * Check to see if we're still projecting out tuples from a previous group
+ * tuple (because there is a function-returning-set in the projection
+ * expressions). If so, try to project another one.
+ */
+ if (node->ss.ps.ps_TupFromTlist)
+ {
+ TupleTableSlot *result;
+ ExprDoneCond isDone;
+
+ result = ExecProject(node->ss.ps.ps_ProjInfo, &isDone);
+ if (isDone == ExprMultipleResult)
+ return result;
+ /* Done with that source tuple... */
+ node->ss.ps.ps_TupFromTlist = false;
+ }
+
+ /*
* The ScanTupleSlot holds the (copied) first tuple of each group.
*/
firsttupleslot = node->ss.ss_ScanTupleSlot;
@@ -90,7 +107,16 @@ ExecGroup(GroupState *node)
/*
* Form and return a projection tuple using the first input tuple.
*/
- return ExecProject(node->ss.ps.ps_ProjInfo, NULL);
+ TupleTableSlot *result;
+ ExprDoneCond isDone;
+
+ result = ExecProject(node->ss.ps.ps_ProjInfo, &isDone);
+
+ if (isDone != ExprEndResult)
+ {
+ node->ss.ps.ps_TupFromTlist = (isDone == ExprMultipleResult);
+ return result;
+ }
}
}
@@ -142,7 +168,16 @@ ExecGroup(GroupState *node)
/*
* Form and return a projection tuple using the first input tuple.
*/
- return ExecProject(node->ss.ps.ps_ProjInfo, NULL);
+ TupleTableSlot *result;
+ ExprDoneCond isDone;
+
+ result = ExecProject(node->ss.ps.ps_ProjInfo, &isDone);
+
+ if (isDone != ExprEndResult)
+ {
+ node->ss.ps.ps_TupFromTlist = (isDone == ExprMultipleResult);
+ return result;
+ }
}
}