]> granicus.if.org Git - postgresql/commitdiff
array_map can't use the fn_extra field of the provided fcinfo struct as
authorTom Lane <tgl@sss.pgh.pa.us>
Thu, 24 Mar 2005 21:51:04 +0000 (21:51 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Thu, 24 Mar 2005 21:51:04 +0000 (21:51 +0000)
its private storage, because that belongs to the function that it is
supposed to call.  Per report from Ezequiel Tolnay.

src/backend/utils/adt/arrayfuncs.c
src/include/utils/array.h

index eedc3990fa4671dc151eed38f43d945e0e3f9093..9c9d3541e1e9e2bd227169ef56e4c4fcc0e9f5c5 100644 (file)
@@ -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);
 }
 
 /*
index f37a8e117e76dd01f775919fc4289c8b098d4adb..1c0f1090214b268cd0968b6c8537641d32497142 100644 (file)
@@ -10,7 +10,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: array.h,v 1.45 2003/08/08 21:42:55 momjian Exp $
+ * $Id: array.h,v 1.45.4.1 2005/03/24 21:51:04 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -64,6 +64,15 @@ typedef struct ArrayMetaState
        FmgrInfo        proc;
 } ArrayMetaState;
 
+/*
+ * private state needed by array_map (here because caller must provide it)
+ */
+typedef struct ArrayMapState
+{
+       ArrayMetaState inp_extra;
+       ArrayMetaState ret_extra;
+} ArrayMapState;
+
 /*
  * fmgr macros for array objects
  */
@@ -146,7 +155,8 @@ extern ArrayType *array_set_slice(ArrayType *array, int nSubscripts,
                                int arraylen, int elmlen, bool elmbyval, char elmalign,
                                bool *isNull);
 
-extern Datum array_map(FunctionCallInfo fcinfo, Oid inpType, Oid retType);
+extern Datum array_map(FunctionCallInfo fcinfo, Oid inpType, Oid retType,
+                                          ArrayMapState *amstate);
 
 extern ArrayType *construct_array(Datum *elems, int nelems,
                                Oid elmtype,