Skip to content

Commit 0dca4fc

Browse files
committed
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.
1 parent 8269ad4 commit 0dca4fc

File tree

2 files changed

+33
-34
lines changed

2 files changed

+33
-34
lines changed

src/backend/utils/adt/arrayfuncs.c

Lines changed: 21 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.116 2005/02/28 03:45:21 neilc Exp $
11+
* $PostgreSQL: pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.117 2005/03/24 21:50:37 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -2193,13 +2193,20 @@ array_set_slice(ArrayType *array,
21932193
* or binary-compatible with, the first argument type of fn().
21942194
* * retType: OID of element type of output array. This must be the same as,
21952195
* or binary-compatible with, the result type of fn().
2196+
* * amstate: workspace for array_map. Must be zeroed by caller before
2197+
* first call, and not touched after that.
2198+
*
2199+
* It is legitimate to pass a freshly-zeroed ArrayMapState on each call,
2200+
* but better performance can be had if the state can be preserved across
2201+
* a series of calls.
21962202
*
21972203
* NB: caller must assure that input array is not NULL. Currently,
21982204
* any additional parameters passed to fn() may not be specified as NULL
21992205
* either.
22002206
*/
22012207
Datum
2202-
array_map(FunctionCallInfo fcinfo, Oid inpType, Oid retType)
2208+
array_map(FunctionCallInfo fcinfo, Oid inpType, Oid retType,
2209+
ArrayMapState *amstate)
22032210
{
22042211
ArrayType *v;
22052212
ArrayType *result;
@@ -2217,12 +2224,6 @@ array_map(FunctionCallInfo fcinfo, Oid inpType, Oid retType)
22172224
bool typbyval;
22182225
char typalign;
22192226
char *s;
2220-
typedef struct
2221-
{
2222-
ArrayMetaState inp_extra;
2223-
ArrayMetaState ret_extra;
2224-
} am_extra;
2225-
am_extra *my_extra;
22262227
ArrayMetaState *inp_extra;
22272228
ArrayMetaState *ret_extra;
22282229

@@ -2254,22 +2255,8 @@ array_map(FunctionCallInfo fcinfo, Oid inpType, Oid retType)
22542255
* only once per series of calls, assuming the element type doesn't
22552256
* change underneath us.
22562257
*/
2257-
my_extra = (am_extra *) fcinfo->flinfo->fn_extra;
2258-
if (my_extra == NULL)
2259-
{
2260-
fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
2261-
sizeof(am_extra));
2262-
my_extra = (am_extra *) fcinfo->flinfo->fn_extra;
2263-
inp_extra = &my_extra->inp_extra;
2264-
inp_extra->element_type = InvalidOid;
2265-
ret_extra = &my_extra->ret_extra;
2266-
ret_extra->element_type = InvalidOid;
2267-
}
2268-
else
2269-
{
2270-
inp_extra = &my_extra->inp_extra;
2271-
ret_extra = &my_extra->ret_extra;
2272-
}
2258+
inp_extra = &amstate->inp_extra;
2259+
ret_extra = &amstate->ret_extra;
22732260

22742261
if (inp_extra->element_type != inpType)
22752262
{
@@ -3101,6 +3088,7 @@ array_type_length_coerce_internal(ArrayType *src,
31013088
Oid srctype;
31023089
Oid desttype;
31033090
FmgrInfo coerce_finfo;
3091+
ArrayMapState amstate;
31043092
} atc_extra;
31053093
atc_extra *my_extra;
31063094
FunctionCallInfoData locfcinfo;
@@ -3113,10 +3101,9 @@ array_type_length_coerce_internal(ArrayType *src,
31133101
my_extra = (atc_extra *) fmgr_info->fn_extra;
31143102
if (my_extra == NULL)
31153103
{
3116-
fmgr_info->fn_extra = MemoryContextAlloc(fmgr_info->fn_mcxt,
3117-
sizeof(atc_extra));
3104+
fmgr_info->fn_extra = MemoryContextAllocZero(fmgr_info->fn_mcxt,
3105+
sizeof(atc_extra));
31183106
my_extra = (atc_extra *) fmgr_info->fn_extra;
3119-
my_extra->srctype = InvalidOid;
31203107
}
31213108

31223109
if (my_extra->srctype != src_elem_type)
@@ -3192,7 +3179,8 @@ array_type_length_coerce_internal(ArrayType *src,
31923179
locfcinfo.arg[1] = Int32GetDatum(desttypmod);
31933180
locfcinfo.arg[2] = BoolGetDatum(isExplicit);
31943181

3195-
return array_map(&locfcinfo, my_extra->srctype, my_extra->desttype);
3182+
return array_map(&locfcinfo, my_extra->srctype, my_extra->desttype,
3183+
&my_extra->amstate);
31963184
}
31973185

31983186
/*
@@ -3210,6 +3198,7 @@ array_length_coerce(PG_FUNCTION_ARGS)
32103198
{
32113199
Oid elemtype;
32123200
FmgrInfo coerce_finfo;
3201+
ArrayMapState amstate;
32133202
} alc_extra;
32143203
alc_extra *my_extra;
32153204
FunctionCallInfoData locfcinfo;
@@ -3226,10 +3215,9 @@ array_length_coerce(PG_FUNCTION_ARGS)
32263215
my_extra = (alc_extra *) fmgr_info->fn_extra;
32273216
if (my_extra == NULL)
32283217
{
3229-
fmgr_info->fn_extra = MemoryContextAlloc(fmgr_info->fn_mcxt,
3230-
sizeof(alc_extra));
3218+
fmgr_info->fn_extra = MemoryContextAllocZero(fmgr_info->fn_mcxt,
3219+
sizeof(alc_extra));
32313220
my_extra = (alc_extra *) fmgr_info->fn_extra;
3232-
my_extra->elemtype = InvalidOid;
32333221
}
32343222

32353223
if (my_extra->elemtype != ARR_ELEMTYPE(v))
@@ -3265,7 +3253,8 @@ array_length_coerce(PG_FUNCTION_ARGS)
32653253
locfcinfo.arg[1] = Int32GetDatum(desttypmod);
32663254
locfcinfo.arg[2] = BoolGetDatum(isExplicit);
32673255

3268-
return array_map(&locfcinfo, ARR_ELEMTYPE(v), ARR_ELEMTYPE(v));
3256+
return array_map(&locfcinfo, ARR_ELEMTYPE(v), ARR_ELEMTYPE(v),
3257+
&my_extra->amstate);
32693258
}
32703259

32713260
/*

src/include/utils/array.h

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
1111
* Portions Copyright (c) 1994, Regents of the University of California
1212
*
13-
* $PostgreSQL: pgsql/src/include/utils/array.h,v 1.52 2005/02/28 03:45:23 neilc Exp $
13+
* $PostgreSQL: pgsql/src/include/utils/array.h,v 1.53 2005/03/24 21:50:38 tgl Exp $
1414
*
1515
*-------------------------------------------------------------------------
1616
*/
@@ -64,6 +64,15 @@ typedef struct ArrayMetaState
6464
FmgrInfo proc;
6565
} ArrayMetaState;
6666

67+
/*
68+
* private state needed by array_map (here because caller must provide it)
69+
*/
70+
typedef struct ArrayMapState
71+
{
72+
ArrayMetaState inp_extra;
73+
ArrayMetaState ret_extra;
74+
} ArrayMapState;
75+
6776
/*
6877
* fmgr macros for array objects
6978
*/
@@ -149,7 +158,8 @@ extern ArrayType *array_set_slice(ArrayType *array, int nSubscripts,
149158
int arraylen, int elmlen, bool elmbyval, char elmalign,
150159
bool *isNull);
151160

152-
extern Datum array_map(FunctionCallInfo fcinfo, Oid inpType, Oid retType);
161+
extern Datum array_map(FunctionCallInfo fcinfo, Oid inpType, Oid retType,
162+
ArrayMapState *amstate);
153163

154164
extern ArrayType *construct_array(Datum *elems, int nelems,
155165
Oid elmtype,

0 commit comments

Comments
 (0)