diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2014-04-12 20:33:09 -0400 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2014-04-12 20:33:09 -0400 |
commit | 9d229f399e87d2ae7132c2e8feef317ce1479728 (patch) | |
tree | f808e533fa6b89202733e2b8666361dc5482ca97 /src/backend/utils/adt/int8.c | |
parent | a9d9acbf219b9e96585779cd5f99d674d4ccba74 (diff) | |
download | postgresql-9d229f399e87d2ae7132c2e8feef317ce1479728.tar.gz postgresql-9d229f399e87d2ae7132c2e8feef317ce1479728.zip |
Provide moving-aggregate support for a bunch of numerical aggregates.
First installment of the promised moving-aggregate support in built-in
aggregates: count(), sum(), avg(), stddev() and variance() for
assorted datatypes, though not for float4/float8.
In passing, remove a 2001-vintage kluge in interval_accum(): interval
array elements have been properly aligned since around 2003, but
nobody remembered to take out this workaround. Also, fix a thinko
in the opr_sanity tests for moving-aggregate catalog entries.
David Rowley and Florian Pflug, reviewed by Dean Rasheed
Diffstat (limited to 'src/backend/utils/adt/int8.c')
-rw-r--r-- | src/backend/utils/adt/int8.c | 63 |
1 files changed, 57 insertions, 6 deletions
diff --git a/src/backend/utils/adt/int8.c b/src/backend/utils/adt/int8.c index 5e1be90dac3..e78eb2a2022 100644 --- a/src/backend/utils/adt/int8.c +++ b/src/backend/utils/adt/int8.c @@ -717,13 +717,58 @@ int8inc(PG_FUNCTION_ARGS) } } +Datum +int8dec(PG_FUNCTION_ARGS) +{ + /* + * When int8 is pass-by-reference, we provide this special case to avoid + * palloc overhead for COUNT(): when called as an aggregate, we know that + * the argument is modifiable local storage, so just update it in-place. + * (If int8 is pass-by-value, then of course this is useless as well as + * incorrect, so just ifdef it out.) + */ +#ifndef USE_FLOAT8_BYVAL /* controls int8 too */ + if (AggCheckCallContext(fcinfo, NULL)) + { + int64 *arg = (int64 *) PG_GETARG_POINTER(0); + int64 result; + + result = *arg - 1; + /* Overflow check */ + if (result > 0 && *arg < 0) + ereport(ERROR, + (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), + errmsg("bigint out of range"))); + + *arg = result; + PG_RETURN_POINTER(arg); + } + else +#endif + { + /* Not called as an aggregate, so just do it the dumb way */ + int64 arg = PG_GETARG_INT64(0); + int64 result; + + result = arg - 1; + /* Overflow check */ + if (result > 0 && arg < 0) + ereport(ERROR, + (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), + errmsg("bigint out of range"))); + + PG_RETURN_INT64(result); + } +} + + /* - * These functions are exactly like int8inc but are used for aggregates that - * count only non-null values. Since the functions are declared strict, - * the null checks happen before we ever get here, and all we need do is - * increment the state value. We could actually make these pg_proc entries - * point right at int8inc, but then the opr_sanity regression test would - * complain about mismatched entries for a built-in function. + * These functions are exactly like int8inc/int8dec but are used for + * aggregates that count only non-null values. Since the functions are + * declared strict, the null checks happen before we ever get here, and all we + * need do is increment the state value. We could actually make these pg_proc + * entries point right at int8inc/int8dec, but then the opr_sanity regression + * test would complain about mismatched entries for a built-in function. */ Datum @@ -738,6 +783,12 @@ int8inc_float8_float8(PG_FUNCTION_ARGS) return int8inc(fcinfo); } +Datum +int8dec_any(PG_FUNCTION_ARGS) +{ + return int8dec(fcinfo); +} + Datum int8larger(PG_FUNCTION_ARGS) |