Hi, Working on committing this: * Converted the configure test to AC_LINK_IFELSE
* I dislike the way the configure test and the resulting HAVE_* is named. This imo shouldn't be so gcc specific, even if it right now only detects gcc support. Changed. * Furthermore does the test use 64bit literals without marking them as such. That doesn't strike me as a great idea. * Stuff like: static int32 numericvar_to_int4(NumericVar *var); static bool numericvar_to_int8(NumericVar *var, int64 *result); static void int64_to_numericvar(int64 val, NumericVar *var); #ifdef HAVE_INT128 static void int128_to_numericvar(int128 val, NumericVar *var); #endif is beyond ugly. Imnsho the only int2/4/8 functions that should keep their name are the SQL callable ones. It's surely one to have numericvar_to_int8 and int64_to_numericvar. * I'm not a fan at all of the c.h comment you added. That comment seems, besides being oddly formatted, to be designed to be outdated ;) I'll just rip it out and replace it by something shorter. This shouldn't be so overly specific for this patch. * This thread is long, I'm not sure who to list as reviewers. Please check whether those are appropriate. * I've split off the int128 support from the aggregate changes. Greetings, Andres Freund -- Andres Freund http://www.2ndQuadrant.com/ PostgreSQL Development, 24x7 Support, Training & Services
>From 247c00714fc7cf8a1922f2bb37c6ec08a6e63133 Mon Sep 17 00:00:00 2001 From: Andres Freund <and...@anarazel.de> Date: Thu, 19 Mar 2015 18:58:22 +0100 Subject: [PATCH 1/2] Add optional support for 128bit integers. We will, for the foreseeable future, not expose 128 bit datatypes to SQL. But being able to use 128bit math will allow us, in a later patch, to use 128bit accumulators for some aggregates; leading to noticeable speedups over using numeric. So far we only detect a gcc/clang extension that supports 128bit math, but no 128bit literals, and no *printf support. We might want to expand this in the future to further compilers; if there are any that that provide similar support. Discussion: 544bb5f1.50...@proxel.se Author: Andreas Karlsson, with modifications by me Reviewed-By: Peter Geoghegan, Oskari Saarenmaa --- config/c-compiler.m4 | 37 ++++++++++++++++++++++++++++++ configure | 52 +++++++++++++++++++++++++++++++++++++++++++ configure.in | 3 +++ src/include/c.h | 11 +++++++++ src/include/pg_config.h.in | 3 +++ src/include/pg_config.h.win32 | 3 +++ 6 files changed, 109 insertions(+) diff --git a/config/c-compiler.m4 b/config/c-compiler.m4 index 509f961..38aab11 100644 --- a/config/c-compiler.m4 +++ b/config/c-compiler.m4 @@ -125,6 +125,43 @@ undefine([Ac_cachevar])dnl ])# PGAC_TYPE_64BIT_INT +# PGAC_TYPE_128BIT_INT +# --------------------- +# Check if __int128 is a working 128 bit integer type, and if so +# define PG_INT128_TYPE to that typename. This currently only detects +# a GCC/clang extension, but support for different environments may be +# added in the future. +# +# For the moment we only test for support for 128bit math; support for +# 128bit literals and snprintf is not required. +AC_DEFUN([PGAC_TYPE_128BIT_INT], +[AC_CACHE_CHECK([for __int128], [pgac_cv__128bit_int], +[AC_LINK_IFELSE([AC_LANG_PROGRAM([ +/* + * These are globals to discourage the compiler from folding all the + * arithmetic tests down to compile-time constants. We do not have + * convenient support for 64bit literals at this point... + */ +__int128 a = 48828125; +__int128 b = 97656255; +],[ +__int128 c,d; +a = (a << 12) + 1; /* 200000000001 */ +b = (b << 12) + 5; /* 400000000005 */ +/* use the most relevant arithmetic ops */ +c = a * b; +d = (c + b) / b; +/* return different values, to prevent optimizations */ +if (d != a+1) + return 0; +return 1; +])], +[pgac_cv__128bit_int=yes], +[pgac_cv__128bit_int=no])]) +if test x"$pgac_cv__128bit_int" = xyes ; then + AC_DEFINE(PG_INT128_TYPE, __int128, [Define to the name of a signed 128-bit integer type.]) +fi])# PGAC_TYPE_128BIT_INT + # PGAC_C_FUNCNAME_SUPPORT # ----------------------- diff --git a/configure b/configure index 379dab1..2c9b3a7 100755 --- a/configure +++ b/configure @@ -13803,6 +13803,58 @@ _ACEOF fi +# Check for extensions offering the integer scalar type __int128. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __int128" >&5 +$as_echo_n "checking for __int128... " >&6; } +if ${pgac_cv__128bit_int+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* + * These are globals to discourage the compiler from folding all the + * arithmetic tests down to compile-time constants. We do not have + * convenient support for 64bit literals at this point... + */ +__int128 a = 48828125; +__int128 b = 97656255; + +int +main () +{ + +__int128 c,d; +a = (a << 12) + 1; /* 200000000001 */ +b = (b << 12) + 5; /* 400000000005 */ +/* use the most relevant arithmetic ops */ +c = a * b; +d = (c + b) / b; +/* return different values, to prevent optimizations */ +if (d != a+1) + return 0; +return 1; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + pgac_cv__128bit_int=yes +else + pgac_cv__128bit_int=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv__128bit_int" >&5 +$as_echo "$pgac_cv__128bit_int" >&6; } +if test x"$pgac_cv__128bit_int" = xyes ; then + +$as_echo "#define PG_INT128_TYPE __int128" >>confdefs.h + +fi + # Check for various atomic operations now that we have checked how to declare # 64bit integers. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for builtin __sync char locking functions" >&5 diff --git a/configure.in b/configure.in index ca29e93..b2c1ce7 100644 --- a/configure.in +++ b/configure.in @@ -1771,6 +1771,9 @@ AC_CHECK_TYPES([int8, uint8, int64, uint64], [], [], # C, but is missing on some old platforms. AC_CHECK_TYPES(sig_atomic_t, [], [], [#include <signal.h>]) +# Check for extensions offering the integer scalar type __int128. +PGAC_TYPE_128BIT_INT + # Check for various atomic operations now that we have checked how to declare # 64bit integers. PGAC_HAVE_GCC__SYNC_CHAR_TAS diff --git a/src/include/c.h b/src/include/c.h index a2d4a2c..7447218 100644 --- a/src/include/c.h +++ b/src/include/c.h @@ -293,6 +293,17 @@ typedef unsigned long long int uint64; #define HAVE_INT64_TIMESTAMP #endif +/* + * 128-bit signed and unsigned integers + * There currently is only a limited support for the type. E.g. 128bit + * literals and snprintf are not supported; but math is. + */ +#if defined(PG_INT128_TYPE) +#define HAVE_INT128 +typedef PG_INT128_TYPE int128; +typedef unsigned PG_INT128_TYPE uint128; +#endif + /* sig_atomic_t is required by ANSI C, but may be missing on old platforms */ #ifndef HAVE_SIG_ATOMIC_T typedef int sig_atomic_t; diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in index ece57c8..202c51a 100644 --- a/src/include/pg_config.h.in +++ b/src/include/pg_config.h.in @@ -711,6 +711,9 @@ /* Define to the version of this package. */ #undef PACKAGE_VERSION +/* Define to the name of a signed 128-bit integer type. */ +#undef PG_INT128_TYPE + /* Define to the name of a signed 64-bit integer type. */ #undef PG_INT64_TYPE diff --git a/src/include/pg_config.h.win32 b/src/include/pg_config.h.win32 index 3f858c6..1baf64f 100644 --- a/src/include/pg_config.h.win32 +++ b/src/include/pg_config.h.win32 @@ -562,6 +562,9 @@ /* Define to the version of this package. */ #define PACKAGE_VERSION "9.5devel" +/* Define to the name of a signed 128-bit integer type. */ +#undef PG_INT128_TYPE + /* Define to the name of a signed 64-bit integer type. */ #define PG_INT64_TYPE long long int -- 2.3.0.149.gf3f4077
>From 4b5ef817dfde7d423810521f088c99c0af5437d0 Mon Sep 17 00:00:00 2001 From: Andres Freund <and...@anarazel.de> Date: Thu, 19 Mar 2015 18:58:22 +0100 Subject: [PATCH 2/2] Use 128-bit math to accelerate some aggregation functions. On platforms where we support 128bit integers, use them to implement faster transition functions for sum(int8), avg(int8), var_*(int2/int4),stdev_*(int2/int4). Where not supported continue to use numeric as a transition type. In some synthetic benchmarks this has been shown to provide significant speedups. Bumps catversion. Discussion: 544bb5f1.50...@proxel.se Author: Andreas Karlsson Reviewed-By: Peter Geoghegan, Petr Jelinek, Andres Freund, Oskari Saarenmaa --- src/backend/utils/adt/numeric.c | 428 +++++++++++++++++++++++++++++++++---- src/include/catalog/catversion.h | 2 +- src/include/catalog/pg_aggregate.h | 102 ++++----- src/include/catalog/pg_proc.h | 15 ++ src/include/utils/builtins.h | 7 + 5 files changed, 463 insertions(+), 91 deletions(-) diff --git a/src/backend/utils/adt/numeric.c b/src/backend/utils/adt/numeric.c index 715917b..ff9bfcc 100644 --- a/src/backend/utils/adt/numeric.c +++ b/src/backend/utils/adt/numeric.c @@ -400,9 +400,12 @@ static Numeric make_result(NumericVar *var); static void apply_typmod(NumericVar *var, int32 typmod); -static int32 numericvar_to_int4(NumericVar *var); -static bool numericvar_to_int8(NumericVar *var, int64 *result); -static void int8_to_numericvar(int64 val, NumericVar *var); +static int32 numericvar_to_int32(NumericVar *var); +static bool numericvar_to_int64(NumericVar *var, int64 *result); +static void int64_to_numericvar(int64 val, NumericVar *var); +#ifdef HAVE_INT128 +static void int128_to_numericvar(int128 val, NumericVar *var); +#endif static double numeric_to_double_no_overflow(Numeric num); static double numericvar_to_double_no_overflow(NumericVar *var); @@ -1414,7 +1417,7 @@ width_bucket_numeric(PG_FUNCTION_ARGS) init_var(&count_var); /* Convert 'count' to a numeric, for ease of use later */ - int8_to_numericvar((int64) count, &count_var); + int64_to_numericvar((int64) count, &count_var); switch (cmp_numerics(bound1, bound2)) { @@ -1447,7 +1450,7 @@ width_bucket_numeric(PG_FUNCTION_ARGS) } /* if result exceeds the range of a legal int4, we ereport here */ - result = numericvar_to_int4(&result_var); + result = numericvar_to_int32(&result_var); free_var(&count_var); free_var(&result_var); @@ -2083,14 +2086,14 @@ numeric_fac(PG_FUNCTION_ARGS) init_var(&fact); init_var(&result); - int8_to_numericvar(num, &result); + int64_to_numericvar(num, &result); for (num = num - 1; num > 1; num--) { /* this loop can take awhile, so allow it to be interrupted */ CHECK_FOR_INTERRUPTS(); - int8_to_numericvar(num, &fact); + int64_to_numericvar(num, &fact); mul_var(&result, &fact, &result, 0); } @@ -2388,7 +2391,7 @@ int4_numeric(PG_FUNCTION_ARGS) init_var(&result); - int8_to_numericvar((int64) val, &result); + int64_to_numericvar((int64) val, &result); res = make_result(&result); @@ -2413,7 +2416,7 @@ numeric_int4(PG_FUNCTION_ARGS) /* Convert to variable format, then convert to int4 */ init_var_from_num(num, &x); - result = numericvar_to_int4(&x); + result = numericvar_to_int32(&x); PG_RETURN_INT32(result); } @@ -2423,12 +2426,12 @@ numeric_int4(PG_FUNCTION_ARGS) * ereport(). The input NumericVar is *not* free'd. */ static int32 -numericvar_to_int4(NumericVar *var) +numericvar_to_int32(NumericVar *var) { int32 result; int64 val; - if (!numericvar_to_int8(var, &val)) + if (!numericvar_to_int64(var, &val)) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("integer out of range"))); @@ -2454,7 +2457,7 @@ int8_numeric(PG_FUNCTION_ARGS) init_var(&result); - int8_to_numericvar(val, &result); + int64_to_numericvar(val, &result); res = make_result(&result); @@ -2480,7 +2483,7 @@ numeric_int8(PG_FUNCTION_ARGS) /* Convert to variable format and thence to int8 */ init_var_from_num(num, &x); - if (!numericvar_to_int8(&x, &result)) + if (!numericvar_to_int64(&x, &result)) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("bigint out of range"))); @@ -2498,7 +2501,7 @@ int2_numeric(PG_FUNCTION_ARGS) init_var(&result); - int8_to_numericvar((int64) val, &result); + int64_to_numericvar((int64) val, &result); res = make_result(&result); @@ -2525,7 +2528,7 @@ numeric_int2(PG_FUNCTION_ARGS) /* Convert to variable format and thence to int8 */ init_var_from_num(num, &x); - if (!numericvar_to_int8(&x, &val)) + if (!numericvar_to_int64(&x, &val)) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("smallint out of range"))); @@ -2660,6 +2663,9 @@ numeric_float4(PG_FUNCTION_ARGS) * Actually, it's a pointer to a NumericAggState allocated in the aggregate * context. The digit buffers for the NumericVars will be there too. * + * On platforms which support 128-bit integers some aggregates instead use a + * 128-bit integer based transition datatype to speed up calculations. + * * ---------------------------------------------------------------------- */ @@ -2920,32 +2926,107 @@ numeric_accum_inv(PG_FUNCTION_ARGS) /* - * Integer data types all use Numeric accumulators to share code and - * 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. + * Integer data types in general use Numeric accumulators to share code + * and avoid risk of overflow. + * + * However for performance reasons optimized special-purpose accumulator + * routines are used when possible. + * + * On platforms with 128-bit integer support, the 128-bit routines will be + * used when sum(X) or sum(X*X) fit into 128-bit. + * + * For 16 and 32 bit inputs, the N and sum(X) fit into 64-bit so the 64-bit + * accumulators will be used for SUM and AVG of these data types. + */ + +#ifdef HAVE_INT128 +typedef struct Int128AggState +{ + bool calcSumX2; /* if true, calculate sumX2 */ + int64 N; /* count of processed numbers */ + int128 sumX; /* sum of processed numbers */ + int128 sumX2; /* sum of squares of processed numbers */ +} Int128AggState; + +/* + * Prepare state data for a 128-bit aggregate function that needs to compute + * sum, count and optionally sum of squares of the input. + */ +static Int128AggState * +makeInt128AggState(FunctionCallInfo fcinfo, bool calcSumX2) +{ + Int128AggState *state; + MemoryContext agg_context; + MemoryContext old_context; + + if (!AggCheckCallContext(fcinfo, &agg_context)) + elog(ERROR, "aggregate function called in non-aggregate context"); + + old_context = MemoryContextSwitchTo(agg_context); + + state = (Int128AggState *) palloc0(sizeof(Int128AggState)); + state->calcSumX2 = calcSumX2; + + MemoryContextSwitchTo(old_context); + + return state; +} + +/* + * Accumulate a new input value for 128-bit aggregate functions. + */ +static void +do_int128_accum(Int128AggState *state, int128 newval) +{ + if (state->calcSumX2) + state->sumX2 += newval * newval; + + state->sumX += newval; + state->N++; +} + +/* + * Remove an input value from the aggregated state. */ +static void +do_int128_discard(Int128AggState *state, int128 newval) +{ + if (state->calcSumX2) + state->sumX2 -= newval * newval; + + state->sumX -= newval; + state->N--; +} + +typedef Int128AggState PolyNumAggState; +#define makePolyNumAggState makeInt128AggState +#else +typedef NumericAggState PolyNumAggState; +#define makePolyNumAggState makeNumericAggState +#endif Datum int2_accum(PG_FUNCTION_ARGS) { - NumericAggState *state; + PolyNumAggState *state; - state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0); + state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0); /* Create the state data on the first call */ if (state == NULL) - state = makeNumericAggState(fcinfo, true); + state = makePolyNumAggState(fcinfo, true); if (!PG_ARGISNULL(1)) { +#ifdef HAVE_INT128 + do_int128_accum(state, (int128) PG_GETARG_INT32(1)); +#else Numeric newval; newval = DatumGetNumeric(DirectFunctionCall1(int2_numeric, PG_GETARG_DATUM(1))); do_numeric_accum(state, newval); +#endif } PG_RETURN_POINTER(state); @@ -2954,21 +3035,25 @@ int2_accum(PG_FUNCTION_ARGS) Datum int4_accum(PG_FUNCTION_ARGS) { - NumericAggState *state; + PolyNumAggState *state; - state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0); + state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0); /* Create the state data on the first call */ if (state == NULL) - state = makeNumericAggState(fcinfo, true); + state = makePolyNumAggState(fcinfo, true); if (!PG_ARGISNULL(1)) { +#ifdef HAVE_INT128 + do_int128_accum(state, (int128) PG_GETARG_INT32(1)); +#else Numeric newval; newval = DatumGetNumeric(DirectFunctionCall1(int4_numeric, PG_GETARG_DATUM(1))); do_numeric_accum(state, newval); +#endif } PG_RETURN_POINTER(state); @@ -3003,21 +3088,25 @@ int8_accum(PG_FUNCTION_ARGS) Datum int8_avg_accum(PG_FUNCTION_ARGS) { - NumericAggState *state; + PolyNumAggState *state; - state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0); + state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0); /* Create the state data on the first call */ if (state == NULL) - state = makeNumericAggState(fcinfo, false); + state = makePolyNumAggState(fcinfo, false); if (!PG_ARGISNULL(1)) { +#ifdef HAVE_INT128 + do_int128_accum(state, (int128) PG_GETARG_INT64(1)); +#else Numeric newval; newval = DatumGetNumeric(DirectFunctionCall1(int8_numeric, PG_GETARG_DATUM(1))); do_numeric_accum(state, newval); +#endif } PG_RETURN_POINTER(state); @@ -3031,9 +3120,9 @@ int8_avg_accum(PG_FUNCTION_ARGS) Datum int2_accum_inv(PG_FUNCTION_ARGS) { - NumericAggState *state; + PolyNumAggState *state; - state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0); + state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0); /* Should not get here with no state */ if (state == NULL) @@ -3041,6 +3130,9 @@ int2_accum_inv(PG_FUNCTION_ARGS) if (!PG_ARGISNULL(1)) { +#ifdef HAVE_INT128 + do_int128_discard(state, (int128) PG_GETARG_INT16(1)); +#else Numeric newval; newval = DatumGetNumeric(DirectFunctionCall1(int2_numeric, @@ -3049,6 +3141,7 @@ int2_accum_inv(PG_FUNCTION_ARGS) /* Should never fail, all inputs have dscale 0 */ if (!do_numeric_discard(state, newval)) elog(ERROR, "do_numeric_discard failed unexpectedly"); +#endif } PG_RETURN_POINTER(state); @@ -3057,9 +3150,9 @@ int2_accum_inv(PG_FUNCTION_ARGS) Datum int4_accum_inv(PG_FUNCTION_ARGS) { - NumericAggState *state; + PolyNumAggState *state; - state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0); + state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0); /* Should not get here with no state */ if (state == NULL) @@ -3067,6 +3160,9 @@ int4_accum_inv(PG_FUNCTION_ARGS) if (!PG_ARGISNULL(1)) { +#ifdef HAVE_INT128 + do_int128_discard(state, (int128) PG_GETARG_INT32(1)); +#else Numeric newval; newval = DatumGetNumeric(DirectFunctionCall1(int4_numeric, @@ -3075,6 +3171,7 @@ int4_accum_inv(PG_FUNCTION_ARGS) /* Should never fail, all inputs have dscale 0 */ if (!do_numeric_discard(state, newval)) elog(ERROR, "do_numeric_discard failed unexpectedly"); +#endif } PG_RETURN_POINTER(state); @@ -3107,6 +3204,94 @@ int8_accum_inv(PG_FUNCTION_ARGS) } Datum +int8_avg_accum_inv(PG_FUNCTION_ARGS) +{ + PolyNumAggState *state; + + state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0); + + /* Should not get here with no state */ + if (state == NULL) + elog(ERROR, "int8_avg_accum_inv called with NULL state"); + + if (!PG_ARGISNULL(1)) + { +#ifdef HAVE_INT128 + do_int128_discard(state, (int128) PG_GETARG_INT64(1)); +#else + Numeric newval; + + newval = DatumGetNumeric(DirectFunctionCall1(int8_numeric, + PG_GETARG_DATUM(1))); + + /* Should never fail, all inputs have dscale 0 */ + if (!do_numeric_discard(state, newval)) + elog(ERROR, "do_numeric_discard failed unexpectedly"); +#endif + } + + PG_RETURN_POINTER(state); +} + +Datum +numeric_poly_sum(PG_FUNCTION_ARGS) +{ +#ifdef HAVE_INT128 + PolyNumAggState *state; + Numeric res; + NumericVar result; + + state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0); + + /* If there were no non-null inputs, return NULL */ + if (state == NULL || state->N == 0) + PG_RETURN_NULL(); + + init_var(&result); + + int128_to_numericvar(state->sumX, &result); + + res = make_result(&result); + + free_var(&result); + + PG_RETURN_NUMERIC(res); +#else + return numeric_sum(fcinfo); +#endif +} + +Datum +numeric_poly_avg(PG_FUNCTION_ARGS) +{ +#ifdef HAVE_INT128 + PolyNumAggState *state; + NumericVar result; + Datum countd, sumd; + + state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0); + + /* If there were no non-null inputs, return NULL */ + if (state == NULL || state->N == 0) + PG_RETURN_NULL(); + + init_var(&result); + + int128_to_numericvar(state->sumX, &result); + + countd = DirectFunctionCall1(int8_numeric, + Int64GetDatumFast(state->N)); + sumd = NumericGetDatum(make_result(&result)); + + free_var(&result); + + PG_RETURN_DATUM(DirectFunctionCall2(numeric_div, sumd, countd)); +#else + return numeric_avg(fcinfo); +#endif +} + +Datum numeric_avg(PG_FUNCTION_ARGS) { NumericAggState *state; @@ -3185,7 +3370,7 @@ numeric_stddev_internal(NumericAggState *state, init_var(&vsumX); init_var(&vsumX2); - int8_to_numericvar(state->N, &vN); + int64_to_numericvar(state->N, &vN); set_var_from_var(&(state->sumX), &vsumX); set_var_from_var(&(state->sumX2), &vsumX2); @@ -3308,6 +3493,124 @@ numeric_stddev_pop(PG_FUNCTION_ARGS) PG_RETURN_NUMERIC(res); } +#ifdef HAVE_INT128 +static Numeric +numeric_poly_stddev_internal(Int128AggState *state, + bool variance, bool sample, + bool *is_null) +{ + NumericAggState numstate; + Numeric res; + + init_var(&numstate.sumX); + init_var(&numstate.sumX2); + numstate.NaNcount = 0; + numstate.agg_context = NULL; + + if (state) + { + numstate.N = state->N; + int128_to_numericvar(state->sumX, &numstate.sumX); + int128_to_numericvar(state->sumX2, &numstate.sumX2); + } + else + { + numstate.N = 0; + } + + res = numeric_stddev_internal(&numstate, variance, sample, is_null); + + free_var(&numstate.sumX); + free_var(&numstate.sumX2); + + return res; +} +#endif + +Datum +numeric_poly_var_samp(PG_FUNCTION_ARGS) +{ +#ifdef HAVE_INT128 + PolyNumAggState *state; + Numeric res; + bool is_null; + + state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0); + + res = numeric_poly_stddev_internal(state, true, true, &is_null); + + if (is_null) + PG_RETURN_NULL(); + else + PG_RETURN_NUMERIC(res); +#else + return numeric_var_samp(fcinfo); +#endif +} + +Datum +numeric_poly_stddev_samp(PG_FUNCTION_ARGS) +{ +#ifdef HAVE_INT128 + PolyNumAggState *state; + Numeric res; + bool is_null; + + state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0); + + res = numeric_poly_stddev_internal(state, false, true, &is_null); + + if (is_null) + PG_RETURN_NULL(); + else + PG_RETURN_NUMERIC(res); +#else + return numeric_stddev_samp(fcinfo); +#endif +} + +Datum +numeric_poly_var_pop(PG_FUNCTION_ARGS) +{ +#ifdef HAVE_INT128 + PolyNumAggState *state; + Numeric res; + bool is_null; + + state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0); + + res = numeric_poly_stddev_internal(state, true, false, &is_null); + + if (is_null) + PG_RETURN_NULL(); + else + PG_RETURN_NUMERIC(res); +#else + return numeric_var_pop(fcinfo); +#endif +} + +Datum +numeric_poly_stddev_pop(PG_FUNCTION_ARGS) +{ +#ifdef HAVE_INT128 + PolyNumAggState *state; + Numeric res; + bool is_null; + + state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0); + + res = numeric_poly_stddev_internal(state, false, false, &is_null); + + if (is_null) + PG_RETURN_NULL(); + else + PG_RETURN_NUMERIC(res); +#else + return numeric_stddev_pop(fcinfo); +#endif +} + /* * SUM transition functions for integer datatypes. * @@ -4418,7 +4721,7 @@ apply_typmod(NumericVar *var, int32 typmod) * If overflow, return FALSE (no error is raised). Return TRUE if okay. */ static bool -numericvar_to_int8(NumericVar *var, int64 *result) +numericvar_to_int64(NumericVar *var, int64 *result) { NumericDigit *digits; int ndigits; @@ -4489,14 +4792,14 @@ numericvar_to_int8(NumericVar *var, int64 *result) * Convert int8 value to numeric. */ static void -int8_to_numericvar(int64 val, NumericVar *var) +int64_to_numericvar(int64 val, NumericVar *var) { uint64 uval, newuval; NumericDigit *ptr; int ndigits; - /* int8 can require at most 19 decimal digits; add one for safety */ + /* int64 can require at most 19 decimal digits; add one for safety */ alloc_var(var, 20 / DEC_DIGITS); if (val < 0) { @@ -4530,6 +4833,53 @@ int8_to_numericvar(int64 val, NumericVar *var) var->weight = ndigits - 1; } +#ifdef HAVE_INT128 +/* + * Convert 128 bit integer to numeric. + */ +static void +int128_to_numericvar(int128 val, NumericVar *var) +{ + uint128 uval, + newuval; + NumericDigit *ptr; + int ndigits; + + /* int128 can require at most 39 decimal digits; add one for safety */ + alloc_var(var, 40 / DEC_DIGITS); + if (val < 0) + { + var->sign = NUMERIC_NEG; + uval = -val; + } + else + { + var->sign = NUMERIC_POS; + uval = val; + } + var->dscale = 0; + if (val == 0) + { + var->ndigits = 0; + var->weight = 0; + return; + } + ptr = var->digits + var->ndigits; + ndigits = 0; + do + { + ptr--; + ndigits++; + newuval = uval / NBASE; + *ptr = uval - newuval * NBASE; + uval = newuval; + } while (uval); + var->digits = ptr; + var->ndigits = ndigits; + var->weight = ndigits - 1; +} +#endif + /* * Convert numeric to float8; if out of range, return +/- HUGE_VAL */ @@ -6136,7 +6486,7 @@ power_var(NumericVar *base, NumericVar *exp, NumericVar *result) /* exact integer, but does it fit in int? */ int64 expval64; - if (numericvar_to_int8(exp, &expval64)) + if (numericvar_to_int64(exp, &expval64)) { int expval = (int) expval64; diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index 0c435c2..da6035f 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -53,6 +53,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 201503181 +#define CATALOG_VERSION_NO 201503191 #endif diff --git a/src/include/catalog/pg_aggregate.h b/src/include/catalog/pg_aggregate.h index 3e28e2f..b6b6988 100644 --- a/src/include/catalog/pg_aggregate.h +++ b/src/include/catalog/pg_aggregate.h @@ -126,23 +126,23 @@ typedef FormData_pg_aggregate *Form_pg_aggregate; */ /* avg */ -DATA(insert ( 2100 n 0 int8_avg_accum numeric_avg int8_avg_accum int8_accum_inv numeric_avg f f 0 2281 128 2281 128 _null_ _null_ )); -DATA(insert ( 2101 n 0 int4_avg_accum int8_avg int4_avg_accum int4_avg_accum_inv int8_avg f f 0 1016 0 1016 0 "{0,0}" "{0,0}" )); -DATA(insert ( 2102 n 0 int2_avg_accum int8_avg int2_avg_accum int2_avg_accum_inv int8_avg f f 0 1016 0 1016 0 "{0,0}" "{0,0}" )); -DATA(insert ( 2103 n 0 numeric_avg_accum numeric_avg numeric_avg_accum numeric_accum_inv numeric_avg f f 0 2281 128 2281 128 _null_ _null_ )); -DATA(insert ( 2104 n 0 float4_accum float8_avg - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ )); -DATA(insert ( 2105 n 0 float8_accum float8_avg - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ )); -DATA(insert ( 2106 n 0 interval_accum interval_avg interval_accum interval_accum_inv interval_avg f f 0 1187 0 1187 0 "{0 second,0 second}" "{0 second,0 second}" )); +DATA(insert ( 2100 n 0 int8_avg_accum numeric_poly_avg int8_avg_accum int8_avg_accum_inv numeric_poly_avg f f 0 2281 48 2281 48 _null_ _null_ )); +DATA(insert ( 2101 n 0 int4_avg_accum int8_avg int4_avg_accum int4_avg_accum_inv int8_avg f f 0 1016 0 1016 0 "{0,0}" "{0,0}" )); +DATA(insert ( 2102 n 0 int2_avg_accum int8_avg int2_avg_accum int2_avg_accum_inv int8_avg f f 0 1016 0 1016 0 "{0,0}" "{0,0}" )); +DATA(insert ( 2103 n 0 numeric_avg_accum numeric_avg numeric_avg_accum numeric_accum_inv numeric_avg f f 0 2281 128 2281 128 _null_ _null_ )); +DATA(insert ( 2104 n 0 float4_accum float8_avg - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ )); +DATA(insert ( 2105 n 0 float8_accum float8_avg - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ )); +DATA(insert ( 2106 n 0 interval_accum interval_avg interval_accum interval_accum_inv interval_avg f f 0 1187 0 1187 0 "{0 second,0 second}" "{0 second,0 second}" )); /* sum */ -DATA(insert ( 2107 n 0 int8_avg_accum numeric_sum int8_avg_accum int8_accum_inv numeric_sum f f 0 2281 128 2281 128 _null_ _null_ )); -DATA(insert ( 2108 n 0 int4_sum - int4_avg_accum int4_avg_accum_inv int2int4_sum f f 0 20 0 1016 0 _null_ "{0,0}" )); -DATA(insert ( 2109 n 0 int2_sum - int2_avg_accum int2_avg_accum_inv int2int4_sum f f 0 20 0 1016 0 _null_ "{0,0}" )); -DATA(insert ( 2110 n 0 float4pl - - - - f f 0 700 0 0 0 _null_ _null_ )); -DATA(insert ( 2111 n 0 float8pl - - - - f f 0 701 0 0 0 _null_ _null_ )); -DATA(insert ( 2112 n 0 cash_pl - cash_pl cash_mi - f f 0 790 0 790 0 _null_ _null_ )); -DATA(insert ( 2113 n 0 interval_pl - interval_pl interval_mi - f f 0 1186 0 1186 0 _null_ _null_ )); -DATA(insert ( 2114 n 0 numeric_avg_accum numeric_sum numeric_avg_accum numeric_accum_inv numeric_sum f f 0 2281 128 2281 128 _null_ _null_ )); +DATA(insert ( 2107 n 0 int8_avg_accum numeric_poly_sum int8_avg_accum int8_avg_accum_inv numeric_poly_sum f f 0 2281 48 2281 48 _null_ _null_ )); +DATA(insert ( 2108 n 0 int4_sum - int4_avg_accum int4_avg_accum_inv int2int4_sum f f 0 20 0 1016 0 _null_ "{0,0}" )); +DATA(insert ( 2109 n 0 int2_sum - int2_avg_accum int2_avg_accum_inv int2int4_sum f f 0 20 0 1016 0 _null_ "{0,0}" )); +DATA(insert ( 2110 n 0 float4pl - - - - f f 0 700 0 0 0 _null_ _null_ )); +DATA(insert ( 2111 n 0 float8pl - - - - f f 0 701 0 0 0 _null_ _null_ )); +DATA(insert ( 2112 n 0 cash_pl - cash_pl cash_mi - f f 0 790 0 790 0 _null_ _null_ )); +DATA(insert ( 2113 n 0 interval_pl - interval_pl interval_mi - f f 0 1186 0 1186 0 _null_ _null_ )); +DATA(insert ( 2114 n 0 numeric_avg_accum numeric_sum numeric_avg_accum numeric_accum_inv numeric_sum f f 0 2281 128 2281 128 _null_ _null_ )); /* max */ DATA(insert ( 2115 n 0 int8larger - - - - f f 413 20 0 0 0 _null_ _null_ )); @@ -195,52 +195,52 @@ DATA(insert ( 2147 n 0 int8inc_any - int8inc_any int8dec_any - f f 0 2 DATA(insert ( 2803 n 0 int8inc - int8inc int8dec - f f 0 20 0 20 0 "0" "0" )); /* var_pop */ -DATA(insert ( 2718 n 0 int8_accum numeric_var_pop int8_accum int8_accum_inv numeric_var_pop f f 0 2281 128 2281 128 _null_ _null_ )); -DATA(insert ( 2719 n 0 int4_accum numeric_var_pop int4_accum int4_accum_inv numeric_var_pop f f 0 2281 128 2281 128 _null_ _null_ )); -DATA(insert ( 2720 n 0 int2_accum numeric_var_pop int2_accum int2_accum_inv numeric_var_pop f f 0 2281 128 2281 128 _null_ _null_ )); -DATA(insert ( 2721 n 0 float4_accum float8_var_pop - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ )); -DATA(insert ( 2722 n 0 float8_accum float8_var_pop - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ )); -DATA(insert ( 2723 n 0 numeric_accum numeric_var_pop numeric_accum numeric_accum_inv numeric_var_pop f f 0 2281 128 2281 128 _null_ _null_ )); +DATA(insert ( 2718 n 0 int8_accum numeric_var_pop int8_accum int8_accum_inv numeric_var_pop f f 0 2281 128 2281 128 _null_ _null_ )); +DATA(insert ( 2719 n 0 int4_accum numeric_poly_var_pop int4_accum int4_accum_inv numeric_poly_var_pop f f 0 2281 48 2281 48 _null_ _null_ )); +DATA(insert ( 2720 n 0 int2_accum numeric_poly_var_pop int2_accum int2_accum_inv numeric_poly_var_pop f f 0 2281 48 2281 48 _null_ _null_ )); +DATA(insert ( 2721 n 0 float4_accum float8_var_pop - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ )); +DATA(insert ( 2722 n 0 float8_accum float8_var_pop - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ )); +DATA(insert ( 2723 n 0 numeric_accum numeric_var_pop numeric_accum numeric_accum_inv numeric_var_pop f f 0 2281 128 2281 128 _null_ _null_ )); /* var_samp */ -DATA(insert ( 2641 n 0 int8_accum numeric_var_samp int8_accum int8_accum_inv numeric_var_samp f f 0 2281 128 2281 128 _null_ _null_ )); -DATA(insert ( 2642 n 0 int4_accum numeric_var_samp int4_accum int4_accum_inv numeric_var_samp f f 0 2281 128 2281 128 _null_ _null_ )); -DATA(insert ( 2643 n 0 int2_accum numeric_var_samp int2_accum int2_accum_inv numeric_var_samp f f 0 2281 128 2281 128 _null_ _null_ )); -DATA(insert ( 2644 n 0 float4_accum float8_var_samp - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ )); -DATA(insert ( 2645 n 0 float8_accum float8_var_samp - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ )); -DATA(insert ( 2646 n 0 numeric_accum numeric_var_samp numeric_accum numeric_accum_inv numeric_var_samp f f 0 2281 128 2281 128 _null_ _null_ )); +DATA(insert ( 2641 n 0 int8_accum numeric_var_samp int8_accum int8_accum_inv numeric_var_samp f f 0 2281 128 2281 128 _null_ _null_ )); +DATA(insert ( 2642 n 0 int4_accum numeric_poly_var_samp int4_accum int4_accum_inv numeric_poly_var_samp f f 0 2281 48 2281 48 _null_ _null_ )); +DATA(insert ( 2643 n 0 int2_accum numeric_poly_var_samp int2_accum int2_accum_inv numeric_poly_var_samp f f 0 2281 48 2281 48 _null_ _null_ )); +DATA(insert ( 2644 n 0 float4_accum float8_var_samp - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ )); +DATA(insert ( 2645 n 0 float8_accum float8_var_samp - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ )); +DATA(insert ( 2646 n 0 numeric_accum numeric_var_samp numeric_accum numeric_accum_inv numeric_var_samp f f 0 2281 128 2281 128 _null_ _null_ )); /* variance: historical Postgres syntax for var_samp */ -DATA(insert ( 2148 n 0 int8_accum numeric_var_samp int8_accum int8_accum_inv numeric_var_samp f f 0 2281 128 2281 128 _null_ _null_ )); -DATA(insert ( 2149 n 0 int4_accum numeric_var_samp int4_accum int4_accum_inv numeric_var_samp f f 0 2281 128 2281 128 _null_ _null_ )); -DATA(insert ( 2150 n 0 int2_accum numeric_var_samp int2_accum int2_accum_inv numeric_var_samp f f 0 2281 128 2281 128 _null_ _null_ )); -DATA(insert ( 2151 n 0 float4_accum float8_var_samp - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ )); -DATA(insert ( 2152 n 0 float8_accum float8_var_samp - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ )); -DATA(insert ( 2153 n 0 numeric_accum numeric_var_samp numeric_accum numeric_accum_inv numeric_var_samp f f 0 2281 128 2281 128 _null_ _null_ )); +DATA(insert ( 2148 n 0 int8_accum numeric_var_samp int8_accum int8_accum_inv numeric_var_samp f f 0 2281 128 2281 128 _null_ _null_ )); +DATA(insert ( 2149 n 0 int4_accum numeric_poly_var_samp int4_accum int4_accum_inv numeric_poly_var_samp f f 0 2281 48 2281 48 _null_ _null_ )); +DATA(insert ( 2150 n 0 int2_accum numeric_poly_var_samp int2_accum int2_accum_inv numeric_poly_var_samp f f 0 2281 48 2281 48 _null_ _null_ )); +DATA(insert ( 2151 n 0 float4_accum float8_var_samp - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ )); +DATA(insert ( 2152 n 0 float8_accum float8_var_samp - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ )); +DATA(insert ( 2153 n 0 numeric_accum numeric_var_samp numeric_accum numeric_accum_inv numeric_var_samp f f 0 2281 128 2281 128 _null_ _null_ )); /* stddev_pop */ -DATA(insert ( 2724 n 0 int8_accum numeric_stddev_pop int8_accum int8_accum_inv numeric_stddev_pop f f 0 2281 128 2281 128 _null_ _null_ )); -DATA(insert ( 2725 n 0 int4_accum numeric_stddev_pop int4_accum int4_accum_inv numeric_stddev_pop f f 0 2281 128 2281 128 _null_ _null_ )); -DATA(insert ( 2726 n 0 int2_accum numeric_stddev_pop int2_accum int2_accum_inv numeric_stddev_pop f f 0 2281 128 2281 128 _null_ _null_ )); -DATA(insert ( 2727 n 0 float4_accum float8_stddev_pop - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ )); -DATA(insert ( 2728 n 0 float8_accum float8_stddev_pop - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ )); -DATA(insert ( 2729 n 0 numeric_accum numeric_stddev_pop numeric_accum numeric_accum_inv numeric_stddev_pop f f 0 2281 128 2281 128 _null_ _null_ )); +DATA(insert ( 2724 n 0 int8_accum numeric_stddev_pop int8_accum int8_accum_inv numeric_stddev_pop f f 0 2281 128 2281 128 _null_ _null_ )); +DATA(insert ( 2725 n 0 int4_accum numeric_poly_stddev_pop int4_accum int4_accum_inv numeric_poly_stddev_pop f f 0 2281 48 2281 48 _null_ _null_ )); +DATA(insert ( 2726 n 0 int2_accum numeric_poly_stddev_pop int2_accum int2_accum_inv numeric_poly_stddev_pop f f 0 2281 48 2281 48 _null_ _null_ )); +DATA(insert ( 2727 n 0 float4_accum float8_stddev_pop - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ )); +DATA(insert ( 2728 n 0 float8_accum float8_stddev_pop - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ )); +DATA(insert ( 2729 n 0 numeric_accum numeric_stddev_pop numeric_accum numeric_accum_inv numeric_stddev_pop f f 0 2281 128 2281 128 _null_ _null_ )); /* stddev_samp */ -DATA(insert ( 2712 n 0 int8_accum numeric_stddev_samp int8_accum int8_accum_inv numeric_stddev_samp f f 0 2281 128 2281 128 _null_ _null_ )); -DATA(insert ( 2713 n 0 int4_accum numeric_stddev_samp int4_accum int4_accum_inv numeric_stddev_samp f f 0 2281 128 2281 128 _null_ _null_ )); -DATA(insert ( 2714 n 0 int2_accum numeric_stddev_samp int2_accum int2_accum_inv numeric_stddev_samp f f 0 2281 128 2281 128 _null_ _null_ )); -DATA(insert ( 2715 n 0 float4_accum float8_stddev_samp - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ )); -DATA(insert ( 2716 n 0 float8_accum float8_stddev_samp - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ )); -DATA(insert ( 2717 n 0 numeric_accum numeric_stddev_samp numeric_accum numeric_accum_inv numeric_stddev_samp f f 0 2281 128 2281 128 _null_ _null_ )); +DATA(insert ( 2712 n 0 int8_accum numeric_stddev_samp int8_accum int8_accum_inv numeric_stddev_samp f f 0 2281 128 2281 128 _null_ _null_ )); +DATA(insert ( 2713 n 0 int4_accum numeric_poly_stddev_samp int4_accum int4_accum_inv numeric_poly_stddev_samp f f 0 2281 48 2281 48 _null_ _null_ )); +DATA(insert ( 2714 n 0 int2_accum numeric_poly_stddev_samp int2_accum int2_accum_inv numeric_poly_stddev_samp f f 0 2281 48 2281 48 _null_ _null_ )); +DATA(insert ( 2715 n 0 float4_accum float8_stddev_samp - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ )); +DATA(insert ( 2716 n 0 float8_accum float8_stddev_samp - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ )); +DATA(insert ( 2717 n 0 numeric_accum numeric_stddev_samp numeric_accum numeric_accum_inv numeric_stddev_samp f f 0 2281 128 2281 128 _null_ _null_ )); /* stddev: historical Postgres syntax for stddev_samp */ -DATA(insert ( 2154 n 0 int8_accum numeric_stddev_samp int8_accum int8_accum_inv numeric_stddev_samp f f 0 2281 128 2281 128 _null_ _null_ )); -DATA(insert ( 2155 n 0 int4_accum numeric_stddev_samp int4_accum int4_accum_inv numeric_stddev_samp f f 0 2281 128 2281 128 _null_ _null_ )); -DATA(insert ( 2156 n 0 int2_accum numeric_stddev_samp int2_accum int2_accum_inv numeric_stddev_samp f f 0 2281 128 2281 128 _null_ _null_ )); -DATA(insert ( 2157 n 0 float4_accum float8_stddev_samp - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ )); -DATA(insert ( 2158 n 0 float8_accum float8_stddev_samp - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ )); -DATA(insert ( 2159 n 0 numeric_accum numeric_stddev_samp numeric_accum numeric_accum_inv numeric_stddev_samp f f 0 2281 128 2281 128 _null_ _null_ )); +DATA(insert ( 2154 n 0 int8_accum numeric_stddev_samp int8_accum int8_accum_inv numeric_stddev_samp f f 0 2281 128 2281 128 _null_ _null_ )); +DATA(insert ( 2155 n 0 int4_accum numeric_poly_stddev_samp int4_accum int4_accum_inv numeric_poly_stddev_samp f f 0 2281 48 2281 48 _null_ _null_ )); +DATA(insert ( 2156 n 0 int2_accum numeric_poly_stddev_samp int2_accum int2_accum_inv numeric_poly_stddev_samp f f 0 2281 48 2281 48 _null_ _null_ )); +DATA(insert ( 2157 n 0 float4_accum float8_stddev_samp - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ )); +DATA(insert ( 2158 n 0 float8_accum float8_stddev_samp - - - f f 0 1022 0 0 0 "{0,0,0}" _null_ )); +DATA(insert ( 2159 n 0 numeric_accum numeric_stddev_samp numeric_accum numeric_accum_inv numeric_stddev_samp f f 0 2281 128 2281 128 _null_ _null_ )); /* SQL2003 binary regression aggregates */ DATA(insert ( 2818 n 0 int8inc_float8_float8 - - - - f f 0 20 0 0 0 "0" _null_ )); diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h index 6a757f3..3c218a3 100644 --- a/src/include/catalog/pg_proc.h +++ b/src/include/catalog/pg_proc.h @@ -2501,6 +2501,8 @@ DATA(insert OID = 3568 ( int4_accum_inv PGNSP PGUID 12 1 0 0 0 f f f f f f i DESCR("aggregate transition function"); DATA(insert OID = 3569 ( int8_accum_inv PGNSP PGUID 12 1 0 0 0 f f f f f f i 2 0 2281 "2281 20" _null_ _null_ _null_ _null_ int8_accum_inv _null_ _null_ _null_ )); DESCR("aggregate transition function"); +DATA(insert OID = 3387 ( int8_avg_accum_inv PGNSP PGUID 12 1 0 0 0 f f f f f f i 2 0 2281 "2281 20" _null_ _null_ _null_ _null_ int8_avg_accum_inv _null_ _null_ _null_ )); +DESCR("aggregate transition function"); DATA(insert OID = 3178 ( numeric_sum PGNSP PGUID 12 1 0 0 0 f f f f f f i 1 0 1700 "2281" _null_ _null_ _null_ _null_ numeric_sum _null_ _null_ _null_ )); DESCR("aggregate final function"); DATA(insert OID = 1837 ( numeric_avg PGNSP PGUID 12 1 0 0 0 f f f f f f i 1 0 1700 "2281" _null_ _null_ _null_ _null_ numeric_avg _null_ _null_ _null_ )); @@ -2519,6 +2521,19 @@ DATA(insert OID = 1841 ( int4_sum PGNSP PGUID 12 1 0 0 0 f f f f f f i 2 0 DESCR("aggregate transition function"); DATA(insert OID = 1842 ( int8_sum PGNSP PGUID 12 1 0 0 0 f f f f f f i 2 0 1700 "1700 20" _null_ _null_ _null_ _null_ int8_sum _null_ _null_ _null_ )); DESCR("aggregate transition function"); +DATA(insert OID = 3388 ( numeric_poly_sum PGNSP PGUID 12 1 0 0 0 f f f f f f i 1 0 1700 "2281" _null_ _null_ _null_ _null_ numeric_poly_sum _null_ _null_ _null_ )); +DESCR("aggregate final function"); +DATA(insert OID = 3389 ( numeric_poly_avg PGNSP PGUID 12 1 0 0 0 f f f f f f i 1 0 1700 "2281" _null_ _null_ _null_ _null_ numeric_poly_avg _null_ _null_ _null_ )); +DESCR("aggregate final function"); +DATA(insert OID = 3390 ( numeric_poly_var_pop PGNSP PGUID 12 1 0 0 0 f f f f f f i 1 0 1700 "2281" _null_ _null_ _null_ _null_ numeric_poly_var_pop _null_ _null_ _null_ )); +DESCR("aggregate final function"); +DATA(insert OID = 3391 ( numeric_poly_var_samp PGNSP PGUID 12 1 0 0 0 f f f f f f i 1 0 1700 "2281" _null_ _null_ _null_ _null_ numeric_poly_var_samp _null_ _null_ _null_ )); +DESCR("aggregate final function"); +DATA(insert OID = 3392 ( numeric_poly_stddev_pop PGNSP PGUID 12 1 0 0 0 f f f f f f i 1 0 1700 "2281" _null_ _null_ _null_ _null_ numeric_poly_stddev_pop _null_ _null_ _null_ )); +DESCR("aggregate final function"); +DATA(insert OID = 3393 ( numeric_poly_stddev_samp PGNSP PGUID 12 1 0 0 0 f f f f f f i 1 0 1700 "2281" _null_ _null_ _null_ _null_ numeric_poly_stddev_samp _null_ _null_ _null_ )); +DESCR("aggregate final function"); + DATA(insert OID = 1843 ( interval_accum PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 1187 "1187 1186" _null_ _null_ _null_ _null_ interval_accum _null_ _null_ _null_ )); DESCR("aggregate transition function"); DATA(insert OID = 3549 ( interval_accum_inv PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 1187 "1187 1186" _null_ _null_ _null_ _null_ interval_accum_inv _null_ _null_ _null_ )); diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h index bc4517d..6310641 100644 --- a/src/include/utils/builtins.h +++ b/src/include/utils/builtins.h @@ -1027,6 +1027,12 @@ extern Datum numeric_var_pop(PG_FUNCTION_ARGS); extern Datum numeric_var_samp(PG_FUNCTION_ARGS); extern Datum numeric_stddev_pop(PG_FUNCTION_ARGS); extern Datum numeric_stddev_samp(PG_FUNCTION_ARGS); +extern Datum numeric_poly_sum(PG_FUNCTION_ARGS); +extern Datum numeric_poly_avg(PG_FUNCTION_ARGS); +extern Datum numeric_poly_var_pop(PG_FUNCTION_ARGS); +extern Datum numeric_poly_var_samp(PG_FUNCTION_ARGS); +extern Datum numeric_poly_stddev_pop(PG_FUNCTION_ARGS); +extern Datum numeric_poly_stddev_samp(PG_FUNCTION_ARGS); extern Datum int2_sum(PG_FUNCTION_ARGS); extern Datum int4_sum(PG_FUNCTION_ARGS); extern Datum int8_sum(PG_FUNCTION_ARGS); @@ -1034,6 +1040,7 @@ extern Datum int2_avg_accum(PG_FUNCTION_ARGS); extern Datum int4_avg_accum(PG_FUNCTION_ARGS); extern Datum int2_avg_accum_inv(PG_FUNCTION_ARGS); extern Datum int4_avg_accum_inv(PG_FUNCTION_ARGS); +extern Datum int8_avg_accum_inv(PG_FUNCTION_ARGS); extern Datum int8_avg(PG_FUNCTION_ARGS); extern Datum int2int4_sum(PG_FUNCTION_ARGS); extern Datum width_bucket_numeric(PG_FUNCTION_ARGS); -- 2.3.0.149.gf3f4077
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers