diff --git a/src/backend/utils/adt/float.c b/src/backend/utils/adt/float.c
index e51babfebfb7f9cd801f2caac545faa09c3439ae..c943ee2c71d405ef5c9eb0a761f596ce2c6676dc 100644
--- a/src/backend/utils/adt/float.c
+++ b/src/backend/utils/adt/float.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/adt/float.c,v 1.113 2005/02/11 04:08:58 neilc Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/adt/float.c,v 1.114 2005/04/06 23:56:07 neilc Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1902,8 +1902,6 @@ float8_accum(PG_FUNCTION_ARGS)
 	float8		N,
 				sumX,
 				sumX2;
-	Datum		transdatums[3];
-	ArrayType  *result;
 
 	transvalues = check_float8_array(transarray, "float8_accum");
 	N = transvalues[0];
@@ -1914,15 +1912,35 @@ float8_accum(PG_FUNCTION_ARGS)
 	sumX += newval;
 	sumX2 += newval * newval;
 
-	transdatums[0] = Float8GetDatumFast(N);
-	transdatums[1] = Float8GetDatumFast(sumX);
-	transdatums[2] = Float8GetDatumFast(sumX2);
+	/*
+	 * If we're invoked by nodeAgg, we can cheat and modify our first
+	 * parameter in-place to reduce palloc overhead. Otherwise we
+	 * construct a new array with the updated transition data and
+	 * return it.
+	 */
+	if (fcinfo->context && IsA(fcinfo->context, AggState))
+	{
+		transvalues[0] = N;
+		transvalues[1] = sumX;
+		transvalues[2] = sumX2;
 
-	result = construct_array(transdatums, 3,
-							 FLOAT8OID,
-						 sizeof(float8), false /* float8 byval */ , 'd');
+		PG_RETURN_ARRAYTYPE_P(transarray);
+	}
+	else
+	{
+		Datum		transdatums[3];
+		ArrayType  *result;
+
+		transdatums[0] = Float8GetDatumFast(N);
+		transdatums[1] = Float8GetDatumFast(sumX);
+		transdatums[2] = Float8GetDatumFast(sumX2);
 
-	PG_RETURN_ARRAYTYPE_P(result);
+		result = construct_array(transdatums, 3,
+								 FLOAT8OID,
+								 sizeof(float8), false /* float8 byval */ , 'd');
+
+		PG_RETURN_ARRAYTYPE_P(result);
+	}
 }
 
 Datum
@@ -1935,8 +1953,6 @@ float4_accum(PG_FUNCTION_ARGS)
 				sumX,
 				sumX2,
 				newval;
-	Datum		transdatums[3];
-	ArrayType  *result;
 
 	transvalues = check_float8_array(transarray, "float4_accum");
 	N = transvalues[0];
@@ -1950,15 +1966,35 @@ float4_accum(PG_FUNCTION_ARGS)
 	sumX += newval;
 	sumX2 += newval * newval;
 
-	transdatums[0] = Float8GetDatumFast(N);
-	transdatums[1] = Float8GetDatumFast(sumX);
-	transdatums[2] = Float8GetDatumFast(sumX2);
+	/*
+	 * If we're invoked by nodeAgg, we can cheat and modify our first
+	 * parameter in-place to reduce palloc overhead. Otherwise we
+	 * construct a new array with the updated transition data and
+	 * return it.
+	 */
+	if (fcinfo->context && IsA(fcinfo->context, AggState))
+	{
+		transvalues[0] = N;
+		transvalues[1] = sumX;
+		transvalues[2] = sumX2;
 
-	result = construct_array(transdatums, 3,
-							 FLOAT8OID,
-						 sizeof(float8), false /* float8 byval */ , 'd');
+		PG_RETURN_ARRAYTYPE_P(transarray);
+	}
+	else
+	{
+		Datum		transdatums[3];
+		ArrayType  *result;
+
+		transdatums[0] = Float8GetDatumFast(N);
+		transdatums[1] = Float8GetDatumFast(sumX);
+		transdatums[2] = Float8GetDatumFast(sumX2);
 
-	PG_RETURN_ARRAYTYPE_P(result);
+		result = construct_array(transdatums, 3,
+								 FLOAT8OID,
+								 sizeof(float8), false /* float8 byval */ , 'd');
+
+		PG_RETURN_ARRAYTYPE_P(result);
+	}
 }
 
 Datum
diff --git a/src/backend/utils/adt/numeric.c b/src/backend/utils/adt/numeric.c
index a459ca2d6e42975699e52b26c6bc16e0ea8d25bb..214f9ff7a347919008342a94d3724a5e7d68653c 100644
--- a/src/backend/utils/adt/numeric.c
+++ b/src/backend/utils/adt/numeric.c
@@ -14,7 +14,7 @@
  * Copyright (c) 1998-2005, PostgreSQL Global Development Group
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/adt/numeric.c,v 1.82 2005/04/04 23:50:27 neilc Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/adt/numeric.c,v 1.83 2005/04/06 23:56:07 neilc Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -2357,7 +2357,6 @@ numeric_stddev(PG_FUNCTION_ARGS)
 Datum
 int2_sum(PG_FUNCTION_ARGS)
 {
-	int64		oldsum;
 	int64		newval;
 
 	if (PG_ARGISNULL(0))
@@ -2370,22 +2369,39 @@ int2_sum(PG_FUNCTION_ARGS)
 		PG_RETURN_INT64(newval);
 	}
 
-	oldsum = PG_GETARG_INT64(0);
+	/*
+	 * If we're invoked by nodeAgg, we can cheat and modify out first
+	 * parameter in-place to avoid palloc overhead. If not, we need to
+	 * return the new value of the transition variable.
+	 */
+	if (fcinfo->context && IsA(fcinfo->context, AggState))
+	{
+		int64 *oldsum = (int64 *) PG_GETARG_POINTER(0);
 
-	/* Leave sum unchanged if new input is null. */
-	if (PG_ARGISNULL(1))
-		PG_RETURN_INT64(oldsum);
+		/* Leave the running sum unchanged in the new input is null */
+		if (!PG_ARGISNULL(1))
+			*oldsum = *oldsum + (int64) PG_GETARG_INT16(1);
 
-	/* OK to do the addition. */
-	newval = oldsum + (int64) PG_GETARG_INT16(1);
+		PG_RETURN_POINTER(oldsum);
+	}
+	else
+	{
+		int64		oldsum = PG_GETARG_INT64(0);
+
+		/* Leave sum unchanged if new input is null. */
+		if (PG_ARGISNULL(1))
+			PG_RETURN_INT64(oldsum);
+
+		/* OK to do the addition. */
+		newval = oldsum + (int64) PG_GETARG_INT16(1);
 
-	PG_RETURN_INT64(newval);
+		PG_RETURN_INT64(newval);
+	}
 }
 
 Datum
 int4_sum(PG_FUNCTION_ARGS)
 {
-	int64		oldsum;
 	int64		newval;
 
 	if (PG_ARGISNULL(0))
@@ -2398,16 +2414,34 @@ int4_sum(PG_FUNCTION_ARGS)
 		PG_RETURN_INT64(newval);
 	}
 
-	oldsum = PG_GETARG_INT64(0);
+	/*
+	 * If we're invoked by nodeAgg, we can cheat and modify out first
+	 * parameter in-place to avoid palloc overhead. If not, we need to
+	 * return the new value of the transition variable.
+	 */
+	if (fcinfo->context && IsA(fcinfo->context, AggState))
+	{
+		int64 *oldsum = (int64 *) PG_GETARG_POINTER(0);
 
-	/* Leave sum unchanged if new input is null. */
-	if (PG_ARGISNULL(1))
-		PG_RETURN_INT64(oldsum);
+		/* Leave the running sum unchanged in the new input is null */
+		if (!PG_ARGISNULL(1))
+			*oldsum = *oldsum + (int64) PG_GETARG_INT32(1);
 
-	/* OK to do the addition. */
-	newval = oldsum + (int64) PG_GETARG_INT32(1);
+		PG_RETURN_POINTER(oldsum);
+	}
+	else
+	{
+		int64		oldsum = PG_GETARG_INT64(0);
 
-	PG_RETURN_INT64(newval);
+		/* Leave sum unchanged if new input is null. */
+		if (PG_ARGISNULL(1))
+			PG_RETURN_INT64(oldsum);
+
+		/* OK to do the addition. */
+		newval = oldsum + (int64) PG_GETARG_INT32(1);
+
+		PG_RETURN_INT64(newval);
+	}
 }
 
 Datum
@@ -2426,6 +2460,12 @@ int8_sum(PG_FUNCTION_ARGS)
 		PG_RETURN_DATUM(newval);
 	}
 
+	/*
+	 * Note that we cannot special-case the nodeAgg case here, as we
+	 * do for int2_sum and int4_sum: numeric is of variable size, so
+	 * we cannot modify our first parameter in-place.
+	 */
+
 	oldsum = PG_GETARG_NUMERIC(0);
 
 	/* Leave sum unchanged if new input is null. */