aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/array_userfuncs.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils/adt/array_userfuncs.c')
-rw-r--r--src/backend/utils/adt/array_userfuncs.c35
1 files changed, 29 insertions, 6 deletions
diff --git a/src/backend/utils/adt/array_userfuncs.c b/src/backend/utils/adt/array_userfuncs.c
index 4c147f0021d..1401b29359f 100644
--- a/src/backend/utils/adt/array_userfuncs.c
+++ b/src/backend/utils/adt/array_userfuncs.c
@@ -6,7 +6,7 @@
* Copyright (c) 2003-2008, PostgreSQL Global Development Group
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/adt/array_userfuncs.c,v 1.26 2008/11/14 02:09:51 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/array_userfuncs.c,v 1.27 2008/12/28 18:53:59 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -475,6 +475,7 @@ Datum
array_agg_transfn(PG_FUNCTION_ARGS)
{
Oid arg1_typeid = get_fn_expr_argtype(fcinfo->flinfo, 1);
+ MemoryContext aggcontext;
ArrayBuildState *state;
Datum elem;
@@ -483,8 +484,16 @@ array_agg_transfn(PG_FUNCTION_ARGS)
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("could not determine input data type")));
- /* cannot be called directly because of internal-type argument */
- Assert(fcinfo->context && IsA(fcinfo->context, AggState));
+ if (fcinfo->context && IsA(fcinfo->context, AggState))
+ aggcontext = ((AggState *) fcinfo->context)->aggcontext;
+ else if (fcinfo->context && IsA(fcinfo->context, WindowAggState))
+ aggcontext = ((WindowAggState *) fcinfo->context)->wincontext;
+ else
+ {
+ /* cannot be called directly because of internal-type argument */
+ elog(ERROR, "array_agg_transfn called in non-aggregate context");
+ aggcontext = NULL; /* keep compiler quiet */
+ }
state = PG_ARGISNULL(0) ? NULL : (ArrayBuildState *) PG_GETARG_POINTER(0);
elem = PG_ARGISNULL(1) ? (Datum) 0 : PG_GETARG_DATUM(1);
@@ -492,7 +501,7 @@ array_agg_transfn(PG_FUNCTION_ARGS)
elem,
PG_ARGISNULL(1),
arg1_typeid,
- ((AggState *) fcinfo->context)->aggcontext);
+ aggcontext);
/*
* The transition type for array_agg() is declared to be "internal",
@@ -506,14 +515,28 @@ array_agg_transfn(PG_FUNCTION_ARGS)
Datum
array_agg_finalfn(PG_FUNCTION_ARGS)
{
+ Datum result;
ArrayBuildState *state;
+ int dims[1];
+ int lbs[1];
/* cannot be called directly because of internal-type argument */
- Assert(fcinfo->context && IsA(fcinfo->context, AggState));
+ Assert(fcinfo->context &&
+ (IsA(fcinfo->context, AggState) ||
+ IsA(fcinfo->context, WindowAggState)));
if (PG_ARGISNULL(0))
PG_RETURN_NULL(); /* returns null iff no input values */
state = (ArrayBuildState *) PG_GETARG_POINTER(0);
- PG_RETURN_ARRAYTYPE_P(makeArrayResult(state, CurrentMemoryContext));
+
+ dims[0] = state->nelems;
+ lbs[0] = 1;
+
+ /* Release working state if regular aggregate, but not if window agg */
+ result = makeMdArrayResult(state, 1, dims, lbs,
+ CurrentMemoryContext,
+ IsA(fcinfo->context, AggState));
+
+ PG_RETURN_DATUM(result);
}