aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/int8.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2014-04-12 20:33:09 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2014-04-12 20:33:09 -0400
commit9d229f399e87d2ae7132c2e8feef317ce1479728 (patch)
treef808e533fa6b89202733e2b8666361dc5482ca97 /src/backend/utils/adt/int8.c
parenta9d9acbf219b9e96585779cd5f99d674d4ccba74 (diff)
downloadpostgresql-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.c63
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)