diff --git a/src/backend/utils/adt/float.c b/src/backend/utils/adt/float.c index e51babfebf..c943ee2c71 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; - PG_RETURN_ARRAYTYPE_P(result); + transdatums[0] = Float8GetDatumFast(N); + transdatums[1] = Float8GetDatumFast(sumX); + transdatums[2] = Float8GetDatumFast(sumX2); + + 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; - PG_RETURN_ARRAYTYPE_P(result); + transdatums[0] = Float8GetDatumFast(N); + transdatums[1] = Float8GetDatumFast(sumX); + transdatums[2] = Float8GetDatumFast(sumX2); + + 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 a459ca2d6e..214f9ff7a3 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); - 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_INT16(1); + + 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. */