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

Commit75b39e7

Browse files
committed
Add infrastructure for storing a VARIADIC ANY function's VARIADIC flag.
Originally we didn't bother to mark FuncExprs with any indication whetherVARIADIC had been given in the source text, because there didn't seem to beany need for it at runtime. However, because we cannot fold a VARIADIC ANYfunction's arguments into an array (since they're not necessarily all thesame type), we do actually need that information at runtime if VARIADIC ANYfunctions are to respond unsurprisingly to use of the VARIADIC keyword.Add the missing field, and also fix ruleutils.c so that VARIADIC ANYfunction calls are dumped properly.Extracted from a larger patch that also fixes concat() and format() (theonly two extant VARIADIC ANY functions) to behave properly when VARIADIC isspecified. This portion seems appropriate to review and commit separately.Pavel Stehule
1 parent841a515 commit75b39e7

File tree

12 files changed

+113
-32
lines changed

12 files changed

+113
-32
lines changed

‎src/backend/nodes/copyfuncs.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1194,6 +1194,7 @@ _copyFuncExpr(const FuncExpr *from)
11941194
COPY_SCALAR_FIELD(funcid);
11951195
COPY_SCALAR_FIELD(funcresulttype);
11961196
COPY_SCALAR_FIELD(funcretset);
1197+
COPY_SCALAR_FIELD(funcvariadic);
11971198
COPY_SCALAR_FIELD(funcformat);
11981199
COPY_SCALAR_FIELD(funccollid);
11991200
COPY_SCALAR_FIELD(inputcollid);

‎src/backend/nodes/equalfuncs.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,7 @@ _equalFuncExpr(const FuncExpr *a, const FuncExpr *b)
239239
COMPARE_SCALAR_FIELD(funcid);
240240
COMPARE_SCALAR_FIELD(funcresulttype);
241241
COMPARE_SCALAR_FIELD(funcretset);
242+
COMPARE_SCALAR_FIELD(funcvariadic);
242243
COMPARE_COERCIONFORM_FIELD(funcformat);
243244
COMPARE_SCALAR_FIELD(funccollid);
244245
COMPARE_SCALAR_FIELD(inputcollid);

‎src/backend/nodes/makefuncs.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,7 @@ makeFuncExpr(Oid funcid, Oid rettype, List *args,
461461
funcexpr->funcid=funcid;
462462
funcexpr->funcresulttype=rettype;
463463
funcexpr->funcretset= false;/* only allowed case here */
464+
funcexpr->funcvariadic= false;/* only allowed case here */
464465
funcexpr->funcformat=fformat;
465466
funcexpr->funccollid=funccollid;
466467
funcexpr->inputcollid=inputcollid;

‎src/backend/nodes/outfuncs.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1000,6 +1000,7 @@ _outFuncExpr(StringInfo str, const FuncExpr *node)
10001000
WRITE_OID_FIELD(funcid);
10011001
WRITE_OID_FIELD(funcresulttype);
10021002
WRITE_BOOL_FIELD(funcretset);
1003+
WRITE_BOOL_FIELD(funcvariadic);
10031004
WRITE_ENUM_FIELD(funcformat,CoercionForm);
10041005
WRITE_OID_FIELD(funccollid);
10051006
WRITE_OID_FIELD(inputcollid);

‎src/backend/nodes/readfuncs.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -537,6 +537,7 @@ _readFuncExpr(void)
537537
READ_OID_FIELD(funcid);
538538
READ_OID_FIELD(funcresulttype);
539539
READ_BOOL_FIELD(funcretset);
540+
READ_BOOL_FIELD(funcvariadic);
540541
READ_ENUM_FIELD(funcformat,CoercionForm);
541542
READ_OID_FIELD(funccollid);
542543
READ_OID_FIELD(inputcollid);

‎src/backend/optimizer/util/clauses.c

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ static Node *simplify_boolean_equality(Oid opno, List *args);
110110
staticExpr*simplify_function(Oidfuncid,
111111
Oidresult_type,int32result_typmod,
112112
Oidresult_collid,Oidinput_collid,List**args_p,
113-
boolprocess_args,boolallow_non_const,
113+
boolfuncvariadic,boolprocess_args,boolallow_non_const,
114114
eval_const_expressions_context*context);
115115
staticList*expand_function_arguments(List*args,Oidresult_type,
116116
HeapTuplefunc_tuple);
@@ -121,10 +121,12 @@ static void recheck_cast_function_args(List *args, Oid result_type,
121121
HeapTuplefunc_tuple);
122122
staticExpr*evaluate_function(Oidfuncid,Oidresult_type,int32result_typmod,
123123
Oidresult_collid,Oidinput_collid,List*args,
124+
boolfuncvariadic,
124125
HeapTuplefunc_tuple,
125126
eval_const_expressions_context*context);
126127
staticExpr*inline_function(Oidfuncid,Oidresult_type,Oidresult_collid,
127128
Oidinput_collid,List*args,
129+
boolfuncvariadic,
128130
HeapTuplefunc_tuple,
129131
eval_const_expressions_context*context);
130132
staticNode*substitute_actual_parameters(Node*expr,intnargs,List*args,
@@ -2314,6 +2316,7 @@ eval_const_expressions_mutator(Node *node,
23142316
expr->funccollid,
23152317
expr->inputcollid,
23162318
&args,
2319+
expr->funcvariadic,
23172320
true,
23182321
true,
23192322
context);
@@ -2330,6 +2333,7 @@ eval_const_expressions_mutator(Node *node,
23302333
newexpr->funcid=expr->funcid;
23312334
newexpr->funcresulttype=expr->funcresulttype;
23322335
newexpr->funcretset=expr->funcretset;
2336+
newexpr->funcvariadic=expr->funcvariadic;
23332337
newexpr->funcformat=expr->funcformat;
23342338
newexpr->funccollid=expr->funccollid;
23352339
newexpr->inputcollid=expr->inputcollid;
@@ -2359,6 +2363,7 @@ eval_const_expressions_mutator(Node *node,
23592363
expr->opcollid,
23602364
expr->inputcollid,
23612365
&args,
2366+
false,
23622367
true,
23632368
true,
23642369
context);
@@ -2464,6 +2469,7 @@ eval_const_expressions_mutator(Node *node,
24642469
&args,
24652470
false,
24662471
false,
2472+
false,
24672473
context);
24682474
if (simple)/* successfully simplified it */
24692475
{
@@ -2665,6 +2671,7 @@ eval_const_expressions_mutator(Node *node,
26652671
InvalidOid,
26662672
InvalidOid,
26672673
&args,
2674+
false,
26682675
true,
26692676
true,
26702677
context);
@@ -2697,6 +2704,7 @@ eval_const_expressions_mutator(Node *node,
26972704
InvalidOid,
26982705
&args,
26992706
false,
2707+
false,
27002708
true,
27012709
context);
27022710
if (simple)/* successfully simplified input fn */
@@ -3565,7 +3573,7 @@ simplify_boolean_equality(Oid opno, List *args)
35653573
staticExpr*
35663574
simplify_function(Oidfuncid,Oidresult_type,int32result_typmod,
35673575
Oidresult_collid,Oidinput_collid,List**args_p,
3568-
boolprocess_args,boolallow_non_const,
3576+
boolfuncvariadic,boolprocess_args,boolallow_non_const,
35693577
eval_const_expressions_context*context)
35703578
{
35713579
List*args=*args_p;
@@ -3609,7 +3617,8 @@ simplify_function(Oid funcid, Oid result_type, int32 result_typmod,
36093617
/* Now attempt simplification of the function call proper. */
36103618

36113619
newexpr=evaluate_function(funcid,result_type,result_typmod,
3612-
result_collid,input_collid,args,
3620+
result_collid,input_collid,
3621+
args,funcvariadic,
36133622
func_tuple,context);
36143623

36153624
if (!newexpr&&allow_non_const&&OidIsValid(func_form->protransform))
@@ -3625,6 +3634,7 @@ simplify_function(Oid funcid, Oid result_type, int32 result_typmod,
36253634
fexpr.funcid=funcid;
36263635
fexpr.funcresulttype=result_type;
36273636
fexpr.funcretset=func_form->proretset;
3637+
fexpr.funcvariadic=funcvariadic;
36283638
fexpr.funcformat=COERCE_EXPLICIT_CALL;
36293639
fexpr.funccollid=result_collid;
36303640
fexpr.inputcollid=input_collid;
@@ -3638,7 +3648,7 @@ simplify_function(Oid funcid, Oid result_type, int32 result_typmod,
36383648

36393649
if (!newexpr&&allow_non_const)
36403650
newexpr=inline_function(funcid,result_type,result_collid,
3641-
input_collid,args,
3651+
input_collid,args,funcvariadic,
36423652
func_tuple,context);
36433653

36443654
ReleaseSysCache(func_tuple);
@@ -3878,6 +3888,7 @@ recheck_cast_function_args(List *args, Oid result_type, HeapTuple func_tuple)
38783888
staticExpr*
38793889
evaluate_function(Oidfuncid,Oidresult_type,int32result_typmod,
38803890
Oidresult_collid,Oidinput_collid,List*args,
3891+
boolfuncvariadic,
38813892
HeapTuplefunc_tuple,
38823893
eval_const_expressions_context*context)
38833894
{
@@ -3959,6 +3970,7 @@ evaluate_function(Oid funcid, Oid result_type, int32 result_typmod,
39593970
newexpr->funcid=funcid;
39603971
newexpr->funcresulttype=result_type;
39613972
newexpr->funcretset= false;
3973+
newexpr->funcvariadic=funcvariadic;
39623974
newexpr->funcformat=COERCE_EXPLICIT_CALL;/* doesn't matter */
39633975
newexpr->funccollid=result_collid;/* doesn't matter */
39643976
newexpr->inputcollid=input_collid;
@@ -4001,6 +4013,7 @@ evaluate_function(Oid funcid, Oid result_type, int32 result_typmod,
40014013
staticExpr*
40024014
inline_function(Oidfuncid,Oidresult_type,Oidresult_collid,
40034015
Oidinput_collid,List*args,
4016+
boolfuncvariadic,
40044017
HeapTuplefunc_tuple,
40054018
eval_const_expressions_context*context)
40064019
{
@@ -4089,6 +4102,7 @@ inline_function(Oid funcid, Oid result_type, Oid result_collid,
40894102
fexpr->funcid=funcid;
40904103
fexpr->funcresulttype=result_type;
40914104
fexpr->funcretset= false;
4105+
fexpr->funcvariadic=funcvariadic;
40924106
fexpr->funcformat=COERCE_EXPLICIT_CALL;/* doesn't matter */
40934107
fexpr->funccollid=result_collid;/* doesn't matter */
40944108
fexpr->inputcollid=input_collid;

‎src/backend/parser/parse_func.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,7 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
384384
funcexpr->funcid=funcid;
385385
funcexpr->funcresulttype=rettype;
386386
funcexpr->funcretset=retset;
387+
funcexpr->funcvariadic=func_variadic;
387388
funcexpr->funcformat=COERCE_EXPLICIT_CALL;
388389
/* funccollid and inputcollid will be set by parse_collate.c */
389390
funcexpr->args=fargs;

‎src/backend/utils/adt/ruleutils.c

Lines changed: 60 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -396,8 +396,9 @@ static Node *processIndirection(Node *node, deparse_context *context,
396396
staticvoidprintSubscripts(ArrayRef*aref,deparse_context*context);
397397
staticchar*get_relation_name(Oidrelid);
398398
staticchar*generate_relation_name(Oidrelid,List*namespaces);
399-
staticchar*generate_function_name(Oidfuncid,intnargs,List*argnames,
400-
Oid*argtypes,bool*is_variadic);
399+
staticchar*generate_function_name(Oidfuncid,intnargs,
400+
List*argnames,Oid*argtypes,
401+
boolwas_variadic,bool*use_variadic_p);
401402
staticchar*generate_operator_name(Oidoperid,Oidarg1,Oidarg2);
402403
statictext*string_to_text(char*str);
403404
staticchar*flatten_reloptions(Oidrelid);
@@ -858,7 +859,8 @@ pg_get_triggerdef_worker(Oid trigid, bool pretty)
858859

859860
appendStringInfo(&buf,"EXECUTE PROCEDURE %s(",
860861
generate_function_name(trigrec->tgfoid,0,
861-
NIL,NULL,NULL));
862+
NIL,NULL,
863+
false,NULL));
862864

863865
if (trigrec->tgnargs>0)
864866
{
@@ -7269,7 +7271,7 @@ get_func_expr(FuncExpr *expr, deparse_context *context,
72697271
Oidargtypes[FUNC_MAX_ARGS];
72707272
intnargs;
72717273
List*argnames;
7272-
boolis_variadic;
7274+
booluse_variadic;
72737275
ListCell*l;
72747276

72757277
/*
@@ -7327,13 +7329,14 @@ get_func_expr(FuncExpr *expr, deparse_context *context,
73277329
appendStringInfo(buf,"%s(",
73287330
generate_function_name(funcoid,nargs,
73297331
argnames,argtypes,
7330-
&is_variadic));
7332+
expr->funcvariadic,
7333+
&use_variadic));
73317334
nargs=0;
73327335
foreach(l,expr->args)
73337336
{
73347337
if (nargs++>0)
73357338
appendStringInfoString(buf,", ");
7336-
if (is_variadic&&lnext(l)==NULL)
7339+
if (use_variadic&&lnext(l)==NULL)
73377340
appendStringInfoString(buf,"VARIADIC ");
73387341
get_rule_expr((Node*)lfirst(l),context, true);
73397342
}
@@ -7374,7 +7377,8 @@ get_agg_expr(Aggref *aggref, deparse_context *context)
73747377

73757378
appendStringInfo(buf,"%s(%s",
73767379
generate_function_name(aggref->aggfnoid,nargs,
7377-
NIL,argtypes,NULL),
7380+
NIL,argtypes,
7381+
false,NULL),
73787382
(aggref->aggdistinct!=NIL) ?"DISTINCT " :"");
73797383
/* aggstar can be set only in zero-argument aggregates */
73807384
if (aggref->aggstar)
@@ -7416,7 +7420,8 @@ get_windowfunc_expr(WindowFunc *wfunc, deparse_context *context)
74167420

74177421
appendStringInfo(buf,"%s(",
74187422
generate_function_name(wfunc->winfnoid,nargs,
7419-
NIL,argtypes,NULL));
7423+
NIL,argtypes,
7424+
false,NULL));
74207425
/* winstar can be set only in zero-argument aggregates */
74217426
if (wfunc->winstar)
74227427
appendStringInfoChar(buf,'*');
@@ -8507,18 +8512,25 @@ generate_relation_name(Oid relid, List *namespaces)
85078512
*given that it is being called with the specified actual arg names and
85088513
*types.(Those matter because of ambiguous-function resolution rules.)
85098514
*
8510-
* The result includes all necessary quoting and schema-prefixing.We can
8511-
* also pass back an indication of whether the function is variadic.
8515+
* If we're dealing with a potentially variadic function (in practice, this
8516+
* means a FuncExpr and not some other way of calling the function), then
8517+
* was_variadic must specify whether VARIADIC appeared in the original call,
8518+
* and *use_variadic_p will be set to indicate whether to print VARIADIC in
8519+
* the output. For non-FuncExpr cases, was_variadic should be FALSE and
8520+
* use_variadic_p can be NULL.
8521+
*
8522+
* The result includes all necessary quoting and schema-prefixing.
85128523
*/
85138524
staticchar*
8514-
generate_function_name(Oidfuncid,intnargs,List*argnames,
8515-
Oid*argtypes,bool*is_variadic)
8525+
generate_function_name(Oidfuncid,intnargs,List*argnames,Oid*argtypes,
8526+
boolwas_variadic,bool*use_variadic_p)
85168527
{
8528+
char*result;
85178529
HeapTupleproctup;
85188530
Form_pg_procprocform;
85198531
char*proname;
8532+
booluse_variadic;
85208533
char*nspname;
8521-
char*result;
85228534
FuncDetailCodep_result;
85238535
Oidp_funcid;
85248536
Oidp_rettype;
@@ -8532,15 +8544,47 @@ generate_function_name(Oid funcid, int nargs, List *argnames,
85328544
procform= (Form_pg_proc)GETSTRUCT(proctup);
85338545
proname=NameStr(procform->proname);
85348546

8547+
/*
8548+
* Determine whether VARIADIC should be printed. We must do this first
8549+
* since it affects the lookup rules in func_get_detail().
8550+
*
8551+
* Currently, we always print VARIADIC if the function is variadic and
8552+
* takes a variadic type other than ANY. (In principle, if VARIADIC
8553+
* wasn't originally specified and the array actual argument is
8554+
* deconstructable, we could print the array elements separately and not
8555+
* print VARIADIC, thus more nearly reproducing the original input. For
8556+
* the moment that seems like too much complication for the benefit.)
8557+
* However, if the function takes VARIADIC ANY, then the parser didn't
8558+
* fold the arguments together into an array, so we must print VARIADIC if
8559+
* and only if it was used originally.
8560+
*/
8561+
if (use_variadic_p)
8562+
{
8563+
if (OidIsValid(procform->provariadic))
8564+
{
8565+
if (procform->provariadic!=ANYOID)
8566+
use_variadic= true;
8567+
else
8568+
use_variadic=was_variadic;
8569+
}
8570+
else
8571+
use_variadic= false;
8572+
*use_variadic_p=use_variadic;
8573+
}
8574+
else
8575+
{
8576+
Assert(!was_variadic);
8577+
use_variadic= false;
8578+
}
8579+
85358580
/*
85368581
* The idea here is to schema-qualify only if the parser would fail to
85378582
* resolve the correct function given the unqualified func name with the
8538-
* specified argtypes.If the function is variadic, we should presume
8539-
* that VARIADIC will be included in the call.
8583+
* specified argtypes and VARIADIC flag.
85408584
*/
85418585
p_result=func_get_detail(list_make1(makeString(proname)),
85428586
NIL,argnames,nargs,argtypes,
8543-
!OidIsValid(procform->provariadic), true,
8587+
!use_variadic, true,
85448588
&p_funcid,&p_rettype,
85458589
&p_retset,&p_nvargs,&p_true_typeids,NULL);
85468590
if ((p_result==FUNCDETAIL_NORMAL||
@@ -8553,17 +8597,6 @@ generate_function_name(Oid funcid, int nargs, List *argnames,
85538597

85548598
result=quote_qualified_identifier(nspname,proname);
85558599

8556-
/* Check variadic-ness if caller cares */
8557-
if (is_variadic)
8558-
{
8559-
/* "any" variadics are not treated as variadics for listing */
8560-
if (OidIsValid(procform->provariadic)&&
8561-
procform->provariadic!=ANYOID)
8562-
*is_variadic= true;
8563-
else
8564-
*is_variadic= false;
8565-
}
8566-
85678600
ReleaseSysCache(proctup);
85688601

85698602
returnresult;

‎src/backend/utils/fmgr/fmgr.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2281,6 +2281,7 @@ pg_detoast_datum_packed(struct varlena * datum)
22812281
* These are needed by polymorphic functions, which accept multiple possible
22822282
* input types and need help from the parser to know what they've got.
22832283
* Also, some functions might be interested in whether a parameter is constant.
2284+
* Functions taking VARIADIC ANY also need to know about the VARIADIC keyword.
22842285
*-------------------------------------------------------------------------
22852286
*/
22862287

@@ -2445,3 +2446,28 @@ get_call_expr_arg_stable(Node *expr, int argnum)
24452446

24462447
return false;
24472448
}
2449+
2450+
/*
2451+
* Get the VARIADIC flag from the function invocation
2452+
*
2453+
* Returns false (the default assumption) if information is not available
2454+
*/
2455+
bool
2456+
get_fn_expr_variadic(FmgrInfo*flinfo)
2457+
{
2458+
Node*expr;
2459+
2460+
/*
2461+
* can't return anything useful if we have no FmgrInfo or if its fn_expr
2462+
* node has not been initialized
2463+
*/
2464+
if (!flinfo|| !flinfo->fn_expr)
2465+
return false;
2466+
2467+
expr=flinfo->fn_expr;
2468+
2469+
if (IsA(expr,FuncExpr))
2470+
return ((FuncExpr*)expr)->funcvariadic;
2471+
else
2472+
return false;
2473+
}

‎src/include/catalog/catversion.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,6 @@
5353
*/
5454

5555
/*yyyymmddN */
56-
#defineCATALOG_VERSION_NO201301171
56+
#defineCATALOG_VERSION_NO201301211
5757

5858
#endif

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp