*** a/doc/src/sgml/catalogs.sgml
--- b/doc/src/sgml/catalogs.sgml
***************
*** 373,378 ****
--- 373,384 ----
        <entry>Data type of the aggregate function's internal transition (state) data</entry>
       </row>
       <row>
+       <entry><structfield>aggtransspace</structfield></entry>
+       <entry><type>int4</type></entry>
+       <entry></entry>
+       <entry>Approximation for the average size of the aggregate function's internal transition (state) data</entry>
+      </row>
+      <row>
        <entry><structfield>agginitval</structfield></entry>
        <entry><type>text</type></entry>
        <entry></entry>
*** a/doc/src/sgml/ref/create_aggregate.sgml
--- b/doc/src/sgml/ref/create_aggregate.sgml
***************
*** 24,29 **** PostgreSQL documentation
--- 24,30 ----
  CREATE AGGREGATE <replaceable class="parameter">name</replaceable> ( [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">arg_name</replaceable> ] <replaceable class="parameter">arg_data_type</replaceable> [ , ... ] ) (
      SFUNC = <replaceable class="PARAMETER">sfunc</replaceable>,
      STYPE = <replaceable class="PARAMETER">state_data_type</replaceable>
+     [ , SSPACE = <replaceable class="PARAMETER">state_data_size</replaceable> ]
      [ , FINALFUNC = <replaceable class="PARAMETER">ffunc</replaceable> ]
      [ , INITCOND = <replaceable class="PARAMETER">initial_condition</replaceable> ]
      [ , SORTOP = <replaceable class="PARAMETER">sort_operator</replaceable> ]
***************
*** 35,40 **** CREATE AGGREGATE <replaceable class="PARAMETER">name</replaceable> (
--- 36,42 ----
      BASETYPE = <replaceable class="PARAMETER">base_type</replaceable>,
      SFUNC = <replaceable class="PARAMETER">sfunc</replaceable>,
      STYPE = <replaceable class="PARAMETER">state_data_type</replaceable>
+     [ , SSPACE = <replaceable class="PARAMETER">state_data_size</replaceable> ]
      [ , FINALFUNC = <replaceable class="PARAMETER">ffunc</replaceable> ]
      [ , INITCOND = <replaceable class="PARAMETER">initial_condition</replaceable> ]
      [ , SORTOP = <replaceable class="PARAMETER">sort_operator</replaceable> ]
***************
*** 265,270 **** SELECT col FROM tab ORDER BY col USING sortop LIMIT 1;
--- 267,284 ----
     </varlistentry>
  
     <varlistentry>
+     <term><replaceable class="PARAMETER">state_data_size</replaceable></term>
+     <listitem>
+      <para>
+       Approximate average size (in bytes) of aggregate's state value. 
+       Planner uses this value to approximate the memory required for 
+       the aggregation. If this value is not provided, a default value is 
+       used based on state_data_type.
+      </para>
+     </listitem>
+    </varlistentry>
+ 
+    <varlistentry>
      <term><replaceable class="PARAMETER">ffunc</replaceable></term>
      <listitem>
       <para>
*** a/src/backend/catalog/pg_aggregate.c
--- b/src/backend/catalog/pg_aggregate.c
***************
*** 55,60 **** AggregateCreate(const char *aggName,
--- 55,61 ----
  				List *aggfinalfnName,
  				List *aggsortopName,
  				Oid aggTransType,
+ 				int32 aggTransSpace,
  				const char *agginitval)
  {
  	Relation	aggdesc;
***************
*** 195,200 **** AggregateCreate(const char *aggName,
--- 196,211 ----
  				 errmsg("unsafe use of pseudo-type \"internal\""),
  				 errdetail("A function returning \"internal\" must have at least one \"internal\" argument.")));
  
+ 	/*
+ 	 * Allow non zerro aggTransSpace only for INTERNALOID aggTransType 
+ 	 * Other types has known size.
+ 	 */
+ 	if (aggTransType != INTERNALOID && aggTransSpace > 0)
+ 		ereport(ERROR,
+ 				(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
+ 				 errmsg("SSPACE can be used only for \"internal\" transition type"),
+ 				 errdetail("SSPACE can be defined only together with a \"internal\" transition type.")));
+ 
  	/* handle sortop, if supplied */
  	if (aggsortopName)
  	{
***************
*** 273,278 **** AggregateCreate(const char *aggName,
--- 284,290 ----
  	values[Anum_pg_aggregate_aggfinalfn - 1] = ObjectIdGetDatum(finalfn);
  	values[Anum_pg_aggregate_aggsortop - 1] = ObjectIdGetDatum(sortop);
  	values[Anum_pg_aggregate_aggtranstype - 1] = ObjectIdGetDatum(aggTransType);
+ 	values[Anum_pg_aggregate_aggtransspace - 1] = Int32GetDatum(aggTransSpace);
  	if (agginitval)
  		values[Anum_pg_aggregate_agginitval - 1] = CStringGetTextDatum(agginitval);
  	else
*** a/src/backend/commands/aggregatecmds.c
--- b/src/backend/commands/aggregatecmds.c
***************
*** 68,73 **** DefineAggregate(List *name, List *args, bool oldstyle, List *parameters,
--- 68,74 ----
  	ArrayType  *parameterNames;
  	List	   *parameterDefaults;
  	Oid			transTypeId;
+ 	int32		transSpace = 0;
  	char		transTypeType;
  	ListCell   *pl;
  
***************
*** 102,107 **** DefineAggregate(List *name, List *args, bool oldstyle, List *parameters,
--- 103,110 ----
  			transType = defGetTypeName(defel);
  		else if (pg_strcasecmp(defel->defname, "stype1") == 0)
  			transType = defGetTypeName(defel);
+ 		else if (pg_strcasecmp(defel->defname, "sspace") == 0)
+ 			transSpace = defGetInt32(defel);
  		else if (pg_strcasecmp(defel->defname, "initcond") == 0)
  			initval = defGetString(defel);
  		else if (pg_strcasecmp(defel->defname, "initcond1") == 0)
***************
*** 248,252 **** DefineAggregate(List *name, List *args, bool oldstyle, List *parameters,
--- 251,256 ----
  						   finalfuncName,		/* final function name */
  						   sortoperatorName,	/* sort operator name */
  						   transTypeId, /* transition data type */
+ 						   transSpace,			/* transition space */
  						   initval);	/* initial condition */
  }
*** a/src/backend/commands/define.c
--- b/src/backend/commands/define.c
***************
*** 165,170 **** defGetBoolean(DefElem *def)
--- 165,194 ----
  }
  
  /*
+  * Extract an int32 value from a DefElem.
+  */
+ int32
+ defGetInt32(DefElem *def)
+ {
+ 	if (def->arg == NULL)
+ 		ereport(ERROR,
+ 				(errcode(ERRCODE_SYNTAX_ERROR),
+ 				 errmsg("%s requires an integer value",
+ 						def->defname)));
+ 	switch (nodeTag(def->arg))
+ 	{
+ 		case T_Integer:
+ 			return (int32) intVal(def->arg);
+ 		default:
+ 			ereport(ERROR,
+ 					(errcode(ERRCODE_SYNTAX_ERROR),
+ 					 errmsg("%s requires an integer value",
+ 							def->defname)));
+ 	}
+ 	return 0;					/* keep compiler quiet */
+ }
+ 
+ /*
   * Extract an int64 value from a DefElem.
   */
  int64
*** a/src/backend/optimizer/util/clauses.c
--- b/src/backend/optimizer/util/clauses.c
***************
*** 461,466 **** count_agg_clauses_walker(Node *node, count_agg_clauses_context *context)
--- 461,467 ----
  		Oid			aggtransfn;
  		Oid			aggfinalfn;
  		Oid			aggtranstype;
+ 		int32 		aggtransspace;
  		QualCost	argcosts;
  		Oid		   *inputTypes;
  		int			numArguments;
***************
*** 478,483 **** count_agg_clauses_walker(Node *node, count_agg_clauses_context *context)
--- 479,485 ----
  		aggtransfn = aggform->aggtransfn;
  		aggfinalfn = aggform->aggfinalfn;
  		aggtranstype = aggform->aggtranstype;
+ 		aggtransspace = aggform->aggtransspace;
  		ReleaseSysCache(aggTuple);
  
  		/* count it */
***************
*** 533,545 **** count_agg_clauses_walker(Node *node, count_agg_clauses_context *context)
  			pfree(declaredArgTypes);
  		}
  
  		/*
  		 * If the transition type is pass-by-value then it doesn't add
  		 * anything to the required size of the hashtable.	If it is
  		 * pass-by-reference then we have to add the estimated size of the
  		 * value itself, plus palloc overhead.
  		 */
! 		if (!get_typbyval(aggtranstype))
  		{
  			int32		aggtranstypmod;
  			int32		avgwidth;
--- 535,555 ----
  			pfree(declaredArgTypes);
  		}
  
+ 		/* 
+ 		 * If approximate average space used by aggregate transition value is
+ 		 * specified in pg_aggregate, then use it for transitionSpace.
+ 		 */
+ 		if (aggtransspace > 0)
+ 		{
+ 			costs->transitionSpace += aggtransspace;
+ 		}
  		/*
  		 * If the transition type is pass-by-value then it doesn't add
  		 * anything to the required size of the hashtable.	If it is
  		 * pass-by-reference then we have to add the estimated size of the
  		 * value itself, plus palloc overhead.
  		 */
! 		else if (!get_typbyval(aggtranstype))
  		{
  			int32		aggtranstypmod;
  			int32		avgwidth;
*** a/src/backend/utils/adt/numeric.c
--- b/src/backend/utils/adt/numeric.c
***************
*** 2464,2571 **** numeric_float4(PG_FUNCTION_ARGS)
   *
   * Aggregate functions
   *
!  * The transition datatype for all these aggregates is a 3-element array
!  * of Numeric, holding the values N, sum(X), sum(X*X) in that order.
!  *
!  * We represent N as a numeric mainly to avoid having to build a special
!  * datatype; it's unlikely it'd overflow an int4, but ...
   *
   * ----------------------------------------------------------------------
   */
  
! static ArrayType *
! do_numeric_accum(ArrayType *transarray, Numeric newval)
  {
! 	Datum	   *transdatums;
! 	int			ndatums;
! 	Datum		N,
! 				sumX,
! 				sumX2;
! 	ArrayType  *result;
! 
! 	/* We assume the input is array of numeric */
! 	deconstruct_array(transarray,
! 					  NUMERICOID, -1, false, 'i',
! 					  &transdatums, NULL, &ndatums);
! 	if (ndatums != 3)
! 		elog(ERROR, "expected 3-element numeric array");
! 	N = transdatums[0];
! 	sumX = transdatums[1];
! 	sumX2 = transdatums[2];
! 
! 	N = DirectFunctionCall1(numeric_inc, N);
! 	sumX = DirectFunctionCall2(numeric_add, sumX,
! 							   NumericGetDatum(newval));
! 	sumX2 = DirectFunctionCall2(numeric_add, sumX2,
! 								DirectFunctionCall2(numeric_mul,
! 													NumericGetDatum(newval),
! 													NumericGetDatum(newval)));
! 
! 	transdatums[0] = N;
! 	transdatums[1] = sumX;
! 	transdatums[2] = sumX2;
! 
! 	result = construct_array(transdatums, 3,
! 							 NUMERICOID, -1, false, 'i');
  
! 	return result;
  }
  
  /*
!  * Improve avg performance by not caclulating sum(X*X).
   */
! static ArrayType *
! do_numeric_avg_accum(ArrayType *transarray, Numeric newval)
  {
! 	Datum	   *transdatums;
! 	int			ndatums;
! 	Datum		N,
! 				sumX;
! 	ArrayType  *result;
! 
! 	/* We assume the input is array of numeric */
! 	deconstruct_array(transarray,
! 					  NUMERICOID, -1, false, 'i',
! 					  &transdatums, NULL, &ndatums);
! 	if (ndatums != 2)
! 		elog(ERROR, "expected 2-element numeric array");
! 	N = transdatums[0];
! 	sumX = transdatums[1];
! 
! 	N = DirectFunctionCall1(numeric_inc, N);
! 	sumX = DirectFunctionCall2(numeric_add, sumX,
! 							   NumericGetDatum(newval));
! 
! 	transdatums[0] = N;
! 	transdatums[1] = sumX;
! 
! 	result = construct_array(transdatums, 2,
! 							 NUMERICOID, -1, false, 'i');
  
! 	return result;
  }
  
  Datum
  numeric_accum(PG_FUNCTION_ARGS)
  {
! 	ArrayType  *transarray = PG_GETARG_ARRAYTYPE_P(0);
! 	Numeric		newval = PG_GETARG_NUMERIC(1);
  
! 	PG_RETURN_ARRAYTYPE_P(do_numeric_accum(transarray, newval));
  }
  
  /*
!  * Optimized case for average of numeric.
   */
  Datum
  numeric_avg_accum(PG_FUNCTION_ARGS)
  {
! 	ArrayType  *transarray = PG_GETARG_ARRAYTYPE_P(0);
! 	Numeric		newval = PG_GETARG_NUMERIC(1);
  
! 	PG_RETURN_ARRAYTYPE_P(do_numeric_avg_accum(transarray, newval));
  }
  
  /*
   * Integer data types all use Numeric accumulators to share code and
   * avoid risk of overflow.	For int2 and int4 inputs, Numeric accumulation
--- 2464,2632 ----
   *
   * Aggregate functions
   *
!  * The transition datatype for all these aggregates is a pointer to 
!  * a struct NumericAggState allocated in the aggregate context.
   *
   * ----------------------------------------------------------------------
   */
  
! typedef struct NumericAggState
  {
! 	bool 			isNaN;			/* true, when some processed number is NaN */
! 	uint64			N;			/* count of processed numbers */
! 	NumericVar 		sumX;			/* sum of processed numbers */
! 	NumericVar 		sumX2;			/* sum of square of processed numbers */
! 	bool 			calcSumX2;		/* when is true, then sumX2 is calculated */
! 	MemoryContext 	agg_context;
! } NumericAggState;
  
! 
! /*
!  * Prepare state data for Numeric aggregate function that needs to know a sum, count
!  * and sometimes sum of square (when calcSumX2 is true).
!  */
! 
! static NumericAggState *
! makeNumericAggState(FunctionCallInfo fcinfo, bool calcSumX2)
! {
! 	NumericAggState 	*state;
! 	MemoryContext 		 agg_context;
! 	MemoryContext 		 old_context;
! 
! 	if (!AggCheckCallContext(fcinfo, &agg_context))
! 		elog(ERROR, "a numeric aggregate function called in non-aggregate context");
! 
! 	old_context = MemoryContextSwitchTo(agg_context);
! 
! 	state = palloc0(sizeof(NumericAggState));
! 	state->calcSumX2 = calcSumX2;
! 	state->agg_context = agg_context;
! 
! 	MemoryContextSwitchTo(old_context);
! 
! 	return state;
  }
  
+ 
  /*
!  * a workhorse for numeric accum functions. A different behave (controlled by calcSumX2)
!  * is specified when NumericAggState is initiated. This accum function is used for numeric
!  * sum too due minimize overhead related to packing and unpacking Numeric value.
!  *
   */
! 
! static void
! do_numeric_accum(NumericAggState *state, Numeric newval)
  {
! 	NumericVar 		X;
! 	NumericVar 		X2;
! 	MemoryContext 	old_context;
  
! 	/* result is NaN, when some processed number is NaN */
! 	if (state->isNaN || NUMERIC_IS_NAN(newval))
! 	{
! 		state->isNaN = true;
! 		return;
! 	}
! 
! 	/* load processed number */
! 	init_var_from_num(newval, &X);
! 
! 	if (state->calcSumX2)
! 	{
! 		init_var(&X2);
! 		mul_var(&X, &X, &X2, X.dscale * 2);
! 	}
! 
! 	old_context = MemoryContextSwitchTo(state->agg_context);
! 
! 	if (state->N++ > 0)
! 	{
! 		NumericVar preSumX;
! 
! 		/* increase counters */
! 		memcpy(&preSumX, &(state->sumX), sizeof(NumericVar));
! 		init_var(&(state->sumX));
! 		add_var(&X, &preSumX, &(state->sumX));
! 		free_var(&preSumX);
! 
! 		if (state->calcSumX2)
! 		{
! 			NumericVar preSumX2;
! 
! 			memcpy(&preSumX2, &(state->sumX2), sizeof(NumericVar));
! 			init_var(&(state->sumX2));
! 			add_var(&X2, &preSumX2, &(state->sumX2));
! 			free_var(&preSumX2);
! 		}
! 	}
! 	else
! 	{
! 		/* initialize counters */
! 		set_var_from_var(&X, &(state->sumX));
! 
! 		if (state->calcSumX2)
! 			set_var_from_var(&X2, &(state->sumX2));
! 	}
! 
! 	MemoryContextSwitchTo(old_context);
  }
  
+ /*
+  * Generic accum function for Numeric aggregates. It initialize NumericAggState
+  * with calcSumX2 is true - it ensure a sumX2 calcualtion.
+  */
+ 
  Datum
  numeric_accum(PG_FUNCTION_ARGS)
  {
! 	NumericAggState *state;
! 
! 	state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
  
! 	if (!PG_ARGISNULL(1))
! 	{
! 		/* On the first time through, create the state variable. */
! 		if (state == NULL)
! 			state = makeNumericAggState(fcinfo, true);
! 		
! 		do_numeric_accum(state, PG_GETARG_NUMERIC(1));
! 	}
! 
! 	if (state == NULL)
! 		PG_RETURN_NULL();
! 	else
! 		PG_RETURN_POINTER(state);
  }
  
+ 
  /*
!  * Optimized accum function for average and sum aggregate function. Doesn't calculate sumX2.
   */
+ 
  Datum
  numeric_avg_accum(PG_FUNCTION_ARGS)
  {
! 	NumericAggState *state;
  
! 	state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
! 
! 	if (!PG_ARGISNULL(1))
! 	{
! 		/* On the first time through, create the state variable. */
! 		if (state == NULL)
! 			state = makeNumericAggState(fcinfo, false);
! 		
! 		do_numeric_accum(state, PG_GETARG_NUMERIC(1));
! 	}
! 
! 	if (state == NULL)
! 		PG_RETURN_NULL();
! 	else
! 		PG_RETURN_POINTER(state);
  }
  
+ 
  /*
   * Integer data types all use Numeric accumulators to share code and
   * avoid risk of overflow.	For int2 and int4 inputs, Numeric accumulation
***************
*** 2578,2664 **** numeric_avg_accum(PG_FUNCTION_ARGS)
  Datum
  int2_accum(PG_FUNCTION_ARGS)
  {
! 	ArrayType  *transarray = PG_GETARG_ARRAYTYPE_P(0);
! 	Datum		newval2 = PG_GETARG_DATUM(1);
! 	Numeric		newval;
  
! 	newval = DatumGetNumeric(DirectFunctionCall1(int2_numeric, newval2));
  
! 	PG_RETURN_ARRAYTYPE_P(do_numeric_accum(transarray, newval));
  }
  
  Datum
  int4_accum(PG_FUNCTION_ARGS)
  {
! 	ArrayType  *transarray = PG_GETARG_ARRAYTYPE_P(0);
! 	Datum		newval4 = PG_GETARG_DATUM(1);
! 	Numeric		newval;
  
! 	newval = DatumGetNumeric(DirectFunctionCall1(int4_numeric, newval4));
  
! 	PG_RETURN_ARRAYTYPE_P(do_numeric_accum(transarray, newval));
  }
  
  Datum
  int8_accum(PG_FUNCTION_ARGS)
  {
! 	ArrayType  *transarray = PG_GETARG_ARRAYTYPE_P(0);
! 	Datum		newval8 = PG_GETARG_DATUM(1);
! 	Numeric		newval;
  
! 	newval = DatumGetNumeric(DirectFunctionCall1(int8_numeric, newval8));
  
! 	PG_RETURN_ARRAYTYPE_P(do_numeric_accum(transarray, newval));
  }
  
  /*
   * Optimized case for average of int8.
   */
  Datum
  int8_avg_accum(PG_FUNCTION_ARGS)
  {
! 	ArrayType  *transarray = PG_GETARG_ARRAYTYPE_P(0);
! 	Datum		newval8 = PG_GETARG_DATUM(1);
! 	Numeric		newval;
! 
! 	newval = DatumGetNumeric(DirectFunctionCall1(int8_numeric, newval8));
  
! 	PG_RETURN_ARRAYTYPE_P(do_numeric_avg_accum(transarray, newval));
  }
  
  
  Datum
  numeric_avg(PG_FUNCTION_ARGS)
  {
! 	ArrayType  *transarray = PG_GETARG_ARRAYTYPE_P(0);
! 	Datum	   *transdatums;
! 	int			ndatums;
! 	Numeric		N,
! 				sumX;
! 
! 	/* We assume the input is array of numeric */
! 	deconstruct_array(transarray,
! 					  NUMERICOID, -1, false, 'i',
! 					  &transdatums, NULL, &ndatums);
! 	if (ndatums != 2)
! 		elog(ERROR, "expected 2-element numeric array");
! 	N = DatumGetNumeric(transdatums[0]);
! 	sumX = DatumGetNumeric(transdatums[1]);
  
! 	/* SQL defines AVG of no values to be NULL */
! 	/* N is zero iff no digits (cf. numeric_uminus) */
! 	if (NUMERIC_NDIGITS(N) == 0)
  		PG_RETURN_NULL();
  
! 	PG_RETURN_DATUM(DirectFunctionCall2(numeric_div,
! 										NumericGetDatum(sumX),
! 										NumericGetDatum(N)));
  }
  
  /*
   * Workhorse routine for the standard deviance and variance
!  * aggregates. 'transarray' is the aggregate's transition
!  * array. 'variance' specifies whether we should calculate the
   * variance or the standard deviation. 'sample' indicates whether the
   * caller is interested in the sample or the population
   * variance/stddev.
--- 2639,2788 ----
  Datum
  int2_accum(PG_FUNCTION_ARGS)
  {
! 	NumericAggState *state;
! 
! 	state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
  
! 	if (!PG_ARGISNULL(1))
! 	{
! 		Datum		newval2 = PG_GETARG_DATUM(1);
! 		Numeric		newval;
! 
! 		/* On the first time through, create the state variable. */
! 		if (state == NULL)
! 			state = makeNumericAggState(fcinfo, true);
! 		
! 		newval = DatumGetNumeric(DirectFunctionCall1(int2_numeric, newval2));
! 		do_numeric_accum(state, newval);
! 	}
  
! 	if (state == NULL)
! 		PG_RETURN_NULL();
! 	else
! 		PG_RETURN_POINTER(state);
  }
  
+ 
  Datum
  int4_accum(PG_FUNCTION_ARGS)
  {
! 	NumericAggState *state;
  
! 	state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
  
! 	if (!PG_ARGISNULL(1))
! 	{
! 		Datum		newval4 = PG_GETARG_DATUM(1);
! 		Numeric		newval;
! 
! 		/* On the first time through, create the state variable. */
! 		if (state == NULL)
! 			state = makeNumericAggState(fcinfo, true);
! 		
! 		newval = DatumGetNumeric(DirectFunctionCall1(int4_numeric, newval4));
! 		do_numeric_accum(state, newval);
! 	}
! 
! 	if (state == NULL)
! 		PG_RETURN_NULL();
! 	else
! 		PG_RETURN_POINTER(state);
  }
  
+ 
  Datum
  int8_accum(PG_FUNCTION_ARGS)
  {
! 	NumericAggState *state;
  
! 	state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
  
! 	if (!PG_ARGISNULL(1))
! 	{
! 		Datum		newval8 = PG_GETARG_DATUM(1);
! 		Numeric		newval;
! 
! 		/* On the first time through, create the state variable. */
! 		if (state == NULL)
! 			state = makeNumericAggState(fcinfo, true);
! 		
! 		newval = DatumGetNumeric(DirectFunctionCall1(int8_numeric, newval8));
! 		do_numeric_accum(state, newval);
! 	}
! 
! 	if (state == NULL)
! 		PG_RETURN_NULL();
! 	else
! 		PG_RETURN_POINTER(state);
  }
  
+ 
  /*
   * Optimized case for average of int8.
   */
  Datum
  int8_avg_accum(PG_FUNCTION_ARGS)
  {
! 	NumericAggState *state;	
! 	state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
  
! 	if (!PG_ARGISNULL(1))
! 	{
! 		Datum		newval8 = PG_GETARG_DATUM(1);
! 		Numeric		newval;
! 
! 		/* On the first time through, create the state variable. */
! 		if (state == NULL)
! 			state = makeNumericAggState(fcinfo, false);
! 		
! 		newval = DatumGetNumeric(DirectFunctionCall1(int8_numeric, newval8));
! 		do_numeric_accum(state, newval);
! 	}
!  
! 	if (state == NULL)
! 		PG_RETURN_NULL();
! 	else
! 		PG_RETURN_POINTER(state);
  }
  
  
  Datum
  numeric_avg(PG_FUNCTION_ARGS)
  {
! 	Datum 		 		N_datum;
! 	Datum 				sumX_datum;
! 	NumericAggState 	*state;
  
! 	if (PG_ARGISNULL(0))
! 		PG_RETURN_NULL();
! 
! 	state = (NumericAggState *) PG_GETARG_POINTER(0);
! 
! 	N_datum = DirectFunctionCall1(int8_numeric, Int64GetDatum(state->N));
! 	sumX_datum = NumericGetDatum(make_result(&state->sumX));
! 
! 	PG_RETURN_DATUM(DirectFunctionCall2(numeric_div, sumX_datum, N_datum));
! }
! 
! 
! Datum
! numeric_sum(PG_FUNCTION_ARGS)
! {
! 	NumericAggState 	*state;
! 
! 	if (PG_ARGISNULL(0))
  		PG_RETURN_NULL();
+  
+ 	state = (NumericAggState *) PG_GETARG_POINTER(0);
  
! 	PG_RETURN_NUMERIC(make_result(&(state->sumX)));
  }
  
+ 
  /*
   * Workhorse routine for the standard deviance and variance
!  * aggregates. 'state' is aggregate's transition state.
!  * 'variance' specifies whether we should calculate the
   * variance or the standard deviation. 'sample' indicates whether the
   * caller is interested in the sample or the population
   * variance/stddev.
***************
*** 2667,2682 **** numeric_avg(PG_FUNCTION_ARGS)
   * *is_null is set to true and NULL is returned.
   */
  static Numeric
! numeric_stddev_internal(ArrayType *transarray,
  						bool variance, bool sample,
  						bool *is_null)
  {
! 	Datum	   *transdatums;
! 	int			ndatums;
! 	Numeric		N,
! 				sumX,
! 				sumX2,
! 				res;
  	NumericVar	vN,
  				vsumX,
  				vsumX2,
--- 2791,2801 ----
   * *is_null is set to true and NULL is returned.
   */
  static Numeric
! numeric_stddev_internal(NumericAggState *state,
  						bool variance, bool sample,
  						bool *is_null)
  {
! 	Numeric		res;
  	NumericVar	vN,
  				vsumX,
  				vsumX2,
***************
*** 2684,2705 **** numeric_stddev_internal(ArrayType *transarray,
  	NumericVar *comp;
  	int			rscale;
  
  	*is_null = false;
  
! 	/* We assume the input is array of numeric */
! 	deconstruct_array(transarray,
! 					  NUMERICOID, -1, false, 'i',
! 					  &transdatums, NULL, &ndatums);
! 	if (ndatums != 3)
! 		elog(ERROR, "expected 3-element numeric array");
! 	N = DatumGetNumeric(transdatums[0]);
! 	sumX = DatumGetNumeric(transdatums[1]);
! 	sumX2 = DatumGetNumeric(transdatums[2]);
! 
! 	if (NUMERIC_IS_NAN(N) || NUMERIC_IS_NAN(sumX) || NUMERIC_IS_NAN(sumX2))
  		return make_result(&const_nan);
  
! 	init_var_from_num(N, &vN);
  
  	/*
  	 * Sample stddev and variance are undefined when N <= 1; population stddev
--- 2803,2826 ----
  	NumericVar *comp;
  	int			rscale;
  
+ 	if (state == NULL)
+ 	{
+ 		*is_null = true;
+ 		return NULL;
+ 	}
+ 
  	*is_null = false;
  
! 	if (state->isNaN)
  		return make_result(&const_nan);
  
! 	init_var(&vN);
! 	init_var(&vsumX);
! 	init_var(&vsumX2);
! 
! 	int8_to_numericvar(state->N, &vN);
! 	set_var_from_var(&(state->sumX), &vsumX);
! 	set_var_from_var(&(state->sumX2), &vsumX2);
  
  	/*
  	 * Sample stddev and variance are undefined when N <= 1; population stddev
***************
*** 2719,2726 **** numeric_stddev_internal(ArrayType *transarray,
  	init_var(&vNminus1);
  	sub_var(&vN, &const_one, &vNminus1);
  
! 	init_var_from_num(sumX, &vsumX);
! 	init_var_from_num(sumX2, &vsumX2);
  
  	/* compute rscale for mul_var calls */
  	rscale = vsumX.dscale * 2;
--- 2840,2847 ----
  	init_var(&vNminus1);
  	sub_var(&vN, &const_one, &vNminus1);
  
! 	set_var_from_var(&(state->sumX), &vsumX);
! 	set_var_from_var(&(state->sumX2), &vsumX2);
  
  	/* compute rscale for mul_var calls */
  	rscale = vsumX.dscale * 2;
***************
*** 2761,2767 **** numeric_var_samp(PG_FUNCTION_ARGS)
  	Numeric		res;
  	bool		is_null;
  
! 	res = numeric_stddev_internal(PG_GETARG_ARRAYTYPE_P(0),
  								  true, true, &is_null);
  
  	if (is_null)
--- 2882,2888 ----
  	Numeric		res;
  	bool		is_null;
  
! 	res = numeric_stddev_internal((NumericAggState *) PG_GETARG_POINTER(0),
  								  true, true, &is_null);
  
  	if (is_null)
***************
*** 2776,2782 **** numeric_stddev_samp(PG_FUNCTION_ARGS)
  	Numeric		res;
  	bool		is_null;
  
! 	res = numeric_stddev_internal(PG_GETARG_ARRAYTYPE_P(0),
  								  false, true, &is_null);
  
  	if (is_null)
--- 2897,2903 ----
  	Numeric		res;
  	bool		is_null;
  
! 	res = numeric_stddev_internal((NumericAggState *) PG_GETARG_POINTER(0),
  								  false, true, &is_null);
  
  	if (is_null)
***************
*** 2791,2797 **** numeric_var_pop(PG_FUNCTION_ARGS)
  	Numeric		res;
  	bool		is_null;
  
! 	res = numeric_stddev_internal(PG_GETARG_ARRAYTYPE_P(0),
  								  true, false, &is_null);
  
  	if (is_null)
--- 2912,2918 ----
  	Numeric		res;
  	bool		is_null;
  
! 	res = numeric_stddev_internal((NumericAggState *) PG_GETARG_POINTER(0),
  								  true, false, &is_null);
  
  	if (is_null)
***************
*** 2806,2812 **** numeric_stddev_pop(PG_FUNCTION_ARGS)
  	Numeric		res;
  	bool		is_null;
  
! 	res = numeric_stddev_internal(PG_GETARG_ARRAYTYPE_P(0),
  								  false, false, &is_null);
  
  	if (is_null)
--- 2927,2933 ----
  	Numeric		res;
  	bool		is_null;
  
! 	res = numeric_stddev_internal((NumericAggState *) PG_GETARG_POINTER(0),
  								  false, false, &is_null);
  
  	if (is_null)
*** a/src/bin/pg_dump/pg_dump.c
--- b/src/bin/pg_dump/pg_dump.c
***************
*** 11419,11430 **** dumpAgg(Archive *fout, AggInfo *agginfo)
--- 11419,11432 ----
  	int			i_aggfinalfn;
  	int			i_aggsortop;
  	int			i_aggtranstype;
+ 	int			i_aggtransspace;
  	int			i_agginitval;
  	int			i_convertok;
  	const char *aggtransfn;
  	const char *aggfinalfn;
  	const char *aggsortop;
  	const char *aggtranstype;
+ 	const char *aggtransspace;
  	const char *agginitval;
  	bool		convertok;
  
***************
*** 11442,11453 **** dumpAgg(Archive *fout, AggInfo *agginfo)
  	selectSourceSchema(fout, agginfo->aggfn.dobj.namespace->dobj.name);
  
  	/* Get aggregate-specific details */
! 	if (fout->remoteVersion >= 80400)
  	{
  		appendPQExpBuffer(query, "SELECT aggtransfn, "
  						  "aggfinalfn, aggtranstype::pg_catalog.regtype, "
  						  "aggsortop::pg_catalog.regoperator, "
! 						  "agginitval, "
  						  "'t'::boolean AS convertok, "
  						  "pg_catalog.pg_get_function_arguments(p.oid) AS funcargs, "
  						  "pg_catalog.pg_get_function_identity_arguments(p.oid) AS funciargs "
--- 11444,11469 ----
  	selectSourceSchema(fout, agginfo->aggfn.dobj.namespace->dobj.name);
  
  	/* Get aggregate-specific details */
! 	if (fout->remoteVersion >= 90300)
! 	{
! 		appendPQExpBuffer(query, "SELECT aggtransfn, "
! 						  "aggfinalfn, aggtranstype::pg_catalog.regtype, "
! 						  "aggsortop::pg_catalog.regoperator, "
! 						  "aggtransspace, agginitval, "
! 						  "'t'::boolean AS convertok, "
! 						  "pg_catalog.pg_get_function_arguments(p.oid) AS funcargs, "
! 						  "pg_catalog.pg_get_function_identity_arguments(p.oid) AS funciargs "
! 					  "FROM pg_catalog.pg_aggregate a, pg_catalog.pg_proc p "
! 						  "WHERE a.aggfnoid = p.oid "
! 						  "AND p.oid = '%u'::pg_catalog.oid",
! 						  agginfo->aggfn.dobj.catId.oid);
! 	}
! 	else if (fout->remoteVersion >= 80400)
  	{
  		appendPQExpBuffer(query, "SELECT aggtransfn, "
  						  "aggfinalfn, aggtranstype::pg_catalog.regtype, "
  						  "aggsortop::pg_catalog.regoperator, "
! 						  "0 AS aggtransspace, agginitval, "
  						  "'t'::boolean AS convertok, "
  						  "pg_catalog.pg_get_function_arguments(p.oid) AS funcargs, "
  						  "pg_catalog.pg_get_function_identity_arguments(p.oid) AS funciargs "
***************
*** 11461,11467 **** dumpAgg(Archive *fout, AggInfo *agginfo)
  		appendPQExpBuffer(query, "SELECT aggtransfn, "
  						  "aggfinalfn, aggtranstype::pg_catalog.regtype, "
  						  "aggsortop::pg_catalog.regoperator, "
! 						  "agginitval, "
  						  "'t'::boolean AS convertok "
  						  "FROM pg_catalog.pg_aggregate a, pg_catalog.pg_proc p "
  						  "WHERE a.aggfnoid = p.oid "
--- 11477,11483 ----
  		appendPQExpBuffer(query, "SELECT aggtransfn, "
  						  "aggfinalfn, aggtranstype::pg_catalog.regtype, "
  						  "aggsortop::pg_catalog.regoperator, "
! 						  "0 AS aggtransspace, agginitval, "
  						  "'t'::boolean AS convertok "
  						  "FROM pg_catalog.pg_aggregate a, pg_catalog.pg_proc p "
  						  "WHERE a.aggfnoid = p.oid "
***************
*** 11473,11479 **** dumpAgg(Archive *fout, AggInfo *agginfo)
  		appendPQExpBuffer(query, "SELECT aggtransfn, "
  						  "aggfinalfn, aggtranstype::pg_catalog.regtype, "
  						  "0 AS aggsortop, "
! 						  "agginitval, "
  						  "'t'::boolean AS convertok "
  					  "FROM pg_catalog.pg_aggregate a, pg_catalog.pg_proc p "
  						  "WHERE a.aggfnoid = p.oid "
--- 11489,11495 ----
  		appendPQExpBuffer(query, "SELECT aggtransfn, "
  						  "aggfinalfn, aggtranstype::pg_catalog.regtype, "
  						  "0 AS aggsortop, "
! 						  "0 AS aggtransspace, agginitval, "
  						  "'t'::boolean AS convertok "
  					  "FROM pg_catalog.pg_aggregate a, pg_catalog.pg_proc p "
  						  "WHERE a.aggfnoid = p.oid "
***************
*** 11485,11491 **** dumpAgg(Archive *fout, AggInfo *agginfo)
  		appendPQExpBuffer(query, "SELECT aggtransfn, aggfinalfn, "
  						  "format_type(aggtranstype, NULL) AS aggtranstype, "
  						  "0 AS aggsortop, "
! 						  "agginitval, "
  						  "'t'::boolean AS convertok "
  						  "FROM pg_aggregate "
  						  "WHERE oid = '%u'::oid",
--- 11501,11507 ----
  		appendPQExpBuffer(query, "SELECT aggtransfn, aggfinalfn, "
  						  "format_type(aggtranstype, NULL) AS aggtranstype, "
  						  "0 AS aggsortop, "
! 						  "0 AS aggtransspace, agginitval, "
  						  "'t'::boolean AS convertok "
  						  "FROM pg_aggregate "
  						  "WHERE oid = '%u'::oid",
***************
*** 11497,11503 **** dumpAgg(Archive *fout, AggInfo *agginfo)
  						  "aggfinalfn, "
  						  "(SELECT typname FROM pg_type WHERE oid = aggtranstype1) AS aggtranstype, "
  						  "0 AS aggsortop, "
! 						  "agginitval1 AS agginitval, "
  						  "(aggtransfn2 = 0 and aggtranstype2 = 0 and agginitval2 is null) AS convertok "
  						  "FROM pg_aggregate "
  						  "WHERE oid = '%u'::oid",
--- 11513,11519 ----
  						  "aggfinalfn, "
  						  "(SELECT typname FROM pg_type WHERE oid = aggtranstype1) AS aggtranstype, "
  						  "0 AS aggsortop, "
! 						  "0 AS aggtransspace, agginitval1 AS agginitval, "
  						  "(aggtransfn2 = 0 and aggtranstype2 = 0 and agginitval2 is null) AS convertok "
  						  "FROM pg_aggregate "
  						  "WHERE oid = '%u'::oid",
***************
*** 11510,11515 **** dumpAgg(Archive *fout, AggInfo *agginfo)
--- 11526,11532 ----
  	i_aggfinalfn = PQfnumber(res, "aggfinalfn");
  	i_aggsortop = PQfnumber(res, "aggsortop");
  	i_aggtranstype = PQfnumber(res, "aggtranstype");
+ 	i_aggtransspace = PQfnumber(res, "aggtransspace");
  	i_agginitval = PQfnumber(res, "agginitval");
  	i_convertok = PQfnumber(res, "convertok");
  
***************
*** 11517,11522 **** dumpAgg(Archive *fout, AggInfo *agginfo)
--- 11534,11540 ----
  	aggfinalfn = PQgetvalue(res, 0, i_aggfinalfn);
  	aggsortop = PQgetvalue(res, 0, i_aggsortop);
  	aggtranstype = PQgetvalue(res, 0, i_aggtranstype);
+ 	aggtransspace = PQgetvalue(res, 0, i_aggtransspace);
  	agginitval = PQgetvalue(res, 0, i_agginitval);
  	convertok = (PQgetvalue(res, 0, i_convertok)[0] == 't');
  
***************
*** 11570,11575 **** dumpAgg(Archive *fout, AggInfo *agginfo)
--- 11588,11599 ----
  						  fmtId(aggtranstype));
  	}
  
+ 	if (strcmp(aggfinalfn, "0") != 0)
+ 	{
+ 		appendPQExpBuffer(details, ",\n    SSPACE = %s",
+ 						  aggtransspace);
+ 	}
+ 
  	if (!PQgetisnull(res, 0, i_agginitval))
  	{
  		appendPQExpBuffer(details, ",\n    INITCOND = ");
*** a/src/include/catalog/pg_aggregate.h
--- b/src/include/catalog/pg_aggregate.h
***************
*** 44,49 **** CATALOG(pg_aggregate,2600) BKI_WITHOUT_OIDS
--- 44,50 ----
  	regproc		aggfinalfn;
  	Oid			aggsortop;
  	Oid			aggtranstype;
+ 	int32		aggtransspace;
  
  #ifdef CATALOG_VARLEN			/* variable-length fields start here */
  	text		agginitval;
***************
*** 62,74 **** typedef FormData_pg_aggregate *Form_pg_aggregate;
   * ----------------
   */
  
! #define Natts_pg_aggregate				6
  #define Anum_pg_aggregate_aggfnoid		1
  #define Anum_pg_aggregate_aggtransfn	2
  #define Anum_pg_aggregate_aggfinalfn	3
  #define Anum_pg_aggregate_aggsortop		4
  #define Anum_pg_aggregate_aggtranstype	5
! #define Anum_pg_aggregate_agginitval	6
  
  
  /* ----------------
--- 63,76 ----
   * ----------------
   */
  
! #define Natts_pg_aggregate				7
  #define Anum_pg_aggregate_aggfnoid		1
  #define Anum_pg_aggregate_aggtransfn	2
  #define Anum_pg_aggregate_aggfinalfn	3
  #define Anum_pg_aggregate_aggsortop		4
  #define Anum_pg_aggregate_aggtranstype	5
! #define Anum_pg_aggregate_aggtransspace	6
! #define Anum_pg_aggregate_agginitval	7
  
  
  /* ----------------
***************
*** 77,239 **** typedef FormData_pg_aggregate *Form_pg_aggregate;
   */
  
  /* avg */
! DATA(insert ( 2100	int8_avg_accum	numeric_avg		0	1231	"{0,0}" ));
! DATA(insert ( 2101	int4_avg_accum	int8_avg		0	1016	"{0,0}" ));
! DATA(insert ( 2102	int2_avg_accum	int8_avg		0	1016	"{0,0}" ));
! DATA(insert ( 2103	numeric_avg_accum	numeric_avg		0	1231	"{0,0}" ));
! DATA(insert ( 2104	float4_accum	float8_avg		0	1022	"{0,0,0}" ));
! DATA(insert ( 2105	float8_accum	float8_avg		0	1022	"{0,0,0}" ));
! DATA(insert ( 2106	interval_accum	interval_avg	0	1187	"{0 second,0 second}" ));
  
  /* sum */
! DATA(insert ( 2107	int8_sum		-				0	1700	_null_ ));
! DATA(insert ( 2108	int4_sum		-				0	20		_null_ ));
! DATA(insert ( 2109	int2_sum		-				0	20		_null_ ));
! DATA(insert ( 2110	float4pl		-				0	700		_null_ ));
! DATA(insert ( 2111	float8pl		-				0	701		_null_ ));
! DATA(insert ( 2112	cash_pl			-				0	790		_null_ ));
! DATA(insert ( 2113	interval_pl		-				0	1186	_null_ ));
! DATA(insert ( 2114	numeric_add		-				0	1700	_null_ ));
  
  /* max */
! DATA(insert ( 2115	int8larger		-				413		20		_null_ ));
! DATA(insert ( 2116	int4larger		-				521		23		_null_ ));
! DATA(insert ( 2117	int2larger		-				520		21		_null_ ));
! DATA(insert ( 2118	oidlarger		-				610		26		_null_ ));
! DATA(insert ( 2119	float4larger	-				623		700		_null_ ));
! DATA(insert ( 2120	float8larger	-				674		701		_null_ ));
! DATA(insert ( 2121	int4larger		-				563		702		_null_ ));
! DATA(insert ( 2122	date_larger		-				1097	1082	_null_ ));
! DATA(insert ( 2123	time_larger		-				1112	1083	_null_ ));
! DATA(insert ( 2124	timetz_larger	-				1554	1266	_null_ ));
! DATA(insert ( 2125	cashlarger		-				903		790		_null_ ));
! DATA(insert ( 2126	timestamp_larger	-			2064	1114	_null_ ));
! DATA(insert ( 2127	timestamptz_larger	-			1324	1184	_null_ ));
! DATA(insert ( 2128	interval_larger -				1334	1186	_null_ ));
! DATA(insert ( 2129	text_larger		-				666		25		_null_ ));
! DATA(insert ( 2130	numeric_larger	-				1756	1700	_null_ ));
! DATA(insert ( 2050	array_larger	-				1073	2277	_null_ ));
! DATA(insert ( 2244	bpchar_larger	-				1060	1042	_null_ ));
! DATA(insert ( 2797	tidlarger		-				2800	27		_null_ ));
! DATA(insert ( 3526	enum_larger		-				3519	3500	_null_ ));
  
  /* min */
! DATA(insert ( 2131	int8smaller		-				412		20		_null_ ));
! DATA(insert ( 2132	int4smaller		-				97		23		_null_ ));
! DATA(insert ( 2133	int2smaller		-				95		21		_null_ ));
! DATA(insert ( 2134	oidsmaller		-				609		26		_null_ ));
! DATA(insert ( 2135	float4smaller	-				622		700		_null_ ));
! DATA(insert ( 2136	float8smaller	-				672		701		_null_ ));
! DATA(insert ( 2137	int4smaller		-				562		702		_null_ ));
! DATA(insert ( 2138	date_smaller	-				1095	1082	_null_ ));
! DATA(insert ( 2139	time_smaller	-				1110	1083	_null_ ));
! DATA(insert ( 2140	timetz_smaller	-				1552	1266	_null_ ));
! DATA(insert ( 2141	cashsmaller		-				902		790		_null_ ));
! DATA(insert ( 2142	timestamp_smaller	-			2062	1114	_null_ ));
! DATA(insert ( 2143	timestamptz_smaller -			1322	1184	_null_ ));
! DATA(insert ( 2144	interval_smaller	-			1332	1186	_null_ ));
! DATA(insert ( 2145	text_smaller	-				664		25		_null_ ));
! DATA(insert ( 2146	numeric_smaller -				1754	1700	_null_ ));
! DATA(insert ( 2051	array_smaller	-				1072	2277	_null_ ));
! DATA(insert ( 2245	bpchar_smaller	-				1058	1042	_null_ ));
! DATA(insert ( 2798	tidsmaller		-				2799	27		_null_ ));
! DATA(insert ( 3527	enum_smaller	-				3518	3500	_null_ ));
  
  /* count */
! DATA(insert ( 2147	int8inc_any		-				0		20		"0" ));
! DATA(insert ( 2803	int8inc			-				0		20		"0" ));
  
  /* var_pop */
! DATA(insert ( 2718	int8_accum	numeric_var_pop 0	1231	"{0,0,0}" ));
! DATA(insert ( 2719	int4_accum	numeric_var_pop 0	1231	"{0,0,0}" ));
! DATA(insert ( 2720	int2_accum	numeric_var_pop 0	1231	"{0,0,0}" ));
! DATA(insert ( 2721	float4_accum	float8_var_pop 0	1022	"{0,0,0}" ));
! DATA(insert ( 2722	float8_accum	float8_var_pop 0	1022	"{0,0,0}" ));
! DATA(insert ( 2723	numeric_accum  numeric_var_pop 0	1231	"{0,0,0}" ));
  
  /* var_samp */
! DATA(insert ( 2641	int8_accum	numeric_var_samp	0	1231	"{0,0,0}" ));
! DATA(insert ( 2642	int4_accum	numeric_var_samp	0	1231	"{0,0,0}" ));
! DATA(insert ( 2643	int2_accum	numeric_var_samp	0	1231	"{0,0,0}" ));
! DATA(insert ( 2644	float4_accum	float8_var_samp 0	1022	"{0,0,0}" ));
! DATA(insert ( 2645	float8_accum	float8_var_samp 0	1022	"{0,0,0}" ));
! DATA(insert ( 2646	numeric_accum  numeric_var_samp 0	1231	"{0,0,0}" ));
  
  /* variance: historical Postgres syntax for var_samp */
! DATA(insert ( 2148	int8_accum	numeric_var_samp	0	1231	"{0,0,0}" ));
! DATA(insert ( 2149	int4_accum	numeric_var_samp	0	1231	"{0,0,0}" ));
! DATA(insert ( 2150	int2_accum	numeric_var_samp	0	1231	"{0,0,0}" ));
! DATA(insert ( 2151	float4_accum	float8_var_samp 0	1022	"{0,0,0}" ));
! DATA(insert ( 2152	float8_accum	float8_var_samp 0	1022	"{0,0,0}" ));
! DATA(insert ( 2153	numeric_accum  numeric_var_samp 0	1231	"{0,0,0}" ));
  
  /* stddev_pop */
! DATA(insert ( 2724	int8_accum	numeric_stddev_pop		0	1231	"{0,0,0}" ));
! DATA(insert ( 2725	int4_accum	numeric_stddev_pop		0	1231	"{0,0,0}" ));
! DATA(insert ( 2726	int2_accum	numeric_stddev_pop		0	1231	"{0,0,0}" ));
! DATA(insert ( 2727	float4_accum	float8_stddev_pop	0	1022	"{0,0,0}" ));
! DATA(insert ( 2728	float8_accum	float8_stddev_pop	0	1022	"{0,0,0}" ));
! DATA(insert ( 2729	numeric_accum	numeric_stddev_pop	0	1231	"{0,0,0}" ));
  
  /* stddev_samp */
! DATA(insert ( 2712	int8_accum	numeric_stddev_samp		0	1231	"{0,0,0}" ));
! DATA(insert ( 2713	int4_accum	numeric_stddev_samp		0	1231	"{0,0,0}" ));
! DATA(insert ( 2714	int2_accum	numeric_stddev_samp		0	1231	"{0,0,0}" ));
! DATA(insert ( 2715	float4_accum	float8_stddev_samp	0	1022	"{0,0,0}" ));
! DATA(insert ( 2716	float8_accum	float8_stddev_samp	0	1022	"{0,0,0}" ));
! DATA(insert ( 2717	numeric_accum	numeric_stddev_samp 0	1231	"{0,0,0}" ));
  
  /* stddev: historical Postgres syntax for stddev_samp */
! DATA(insert ( 2154	int8_accum	numeric_stddev_samp		0	1231	"{0,0,0}" ));
! DATA(insert ( 2155	int4_accum	numeric_stddev_samp		0	1231	"{0,0,0}" ));
! DATA(insert ( 2156	int2_accum	numeric_stddev_samp		0	1231	"{0,0,0}" ));
! DATA(insert ( 2157	float4_accum	float8_stddev_samp	0	1022	"{0,0,0}" ));
! DATA(insert ( 2158	float8_accum	float8_stddev_samp	0	1022	"{0,0,0}" ));
! DATA(insert ( 2159	numeric_accum	numeric_stddev_samp 0	1231	"{0,0,0}" ));
  
  /* SQL2003 binary regression aggregates */
! DATA(insert ( 2818	int8inc_float8_float8		-				0	20		"0" ));
! DATA(insert ( 2819	float8_regr_accum	float8_regr_sxx			0	1022	"{0,0,0,0,0,0}" ));
! DATA(insert ( 2820	float8_regr_accum	float8_regr_syy			0	1022	"{0,0,0,0,0,0}" ));
! DATA(insert ( 2821	float8_regr_accum	float8_regr_sxy			0	1022	"{0,0,0,0,0,0}" ));
! DATA(insert ( 2822	float8_regr_accum	float8_regr_avgx		0	1022	"{0,0,0,0,0,0}" ));
! DATA(insert ( 2823	float8_regr_accum	float8_regr_avgy		0	1022	"{0,0,0,0,0,0}" ));
! DATA(insert ( 2824	float8_regr_accum	float8_regr_r2			0	1022	"{0,0,0,0,0,0}" ));
! DATA(insert ( 2825	float8_regr_accum	float8_regr_slope		0	1022	"{0,0,0,0,0,0}" ));
! DATA(insert ( 2826	float8_regr_accum	float8_regr_intercept	0	1022	"{0,0,0,0,0,0}" ));
! DATA(insert ( 2827	float8_regr_accum	float8_covar_pop		0	1022	"{0,0,0,0,0,0}" ));
! DATA(insert ( 2828	float8_regr_accum	float8_covar_samp		0	1022	"{0,0,0,0,0,0}" ));
! DATA(insert ( 2829	float8_regr_accum	float8_corr				0	1022	"{0,0,0,0,0,0}" ));
  
  /* boolean-and and boolean-or */
! DATA(insert ( 2517	booland_statefunc	-			58	16		_null_ ));
! DATA(insert ( 2518	boolor_statefunc	-			59	16		_null_ ));
! DATA(insert ( 2519	booland_statefunc	-			58	16		_null_ ));
  
  /* bitwise integer */
! DATA(insert ( 2236 int2and		  -					0	21		_null_ ));
! DATA(insert ( 2237 int2or		  -					0	21		_null_ ));
! DATA(insert ( 2238 int4and		  -					0	23		_null_ ));
! DATA(insert ( 2239 int4or		  -					0	23		_null_ ));
! DATA(insert ( 2240 int8and		  -					0	20		_null_ ));
! DATA(insert ( 2241 int8or		  -					0	20		_null_ ));
! DATA(insert ( 2242 bitand		  -					0	1560	_null_ ));
! DATA(insert ( 2243 bitor		  -					0	1560	_null_ ));
  
  /* xml */
! DATA(insert ( 2901 xmlconcat2	  -					0	142		_null_ ));
  
  /* array */
! DATA(insert ( 2335	array_agg_transfn	array_agg_finalfn		0	2281	_null_ ));
  
  /* text */
! DATA(insert ( 3538	string_agg_transfn	string_agg_finalfn		0	2281	_null_ ));
  
  /* bytea */
! DATA(insert ( 3545	bytea_string_agg_transfn	bytea_string_agg_finalfn		0	2281	_null_ ));
  
  /* json */
! DATA(insert ( 3175	json_agg_transfn	json_agg_finalfn		0	2281	_null_ ));
  
  /*
   * prototypes for functions in pg_aggregate.c
--- 79,241 ----
   */
  
  /* avg */
! DATA(insert ( 2100	int8_avg_accum		numeric_avg		0	2281	128	_null_ ));
! DATA(insert ( 2101	int4_avg_accum		int8_avg		0	1016	0	"{0,0}" ));
! DATA(insert ( 2102	int2_avg_accum		int8_avg		0	1016	0	"{0,0}" ));
! DATA(insert ( 2103	numeric_avg_accum		numeric_avg		0	2281	128	_null_ ));
! DATA(insert ( 2104	float4_accum		float8_avg		0	1022	0	"{0,0,0}" ));
! DATA(insert ( 2105	float8_accum		float8_avg		0	1022	0	"{0,0,0}" ));
! DATA(insert ( 2106	interval_accum		interval_avg	0	1187	0	"{0 second,0 second}" ));
  
  /* sum */
! DATA(insert ( 2107	int8_avg_accum	numeric_sum		0	2281	128	_null_ ));
! DATA(insert ( 2108	int4_sum		-				0	20		0	_null_ ));
! DATA(insert ( 2109	int2_sum		-				0	20		0	_null_ ));
! DATA(insert ( 2110	float4pl		-				0	700		0	_null_ ));
! DATA(insert ( 2111	float8pl		-				0	701		0	_null_ ));
! DATA(insert ( 2112	cash_pl			-				0	790		0	_null_ ));
! DATA(insert ( 2113	interval_pl		-				0	1186	0	_null_ ));
! DATA(insert ( 2114	numeric_avg_accum	numeric_sum	0	2281	128	_null_ ));
  
  /* max */
! DATA(insert ( 2115	int8larger		-				413		20		0	_null_ ));
! DATA(insert ( 2116	int4larger		-				521		23		0	_null_ ));
! DATA(insert ( 2117	int2larger		-				520		21		0	_null_ ));
! DATA(insert ( 2118	oidlarger		-				610		26		0	_null_ ));
! DATA(insert ( 2119	float4larger	-				623		700		0	_null_ ));
! DATA(insert ( 2120	float8larger	-				674		701		0	_null_ ));
! DATA(insert ( 2121	int4larger		-				563		702		0	_null_ ));
! DATA(insert ( 2122	date_larger		-				1097	1082	0	_null_ ));
! DATA(insert ( 2123	time_larger		-				1112	1083	0	_null_ ));
! DATA(insert ( 2124	timetz_larger	-				1554	1266	0	_null_ ));
! DATA(insert ( 2125	cashlarger		-				903		790		0	_null_ ));
! DATA(insert ( 2126	timestamp_larger	-			2064	1114	0	_null_ ));
! DATA(insert ( 2127	timestamptz_larger	-			1324	1184	0	_null_ ));
! DATA(insert ( 2128	interval_larger -				1334	1186	0	_null_ ));
! DATA(insert ( 2129	text_larger		-				666		25		0	_null_ ));
! DATA(insert ( 2130	numeric_larger	-				1756	1700	0	_null_ ));
! DATA(insert ( 2050	array_larger	-				1073	2277	0	_null_ ));
! DATA(insert ( 2244	bpchar_larger	-				1060	1042	0	_null_ ));
! DATA(insert ( 2797	tidlarger		-				2800	27		0	_null_ ));
! DATA(insert ( 3526	enum_larger		-				3519	3500	0	_null_ ));
  
  /* min */
! DATA(insert ( 2131	int8smaller		-				412		20		0	_null_ ));
! DATA(insert ( 2132	int4smaller		-				97		23		0	_null_ ));
! DATA(insert ( 2133	int2smaller		-				95		21		0	_null_ ));
! DATA(insert ( 2134	oidsmaller		-				609		26		0	_null_ ));
! DATA(insert ( 2135	float4smaller	-				622		700		0	_null_ ));
! DATA(insert ( 2136	float8smaller	-				672		701		0	_null_ ));
! DATA(insert ( 2137	int4smaller		-				562		702		0	_null_ ));
! DATA(insert ( 2138	date_smaller	-				1095	1082	0	_null_ ));
! DATA(insert ( 2139	time_smaller	-				1110	1083	0	_null_ ));
! DATA(insert ( 2140	timetz_smaller	-				1552	1266	0	_null_ ));
! DATA(insert ( 2141	cashsmaller		-				902		790		0	_null_ ));
! DATA(insert ( 2142	timestamp_smaller	-			2062	1114	0	_null_ ));
! DATA(insert ( 2143	timestamptz_smaller -			1322	1184	0	_null_ ));
! DATA(insert ( 2144	interval_smaller	-			1332	1186	0	_null_ ));
! DATA(insert ( 2145	text_smaller	-				664		25		0	_null_ ));
! DATA(insert ( 2146	numeric_smaller -				1754	1700	0	_null_ ));
! DATA(insert ( 2051	array_smaller	-				1072	2277	0	_null_ ));
! DATA(insert ( 2245	bpchar_smaller	-				1058	1042	0	_null_ ));
! DATA(insert ( 2798	tidsmaller		-				2799	27		0	_null_ ));
! DATA(insert ( 3527	enum_smaller	-				3518	3500	0	_null_ ));
  
  /* count */
! DATA(insert ( 2147	int8inc_any		-				0		20		0	"0" ));
! DATA(insert ( 2803	int8inc			-				0		20		0	"0" ));
  
  /* var_pop */
! DATA(insert ( 2718	int8_accum	numeric_var_pop 0	2281	128	_null_ ));
! DATA(insert ( 2719	int4_accum	numeric_var_pop 0	2281	128	_null_ ));
! DATA(insert ( 2720	int2_accum	numeric_var_pop 0	2281	128	_null_ ));
! DATA(insert ( 2721	float4_accum	float8_var_pop 0	1022	0	"{0,0,0}" ));
! DATA(insert ( 2722	float8_accum	float8_var_pop 0	1022	0	"{0,0,0}" ));
! DATA(insert ( 2723	numeric_accum  numeric_var_pop 0	2281	128	_null_ ));
  
  /* var_samp */
! DATA(insert ( 2641	int8_accum	numeric_var_samp	0	2281	128	_null_ ));
! DATA(insert ( 2642	int4_accum	numeric_var_samp	0	2281	128	_null_ ));
! DATA(insert ( 2643	int2_accum	numeric_var_samp	0	2281	128	_null_ ));
! DATA(insert ( 2644	float4_accum	float8_var_samp 0	1022	0	"{0,0,0}" ));
! DATA(insert ( 2645	float8_accum	float8_var_samp 0	1022	0	"{0,0,0}" ));
! DATA(insert ( 2646	numeric_accum  numeric_var_samp 0	2281	128	_null_ ));
  
  /* variance: historical Postgres syntax for var_samp */
! DATA(insert ( 2148	int8_accum	numeric_var_samp	0	2281	128	_null_ ));
! DATA(insert ( 2149	int4_accum	numeric_var_samp	0	2281	128	_null_ ));
! DATA(insert ( 2150	int2_accum	numeric_var_samp	0	2281	128	_null_ ));
! DATA(insert ( 2151	float4_accum	float8_var_samp 0	1022	0	"{0,0,0}" ));
! DATA(insert ( 2152	float8_accum	float8_var_samp 0	1022	0	"{0,0,0}" ));
! DATA(insert ( 2153	numeric_accum  numeric_var_samp 0	2281	128	_null_ ));
  
  /* stddev_pop */
! DATA(insert ( 2724	int8_accum	numeric_stddev_pop		0	2281	128	_null_ ));
! DATA(insert ( 2725	int4_accum	numeric_stddev_pop		0	2281	128	_null_ ));
! DATA(insert ( 2726	int2_accum	numeric_stddev_pop		0	2281	128	_null_ ));
! DATA(insert ( 2727	float4_accum	float8_stddev_pop	0	1022	0	"{0,0,0}" ));
! DATA(insert ( 2728	float8_accum	float8_stddev_pop	0	1022	0	"{0,0,0}" ));
! DATA(insert ( 2729	numeric_accum	numeric_stddev_pop	0	2281	128	_null_ ));
  
  /* stddev_samp */
! DATA(insert ( 2712	int8_accum	numeric_stddev_samp		0	2281	128	_null_ ));
! DATA(insert ( 2713	int4_accum	numeric_stddev_samp		0	2281	128	_null_ ));
! DATA(insert ( 2714	int2_accum	numeric_stddev_samp		0	2281	128	_null_ ));
! DATA(insert ( 2715	float4_accum	float8_stddev_samp	0	1022	0	"{0,0,0}" ));
! DATA(insert ( 2716	float8_accum	float8_stddev_samp	0	1022	0	"{0,0,0}" ));
! DATA(insert ( 2717	numeric_accum	numeric_stddev_samp 0	2281	128	_null_ ));
  
  /* stddev: historical Postgres syntax for stddev_samp */
! DATA(insert ( 2154	int8_accum	numeric_stddev_samp		0	2281	128	_null_ ));
! DATA(insert ( 2155	int4_accum	numeric_stddev_samp		0	2281	128	_null_ ));
! DATA(insert ( 2156	int2_accum	numeric_stddev_samp		0	2281	128	_null_ ));
! DATA(insert ( 2157	float4_accum	float8_stddev_samp	0	1022	0	"{0,0,0}" ));
! DATA(insert ( 2158	float8_accum	float8_stddev_samp	0	1022	0	"{0,0,0}" ));
! DATA(insert ( 2159	numeric_accum	numeric_stddev_samp 0	2281	128	_null_ ));
  
  /* SQL2003 binary regression aggregates */
! DATA(insert ( 2818	int8inc_float8_float8		-				0	20		0	"0" ));
! DATA(insert ( 2819	float8_regr_accum	float8_regr_sxx			0	1022	0	"{0,0,0,0,0,0}" ));
! DATA(insert ( 2820	float8_regr_accum	float8_regr_syy			0	1022	0	"{0,0,0,0,0,0}" ));
! DATA(insert ( 2821	float8_regr_accum	float8_regr_sxy			0	1022	0	"{0,0,0,0,0,0}" ));
! DATA(insert ( 2822	float8_regr_accum	float8_regr_avgx		0	1022	0	"{0,0,0,0,0,0}" ));
! DATA(insert ( 2823	float8_regr_accum	float8_regr_avgy		0	1022	0	"{0,0,0,0,0,0}" ));
! DATA(insert ( 2824	float8_regr_accum	float8_regr_r2			0	1022	0	"{0,0,0,0,0,0}" ));
! DATA(insert ( 2825	float8_regr_accum	float8_regr_slope		0	1022	0	"{0,0,0,0,0,0}" ));
! DATA(insert ( 2826	float8_regr_accum	float8_regr_intercept	0	1022	0	"{0,0,0,0,0,0}" ));
! DATA(insert ( 2827	float8_regr_accum	float8_covar_pop		0	1022	0	"{0,0,0,0,0,0}" ));
! DATA(insert ( 2828	float8_regr_accum	float8_covar_samp		0	1022	0	"{0,0,0,0,0,0}" ));
! DATA(insert ( 2829	float8_regr_accum	float8_corr				0	1022	0	"{0,0,0,0,0,0}" ));
  
  /* boolean-and and boolean-or */
! DATA(insert ( 2517	booland_statefunc	-			58	16		0	_null_ ));
! DATA(insert ( 2518	boolor_statefunc	-			59	16		0	_null_ ));
! DATA(insert ( 2519	booland_statefunc	-			58	16		0	_null_ ));
  
  /* bitwise integer */
! DATA(insert ( 2236 int2and		  -					0	21		0	_null_ ));
! DATA(insert ( 2237 int2or		  -					0	21		0	_null_ ));
! DATA(insert ( 2238 int4and		  -					0	23		0	_null_ ));
! DATA(insert ( 2239 int4or		  -					0	23		0	_null_ ));
! DATA(insert ( 2240 int8and		  -					0	20		0	_null_ ));
! DATA(insert ( 2241 int8or		  -					0	20		0	_null_ ));
! DATA(insert ( 2242 bitand		  -					0	1560	0	_null_ ));
! DATA(insert ( 2243 bitor		  -					0	1560	0	_null_ ));
  
  /* xml */
! DATA(insert ( 2901 xmlconcat2	  -					0	142		0	_null_ ));
  
  /* array */
! DATA(insert ( 2335	array_agg_transfn	array_agg_finalfn		0	2281	0	_null_ ));
  
  /* text */
! DATA(insert ( 3538	string_agg_transfn	string_agg_finalfn		0	2281	0	_null_ ));
  
  /* bytea */
! DATA(insert ( 3545	bytea_string_agg_transfn	bytea_string_agg_finalfn		0	2281	0	_null_ ));
  
  /* json */
! DATA(insert ( 3175	json_agg_transfn	json_agg_finalfn		0	2281	0	_null_ ));
  
  /*
   * prototypes for functions in pg_aggregate.c
***************
*** 250,255 **** extern Oid AggregateCreate(const char *aggName,
--- 252,258 ----
  				List *aggfinalfnName,
  				List *aggsortopName,
  				Oid aggTransType,
+ 				int32 aggTransSpace,
  				const char *agginitval);
  
  #endif   /* PG_AGGREGATE_H */
*** a/src/include/catalog/pg_proc.h
--- b/src/include/catalog/pg_proc.h
***************
*** 2381,2407 **** DATA(insert OID = 2513 (  float8_stddev_pop PGNSP PGUID 12 1 0 0 0 f f f f t f i
  DESCR("aggregate final function");
  DATA(insert OID = 1832 (  float8_stddev_samp	PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 701 "1022" _null_ _null_ _null_ _null_ float8_stddev_samp _null_ _null_ _null_ ));
  DESCR("aggregate final function");
! DATA(insert OID = 1833 (  numeric_accum    PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 1231 "1231 1700" _null_ _null_ _null_ _null_ numeric_accum _null_ _null_ _null_ ));
  DESCR("aggregate transition function");
! DATA(insert OID = 2858 (  numeric_avg_accum    PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 1231 "1231 1700" _null_ _null_ _null_ _null_ numeric_avg_accum _null_ _null_ _null_ ));
  DESCR("aggregate transition function");
! DATA(insert OID = 1834 (  int2_accum	   PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 1231 "1231 21" _null_ _null_ _null_ _null_ int2_accum _null_ _null_ _null_ ));
  DESCR("aggregate transition function");
! DATA(insert OID = 1835 (  int4_accum	   PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 1231 "1231 23" _null_ _null_ _null_ _null_ int4_accum _null_ _null_ _null_ ));
  DESCR("aggregate transition function");
! DATA(insert OID = 1836 (  int8_accum	   PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 1231 "1231 20" _null_ _null_ _null_ _null_ int8_accum _null_ _null_ _null_ ));
  DESCR("aggregate transition function");
! DATA(insert OID = 2746 (  int8_avg_accum	   PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 1231 "1231 20" _null_ _null_ _null_ _null_ int8_avg_accum _null_ _null_ _null_ ));
  DESCR("aggregate transition function");
! DATA(insert OID = 1837 (  numeric_avg	   PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 1700 "1231" _null_ _null_ _null_ _null_ numeric_avg _null_ _null_ _null_ ));
  DESCR("aggregate final function");
! DATA(insert OID = 2514 (  numeric_var_pop  PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 1700 "1231" _null_ _null_ _null_ _null_ numeric_var_pop _null_ _null_ _null_ ));
  DESCR("aggregate final function");
! DATA(insert OID = 1838 (  numeric_var_samp PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 1700 "1231" _null_ _null_ _null_ _null_ numeric_var_samp _null_ _null_ _null_ ));
  DESCR("aggregate final function");
! DATA(insert OID = 2596 (  numeric_stddev_pop PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 1700 "1231" _null_ _null_ _null_ _null_	numeric_stddev_pop _null_ _null_ _null_ ));
  DESCR("aggregate final function");
! DATA(insert OID = 1839 (  numeric_stddev_samp	PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 1700 "1231" _null_ _null_ _null_ _null_ numeric_stddev_samp _null_ _null_ _null_ ));
  DESCR("aggregate final function");
  DATA(insert OID = 1840 (  int2_sum		   PGNSP PGUID 12 1 0 0 0 f f f f f f i 2 0 20 "20 21" _null_ _null_ _null_ _null_ int2_sum _null_ _null_ _null_ ));
  DESCR("aggregate transition function");
--- 2381,2409 ----
  DESCR("aggregate final function");
  DATA(insert OID = 1832 (  float8_stddev_samp	PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 701 "1022" _null_ _null_ _null_ _null_ float8_stddev_samp _null_ _null_ _null_ ));
  DESCR("aggregate final function");
! DATA(insert OID = 1833 (  numeric_accum    PGNSP PGUID 12 1 0 0 0 f f f f f f i 2 0 2281 "2281 1700" _null_ _null_ _null_ _null_ numeric_accum _null_ _null_ _null_ ));
  DESCR("aggregate transition function");
! DATA(insert OID = 2858 (  numeric_avg_accum    PGNSP PGUID 12 1 0 0 0 f f f f f f i 2 0 2281 "2281 1700" _null_ _null_ _null_ _null_ numeric_avg_accum _null_ _null_ _null_ ));
  DESCR("aggregate transition function");
! DATA(insert OID = 1834 (  int2_accum	   PGNSP PGUID 12 1 0 0 0 f f f f f f i 2 0 2281 "2281 21" _null_ _null_ _null_ _null_ int2_accum _null_ _null_ _null_ ));
  DESCR("aggregate transition function");
! DATA(insert OID = 1835 (  int4_accum	   PGNSP PGUID 12 1 0 0 0 f f f f f f i 2 0 2281 "2281 23" _null_ _null_ _null_ _null_ int4_accum _null_ _null_ _null_ ));
  DESCR("aggregate transition function");
! DATA(insert OID = 1836 (  int8_accum	   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 _null_ _null_ _null_ ));
  DESCR("aggregate transition function");
! DATA(insert OID = 2746 (  int8_avg_accum	   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 _null_ _null_ _null_ ));
  DESCR("aggregate transition 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_ ));
  DESCR("aggregate final function");
! DATA(insert OID = 3179 (  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 = 2514 (  numeric_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_var_pop _null_ _null_ _null_ ));
  DESCR("aggregate final function");
! DATA(insert OID = 1838 (  numeric_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_var_samp _null_ _null_ _null_ ));
  DESCR("aggregate final function");
! DATA(insert OID = 2596 (  numeric_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_stddev_pop _null_ _null_ _null_ ));
! DESCR("aggregate final function");
! DATA(insert OID = 1839 (  numeric_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_stddev_samp _null_ _null_ _null_ ));
  DESCR("aggregate final function");
  DATA(insert OID = 1840 (  int2_sum		   PGNSP PGUID 12 1 0 0 0 f f f f f f i 2 0 20 "20 21" _null_ _null_ _null_ _null_ int2_sum _null_ _null_ _null_ ));
  DESCR("aggregate transition function");
*** a/src/include/commands/defrem.h
--- b/src/include/commands/defrem.h
***************
*** 133,138 **** extern Datum transformGenericOptions(Oid catalogId,
--- 133,139 ----
  extern char *defGetString(DefElem *def);
  extern double defGetNumeric(DefElem *def);
  extern bool defGetBoolean(DefElem *def);
+ extern int32 defGetInt32(DefElem *def);
  extern int64 defGetInt64(DefElem *def);
  extern List *defGetQualifiedName(DefElem *def);
  extern TypeName *defGetTypeName(DefElem *def);
*** a/src/include/utils/builtins.h
--- b/src/include/utils/builtins.h
***************
*** 982,987 **** extern Datum int4_accum(PG_FUNCTION_ARGS);
--- 982,988 ----
  extern Datum int8_accum(PG_FUNCTION_ARGS);
  extern Datum int8_avg_accum(PG_FUNCTION_ARGS);
  extern Datum numeric_avg(PG_FUNCTION_ARGS);
+ extern Datum numeric_sum(PG_FUNCTION_ARGS);
  extern Datum numeric_var_pop(PG_FUNCTION_ARGS);
  extern Datum numeric_var_samp(PG_FUNCTION_ARGS);
  extern Datum numeric_stddev_pop(PG_FUNCTION_ARGS);
*** a/src/test/regress/expected/aggregates.out
--- b/src/test/regress/expected/aggregates.out
***************
*** 1262,1264 **** select least_agg(variadic array[q1,q2]) from int8_tbl;
--- 1262,1313 ----
   -4567890123456789
  (1 row)
  
+ -- verify correct calculations for null set
+ select sum(null::int4) from generate_series(1,1);
+  sum 
+ -----
+     
+ (1 row)
+ 
+ select sum(null::int8) from generate_series(1,1);
+  sum 
+ -----
+     
+ (1 row)
+ 
+ select sum(null::numeric) from generate_series(1,1);
+  sum 
+ -----
+     
+ (1 row)
+ 
+ select sum(null::float8) from generate_series(1,1);
+  sum 
+ -----
+     
+ (1 row)
+ 
+ select avg(null::int4) from generate_series(1,1);
+  avg 
+ -----
+     
+ (1 row)
+ 
+ select avg(null::int8) from generate_series(1,1);
+  avg 
+ -----
+     
+ (1 row)
+ 
+ select avg(null::numeric) from generate_series(1,1);
+  avg 
+ -----
+     
+ (1 row)
+ 
+ select avg(null::float8) from generate_series(1,1);
+  avg 
+ -----
+     
+ (1 row)
+ 
*** a/src/test/regress/expected/create_aggregate.out
--- b/src/test/regress/expected/create_aggregate.out
***************
*** 66,68 **** returns anyelement language sql as
--- 66,75 ----
  create aggregate least_agg(variadic items anyarray) (
    stype = anyelement, sfunc = least_accum
  );
+ -- should not work, sspace is allowed only for stype internal
+ create aggregate aggfns(integer,integer,text) (
+    sfunc = aggfns_trans, stype = aggtype[], sspace = 200,
+    initcond = '{}'
+ );
+ ERROR:  SSPACE can be used only for "internal" transition type
+ DETAIL:  SSPACE can be defined only together with a "internal" transition type.
*** a/src/test/regress/sql/aggregates.sql
--- b/src/test/regress/sql/aggregates.sql
***************
*** 484,486 **** select aggfns(distinct a,b,c order by a,c using ~<~,b) filter (where a > 1)
--- 484,497 ----
  -- variadic aggregates
  select least_agg(q1,q2) from int8_tbl;
  select least_agg(variadic array[q1,q2]) from int8_tbl;
+ 
+ -- verify correct calculations for null set
+ select sum(null::int4) from generate_series(1,1);
+ select sum(null::int8) from generate_series(1,1);
+ select sum(null::numeric) from generate_series(1,1);
+ select sum(null::float8) from generate_series(1,1);
+ 
+ select avg(null::int4) from generate_series(1,1);
+ select avg(null::int8) from generate_series(1,1);
+ select avg(null::numeric) from generate_series(1,1);
+ select avg(null::float8) from generate_series(1,1);
*** a/src/test/regress/sql/create_aggregate.sql
--- b/src/test/regress/sql/create_aggregate.sql
***************
*** 80,82 **** returns anyelement language sql as
--- 80,88 ----
  create aggregate least_agg(variadic items anyarray) (
    stype = anyelement, sfunc = least_accum
  );
+ 
+ -- should not work, sspace is allowed only for stype internal
+ create aggregate aggfns(integer,integer,text) (
+    sfunc = aggfns_trans, stype = aggtype[], sspace = 200,
+    initcond = '{}'
+ );
