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)
        PlanState  *outerPlan;
        ExprContext *econtext;
        ExprContext *tmpcontext;
-       ProjectionInfo *projInfo;
        Datum      *aggvalues;
        bool       *aggnulls;
        AggStatePerAgg peragg;
        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;
                {
                        /*
                         * 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;
+                       }
                }
        }
 
 agg_retrieve_hash_table(AggState *aggstate)
 {
        ExprContext *econtext;
-       ProjectionInfo *projInfo;
        Datum      *aggvalues;
        bool       *aggnulls;
        AggStatePerAgg peragg;
        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;
 
                {
                        /*
                         * 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;
+                       }
                }
        }
 
 
        numCols = ((Group *) node->ss.ps.plan)->numCols;
        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.
         */
                        /*
                         * 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;
+                       }
                }
        }
 
                        /*
                         * 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;
+                       }
                }
        }