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

Commitd26888b

Browse files
committed
Move checking an explicit VARIADIC "any" argument into the parser.
This is more efficient and simpler . It does mean that an untyped NULLcan no longer be used in such cases, which should be mentioned inRelease Notes, but doesn't seem a terrible loss. The workaround is tocast the NULL to some array type.Pavel Stehule, reviewed by Jeevan Chalke.
1 parent405a468 commitd26888b

File tree

7 files changed

+55
-39
lines changed

7 files changed

+55
-39
lines changed

‎src/backend/catalog/pg_aggregate.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,7 @@ lookup_agg_function(List *fnName,
332332
OidfnOid;
333333
boolretset;
334334
intnvargs;
335+
Oidvatype;
335336
Oid*true_oid_array;
336337
FuncDetailCodefdresult;
337338
AclResultaclresult;
@@ -346,7 +347,8 @@ lookup_agg_function(List *fnName,
346347
*/
347348
fdresult=func_get_detail(fnName,NIL,NIL,
348349
nargs,input_types, false, false,
349-
&fnOid,rettype,&retset,&nvargs,
350+
&fnOid,rettype,&retset,
351+
&nvargs,&vatype,
350352
&true_oid_array,NULL);
351353

352354
/* only valid case is a normal function not returning a set */

‎src/backend/parser/parse_func.c

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
7979
Node*retval;
8080
boolretset;
8181
intnvargs;
82+
Oidvatype;
8283
FuncDetailCodefdresult;
8384

8485
/*
@@ -214,7 +215,8 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
214215
fdresult=func_get_detail(funcname,fargs,argnames,nargs,
215216
actual_arg_types,
216217
!func_variadic, true,
217-
&funcid,&rettype,&retset,&nvargs,
218+
&funcid,&rettype,&retset,
219+
&nvargs,&vatype,
218220
&declared_arg_types,&argdefaults);
219221
if (fdresult==FUNCDETAIL_COERCION)
220222
{
@@ -382,6 +384,22 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
382384
fargs=lappend(fargs,newa);
383385
}
384386

387+
/*
388+
* When function is called an explicit VARIADIC labeled parameter,
389+
* and the declared_arg_type is "any", then sanity check the actual
390+
* parameter type now - it must be an array.
391+
*/
392+
if (nargs>0&&vatype==ANYOID&&func_variadic)
393+
{
394+
Oidva_arr_typid=actual_arg_types[nargs-1];
395+
396+
if (!OidIsValid(get_element_type(va_arr_typid)))
397+
ereport(ERROR,
398+
(errcode(ERRCODE_DATATYPE_MISMATCH),
399+
errmsg("VARIADIC argument must be an array"),
400+
parser_errposition(pstate,exprLocation((Node*)llast(fargs)))));
401+
}
402+
385403
/* build the appropriate output structure */
386404
if (fdresult==FUNCDETAIL_NORMAL)
387405
{
@@ -1033,6 +1051,7 @@ func_get_detail(List *funcname,
10331051
Oid*rettype,/* return value */
10341052
bool*retset,/* return value */
10351053
int*nvargs,/* return value */
1054+
Oid*vatype,/* return value */
10361055
Oid**true_typeids,/* return value */
10371056
List**argdefaults)/* optional return value */
10381057
{
@@ -1251,6 +1270,7 @@ func_get_detail(List *funcname,
12511270
pform= (Form_pg_proc)GETSTRUCT(ftup);
12521271
*rettype=pform->prorettype;
12531272
*retset=pform->proretset;
1273+
*vatype=pform->provariadic;
12541274
/* fetch default args if caller wants 'em */
12551275
if (argdefaults&&best_candidate->ndargs>0)
12561276
{

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8584,6 +8584,7 @@ generate_function_name(Oid funcid, int nargs, List *argnames, Oid *argtypes,
85848584
Oidp_rettype;
85858585
boolp_retset;
85868586
intp_nvargs;
8587+
Oidp_vatype;
85878588
Oid*p_true_typeids;
85888589

85898590
proctup=SearchSysCache1(PROCOID,ObjectIdGetDatum(funcid));
@@ -8634,7 +8635,8 @@ generate_function_name(Oid funcid, int nargs, List *argnames, Oid *argtypes,
86348635
NIL,argnames,nargs,argtypes,
86358636
!use_variadic, true,
86368637
&p_funcid,&p_rettype,
8637-
&p_retset,&p_nvargs,&p_true_typeids,NULL);
8638+
&p_retset,&p_nvargs,&p_vatype,
8639+
&p_true_typeids,NULL);
86388640
if ((p_result==FUNCDETAIL_NORMAL||
86398641
p_result==FUNCDETAIL_AGGREGATE||
86408642
p_result==FUNCDETAIL_WINDOWFUNC)&&

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

Lines changed: 16 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -3820,7 +3820,6 @@ concat_internal(const char *sepstr, int argidx,
38203820
*/
38213821
if (get_fn_expr_variadic(fcinfo->flinfo))
38223822
{
3823-
Oidarr_typid;
38243823
ArrayType*arr;
38253824

38263825
/* Should have just the one argument */
@@ -3831,20 +3830,16 @@ concat_internal(const char *sepstr, int argidx,
38313830
returnNULL;
38323831

38333832
/*
3834-
* Non-null argument had better be an array. The parser doesn't
3835-
* enforce this for VARIADIC ANY functions (maybe it should?), so that
3836-
* check uses ereport not just elog.
3833+
* Non-null argument had better be an array
3834+
*
3835+
* Correct values are ensured by parser check, but this function
3836+
* can be called directly, bypassing the parser, so we should do
3837+
* some minimal check too - this form of call requires correctly set
3838+
* expr argtype in flinfo.
38373839
*/
3838-
arr_typid=get_fn_expr_argtype(fcinfo->flinfo,argidx);
3839-
if (!OidIsValid(arr_typid))
3840-
elog(ERROR,"could not determine data type of concat() input");
3841-
3842-
if (!OidIsValid(get_element_type(arr_typid)))
3843-
ereport(ERROR,
3844-
(errcode(ERRCODE_DATATYPE_MISMATCH),
3845-
errmsg("VARIADIC argument must be an array")));
3840+
Assert(OidIsValid(get_fn_expr_argtype(fcinfo->flinfo,argidx)));
3841+
Assert(OidIsValid(get_element_type(get_fn_expr_argtype(fcinfo->flinfo,argidx))));
38463842

3847-
/* OK, safe to fetch the array value */
38483843
arr=PG_GETARG_ARRAYTYPE_P(argidx);
38493844

38503845
/*
@@ -4049,7 +4044,6 @@ text_format(PG_FUNCTION_ARGS)
40494044
/* If argument is marked VARIADIC, expand array into elements */
40504045
if (get_fn_expr_variadic(fcinfo->flinfo))
40514046
{
4052-
Oidarr_typid;
40534047
ArrayType*arr;
40544048
int16elmlen;
40554049
boolelmbyval;
@@ -4065,20 +4059,16 @@ text_format(PG_FUNCTION_ARGS)
40654059
else
40664060
{
40674061
/*
4068-
* Non-null argument had better be an array. The parser doesn't
4069-
* enforce this for VARIADIC ANY functions (maybe it should?), so
4070-
* that check uses ereport not just elog.
4062+
* Non-null argument had better be an array
4063+
*
4064+
* Correct values are ensured by parser check, but this function
4065+
* can be called directly, bypassing the parser, so we should do
4066+
* some minimal check too - this form of call requires correctly set
4067+
* expr argtype in flinfo.
40714068
*/
4072-
arr_typid=get_fn_expr_argtype(fcinfo->flinfo,1);
4073-
if (!OidIsValid(arr_typid))
4074-
elog(ERROR,"could not determine data type of format() input");
4075-
4076-
if (!OidIsValid(get_element_type(arr_typid)))
4077-
ereport(ERROR,
4078-
(errcode(ERRCODE_DATATYPE_MISMATCH),
4079-
errmsg("VARIADIC argument must be an array")));
4069+
Assert(OidIsValid(get_fn_expr_argtype(fcinfo->flinfo,1)));
4070+
Assert(OidIsValid(get_element_type(get_fn_expr_argtype(fcinfo->flinfo,1))));
40804071

4081-
/* OK, safe to fetch the array value */
40824072
arr=PG_GETARG_ARRAYTYPE_P(1);
40834073

40844074
/* Get info about array element type */

‎src/include/parser/parse_func.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,8 @@ extern FuncDetailCode func_get_detail(List *funcname,
5252
intnargs,Oid*argtypes,
5353
boolexpand_variadic,boolexpand_defaults,
5454
Oid*funcid,Oid*rettype,
55-
bool*retset,int*nvargs,Oid**true_typeids,
56-
List**argdefaults);
55+
bool*retset,int*nvargs,Oid*vatype,
56+
Oid**true_typeids,List**argdefaults);
5757

5858
externintfunc_match_argtypes(intnargs,
5959
Oid*input_typeids,

‎src/test/regress/expected/text.out

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -149,13 +149,13 @@ select concat_ws(',', variadic array[1,2,3]);
149149
1,2,3
150150
(1 row)
151151

152-
select concat_ws(',', variadic NULL);
152+
select concat_ws(',', variadic NULL::int[]);
153153
concat_ws
154154
-----------
155155

156156
(1 row)
157157

158-
select concat(variadic NULL) is NULL;
158+
select concat(variadic NULL::int[]) is NULL;
159159
?column?
160160
----------
161161
t
@@ -170,6 +170,8 @@ select concat(variadic '{}'::int[]) = '';
170170
--should fail
171171
select concat_ws(',', variadic 10);
172172
ERROR: VARIADIC argument must be an array
173+
LINE 1: select concat_ws(',', variadic 10);
174+
^
173175
/*
174176
* format
175177
*/
@@ -315,8 +317,8 @@ select format('%2$s, %1$s', variadic array[1, 2]);
315317
2, 1
316318
(1 row)
317319

318-
-- variadic argument can be NULL, but should not be referenced
319-
select format('Hello', variadic NULL);
320+
-- variadic argument can bearray typeNULL, but should not be referenced
321+
select format('Hello', variadic NULL::int[]);
320322
format
321323
--------
322324
Hello

‎src/test/regress/sql/text.sql

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@ select quote_literal(e'\\');
4747
-- check variadic labeled argument
4848
select concat(variadic array[1,2,3]);
4949
select concat_ws(',', variadic array[1,2,3]);
50-
select concat_ws(',', variadicNULL);
51-
select concat(variadicNULL) isNULL;
50+
select concat_ws(',', variadicNULL::int[]);
51+
select concat(variadicNULL::int[]) isNULL;
5252
select concat(variadic'{}'::int[])='';
5353
--should fail
5454
select concat_ws(',', variadic10);
@@ -93,8 +93,8 @@ select format('%s, %s', variadic array[true, false]::text[]);
9393
-- check variadic with positional placeholders
9494
select format('%2$s, %1$s', variadic array['first','second']);
9595
select format('%2$s, %1$s', variadic array[1,2]);
96-
-- variadic argument can be NULL, but should not be referenced
97-
select format('Hello', variadicNULL);
96+
-- variadic argument can bearray typeNULL, but should not be referenced
97+
select format('Hello', variadicNULL::int[]);
9898
-- variadic argument allows simulating more than FUNC_MAX_ARGS parameters
9999
select format(string_agg('%s',','), variadic array_agg(i))
100100
from generate_series(1,200) g(i);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp