Repair memory leakage introduced into the non-hashed aggregate case by
authorTom Lane <tgl@sss.pgh.pa.us>
Sat, 13 Mar 2004 00:54:10 +0000 (00:54 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Sat, 13 Mar 2004 00:54:10 +0000 (00:54 +0000)
7.4 rewrite for hashed aggregate support.  If the transition data type
is pass-by-reference, the transValue must be pfreed when starting a new
group boundary, else we have a one-value-per-group leakage.  Thanks to
Rae Steining for providing a reproducible test case.

src/backend/executor/nodeAgg.c

index cb0a64c42771beb660c1f30a4c2aec1f39dd1711..0a872221276b4da83ef5e1b874e633da9c1beb54 100644 (file)
@@ -45,7 +45,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/executor/nodeAgg.c,v 1.118 2004/02/03 17:34:02 tgl Exp $
+ *   $PostgreSQL: pgsql/src/backend/executor/nodeAgg.c,v 1.119 2004/03/13 00:54:10 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -251,6 +251,18 @@ initialize_aggregates(AggState *aggstate,
                                      work_mem, false);
        }
 
+       /*
+        * If we are reinitializing after a group boundary, we have to free
+        * any prior transValue to avoid memory leakage.  We must check not
+        * only the isnull flag but whether the pointer is NULL; since
+        * pergroupstate is initialized with palloc0, the initial condition
+        * has isnull = 0 and null pointer.
+        */
+       if (!peraggstate->transtypeByVal &&
+           !pergroupstate->transValueIsNull &&
+           DatumGetPointer(pergroupstate->transValue) != NULL)
+           pfree(DatumGetPointer(pergroupstate->transValue));
+
        /*
         * (Re)set transValue to the initial value.
         *
@@ -1472,6 +1484,12 @@ ExecReScanAgg(AggState *node, ExprContext *exprCtxt)
        build_hash_table(node);
        node->table_filled = false;
    }
+   else
+   {
+       /* Reset the per-group state (in particular, mark transvalues null) */
+       MemSet(node->pergroup, 0,
+              sizeof(AggStatePerGroupData) * node->numaggs);
+   }
 
    /*
     * if chgParam of subnode is not null then plan will be re-scanned by