diff -ruN postgresql-7.4.5-old/contrib/intagg/int_aggregate.c postgresql-7.4.5/contrib/intagg/int_aggregate.c --- postgresql-7.4.5-old/contrib/intagg/int_aggregate.c 2003-08-04 02:43:10.000000000 +0200 +++ postgresql-7.4.5/contrib/intagg/int_aggregate.c 2005-02-10 13:45:33.085032152 +0100 @@ -59,19 +59,17 @@ } CTX; #define TOASTED 1 -#define START_NUM 8 -#define PGARRAY_SIZE(n) (sizeof(PGARRAY) + ((n-1)*sizeof(int4))) +#define START_NUM 8 /* initial size of arrays */ +#define PGARRAY_SIZE(n) (sizeof(PGARRAY) + (((n)-1)*sizeof(int4))) -static PGARRAY *GetPGArray(int4 state, int fAdd); -static PGARRAY *ShrinkPGArray(PGARRAY * p); +static PGARRAY *GetPGArray(PGARRAY *p, int fAdd); +static PGARRAY *ShrinkPGArray(PGARRAY *p); Datum int_agg_state(PG_FUNCTION_ARGS); -Datum int_agg_final_count(PG_FUNCTION_ARGS); Datum int_agg_final_array(PG_FUNCTION_ARGS); Datum int_enum(PG_FUNCTION_ARGS); PG_FUNCTION_INFO_V1(int_agg_state); -PG_FUNCTION_INFO_V1(int_agg_final_count); PG_FUNCTION_INFO_V1(int_agg_final_array); PG_FUNCTION_INFO_V1(int_enum); @@ -82,11 +80,9 @@ * PortalContext isn't really right, but it's close enough. */ static PGARRAY * -GetPGArray(int4 state, int fAdd) +GetPGArray(PGARRAY *p, int fAdd) { - PGARRAY *p = (PGARRAY *) state; - - if (!state) + if (!p) { /* New array */ int cb = PGARRAY_SIZE(START_NUM); @@ -119,7 +115,8 @@ } /* Shrinks the array to its actual size and moves it into the standard - * memory allocation context, frees working memory */ + * memory allocation context, frees working memory + */ static PGARRAY * ShrinkPGArray(PGARRAY * p) { @@ -143,7 +140,7 @@ #ifndef PG_7_2 pnew->a.elemtype = INT4OID; #endif - pnew->lower = 0; + pnew->lower = 1; pfree(p); } @@ -154,28 +151,37 @@ Datum int_agg_state(PG_FUNCTION_ARGS) { - int4 state = PG_GETARG_INT32(0); - int4 value = PG_GETARG_INT32(1); + PGARRAY *state; + PGARRAY *p; - PGARRAY *p = GetPGArray(state, 1); - - if (!p) - /* internal error */ - elog(ERROR, "no aggregate storage"); - else if (p->items >= p->lower) - /* internal error */ - elog(ERROR, "aggregate storage too small"); + if (PG_ARGISNULL(0)) + state = NULL; else - p->array[p->items++] = value; - PG_RETURN_INT32(p); + state = (PGARRAY *) PG_GETARG_POINTER(0); + p = GetPGArray(state, 1); + + if (!PG_ARGISNULL(1)) + { + int4 value = PG_GETARG_INT32(1); + + if (!p) /* internal error */ + elog(ERROR, "no aggregate storage"); + else if (p->items >= p->lower) /* internal error */ + elog(ERROR, "aggregate storage too small"); + else + p->array[p->items++] = value; + } + PG_RETURN_POINTER(p); } -/* This is the final function used for the integer aggregator. It returns all the integers - * collected as a one dimensional integer array */ +/* This is the final function used for the integer aggregator. It returns all + * the integers collected as a one dimensional integer array + */ Datum int_agg_final_array(PG_FUNCTION_ARGS) { - PGARRAY *pnew = ShrinkPGArray(GetPGArray(PG_GETARG_INT32(0), 0)); + PGARRAY *state = (PGARRAY *) PG_GETARG_POINTER(0); + PGARRAY *pnew = ShrinkPGArray(GetPGArray(state, 0)); if (pnew) PG_RETURN_POINTER(pnew); @@ -207,18 +213,12 @@ /* Allocate a working context */ pc = (CTX *) palloc(sizeof(CTX)); - /* Don't copy attribute if you don't need too */ + /* Don't copy attribute if you don't need to */ if (VARATT_IS_EXTENDED(p)) { /* Toasted!!! */ pc->p = (PGARRAY *) PG_DETOAST_DATUM_COPY(p); pc->flags = TOASTED; - if (!pc->p) - { - /* internal error */ - elog(ERROR, "error in toaster; not detoasting"); - PG_RETURN_NULL(); - } } else { diff -ruN postgresql-7.4.5-old/contrib/intagg/int_aggregate.sql.in postgresql-7.4.5/contrib/intagg/int_aggregate.sql.in --- postgresql-7.4.5-old/contrib/intagg/int_aggregate.sql.in 2003-05-14 05:25:56.000000000 +0200 +++ postgresql-7.4.5/contrib/intagg/int_aggregate.sql.in 2005-02-10 13:50:01.066292808 +0100 @@ -3,17 +3,17 @@ -- Internal function for the aggregate -- Is called for each item in an aggregation -CREATE OR REPLACE FUNCTION int_agg_state (int4, int4) -RETURNS int4 +CREATE OR REPLACE FUNCTION int_agg_state (int4[], int4) +RETURNS int4[] AS 'MODULE_PATHNAME','int_agg_state' -LANGUAGE 'C' IMMUTABLE STRICT; +LANGUAGE 'C'; -- Internal function for the aggregate -- Is called at the end of the aggregation, and returns an array. -CREATE OR REPLACE FUNCTION int_agg_final_array (int4) +CREATE OR REPLACE FUNCTION int_agg_final_array (int4[]) RETURNS int4[] AS 'MODULE_PATHNAME','int_agg_final_array' -LANGUAGE 'C' IMMUTABLE STRICT; +LANGUAGE 'C' STRICT; -- The aggration funcion. -- uses the above functions to create an array of integers from an aggregation. @@ -21,11 +21,15 @@ CREATE AGGREGATE int_array_aggregate ( BASETYPE = int4, SFUNC = int_agg_state, - STYPE = int4, - FINALFUNC = int_agg_final_array, - INITCOND = 0 + STYPE = int4[], + FINALFUNC = int_agg_final_array ); +-- The aggregate component functions are not designed to be called +-- independently, so disable public access to them +REVOKE ALL ON FUNCTION int_agg_state (int4[], int4) FROM PUBLIC; +REVOKE ALL ON FUNCTION int_agg_final_array (int4[]) FROM PUBLIC; + -- The enumeration function -- returns each element in a one dimentional integer array -- as a row.