From 77903ede08845e55bd2a6c99b52d8da6926d6e84 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Wed, 25 Feb 2015 14:19:13 -0500 Subject: [PATCH] Fix over-optimistic caching in fetch_array_arg_replace_nulls(). When I rewrote this in commit 56a79a869bedc4bf6c35853642694cc0b0594dd2, I forgot that it's possible for the input array type to change from one call to the next (this can happen when applying the function to pg_statistic columns, for instance). Fix that. --- src/backend/utils/adt/array_userfuncs.c | 36 +++++++++++++++---------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/src/backend/utils/adt/array_userfuncs.c b/src/backend/utils/adt/array_userfuncs.c index 5781b952f9..6679333522 100644 --- a/src/backend/utils/adt/array_userfuncs.c +++ b/src/backend/utils/adt/array_userfuncs.c @@ -28,14 +28,19 @@ static ArrayType * fetch_array_arg_replace_nulls(FunctionCallInfo fcinfo, int argno) { ArrayType *v; + Oid element_type; ArrayMetaState *my_extra; - my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra; - if (my_extra == NULL) + /* First collect the array value */ + if (!PG_ARGISNULL(argno)) + { + v = PG_GETARG_ARRAYTYPE_P(argno); + element_type = ARR_ELEMTYPE(v); + } + else { - /* First time through, so look up the array type and element type */ + /* We have to look up the array type and element type */ Oid arr_typeid = get_fn_expr_argtype(fcinfo->flinfo, argno); - Oid element_type; if (!OidIsValid(arr_typeid)) ereport(ERROR, @@ -47,26 +52,29 @@ fetch_array_arg_replace_nulls(FunctionCallInfo fcinfo, int argno) (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("input data type is not an array"))); + v = construct_empty_array(element_type); + } + + /* Now cache required info, which might change from call to call */ + my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra; + if (my_extra == NULL) + { my_extra = (ArrayMetaState *) MemoryContextAlloc(fcinfo->flinfo->fn_mcxt, sizeof(ArrayMetaState)); - my_extra->element_type = element_type; + my_extra->element_type = InvalidOid; + fcinfo->flinfo->fn_extra = my_extra; + } - /* Cache info about element type */ + if (my_extra->element_type != element_type) + { get_typlenbyvalalign(element_type, &my_extra->typlen, &my_extra->typbyval, &my_extra->typalign); - - fcinfo->flinfo->fn_extra = my_extra; + my_extra->element_type = element_type; } - /* Now we can collect the array value */ - if (PG_ARGISNULL(argno)) - v = construct_empty_array(my_extra->element_type); - else - v = PG_GETARG_ARRAYTYPE_P(argno); - return v; } -- 2.40.0