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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy