Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit0811ff2

Browse files
committed
Avoid using a local FunctionCallInfoData struct in ExecMakeFunctionResult
and related routines.We already had a redundant FunctionCallInfoData struct in FuncExprState,but were using that copy only in set-returning-function cases, to avoidkeeping function evaluation state in the expression tree for the benefitof plpgsql's "simple expression" logic. But of course that didn't workanyway. Given the recent fixes in plpgsql there is no need to have twoseparate behaviors here. Getting rid of the local FunctionCallInfoDatastructs should make things a little faster (because we don't need to doInitFunctionCallInfoData each time), and it also makes for a noticeablereduction in stack space consumption during recursive calls.
1 parent931b6db commit0811ff2

File tree

2 files changed

+70
-89
lines changed

2 files changed

+70
-89
lines changed

‎src/backend/executor/execQual.c

Lines changed: 61 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -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
returnargIsDone;
13911395
}
@@ -1535,7 +1539,6 @@ ExecMakeFunctionResult(FuncExprState *fcache,
15351539
{
15361540
List*arguments;
15371541
Datumresult;
1538-
FunctionCallInfoDatafcinfo_data;
15391542
FunctionCallInfofcinfo;
15401543
PgStat_FunctionCallUsagefcusage;
15411544
ReturnSetInforsinfo;/* 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
Datumresult;
1859-
FunctionCallInfoDatafcinfo;
1846+
FunctionCallInfofcinfo;
18601847
PgStat_FunctionCallUsagefcusage;
18611848
inti;
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
Datumresult;
2315-
FunctionCallInfoDatafcinfo;
2303+
FunctionCallInfofcinfo;
23162304
ExprDoneCondargDone;
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-
elseif (fcinfo.argnull[0]||fcinfo.argnull[1])
2339+
elseif (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
intnitems;
23892373
Datumresult;
23902374
boolresultnull;
2391-
FunctionCallInfoDatafcinfo;
2375+
FunctionCallInfofcinfo;
23922376
ExprDoneCondargDone;
23932377
inti;
23942378
int16typlen;
@@ -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
elseif (useOr)
25172503
{
@@ -3526,9 +3512,8 @@ ExecEvalNullIf(FuncExprState *nullIfExpr,
35263512
bool*isNull,ExprDoneCond*isDone)
35273513
{
35283514
Datumresult;
3529-
FunctionCallInfoDatafcinfo;
3515+
FunctionCallInfofcinfo;
35303516
ExprDoneCondargDone;
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-
returnfcinfo.arg[0];
3558+
*isNull=fcinfo->argnull[0];
3559+
returnfcinfo->arg[0];
35783560
}
35793561

35803562
/* ----------------------------------------------------------------

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp