Hi,

There was recently talk about if we should start using 128-bit integers (where available) to speed up the aggregate functions over integers which uses numeric for their internal state. So I hacked together a patch for this to see what the performance gain would be.

Previous thread: http://www.postgresql.org/message-id/20141017182500.gf2...@alap3.anarazel.de

What the patch does is switching from using numerics in the aggregate state to int128 and then convert the type from the 128-bit integer in the final function.

The functions where we can make use of int128 states are:

- sum(int8)
- avg(int8)
- var_*(int2)
- var_*(int4)
- stdev_*(int2)
- stdev_*(int4)

The initial benchmark results look very promising. When summing 10 million int8 I get a speedup of ~2.5x and similarly for var_samp() on 10 million int4 I see a speed up of ~3.7x. To me this indicates that it is worth the extra code. What do you say? Is this worth implementing?

The current patch still requires work. I have not written the detection of int128 support yet, and the patch needs code cleanup (for example: I used an int16_ prefix on the added functions, suggestions for better names are welcome). I also need to decide on what estimate to use for the size of that state.

The patch should work and pass make check on platforms where __int128_t is supported.

The simple benchmarks:

CREATE TABLE test_int8 AS SELECT x::int8 FROM generate_series(1, 10000000) x;

Before:

# SELECT sum(x) FROM test_int8;
      sum
----------------
 50000005000000
(1 row)

Time: 2521.217 ms

After:

# SELECT sum(x) FROM test_int8;
      sum
----------------
 50000005000000
(1 row)

Time: 1022.811 ms

CREATE TABLE test_int4 AS SELECT x::int4 FROM generate_series(1, 10000000) x;

Before:

# SELECT var_samp(x) FROM test_int4;
      var_samp
--------------------
 8333334166666.6667
(1 row)

Time: 3808.546 ms

After:

# SELECT var_samp(x) FROM test_int4;
      var_samp
--------------------
 8333334166666.6667
(1 row)

Time: 1033.243 ms

Andreas
diff --git a/src/backend/utils/adt/numeric.c b/src/backend/utils/adt/numeric.c
new file mode 100644
index 2d6a4cb..65a3d08
*** a/src/backend/utils/adt/numeric.c
--- b/src/backend/utils/adt/numeric.c
*************** typedef int16 NumericDigit;
*** 119,124 ****
--- 119,129 ----
   * The weight is arbitrary in that case, but we normally set it to zero.
   */
  
+ /* FIXME: Do this properly */
+ typedef __int128_t int128;
+ typedef __uint128_t uint128;
+ #define HAVE_INT128 1
+ 
  struct NumericShort
  {
  	uint16		n_header;		/* Sign + display scale + weight */
*************** static void apply_typmod(NumericVar *var
*** 389,394 ****
--- 394,402 ----
  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);
+ #ifdef HAVE_INT128
+ static void int16_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);
  
*************** numeric_accum_inv(PG_FUNCTION_ARGS)
*** 2775,2783 ****
--- 2783,2867 ----
   * routines for SUM and AVG of these datatypes.
   */
  
+ #ifdef HAVE_INT128
+ typedef struct Int16AggState
+ {
+ 	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 */
+ } Int16AggState;
+ 
+ /*
+  * Prepare state data for a numeric aggregate function that needs to compute
+  * sum, count and optionally sum of squares of the input.
+  */
+ static Int16AggState *
+ makeInt16AggState(FunctionCallInfo fcinfo, bool calcSumX2)
+ {
+ 	Int16AggState *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 = (Int16AggState *) palloc0(sizeof(Int16AggState));
+ 	state->calcSumX2 = calcSumX2;
+ 
+ 	MemoryContextSwitchTo(old_context);
+ 
+ 	return state;
+ }
+ 
+ /*
+  * Accumulate a new input value for numeric aggregate functions.
+  */
+ static void
+ do_int16_accum(Int16AggState *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_int16_discard(Int16AggState *state, int128 newval)
+ {
+ 	if (state->calcSumX2)
+ 		state->sumX2 -= newval * newval;
+ 
+ 	state->sumX -= newval;
+ 	state->N--;
+ }
+ #endif
+ 
  Datum
  int2_accum(PG_FUNCTION_ARGS)
  {
+ #ifdef HAVE_INT128
+ 	Int16AggState *state;
+ 
+ 	state = PG_ARGISNULL(0) ? NULL : (Int16AggState *) PG_GETARG_POINTER(0);
+ 
+ 	/* Create the state data on the first call */
+ 	if (state == NULL)
+ 		state = makeInt16AggState(fcinfo, true);
+ 
+ 	if (!PG_ARGISNULL(1))
+ 	{
+ 		int16	newval = PG_GETARG_INT16(1);
+ 
+ 		do_int16_accum(state, newval);
+ 	}
+ #else
  	NumericAggState *state;
  
  	state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
*************** int2_accum(PG_FUNCTION_ARGS)
*** 2794,2799 ****
--- 2878,2884 ----
  													 PG_GETARG_DATUM(1)));
  		do_numeric_accum(state, newval);
  	}
+ #endif
  
  	PG_RETURN_POINTER(state);
  }
*************** int2_accum(PG_FUNCTION_ARGS)
*** 2801,2806 ****
--- 2886,2907 ----
  Datum
  int4_accum(PG_FUNCTION_ARGS)
  {
+ #ifdef HAVE_INT128
+ 	Int16AggState *state;
+ 
+ 	state = PG_ARGISNULL(0) ? NULL : (Int16AggState *) PG_GETARG_POINTER(0);
+ 
+ 	/* Create the state data on the first call */
+ 	if (state == NULL)
+ 		state = makeInt16AggState(fcinfo, true);
+ 
+ 	if (!PG_ARGISNULL(1))
+ 	{
+ 		int32	newval = PG_GETARG_INT32(1);
+ 
+ 		do_int16_accum(state, newval);
+ 	}
+ #else
  	NumericAggState *state;
  
  	state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
*************** int4_accum(PG_FUNCTION_ARGS)
*** 2817,2822 ****
--- 2918,2924 ----
  													 PG_GETARG_DATUM(1)));
  		do_numeric_accum(state, newval);
  	}
+ #endif
  
  	PG_RETURN_POINTER(state);
  }
*************** int8_accum(PG_FUNCTION_ARGS)
*** 2850,2855 ****
--- 2952,2973 ----
  Datum
  int8_avg_accum(PG_FUNCTION_ARGS)
  {
+ #ifdef HAVE_INT128
+ 	Int16AggState *state;
+ 
+ 	state = PG_ARGISNULL(0) ? NULL : (Int16AggState *) PG_GETARG_POINTER(0);
+ 
+ 	/* Create the state data on the first call */
+ 	if (state == NULL)
+ 		state = makeInt16AggState(fcinfo, false);
+ 
+ 	if (!PG_ARGISNULL(1))
+ 	{
+ 		int64	newval = PG_GETARG_INT64(1);
+ 
+ 		do_int16_accum(state, newval);
+ 	}
+ #else
  	NumericAggState *state;
  
  	state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
*************** int8_avg_accum(PG_FUNCTION_ARGS)
*** 2866,2871 ****
--- 2984,2990 ----
  													 PG_GETARG_DATUM(1)));
  		do_numeric_accum(state, newval);
  	}
+ #endif
  
  	PG_RETURN_POINTER(state);
  }
*************** int8_avg_accum(PG_FUNCTION_ARGS)
*** 2878,2883 ****
--- 2997,3018 ----
  Datum
  int2_accum_inv(PG_FUNCTION_ARGS)
  {
+ #ifdef HAVE_INT128
+ 	Int16AggState *state;
+ 
+ 	state = PG_ARGISNULL(0) ? NULL : (Int16AggState *) PG_GETARG_POINTER(0);
+ 
+ 	/* Should not get here with no state */
+ 	if (state == NULL)
+ 		elog(ERROR, "int2_accum_inv called with NULL state");
+ 
+ 	if (!PG_ARGISNULL(1))
+ 	{
+ 		int16	newval = PG_GETARG_INT16(1);
+ 
+ 		do_int16_discard(state, newval);
+ 	}
+ #else
  	NumericAggState *state;
  
  	state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
*************** int2_accum_inv(PG_FUNCTION_ARGS)
*** 2897,2902 ****
--- 3032,3038 ----
  		if (!do_numeric_discard(state, newval))
  			elog(ERROR, "do_numeric_discard failed unexpectedly");
  	}
+ #endif
  
  	PG_RETURN_POINTER(state);
  }
*************** int2_accum_inv(PG_FUNCTION_ARGS)
*** 2904,2909 ****
--- 3040,3061 ----
  Datum
  int4_accum_inv(PG_FUNCTION_ARGS)
  {
+ #ifdef HAVE_INT128
+ 	Int16AggState *state;
+ 
+ 	state = PG_ARGISNULL(0) ? NULL : (Int16AggState *) PG_GETARG_POINTER(0);
+ 
+ 	/* Should not get here with no state */
+ 	if (state == NULL)
+ 		elog(ERROR, "int4_accum_inv called with NULL state");
+ 
+ 	if (!PG_ARGISNULL(1))
+ 	{
+ 		int32	newval = PG_GETARG_INT32(1);
+ 
+ 		do_int16_discard(state, newval);
+ 	}
+ #else
  	NumericAggState *state;
  
  	state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
*************** int4_accum_inv(PG_FUNCTION_ARGS)
*** 2923,2928 ****
--- 3075,3081 ----
  		if (!do_numeric_discard(state, newval))
  			elog(ERROR, "do_numeric_discard failed unexpectedly");
  	}
+ #endif
  
  	PG_RETURN_POINTER(state);
  }
*************** int8_accum_inv(PG_FUNCTION_ARGS)
*** 2954,2959 ****
--- 3107,3213 ----
  }
  
  Datum
+ int8_avg_accum_inv(PG_FUNCTION_ARGS)
+ {
+ #ifdef HAVE_INT128
+ 	Int16AggState *state;
+ 
+ 	state = PG_ARGISNULL(0) ? NULL : (Int16AggState *) 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))
+ 	{
+ 		int64	newval = PG_GETARG_INT64(1);
+ 
+ 		do_int16_discard(state, newval);
+ 	}
+ #else
+ 	NumericAggState *state;
+ 
+ 	state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) 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))
+ 	{
+ 		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
+ int16_sum(PG_FUNCTION_ARGS)
+ {
+ #ifdef HAVE_INT128
+ 	Int16AggState	*state;
+ 	Numeric			res;
+ 	NumericVar		result;
+ 
+ 	state = PG_ARGISNULL(0) ? NULL : (Int16AggState *) 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);
+ 
+ 	int16_to_numericvar(state->sumX, &result);
+ 
+ 	res = make_result(&result);
+ 
+ 	free_var(&result);
+ 
+ 	PG_RETURN_NUMERIC(res);
+ #else
+ 	return numeric_sum(fcinfo);
+ #endif
+ }
+ 
+ Datum
+ int16_avg(PG_FUNCTION_ARGS)
+ {
+ #ifdef HAVE_INT128
+ 	Int16AggState	*state;
+ 	NumericVar		result;
+ 	Datum			countd, sumd;
+ 
+ 	state = PG_ARGISNULL(0) ? NULL : (Int16AggState *) 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);
+ 
+ 	int16_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;
*************** numeric_stddev_pop(PG_FUNCTION_ARGS)
*** 3155,3160 ****
--- 3409,3529 ----
  		PG_RETURN_NUMERIC(res);
  }
  
+ #ifdef HAVE_INT128
+ static Numeric
+ int16_stddev_internal(Int16AggState *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;
+ 		int16_to_numericvar(state->sumX, &numstate.sumX);
+ 		int16_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
+ int16_var_samp(PG_FUNCTION_ARGS)
+ {
+ #ifdef HAVE_INT128
+ 	Int16AggState *state;
+ 	Numeric		res;
+ 	bool		is_null;
+ 
+ 	state = PG_ARGISNULL(0) ? NULL : (Int16AggState *) PG_GETARG_POINTER(0);
+ 
+ 	res = int16_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
+ int16_stddev_samp(PG_FUNCTION_ARGS)
+ {
+ #ifdef HAVE_INT128
+ 	Int16AggState *state;
+ 	Numeric		res;
+ 	bool		is_null;
+ 
+ 	state = PG_ARGISNULL(0) ? NULL : (Int16AggState *) PG_GETARG_POINTER(0);
+ 
+ 	res = int16_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
+ int16_var_pop(PG_FUNCTION_ARGS)
+ {
+ #ifdef HAVE_INT128
+ 	Int16AggState *state;
+ 	Numeric		res;
+ 	bool		is_null;
+ 
+ 	state = PG_ARGISNULL(0) ? NULL : (Int16AggState *) PG_GETARG_POINTER(0);
+ 
+ 	res = int16_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
+ int16_stddev_pop(PG_FUNCTION_ARGS)
+ {
+ #ifdef HAVE_INT128
+ 	Int16AggState *state;
+ 	Numeric		res;
+ 	bool		is_null;
+ 
+ 	state = PG_ARGISNULL(0) ? NULL : (Int16AggState *) PG_GETARG_POINTER(0);
+ 
+ 	res = int16_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.
   *
*************** int8_to_numericvar(int64 val, NumericVar
*** 4377,4382 ****
--- 4746,4798 ----
  	var->weight = ndigits - 1;
  }
  
+ #ifdef HAVE_INT128
+ /*
+  * Convert 128 bit integer to numeric.
+  */
+ static void
+ int16_to_numericvar(int128 val, NumericVar *var)
+ {
+ 	uint128		uval,
+ 				newuval;
+ 	NumericDigit *ptr;
+ 	int			ndigits;
+ 
+ 	/* int16 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
   */
diff --git a/src/include/catalog/pg_aggregate.h b/src/include/catalog/pg_aggregate.h
new file mode 100644
index 3ba9e5e..b204bb2
*** a/src/include/catalog/pg_aggregate.h
--- b/src/include/catalog/pg_aggregate.h
*************** typedef FormData_pg_aggregate *Form_pg_a
*** 125,131 ****
   */
  
  /* 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_ ));
--- 125,131 ----
   */
  
  /* avg */
! DATA(insert ( 2100	n 0 int8_avg_accum	int16_avg		int8_avg_accum	int8_avg_accum_inv	int16_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 ( 2105	n 0 float8_accum	floa
*** 134,140 ****
  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_ ));
--- 134,140 ----
  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	int16_sum		int8_avg_accum	int8_avg_accum_inv int16_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 ( 2803	n 0 int8inc			-				in
*** 195,242 ****
  
  /* 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_ ));
  
  /* 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_ ));
  
  /* 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_ ));
  
  /* 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_ ));
  
  /* 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_ ));
  
  /* 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_ ));
--- 195,242 ----
  
  /* 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	int16_var_pop		int4_accum		int4_accum_inv	int16_var_pop f f 0	2281	128 2281	128 _null_ _null_ ));
! DATA(insert ( 2720	n 0 int2_accum	int16_var_pop		int2_accum		int2_accum_inv	int16_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_ ));
  
  /* 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	int16_var_samp		int4_accum		int4_accum_inv	int16_var_samp f f 0	2281	48 	2281	48 _null_ _null_ ));
! DATA(insert ( 2643	n 0 int2_accum	int16_var_samp		int2_accum		int2_accum_inv	int16_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	int16_var_samp		int4_accum		int4_accum_inv	int16_var_samp f f 0	2281	48 	2281	48 	_null_ _null_ ));
! DATA(insert ( 2150	n 0 int2_accum	int16_var_samp		int2_accum		int2_accum_inv	int16_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	int16_stddev_pop		int4_accum	int4_accum_inv	int16_stddev_pop	f f 0	2281	48	2281	48 _null_ _null_ ));
! DATA(insert ( 2726	n 0 int2_accum	int16_stddev_pop		int2_accum	int2_accum_inv	int16_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	int16_stddev_samp		int4_accum	int4_accum_inv	int16_stddev_samp f f 0	2281	48 	2281	48 _null_ _null_ ));
! DATA(insert ( 2714	n 0 int2_accum	int16_stddev_samp		int2_accum	int2_accum_inv	int16_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	int16_stddev_samp		int4_accum	int4_accum_inv	int16_stddev_samp f f 0	2281	48 2281	48 _null_ _null_ ));
! DATA(insert ( 2156	n 0 int2_accum	int16_stddev_samp		int2_accum	int2_accum_inv	int16_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_ ));
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
new file mode 100644
index b6dc1b8..6564f0c
*** a/src/include/catalog/pg_proc.h
--- b/src/include/catalog/pg_proc.h
*************** DATA(insert OID = 3568 (  int4_accum_inv
*** 2455,2460 ****
--- 2455,2462 ----
  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 = 13569 (  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_ ));
*************** DATA(insert OID = 1841 (  int4_sum		   P
*** 2473,2478 ****
--- 2475,2494 ----
  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 = 13178 (  int16_sum	   PGNSP PGUID 12 1 0 0 0 f f f f f f i 1 0 1700 "2281" _null_ _null_ _null_ _null_ int16_sum _null_ _null_ _null_ ));
+ DESCR("aggregate final function");
+ DATA(insert OID = 11837 (  int16_avg	   PGNSP PGUID 12 1 0 0 0 f f f f f f i 1 0 1700 "2281" _null_ _null_ _null_ _null_ int16_avg _null_ _null_ _null_ ));
+ DESCR("aggregate final function");
+ DATA(insert OID = 12514 (  int16_var_pop  PGNSP PGUID 12 1 0 0 0 f f f f f f i 1 0 1700 "2281" _null_ _null_ _null_ _null_ int16_var_pop _null_ _null_ _null_ ));
+ DESCR("aggregate final function");
+ DATA(insert OID = 11838 (  int16_var_samp PGNSP PGUID 12 1 0 0 0 f f f f f f i 1 0 1700 "2281" _null_ _null_ _null_ _null_ int16_var_samp _null_ _null_ _null_ ));
+ DESCR("aggregate final function");
+ DATA(insert OID = 12596 (  int16_stddev_pop PGNSP PGUID 12 1 0 0 0 f f f f f f i 1 0 1700 "2281" _null_ _null_ _null_ _null_	int16_stddev_pop _null_ _null_ _null_ ));
+ DESCR("aggregate final function");
+ DATA(insert OID = 11839 (  int16_stddev_samp	PGNSP PGUID 12 1 0 0 0 f f f f f f i 1 0 1700 "2281" _null_ _null_ _null_ _null_ int16_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
new file mode 100644
index fb1b4a4..02d2c88
*** a/src/include/utils/builtins.h
--- b/src/include/utils/builtins.h
*************** extern Datum numeric_var_pop(PG_FUNCTION
*** 1018,1031 ****
--- 1018,1038 ----
  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 int16_var_pop(PG_FUNCTION_ARGS);
+ extern Datum int16_var_samp(PG_FUNCTION_ARGS);
+ extern Datum int16_stddev_pop(PG_FUNCTION_ARGS);
+ extern Datum int16_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);
+ extern Datum int16_sum(PG_FUNCTION_ARGS);
  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 int16_avg(PG_FUNCTION_ARGS);
  extern Datum int2int4_sum(PG_FUNCTION_ARGS);
  extern Datum width_bucket_numeric(PG_FUNCTION_ARGS);
  extern Datum hash_numeric(PG_FUNCTION_ARGS);
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to