diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2010-02-08 20:39:52 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2010-02-08 20:39:52 +0000 |
commit | d5768dce10576c2fb1254c03fb29475d4fac6bb4 (patch) | |
tree | 7b971cb06b6671d66df26027909e1d9355d65d14 /src/backend/utils/adt/varlena.c | |
parent | 4d3d2e2b0325e3d6d524c6801b7439d3aaea4520 (diff) | |
download | postgresql-d5768dce10576c2fb1254c03fb29475d4fac6bb4.tar.gz postgresql-d5768dce10576c2fb1254c03fb29475d4fac6bb4.zip |
Create an official API function for C functions to use to check if they are
being called as aggregates, and to get the aggregate transition state memory
context if needed. Use it instead of poking directly into AggState and
WindowAggState in places that shouldn't know so much.
We should have done this in 8.4, probably, but better late than never.
Revised version of a patch by Hitoshi Harada.
Diffstat (limited to 'src/backend/utils/adt/varlena.c')
-rw-r--r-- | src/backend/utils/adt/varlena.c | 40 |
1 files changed, 18 insertions, 22 deletions
diff --git a/src/backend/utils/adt/varlena.c b/src/backend/utils/adt/varlena.c index 096ca75bf93..652e1e6add4 100644 --- a/src/backend/utils/adt/varlena.c +++ b/src/backend/utils/adt/varlena.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/adt/varlena.c,v 1.175 2010/02/01 03:14:43 itagaki Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/varlena.c,v 1.176 2010/02/08 20:39:51 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -21,7 +21,6 @@ #include "libpq/md5.h" #include "libpq/pqformat.h" #include "miscadmin.h" -#include "nodes/execnodes.h" #include "parser/scansup.h" #include "regex/regex.h" #include "utils/builtins.h" @@ -74,7 +73,7 @@ static bytea *bytea_substring(Datum str, int L, bool length_not_specified); static bytea *bytea_overlay(bytea *t1, bytea *t2, int sp, int sl); -static StringInfo makeStringAggState(fmNodePtr context); +static StringInfo makeStringAggState(FunctionCallInfo fcinfo); /***************************************************************************** @@ -3327,25 +3326,25 @@ pg_column_size(PG_FUNCTION_ARGS) * actually used at all, and on subsequent calls the delimiter precedes * the associated value. */ + +/* subroutine to initialize state */ static StringInfo -makeStringAggState(fmNodePtr context) +makeStringAggState(FunctionCallInfo fcinfo) { StringInfo state; MemoryContext aggcontext; MemoryContext oldcontext; - if (context && IsA(context, AggState)) - aggcontext = ((AggState *) context)->aggcontext; - else if (context && IsA(context, WindowAggState)) - aggcontext = ((WindowAggState *) context)->wincontext; - else + if (!AggCheckCallContext(fcinfo, &aggcontext)) { /* cannot be called directly because of internal-type argument */ elog(ERROR, "string_agg_transfn called in non-aggregate context"); - aggcontext = NULL; /* keep compiler quiet */ } - /* Create state in aggregate context */ + /* + * Create state in aggregate context. It'll stay there across subsequent + * calls. + */ oldcontext = MemoryContextSwitchTo(aggcontext); state = makeStringInfo(); MemoryContextSwitchTo(oldcontext); @@ -3360,11 +3359,11 @@ string_agg_transfn(PG_FUNCTION_ARGS) state = PG_ARGISNULL(0) ? NULL : (StringInfo) PG_GETARG_POINTER(0); - /* Append the element unless not null. */ + /* Append the element unless null. */ if (!PG_ARGISNULL(1)) { if (state == NULL) - state = makeStringAggState(fcinfo->context); + state = makeStringAggState(fcinfo); appendStringInfoText(state, PG_GETARG_TEXT_PP(1)); /* value */ } @@ -3382,11 +3381,12 @@ string_agg_delim_transfn(PG_FUNCTION_ARGS) state = PG_ARGISNULL(0) ? NULL : (StringInfo) PG_GETARG_POINTER(0); - /* Append the value unless not null. */ + /* Append the value unless null. */ if (!PG_ARGISNULL(1)) { + /* On the first time through, we ignore the delimiter. */ if (state == NULL) - state = makeStringAggState(fcinfo->context); + state = makeStringAggState(fcinfo); else if (!PG_ARGISNULL(2)) appendStringInfoText(state, PG_GETARG_TEXT_PP(2)); /* delimiter */ @@ -3405,15 +3405,11 @@ string_agg_finalfn(PG_FUNCTION_ARGS) { StringInfo state; - if (PG_ARGISNULL(0)) - PG_RETURN_NULL(); - /* cannot be called directly because of internal-type argument */ - Assert(fcinfo->context && - (IsA(fcinfo->context, AggState) || - IsA(fcinfo->context, WindowAggState))); + Assert(AggCheckCallContext(fcinfo, NULL)); + + state = PG_ARGISNULL(0) ? NULL : (StringInfo) PG_GETARG_POINTER(0); - state = (StringInfo) PG_GETARG_POINTER(0); if (state != NULL) PG_RETURN_TEXT_P(cstring_to_text(state->data)); else |