@@ -1204,6 +1204,10 @@ init_fcache(Oid foid, FuncExprState *fcache,
12041204 fmgr_info_cxt (foid , & (fcache -> func ), fcacheCxt );
12051205 fcache -> 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 */
12081212 if (fcache -> func .fn_retset && needDescForSets )
12091213 {
@@ -1385,7 +1389,7 @@ ExecEvalFuncArgs(FunctionCallInfo fcinfo,
13851389 i ++ ;
13861390 }
13871391
1388- fcinfo -> nargs = i ;
1392+ Assert ( i == fcinfo -> nargs ) ;
13891393
13901394 return argIsDone ;
13911395}
@@ -1535,7 +1539,6 @@ ExecMakeFunctionResult(FuncExprState *fcache,
15351539{
15361540 List * arguments ;
15371541 Datum result ;
1538- FunctionCallInfoData fcinfo_data ;
15391542 FunctionCallInfo fcinfo ;
15401543 PgStat_FunctionCallUsage fcusage ;
15411544 ReturnSetInfo rsinfo ; /* for functions returning sets */
@@ -1586,31 +1589,16 @@ ExecMakeFunctionResult(FuncExprState *fcache,
15861589 Assert (!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 ;
16091599 arguments = fcache -> args ;
16101600 if (!fcache -> setArgsValid )
16111601 {
1612- /* Need to prep callinfo structure */
1613- InitFunctionCallInfoData (* fcinfo , & (fcache -> func ), 0 , NULL , NULL );
16141602 argDone = ExecEvalFuncArgs (fcinfo , arguments , econtext );
16151603 if (argDone == ExprEndResult )
16161604 {
@@ -1726,7 +1714,6 @@ ExecMakeFunctionResult(FuncExprState *fcache,
17261714 if (fcache -> func .fn_retset &&
17271715 * isDone == ExprMultipleResult )
17281716 {
1729- Assert (fcinfo == & fcache -> setArgs );
17301717 fcache -> setHasSetArg = hasSetArg ;
17311718 fcache -> setArgsValid = true;
17321719 /* Register cleanup callback if we didn't already */
@@ -1856,7 +1843,7 @@ ExecMakeFunctionResultNoSets(FuncExprState *fcache,
18561843{
18571844 ListCell * arg ;
18581845 Datum result ;
1859- FunctionCallInfoData fcinfo ;
1846+ FunctionCallInfo fcinfo ;
18601847 PgStat_FunctionCallUsage fcusage ;
18611848 int i ;
18621849
@@ -1867,20 +1854,19 @@ ExecMakeFunctionResultNoSets(FuncExprState *fcache,
18671854 * isDone = ExprSingleResult ;
18681855
18691856 /* inlined, simplified version of ExecEvalFuncArgs */
1857+ fcinfo = & fcache -> fcinfo_data ;
18701858 i = 0 ;
18711859 foreach (arg , fcache -> args )
18721860 {
18731861 ExprState * 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 );
18791867 i ++ ;
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 {
18901876 while (-- i >= 0 )
18911877 {
1892- if (fcinfo . argnull [i ])
1878+ if (fcinfo -> argnull [i ])
18931879 {
18941880 * isNull = true;
18951881 return (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
19061892 pgstat_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 );
19521937 rsinfo .type = T_ReturnSetInfo ;
19531938 rsinfo .econtext = econtext ;
19541939 rsinfo .expectedDesc = expectedDesc ;
@@ -1992,6 +1977,9 @@ ExecMakeTableFunctionResult(ExprState *funcexpr,
19921977 econtext -> ecxt_per_query_memory , false);
19931978 }
19941979 returnsSet = 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 );
20051992 argDone = ExecEvalFuncArgs (& fcinfo , fcache -> args , econtext );
20061993 /* We don't allow sets in the arguments of the table function */
20071994 if (argDone != ExprSingleResult )
@@ -2029,6 +2016,7 @@ ExecMakeTableFunctionResult(ExprState *funcexpr,
20292016 {
20302017 /* Treat funcexpr as a generic expression */
20312018 direct_function_call = false;
2019+ InitFunctionCallInfoData (fcinfo , NULL , 0 , NULL , NULL );
20322020 }
20332021
20342022 /*
@@ -2312,9 +2300,8 @@ ExecEvalDistinct(FuncExprState *fcache,
23122300 ExprDoneCond * isDone )
23132301{
23142302 Datum result ;
2315- FunctionCallInfoData fcinfo ;
2303+ FunctionCallInfo fcinfo ;
23162304 ExprDoneCond 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 );
23442328 if (argDone != ExprSingleResult )
23452329 ereport (ERROR ,
23462330 (errcode (ERRCODE_DATATYPE_MISMATCH ),
23472331 errmsg ("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... */
23532337 result = 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... */
23582342 result = BoolGetDatum (TRUE);
23592343 }
23602344 else
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 "=" */
23662350 result = BoolGetDatum (!DatumGetBool (result ));
23672351 }
@@ -2388,7 +2372,7 @@ ExecEvalScalarArrayOp(ScalarArrayOpExprState *sstate,
23882372 int nitems ;
23892373 Datum result ;
23902374 bool resultnull ;
2391- FunctionCallInfoData fcinfo ;
2375+ FunctionCallInfo fcinfo ;
23922376 ExprDoneCond argDone ;
23932377 int i ;
23942378 int16 typlen ;
@@ -2413,26 +2397,28 @@ ExecEvalScalarArrayOp(ScalarArrayOpExprState *sstate,
24132397 Assert (!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 );
24192405 if (argDone != ExprSingleResult )
24202406 ereport (ERROR ,
24212407 (errcode (ERRCODE_DATATYPE_MISMATCH ),
24222408 errmsg ("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;
24322418 return (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;
24542440 return (Datum ) 0 ;
@@ -2486,32 +2472,32 @@ ExecEvalScalarArrayOp(ScalarArrayOpExprState *sstate,
24862472 /* Get array element, checking for NULL */
24872473 if (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 }
24922478 else
24932479 {
24942480 elt = fetch_att (s , typbyval , typlen );
24952481 s = att_addlength_pointer (s , typlen , s );
24962482 s = (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;
25052491 thisresult = (Datum ) 0 ;
25062492 }
25072493 else
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 )
25152501 resultnull = true;
25162502 else if (useOr )
25172503 {
@@ -3526,9 +3512,8 @@ ExecEvalNullIf(FuncExprState *nullIfExpr,
35263512 bool * isNull , ExprDoneCond * isDone )
35273513{
35283514 Datum result ;
3529- FunctionCallInfoData fcinfo ;
3515+ FunctionCallInfo fcinfo ;
35303516 ExprDoneCond argDone ;
3531- List * argList ;
35323517
35333518 if (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 );
35563538 if (argDone != ExprSingleResult )
35573539 ereport (ERROR ,
35583540 (errcode (ERRCODE_DATATYPE_MISMATCH ),
35593541 errmsg ("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;
35713553 return (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/* ----------------------------------------------------------------
0 commit comments