From e8d78d35f45602767f8b2dc5893b9b768b777302 Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Wed, 17 Jun 2009 16:05:34 +0000
Subject: [PATCH] ExecAgg() failed to finish running out set-returning
 functions in the last aggregated tuple of a run.  Per report from Laurenz
 Albe.  This is a new bug in 8.4, but only because prior versions rejected
 SRFs in an Agg plan node altogether.

---
 src/backend/executor/nodeAgg.c | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c
index bd55a5246a3..a6b1f194ae4 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.166 2009/04/02 20:59:10 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/executor/nodeAgg.c,v 1.167 2009/06/17 16:05:34 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -811,9 +811,6 @@ lookup_hash_entry(AggState *aggstate, TupleTableSlot *inputslot)
 TupleTableSlot *
 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
@@ -831,6 +828,15 @@ ExecAgg(AggState *node)
 		node->ss.ps.ps_TupFromTlist = false;
 	}
 
+	/*
+	 * Exit if nothing left to do.  (We must do the ps_TupFromTlist check
+	 * first, because in some cases agg_done gets set before we emit the
+	 * final aggregate tuple, and we have to finish running SRFs for it.)
+	 */
+	if (node->agg_done)
+		return NULL;
+
+	/* Dispatch based on strategy */
 	if (((Agg *) node->ss.ps.plan)->aggstrategy == AGG_HASHED)
 	{
 		if (!node->table_filled)
-- 
GitLab