diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2008-09-08 00:22:56 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2008-09-08 00:22:56 +0000 |
commit | a26c7e3d71d65381bc60b0d0b30f03cd738fb0e9 (patch) | |
tree | 40b2c5d312c2c99cc1d52af323e652036a79ac2e /src/backend/executor/nodeAgg.c | |
parent | 8818f3793e88e183e8eaff21fbb6762e6e73f663 (diff) | |
download | postgresql-a26c7e3d71d65381bc60b0d0b30f03cd738fb0e9.tar.gz postgresql-a26c7e3d71d65381bc60b0d0b30f03cd738fb0e9.zip |
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.
Diffstat (limited to 'src/backend/executor/nodeAgg.c')
-rw-r--r-- | src/backend/executor/nodeAgg.c | 53 |
1 files changed, 42 insertions, 11 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; + } } } |