aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/array_userfuncs.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2015-02-25 14:19:13 -0500
committerTom Lane <tgl@sss.pgh.pa.us>2015-02-25 14:19:13 -0500
commit77903ede08845e55bd2a6c99b52d8da6926d6e84 (patch)
tree4c289d409854d436bfc2290c826ddb22edc55eb9 /src/backend/utils/adt/array_userfuncs.c
parente9f1c01b71dcd11c86fc8516c06dae2e784b96fd (diff)
downloadpostgresql-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.c36
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;
}