Handling of aggregates without initial values (such as min, max, etc.) was buggy. Previously freed memory was being read, resulting in incorrect values showing up unpredictably.
Thanks to Liakakis Kostas (kostas@astro.auth.gr) for finding the problem and providing valuable support in tracking down the bug.
Apply this patch.
diff -c -r1.13 nodeAgg.c
*** 1.13 1995/08/01 20:19:07
--- src/backend/executor/nodeAgg.c 1995/09/07 21:37:28
***************
*** 21,26 ****
--- 21,27 ----
#include "executor/executor.h"
#include "executor/nodeAgg.h"
#include "storage/bufmgr.h"
+ #include "utils/palloc.h"
/*
* AggFuncInfo -
***************
*** 245,250 ****
--- 246,253 ----
}
for(i = 0; i < nagg; i++) {
+ AttrNumber attnum;
+ int2 attlen;
Datum newVal;
AggFuncInfo *aggfns = &aggFuncInfo[i];
Datum args[2];
***************
*** 263,269 ****
* is the first non-NULL value. We use it as the
* initial value.
*/
! value1[i] = newVal;
noInitValue[i] = 0;
nulls[i] = 0;
} else {
--- 266,287 ----
* is the first non-NULL value. We use it as the
* initial value.
*/
! /* but we can't just use it straight, we have
! to make a copy of it since the tuple from which
! it came will be freed on the next iteration
! of the scan */
! attnum = ((Var*)aggregates[i]->target)->varattno;
! attlen = outerslot->ttc_tupleDescriptor->attrs[attnum-1]->attlen;
! if (attlen == -1) {
! /* variable length */
! attlen = VARSIZE((struct varlena*) newVal);
! }
! value1[i] = (Datum)palloc(attlen);
! if (outerslot->ttc_tupleDescriptor->attrs[attnum-1]->attbyval)
! value1[i] = newVal;
! else
! memmove(value1[i], newVal, attlen);
! /* value1[i] = newVal; */
noInitValue[i] = 0;
nulls[i] = 0;
} else {