aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/arrayfuncs.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2005-03-24 21:51:04 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2005-03-24 21:51:04 +0000
commit3e65431bc1a722c5d7e1a7598f3b18f9b3224ace (patch)
tree901d4295f49e3131122f87717c257558ad528eba /src/backend/utils/adt/arrayfuncs.c
parentb4fd104204c0cd81fe942511e172a867b5a29704 (diff)
downloadpostgresql-3e65431bc1a722c5d7e1a7598f3b18f9b3224ace.tar.gz
postgresql-3e65431bc1a722c5d7e1a7598f3b18f9b3224ace.zip
array_map can't use the fn_extra field of the provided fcinfo struct as
its private storage, because that belongs to the function that it is supposed to call. Per report from Ezequiel Tolnay.
Diffstat (limited to 'src/backend/utils/adt/arrayfuncs.c')
-rw-r--r--src/backend/utils/adt/arrayfuncs.c53
1 files changed, 21 insertions, 32 deletions
diff --git a/src/backend/utils/adt/arrayfuncs.c b/src/backend/utils/adt/arrayfuncs.c
index eedc3990fa4..9c9d3541e1e 100644
--- a/src/backend/utils/adt/arrayfuncs.c
+++ b/src/backend/utils/adt/arrayfuncs.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.100.2.2 2004/12/17 20:58:36 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.100.2.3 2005/03/24 21:51:04 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1195,6 +1195,7 @@ array_length_coerce(PG_FUNCTION_ARGS)
{
Oid elemtype;
FmgrInfo coerce_finfo;
+ ArrayMapState amstate;
} alc_extra;
alc_extra *my_extra;
FunctionCallInfoData locfcinfo;
@@ -1211,10 +1212,9 @@ array_length_coerce(PG_FUNCTION_ARGS)
my_extra = (alc_extra *) fmgr_info->fn_extra;
if (my_extra == NULL)
{
- fmgr_info->fn_extra = MemoryContextAlloc(fmgr_info->fn_mcxt,
- sizeof(alc_extra));
+ fmgr_info->fn_extra = MemoryContextAllocZero(fmgr_info->fn_mcxt,
+ sizeof(alc_extra));
my_extra = (alc_extra *) fmgr_info->fn_extra;
- my_extra->elemtype = InvalidOid;
}
if (my_extra->elemtype != ARR_ELEMTYPE(v))
@@ -1251,7 +1251,8 @@ array_length_coerce(PG_FUNCTION_ARGS)
locfcinfo.arg[1] = Int32GetDatum(len);
locfcinfo.arg[2] = BoolGetDatum(isExplicit);
- return array_map(&locfcinfo, ARR_ELEMTYPE(v), ARR_ELEMTYPE(v));
+ return array_map(&locfcinfo, ARR_ELEMTYPE(v), ARR_ELEMTYPE(v),
+ &my_extra->amstate);
}
/*-----------------------------------------------------------------------------
@@ -2015,13 +2016,20 @@ array_set_slice(ArrayType *array,
* or binary-compatible with, the first argument type of fn().
* * retType: OID of element type of output array. This must be the same as,
* or binary-compatible with, the result type of fn().
+ * * amstate: workspace for array_map. Must be zeroed by caller before
+ * first call, and not touched after that.
+ *
+ * It is legitimate to pass a freshly-zeroed ArrayMapState on each call,
+ * but better performance can be had if the state can be preserved across
+ * a series of calls.
*
* NB: caller must assure that input array is not NULL. Currently,
* any additional parameters passed to fn() may not be specified as NULL
* either.
*/
Datum
-array_map(FunctionCallInfo fcinfo, Oid inpType, Oid retType)
+array_map(FunctionCallInfo fcinfo, Oid inpType, Oid retType,
+ ArrayMapState *amstate)
{
ArrayType *v;
ArrayType *result;
@@ -2039,12 +2047,6 @@ array_map(FunctionCallInfo fcinfo, Oid inpType, Oid retType)
bool typbyval;
char typalign;
char *s;
- typedef struct
- {
- ArrayMetaState inp_extra;
- ArrayMetaState ret_extra;
- } am_extra;
- am_extra *my_extra;
ArrayMetaState *inp_extra;
ArrayMetaState *ret_extra;
@@ -2076,22 +2078,8 @@ array_map(FunctionCallInfo fcinfo, Oid inpType, Oid retType)
* only once per series of calls, assuming the element type doesn't
* change underneath us.
*/
- my_extra = (am_extra *) fcinfo->flinfo->fn_extra;
- if (my_extra == NULL)
- {
- fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
- sizeof(am_extra));
- my_extra = (am_extra *) fcinfo->flinfo->fn_extra;
- inp_extra = &my_extra->inp_extra;
- inp_extra->element_type = InvalidOid;
- ret_extra = &my_extra->ret_extra;
- ret_extra->element_type = InvalidOid;
- }
- else
- {
- inp_extra = &my_extra->inp_extra;
- ret_extra = &my_extra->ret_extra;
- }
+ inp_extra = &amstate->inp_extra;
+ ret_extra = &amstate->ret_extra;
if (inp_extra->element_type != inpType)
{
@@ -2898,6 +2886,7 @@ array_type_coerce(PG_FUNCTION_ARGS)
Oid srctype;
Oid desttype;
FmgrInfo coerce_finfo;
+ ArrayMapState amstate;
} atc_extra;
atc_extra *my_extra;
FunctionCallInfoData locfcinfo;
@@ -2910,10 +2899,9 @@ array_type_coerce(PG_FUNCTION_ARGS)
my_extra = (atc_extra *) fmgr_info->fn_extra;
if (my_extra == NULL)
{
- fmgr_info->fn_extra = MemoryContextAlloc(fmgr_info->fn_mcxt,
- sizeof(atc_extra));
+ fmgr_info->fn_extra = MemoryContextAllocZero(fmgr_info->fn_mcxt,
+ sizeof(atc_extra));
my_extra = (atc_extra *) fmgr_info->fn_extra;
- my_extra->srctype = InvalidOid;
}
if (my_extra->srctype != src_elem_type)
@@ -2981,7 +2969,8 @@ array_type_coerce(PG_FUNCTION_ARGS)
locfcinfo.nargs = 1;
locfcinfo.arg[0] = PointerGetDatum(src);
- return array_map(&locfcinfo, my_extra->srctype, my_extra->desttype);
+ return array_map(&locfcinfo, my_extra->srctype, my_extra->desttype,
+ &my_extra->amstate);
}
/*