diff options
Diffstat (limited to 'src/backend')
| -rw-r--r-- | src/backend/utils/adt/int8.c | 10 | ||||
| -rw-r--r-- | src/backend/utils/adt/numeric.c | 145 | ||||
| -rw-r--r-- | src/backend/utils/adt/oid.c | 20 | ||||
| -rw-r--r-- | src/backend/utils/fmgr/fmgr.c | 16 |
4 files changed, 161 insertions, 30 deletions
diff --git a/src/backend/utils/adt/int8.c b/src/backend/utils/adt/int8.c index 055c8439fa..711c17ad8a 100644 --- a/src/backend/utils/adt/int8.c +++ b/src/backend/utils/adt/int8.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/int8.c,v 1.30 2001/06/07 00:09:29 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/int8.c,v 1.31 2001/08/14 22:21:58 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -504,6 +504,14 @@ int8fac(PG_FUNCTION_ARGS) } Datum +int8inc(PG_FUNCTION_ARGS) +{ + int64 arg = PG_GETARG_INT64(0); + + PG_RETURN_INT64(arg + 1); +} + +Datum int8larger(PG_FUNCTION_ARGS) { int64 val1 = PG_GETARG_INT64(0); diff --git a/src/backend/utils/adt/numeric.c b/src/backend/utils/adt/numeric.c index bb0e8b2b7e..f115657102 100644 --- a/src/backend/utils/adt/numeric.c +++ b/src/backend/utils/adt/numeric.c @@ -5,7 +5,7 @@ * * 1998 Jan Wieck * - * $Header: /cvsroot/pgsql/src/backend/utils/adt/numeric.c,v 1.42 2001/06/07 00:09:29 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/numeric.c,v 1.43 2001/08/14 22:21:58 tgl Exp $ * * ---------- */ @@ -1772,7 +1772,11 @@ numeric_accum(PG_FUNCTION_ARGS) /* * Integer data types all use Numeric accumulators to share code and - * avoid risk of overflow. + * avoid risk of overflow. For int2 and int4 inputs, Numeric accumulation + * is overkill for the N and sum(X) values, but definitely not overkill + * for the sum(X*X) value. Hence, we use int2_accum and int4_accum only + * for stddev/variance --- there are faster special-purpose accumulator + * routines for SUM and AVG of these datatypes. */ Datum @@ -1979,20 +1983,25 @@ numeric_stddev(PG_FUNCTION_ARGS) /* * SUM transition functions for integer datatypes. * - * We use a Numeric accumulator to avoid overflow. Because SQL92 defines - * the SUM() of no values to be NULL, not zero, the initial condition of - * the transition data value needs to be NULL. This means we can't rely - * on ExecAgg to automatically insert the first non-null data value into - * the transition data: it doesn't know how to do the type conversion. - * The upshot is that these routines have to be marked non-strict and - * handle substitution of the first non-null input themselves. + * To avoid overflow, we use accumulators wider than the input datatype. + * A Numeric accumulator is needed for int8 input; for int4 and int2 + * inputs, we use int8 accumulators which should be sufficient for practical + * purposes. (The latter two therefore don't really belong in this file, + * but we keep them here anyway.) + * + * Because SQL92 defines the SUM() of no values to be NULL, not zero, + * the initial condition of the transition data value needs to be NULL. This + * means we can't rely on ExecAgg to automatically insert the first non-null + * data value into the transition data: it doesn't know how to do the type + * conversion. The upshot is that these routines have to be marked non-strict + * and handle substitution of the first non-null input themselves. */ Datum int2_sum(PG_FUNCTION_ARGS) { - Numeric oldsum; - Datum newval; + int64 oldsum; + int64 newval; if (PG_ARGISNULL(0)) { @@ -2000,28 +2009,27 @@ int2_sum(PG_FUNCTION_ARGS) if (PG_ARGISNULL(1)) PG_RETURN_NULL(); /* still no non-null */ /* This is the first non-null input. */ - newval = DirectFunctionCall1(int2_numeric, PG_GETARG_DATUM(1)); - PG_RETURN_DATUM(newval); + newval = (int64) PG_GETARG_INT16(1); + PG_RETURN_INT64(newval); } - oldsum = PG_GETARG_NUMERIC(0); + oldsum = PG_GETARG_INT64(0); /* Leave sum unchanged if new input is null. */ if (PG_ARGISNULL(1)) - PG_RETURN_NUMERIC(oldsum); + PG_RETURN_INT64(oldsum); /* OK to do the addition. */ - newval = DirectFunctionCall1(int2_numeric, PG_GETARG_DATUM(1)); + newval = oldsum + (int64) PG_GETARG_INT16(1); - PG_RETURN_DATUM(DirectFunctionCall2(numeric_add, - NumericGetDatum(oldsum), newval)); + PG_RETURN_INT64(newval); } Datum int4_sum(PG_FUNCTION_ARGS) { - Numeric oldsum; - Datum newval; + int64 oldsum; + int64 newval; if (PG_ARGISNULL(0)) { @@ -2029,21 +2037,20 @@ int4_sum(PG_FUNCTION_ARGS) if (PG_ARGISNULL(1)) PG_RETURN_NULL(); /* still no non-null */ /* This is the first non-null input. */ - newval = DirectFunctionCall1(int4_numeric, PG_GETARG_DATUM(1)); - PG_RETURN_DATUM(newval); + newval = (int64) PG_GETARG_INT32(1); + PG_RETURN_INT64(newval); } - oldsum = PG_GETARG_NUMERIC(0); + oldsum = PG_GETARG_INT64(0); /* Leave sum unchanged if new input is null. */ if (PG_ARGISNULL(1)) - PG_RETURN_NUMERIC(oldsum); + PG_RETURN_INT64(oldsum); /* OK to do the addition. */ - newval = DirectFunctionCall1(int4_numeric, PG_GETARG_DATUM(1)); + newval = oldsum + (int64) PG_GETARG_INT32(1); - PG_RETURN_DATUM(DirectFunctionCall2(numeric_add, - NumericGetDatum(oldsum), newval)); + PG_RETURN_INT64(newval); } Datum @@ -2076,6 +2083,90 @@ int8_sum(PG_FUNCTION_ARGS) } +/* + * Routines for avg(int2) and avg(int4). The transition datatype + * is a two-element int8 array, holding count and sum. + */ + +typedef struct Int8TransTypeData +{ +#ifndef INT64_IS_BUSTED + int64 count; + int64 sum; +#else + /* "int64" isn't really 64 bits, so fake up properly-aligned fields */ + int32 count; + int32 pad1; + int32 sum; + int32 pad2; +#endif +} Int8TransTypeData; + +Datum +int2_avg_accum(PG_FUNCTION_ARGS) +{ + ArrayType *transarray = PG_GETARG_ARRAYTYPE_P_COPY(0); + int16 newval = PG_GETARG_INT16(1); + Int8TransTypeData *transdata; + + /* + * We copied the input array, so it's okay to scribble on it directly. + */ + if (ARR_SIZE(transarray) != ARR_OVERHEAD(1) + sizeof(Int8TransTypeData)) + elog(ERROR, "int2_avg_accum: expected 2-element int8 array"); + transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray); + + transdata->count++; + transdata->sum += newval; + + PG_RETURN_ARRAYTYPE_P(transarray); +} + +Datum +int4_avg_accum(PG_FUNCTION_ARGS) +{ + ArrayType *transarray = PG_GETARG_ARRAYTYPE_P_COPY(0); + int32 newval = PG_GETARG_INT32(1); + Int8TransTypeData *transdata; + + /* + * We copied the input array, so it's okay to scribble on it directly. + */ + if (ARR_SIZE(transarray) != ARR_OVERHEAD(1) + sizeof(Int8TransTypeData)) + elog(ERROR, "int4_avg_accum: expected 2-element int8 array"); + transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray); + + transdata->count++; + transdata->sum += newval; + + PG_RETURN_ARRAYTYPE_P(transarray); +} + +Datum +int8_avg(PG_FUNCTION_ARGS) +{ + ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0); + Int8TransTypeData *transdata; + Datum countd, + sumd; + + if (ARR_SIZE(transarray) != ARR_OVERHEAD(1) + sizeof(Int8TransTypeData)) + elog(ERROR, "int8_avg: expected 2-element int8 array"); + transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray); + + /* SQL92 defines AVG of no values to be NULL */ + if (transdata->count == 0) + PG_RETURN_NULL(); + + countd = DirectFunctionCall1(int8_numeric, + Int64GetDatumFast(transdata->count)); + sumd = DirectFunctionCall1(int8_numeric, + Int64GetDatumFast(transdata->sum)); + + PG_RETURN_DATUM(DirectFunctionCall2(numeric_div, sumd, countd)); +} + + /* ---------------------------------------------------------------------- * * Local functions follow diff --git a/src/backend/utils/adt/oid.c b/src/backend/utils/adt/oid.c index 91dbf6c54e..5eb65979f1 100644 --- a/src/backend/utils/adt/oid.c +++ b/src/backend/utils/adt/oid.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/oid.c,v 1.45 2001/03/22 03:59:52 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/oid.c,v 1.46 2001/08/14 22:21:58 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -232,6 +232,24 @@ oidgt(PG_FUNCTION_ARGS) } Datum +oidlarger(PG_FUNCTION_ARGS) +{ + Oid arg1 = PG_GETARG_OID(0); + Oid arg2 = PG_GETARG_OID(1); + + PG_RETURN_OID((arg1 > arg2) ? arg1 : arg2); +} + +Datum +oidsmaller(PG_FUNCTION_ARGS) +{ + Oid arg1 = PG_GETARG_OID(0); + Oid arg2 = PG_GETARG_OID(1); + + PG_RETURN_OID((arg1 < arg2) ? arg1 : arg2); +} + +Datum oidvectoreq(PG_FUNCTION_ARGS) { Oid *arg1 = (Oid *) PG_GETARG_POINTER(0); diff --git a/src/backend/utils/fmgr/fmgr.c b/src/backend/utils/fmgr/fmgr.c index 544dc840c1..45ca532de2 100644 --- a/src/backend/utils/fmgr/fmgr.c +++ b/src/backend/utils/fmgr/fmgr.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/fmgr/fmgr.c,v 1.53 2001/06/01 02:41:36 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/fmgr/fmgr.c,v 1.54 2001/08/14 22:21:58 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1414,10 +1414,24 @@ fmgr(Oid procedureId,...) Datum Int64GetDatum(int64 X) { +#ifndef INT64_IS_BUSTED int64 *retval = (int64 *) palloc(sizeof(int64)); *retval = X; return PointerGetDatum(retval); +#else /* INT64_IS_BUSTED */ + /* + * On a machine with no 64-bit-int C datatype, sizeof(int64) will not be + * 8, but we want Int64GetDatum to return an 8-byte object anyway, with + * zeroes in the unused bits. This is needed so that, for example, + * hash join of int8 will behave properly. + */ + int64 *retval = (int64 *) palloc(Max(sizeof(int64), 8)); + + MemSet(retval, 0, Max(sizeof(int64), 8)); + *retval = X; + return PointerGetDatum(retval); +#endif /* INT64_IS_BUSTED */ } Datum |
