diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2015-02-25 14:19:13 -0500 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2015-02-25 14:19:13 -0500 |
commit | 77903ede08845e55bd2a6c99b52d8da6926d6e84 (patch) | |
tree | 4c289d409854d436bfc2290c826ddb22edc55eb9 /src/backend/utils/adt/array_userfuncs.c | |
parent | e9f1c01b71dcd11c86fc8516c06dae2e784b96fd (diff) | |
download | postgresql-77903ede08845e55bd2a6c99b52d8da6926d6e84.tar.gz postgresql-77903ede08845e55bd2a6c99b52d8da6926d6e84.zip |
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.
Diffstat (limited to 'src/backend/utils/adt/array_userfuncs.c')
-rw-r--r-- | src/backend/utils/adt/array_userfuncs.c | 36 |
1 files changed, 22 insertions, 14 deletions
diff --git a/src/backend/utils/adt/array_userfuncs.c b/src/backend/utils/adt/array_userfuncs.c index 5781b952f97..66793335225 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; } |