1
0
mirror of https://github.com/postgres/postgres.git synced 2025-05-18 17:41:14 +03:00

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.
This commit is contained in:
Tom Lane 2005-03-24 21:51:04 +00:00
parent b4fd104204
commit 3e65431bc1
2 changed files with 33 additions and 34 deletions

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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; Oid elemtype;
FmgrInfo coerce_finfo; FmgrInfo coerce_finfo;
ArrayMapState amstate;
} alc_extra; } alc_extra;
alc_extra *my_extra; alc_extra *my_extra;
FunctionCallInfoData locfcinfo; FunctionCallInfoData locfcinfo;
@ -1211,10 +1212,9 @@ array_length_coerce(PG_FUNCTION_ARGS)
my_extra = (alc_extra *) fmgr_info->fn_extra; my_extra = (alc_extra *) fmgr_info->fn_extra;
if (my_extra == NULL) if (my_extra == NULL)
{ {
fmgr_info->fn_extra = MemoryContextAlloc(fmgr_info->fn_mcxt, fmgr_info->fn_extra = MemoryContextAllocZero(fmgr_info->fn_mcxt,
sizeof(alc_extra)); sizeof(alc_extra));
my_extra = (alc_extra *) fmgr_info->fn_extra; my_extra = (alc_extra *) fmgr_info->fn_extra;
my_extra->elemtype = InvalidOid;
} }
if (my_extra->elemtype != ARR_ELEMTYPE(v)) if (my_extra->elemtype != ARR_ELEMTYPE(v))
@ -1251,7 +1251,8 @@ array_length_coerce(PG_FUNCTION_ARGS)
locfcinfo.arg[1] = Int32GetDatum(len); locfcinfo.arg[1] = Int32GetDatum(len);
locfcinfo.arg[2] = BoolGetDatum(isExplicit); 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(). * or binary-compatible with, the first argument type of fn().
* * retType: OID of element type of output array. This must be the same as, * * retType: OID of element type of output array. This must be the same as,
* or binary-compatible with, the result type of fn(). * 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, * NB: caller must assure that input array is not NULL. Currently,
* any additional parameters passed to fn() may not be specified as NULL * any additional parameters passed to fn() may not be specified as NULL
* either. * either.
*/ */
Datum Datum
array_map(FunctionCallInfo fcinfo, Oid inpType, Oid retType) array_map(FunctionCallInfo fcinfo, Oid inpType, Oid retType,
ArrayMapState *amstate)
{ {
ArrayType *v; ArrayType *v;
ArrayType *result; ArrayType *result;
@ -2039,12 +2047,6 @@ array_map(FunctionCallInfo fcinfo, Oid inpType, Oid retType)
bool typbyval; bool typbyval;
char typalign; char typalign;
char *s; char *s;
typedef struct
{
ArrayMetaState inp_extra;
ArrayMetaState ret_extra;
} am_extra;
am_extra *my_extra;
ArrayMetaState *inp_extra; ArrayMetaState *inp_extra;
ArrayMetaState *ret_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 * only once per series of calls, assuming the element type doesn't
* change underneath us. * change underneath us.
*/ */
my_extra = (am_extra *) fcinfo->flinfo->fn_extra; inp_extra = &amstate->inp_extra;
if (my_extra == NULL) ret_extra = &amstate->ret_extra;
{
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;
}
if (inp_extra->element_type != inpType) if (inp_extra->element_type != inpType)
{ {
@ -2898,6 +2886,7 @@ array_type_coerce(PG_FUNCTION_ARGS)
Oid srctype; Oid srctype;
Oid desttype; Oid desttype;
FmgrInfo coerce_finfo; FmgrInfo coerce_finfo;
ArrayMapState amstate;
} atc_extra; } atc_extra;
atc_extra *my_extra; atc_extra *my_extra;
FunctionCallInfoData locfcinfo; FunctionCallInfoData locfcinfo;
@ -2910,10 +2899,9 @@ array_type_coerce(PG_FUNCTION_ARGS)
my_extra = (atc_extra *) fmgr_info->fn_extra; my_extra = (atc_extra *) fmgr_info->fn_extra;
if (my_extra == NULL) if (my_extra == NULL)
{ {
fmgr_info->fn_extra = MemoryContextAlloc(fmgr_info->fn_mcxt, fmgr_info->fn_extra = MemoryContextAllocZero(fmgr_info->fn_mcxt,
sizeof(atc_extra)); sizeof(atc_extra));
my_extra = (atc_extra *) fmgr_info->fn_extra; my_extra = (atc_extra *) fmgr_info->fn_extra;
my_extra->srctype = InvalidOid;
} }
if (my_extra->srctype != src_elem_type) if (my_extra->srctype != src_elem_type)
@ -2981,7 +2969,8 @@ array_type_coerce(PG_FUNCTION_ARGS)
locfcinfo.nargs = 1; locfcinfo.nargs = 1;
locfcinfo.arg[0] = PointerGetDatum(src); 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);
} }
/* /*

View File

@ -10,7 +10,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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; FmgrInfo proc;
} ArrayMetaState; } 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 * 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, int arraylen, int elmlen, bool elmbyval, char elmalign,
bool *isNull); 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, extern ArrayType *construct_array(Datum *elems, int nelems,
Oid elmtype, Oid elmtype,