@@ -1204,6 +1204,10 @@ init_fcache(Oid foid, FuncExprState *fcache,
12041204fmgr_info_cxt (foid ,& (fcache -> func ),fcacheCxt );
12051205fcache -> func .fn_expr = (Node * )fcache -> xprstate .expr ;
12061206
1207+ /* Initialize the function call parameter struct as well */
1208+ InitFunctionCallInfoData (fcache -> fcinfo_data ,& (fcache -> func ),
1209+ list_length (fcache -> args ),NULL ,NULL );
1210+
12071211/* If function returns set, prepare expected tuple descriptor */
12081212if (fcache -> func .fn_retset && needDescForSets )
12091213{
@@ -1385,7 +1389,7 @@ ExecEvalFuncArgs(FunctionCallInfo fcinfo,
13851389i ++ ;
13861390}
13871391
1388- fcinfo -> nargs = i ;
1392+ Assert ( i == fcinfo -> nargs ) ;
13891393
13901394return argIsDone ;
13911395}
@@ -1535,7 +1539,6 @@ ExecMakeFunctionResult(FuncExprState *fcache,
15351539{
15361540List * arguments ;
15371541Datum result ;
1538- FunctionCallInfoData fcinfo_data ;
15391542FunctionCallInfo fcinfo ;
15401543PgStat_FunctionCallUsage fcusage ;
15411544ReturnSetInfo rsinfo ;/* for functions returning sets */
@@ -1586,31 +1589,16 @@ ExecMakeFunctionResult(FuncExprState *fcache,
15861589Assert (!fcache -> setArgsValid );
15871590}
15881591
1589- /*
1590- * For non-set-returning functions, we just use a local-variable
1591- * FunctionCallInfoData. For set-returning functions we keep the callinfo
1592- * record in fcache->setArgs so that it can survive across multiple
1593- * value-per-call invocations.(The reason we don't just do the latter
1594- * all the time is that plpgsql expects to be able to use simple
1595- * expression trees re-entrantly. Which might not be a good idea, but the
1596- * penalty for not doing so is high.)
1597- */
1598- if (fcache -> func .fn_retset )
1599- fcinfo = & fcache -> setArgs ;
1600- else
1601- fcinfo = & fcinfo_data ;
1602-
16031592/*
16041593 * arguments is a list of expressions to evaluate before passing to the
16051594 * function manager. We skip the evaluation if it was already done in the
16061595 * previous call (ie, we are continuing the evaluation of a set-valued
16071596 * function). Otherwise, collect the current argument values into fcinfo.
16081597 */
1598+ fcinfo = & fcache -> fcinfo_data ;
16091599arguments = fcache -> args ;
16101600if (!fcache -> setArgsValid )
16111601{
1612- /* Need to prep callinfo structure */
1613- InitFunctionCallInfoData (* fcinfo ,& (fcache -> func ),0 ,NULL ,NULL );
16141602argDone = ExecEvalFuncArgs (fcinfo ,arguments ,econtext );
16151603if (argDone == ExprEndResult )
16161604{
@@ -1726,7 +1714,6 @@ ExecMakeFunctionResult(FuncExprState *fcache,
17261714if (fcache -> func .fn_retset &&
17271715* isDone == ExprMultipleResult )
17281716{
1729- Assert (fcinfo == & fcache -> setArgs );
17301717fcache -> setHasSetArg = hasSetArg ;
17311718fcache -> setArgsValid = true;
17321719/* Register cleanup callback if we didn't already */
@@ -1856,7 +1843,7 @@ ExecMakeFunctionResultNoSets(FuncExprState *fcache,
18561843{
18571844ListCell * arg ;
18581845Datum result ;
1859- FunctionCallInfoData fcinfo ;
1846+ FunctionCallInfo fcinfo ;
18601847PgStat_FunctionCallUsage fcusage ;
18611848int i ;
18621849
@@ -1867,20 +1854,19 @@ ExecMakeFunctionResultNoSets(FuncExprState *fcache,
18671854* isDone = ExprSingleResult ;
18681855
18691856/* inlined, simplified version of ExecEvalFuncArgs */
1857+ fcinfo = & fcache -> fcinfo_data ;
18701858i = 0 ;
18711859foreach (arg ,fcache -> args )
18721860{
18731861ExprState * argstate = (ExprState * )lfirst (arg );
18741862
1875- fcinfo . arg [i ]= ExecEvalExpr (argstate ,
1876- econtext ,
1877- & fcinfo . argnull [i ],
1878- NULL );
1863+ fcinfo -> arg [i ]= ExecEvalExpr (argstate ,
1864+ econtext ,
1865+ & fcinfo -> argnull [i ],
1866+ NULL );
18791867i ++ ;
18801868}
18811869
1882- InitFunctionCallInfoData (fcinfo ,& (fcache -> func ),i ,NULL ,NULL );
1883-
18841870/*
18851871 * If function is strict, and there are any NULL arguments, skip calling
18861872 * the function and return NULL.
@@ -1889,19 +1875,19 @@ ExecMakeFunctionResultNoSets(FuncExprState *fcache,
18891875{
18901876while (-- i >=0 )
18911877{
1892- if (fcinfo . argnull [i ])
1878+ if (fcinfo -> argnull [i ])
18931879{
18941880* isNull = true;
18951881return (Datum )0 ;
18961882}
18971883}
18981884}
18991885
1900- pgstat_init_function_usage (& fcinfo ,& fcusage );
1886+ pgstat_init_function_usage (fcinfo ,& fcusage );
19011887
1902- /* fcinfo. isnull = false; */ /* handled by InitFunctionCallInfoData */
1903- result = FunctionCallInvoke (& fcinfo );
1904- * isNull = fcinfo . isnull ;
1888+ fcinfo -> isnull = false;
1889+ result = FunctionCallInvoke (fcinfo );
1890+ * isNull = fcinfo -> isnull ;
19051891
19061892pgstat_end_function_usage (& fcusage , true);
19071893
@@ -1948,7 +1934,6 @@ ExecMakeTableFunctionResult(ExprState *funcexpr,
19481934 * resultinfo, but set it up anyway because we use some of the fields as
19491935 * our own state variables.
19501936 */
1951- InitFunctionCallInfoData (fcinfo ,NULL ,0 ,NULL , (Node * )& rsinfo );
19521937rsinfo .type = T_ReturnSetInfo ;
19531938rsinfo .econtext = econtext ;
19541939rsinfo .expectedDesc = expectedDesc ;
@@ -1992,6 +1977,9 @@ ExecMakeTableFunctionResult(ExprState *funcexpr,
19921977econtext -> ecxt_per_query_memory , false);
19931978}
19941979returnsSet = fcache -> func .fn_retset ;
1980+ InitFunctionCallInfoData (fcinfo ,& (fcache -> func ),
1981+ list_length (fcache -> args ),
1982+ NULL , (Node * )& rsinfo );
19951983
19961984/*
19971985 * Evaluate the function's argument list.
@@ -2001,7 +1989,6 @@ ExecMakeTableFunctionResult(ExprState *funcexpr,
20011989 * inner loop.So do it in caller context. Perhaps we should make a
20021990 * separate context just to hold the evaluated arguments?
20031991 */
2004- fcinfo .flinfo = & (fcache -> func );
20051992argDone = ExecEvalFuncArgs (& fcinfo ,fcache -> args ,econtext );
20061993/* We don't allow sets in the arguments of the table function */
20071994if (argDone != ExprSingleResult )
@@ -2029,6 +2016,7 @@ ExecMakeTableFunctionResult(ExprState *funcexpr,
20292016{
20302017/* Treat funcexpr as a generic expression */
20312018direct_function_call = false;
2019+ InitFunctionCallInfoData (fcinfo ,NULL ,0 ,NULL ,NULL );
20322020}
20332021
20342022/*
@@ -2312,9 +2300,8 @@ ExecEvalDistinct(FuncExprState *fcache,
23122300ExprDoneCond * isDone )
23132301{
23142302Datum result ;
2315- FunctionCallInfoData fcinfo ;
2303+ FunctionCallInfo fcinfo ;
23162304ExprDoneCond argDone ;
2317- List * argList ;
23182305
23192306/* Set default values for result flags: non-null, not a set result */
23202307* isNull = false;
@@ -2334,34 +2321,31 @@ ExecEvalDistinct(FuncExprState *fcache,
23342321}
23352322
23362323/*
2337- *extract info from fcache
2324+ *Evaluate arguments
23382325 */
2339- argList = fcache -> args ;
2340-
2341- /* Need to prep callinfo structure */
2342- InitFunctionCallInfoData (fcinfo ,& (fcache -> func ),0 ,NULL ,NULL );
2343- argDone = ExecEvalFuncArgs (& fcinfo ,argList ,econtext );
2326+ fcinfo = & fcache -> fcinfo_data ;
2327+ argDone = ExecEvalFuncArgs (fcinfo ,fcache -> args ,econtext );
23442328if (argDone != ExprSingleResult )
23452329ereport (ERROR ,
23462330(errcode (ERRCODE_DATATYPE_MISMATCH ),
23472331errmsg ("IS DISTINCT FROM does not support set arguments" )));
2348- Assert (fcinfo . nargs == 2 );
2332+ Assert (fcinfo -> nargs == 2 );
23492333
2350- if (fcinfo . argnull [0 ]&& fcinfo . argnull [1 ])
2334+ if (fcinfo -> argnull [0 ]&& fcinfo -> argnull [1 ])
23512335{
23522336/* Both NULL? Then is not distinct... */
23532337result = BoolGetDatum (FALSE);
23542338}
2355- else if (fcinfo . argnull [0 ]|| fcinfo . argnull [1 ])
2339+ else if (fcinfo -> argnull [0 ]|| fcinfo -> argnull [1 ])
23562340{
23572341/* Only one is NULL? Then is distinct... */
23582342result = BoolGetDatum (TRUE);
23592343}
23602344else
23612345{
2362- fcinfo . isnull = false;
2363- result = FunctionCallInvoke (& fcinfo );
2364- * isNull = fcinfo . isnull ;
2346+ fcinfo -> isnull = false;
2347+ result = FunctionCallInvoke (fcinfo );
2348+ * isNull = fcinfo -> isnull ;
23652349/* Must invert result of "=" */
23662350result = BoolGetDatum (!DatumGetBool (result ));
23672351}
@@ -2388,7 +2372,7 @@ ExecEvalScalarArrayOp(ScalarArrayOpExprState *sstate,
23882372int nitems ;
23892373Datum result ;
23902374bool resultnull ;
2391- FunctionCallInfoData fcinfo ;
2375+ FunctionCallInfo fcinfo ;
23922376ExprDoneCond argDone ;
23932377int i ;
23942378int16 typlen ;
@@ -2413,26 +2397,28 @@ ExecEvalScalarArrayOp(ScalarArrayOpExprState *sstate,
24132397Assert (!sstate -> fxprstate .func .fn_retset );
24142398}
24152399
2416- /* Need to prep callinfo structure */
2417- InitFunctionCallInfoData (fcinfo ,& (sstate -> fxprstate .func ),0 ,NULL ,NULL );
2418- argDone = ExecEvalFuncArgs (& fcinfo ,sstate -> fxprstate .args ,econtext );
2400+ /*
2401+ * Evaluate arguments
2402+ */
2403+ fcinfo = & sstate -> fxprstate .fcinfo_data ;
2404+ argDone = ExecEvalFuncArgs (fcinfo ,sstate -> fxprstate .args ,econtext );
24192405if (argDone != ExprSingleResult )
24202406ereport (ERROR ,
24212407(errcode (ERRCODE_DATATYPE_MISMATCH ),
24222408errmsg ("op ANY/ALL (array) does not support set arguments" )));
2423- Assert (fcinfo . nargs == 2 );
2409+ Assert (fcinfo -> nargs == 2 );
24242410
24252411/*
24262412 * If the array is NULL then we return NULL --- it's not very meaningful
24272413 * to do anything else, even if the operator isn't strict.
24282414 */
2429- if (fcinfo . argnull [1 ])
2415+ if (fcinfo -> argnull [1 ])
24302416{
24312417* isNull = true;
24322418return (Datum )0 ;
24332419}
24342420/* Else okay to fetch and detoast the array */
2435- arr = DatumGetArrayTypeP (fcinfo . arg [1 ]);
2421+ arr = DatumGetArrayTypeP (fcinfo -> arg [1 ]);
24362422
24372423/*
24382424 * If the array is empty, we return either FALSE or TRUE per the useOr
@@ -2448,7 +2434,7 @@ ExecEvalScalarArrayOp(ScalarArrayOpExprState *sstate,
24482434 * If the scalar is NULL, and the function is strict, return NULL; no
24492435 * point in iterating the loop.
24502436 */
2451- if (fcinfo . argnull [0 ]&& sstate -> fxprstate .func .fn_strict )
2437+ if (fcinfo -> argnull [0 ]&& sstate -> fxprstate .func .fn_strict )
24522438{
24532439* isNull = true;
24542440return (Datum )0 ;
@@ -2486,32 +2472,32 @@ ExecEvalScalarArrayOp(ScalarArrayOpExprState *sstate,
24862472/* Get array element, checking for NULL */
24872473if (bitmap && (* bitmap & bitmask )== 0 )
24882474{
2489- fcinfo . arg [1 ]= (Datum )0 ;
2490- fcinfo . argnull [1 ]= true;
2475+ fcinfo -> arg [1 ]= (Datum )0 ;
2476+ fcinfo -> argnull [1 ]= true;
24912477}
24922478else
24932479{
24942480elt = fetch_att (s ,typbyval ,typlen );
24952481s = att_addlength_pointer (s ,typlen ,s );
24962482s = (char * )att_align_nominal (s ,typalign );
2497- fcinfo . arg [1 ]= elt ;
2498- fcinfo . argnull [1 ]= false;
2483+ fcinfo -> arg [1 ]= elt ;
2484+ fcinfo -> argnull [1 ]= false;
24992485}
25002486
25012487/* Call comparison function */
2502- if (fcinfo . argnull [1 ]&& sstate -> fxprstate .func .fn_strict )
2488+ if (fcinfo -> argnull [1 ]&& sstate -> fxprstate .func .fn_strict )
25032489{
2504- fcinfo . isnull = true;
2490+ fcinfo -> isnull = true;
25052491thisresult = (Datum )0 ;
25062492}
25072493else
25082494{
2509- fcinfo . isnull = false;
2510- thisresult = FunctionCallInvoke (& fcinfo );
2495+ fcinfo -> isnull = false;
2496+ thisresult = FunctionCallInvoke (fcinfo );
25112497}
25122498
25132499/* Combine results per OR or AND semantics */
2514- if (fcinfo . isnull )
2500+ if (fcinfo -> isnull )
25152501resultnull = true;
25162502else if (useOr )
25172503{
@@ -3526,9 +3512,8 @@ ExecEvalNullIf(FuncExprState *nullIfExpr,
35263512bool * isNull ,ExprDoneCond * isDone )
35273513{
35283514Datum result ;
3529- FunctionCallInfoData fcinfo ;
3515+ FunctionCallInfo fcinfo ;
35303516ExprDoneCond argDone ;
3531- List * argList ;
35323517
35333518if (isDone )
35343519* isDone = ExprSingleResult ;
@@ -3546,35 +3531,32 @@ ExecEvalNullIf(FuncExprState *nullIfExpr,
35463531}
35473532
35483533/*
3549- *extract info from nullIfExpr
3534+ *Evaluate arguments
35503535 */
3551- argList = nullIfExpr -> args ;
3552-
3553- /* Need to prep callinfo structure */
3554- InitFunctionCallInfoData (fcinfo ,& (nullIfExpr -> func ),0 ,NULL ,NULL );
3555- argDone = ExecEvalFuncArgs (& fcinfo ,argList ,econtext );
3536+ fcinfo = & nullIfExpr -> fcinfo_data ;
3537+ argDone = ExecEvalFuncArgs (fcinfo ,nullIfExpr -> args ,econtext );
35563538if (argDone != ExprSingleResult )
35573539ereport (ERROR ,
35583540(errcode (ERRCODE_DATATYPE_MISMATCH ),
35593541errmsg ("NULLIF does not support set arguments" )));
3560- Assert (fcinfo . nargs == 2 );
3542+ Assert (fcinfo -> nargs == 2 );
35613543
35623544/* if either argument is NULL they can't be equal */
3563- if (!fcinfo . argnull [0 ]&& !fcinfo . argnull [1 ])
3545+ if (!fcinfo -> argnull [0 ]&& !fcinfo -> argnull [1 ])
35643546{
3565- fcinfo . isnull = false;
3566- result = FunctionCallInvoke (& fcinfo );
3547+ fcinfo -> isnull = false;
3548+ result = FunctionCallInvoke (fcinfo );
35673549/* if the arguments are equal return null */
3568- if (!fcinfo . isnull && DatumGetBool (result ))
3550+ if (!fcinfo -> isnull && DatumGetBool (result ))
35693551{
35703552* isNull = true;
35713553return (Datum )0 ;
35723554}
35733555}
35743556
35753557/* else return first argument */
3576- * isNull = fcinfo . argnull [0 ];
3577- return fcinfo . arg [0 ];
3558+ * isNull = fcinfo -> argnull [0 ];
3559+ return fcinfo -> arg [0 ];
35783560}
35793561
35803562/* ----------------------------------------------------------------