#include "postgres.h" #include "fmgr.h" #include "utils/array.h" #include "nodes/execnodes.h" PG_MODULE_MAGIC; PG_FUNCTION_INFO_V1(aaccum_sfunc); Datum aaccum_sfunc(PG_FUNCTION_ARGS) { int32 totlen; bytea *storage; Datum element; ArrayBuildState *astate = NULL; AggState *aggstate; /* Make sure we are in an aggregate. */ if (!fcinfo->context || !IsA(fcinfo->context, AggState)) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("Can not call aaccum_sfunc as a non-aggregate"))); aggstate = (AggState*) fcinfo->context; /* Initial call just passes in NULLs, so just allocate memory * and get set up. */ if (PG_ARGISNULL(0)) { storage = (bytea*) palloc(VARHDRSZ+sizeof(ArrayBuildState*)); storage->vl_len = VARHDRSZ+sizeof(ArrayBuildState*); astate = NULL; memcpy(storage->vl_dat,&astate,sizeof(astate)); } else { storage = PG_GETARG_BYTEA_P(0); } memcpy(&astate,storage->vl_dat,sizeof(astate)); element = PG_GETARG_DATUM(1); astate = accumArrayResult(astate, element, PG_ARGISNULL(1), get_fn_expr_argtype(fcinfo->flinfo, 1), aggstate->aggcontext); memcpy(storage->vl_dat,&astate,sizeof(astate)); PG_RETURN_BYTEA_P(storage); } PG_FUNCTION_INFO_V1(aaccum_ffunc); Datum aaccum_ffunc(PG_FUNCTION_ARGS) { int dims[1]; int lbs[1]; bytea *storage; ArrayBuildState *astate; AggState *aggstate; ArrayType *result; /* Make sure we are in an aggregate. */ if (!fcinfo->context || !IsA(fcinfo->context, AggState)) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("Can not call aaccum_sfunc as a non-aggregate"))); aggstate = (AggState*) fcinfo->context; if (PG_ARGISNULL(0)) PG_RETURN_ARRAYTYPE_P(NULL); storage = (bytea*) PG_GETARG_BYTEA_P(0); memcpy(&astate,storage->vl_dat,sizeof(astate)); dims[0] = astate->nelems; lbs[0] = 1; result = construct_md_array(astate->dvalues, astate->dnulls, 1, dims, lbs, astate->element_type, astate->typlen, astate->typbyval, astate->typalign); PG_RETURN_ARRAYTYPE_P(PointerGetDatum(result)); }