From d26888bc4d1e539a82f21382b0000fe5bbf889d9 Mon Sep 17 00:00:00 2001 From: Andrew Dunstan Date: Thu, 18 Jul 2013 11:52:12 -0400 Subject: Move checking an explicit VARIADIC "any" argument into the parser. This is more efficient and simpler . It does mean that an untyped NULL can no longer be used in such cases, which should be mentioned in Release Notes, but doesn't seem a terrible loss. The workaround is to cast the NULL to some array type. Pavel Stehule, reviewed by Jeevan Chalke. --- src/backend/parser/parse_func.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) (limited to 'src/backend/parser/parse_func.c') diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c index e54922f8037..1f02c9a5757 100644 --- a/src/backend/parser/parse_func.c +++ b/src/backend/parser/parse_func.c @@ -79,6 +79,7 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs, Node *retval; bool retset; int nvargs; + Oid vatype; FuncDetailCode fdresult; /* @@ -214,7 +215,8 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs, fdresult = func_get_detail(funcname, fargs, argnames, nargs, actual_arg_types, !func_variadic, true, - &funcid, &rettype, &retset, &nvargs, + &funcid, &rettype, &retset, + &nvargs, &vatype, &declared_arg_types, &argdefaults); if (fdresult == FUNCDETAIL_COERCION) { @@ -382,6 +384,22 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs, fargs = lappend(fargs, newa); } + /* + * When function is called an explicit VARIADIC labeled parameter, + * and the declared_arg_type is "any", then sanity check the actual + * parameter type now - it must be an array. + */ + if (nargs > 0 && vatype == ANYOID && func_variadic) + { + Oid va_arr_typid = actual_arg_types[nargs - 1]; + + if (!OidIsValid(get_element_type(va_arr_typid))) + ereport(ERROR, + (errcode(ERRCODE_DATATYPE_MISMATCH), + errmsg("VARIADIC argument must be an array"), + parser_errposition(pstate, exprLocation((Node *) llast(fargs))))); + } + /* build the appropriate output structure */ if (fdresult == FUNCDETAIL_NORMAL) { @@ -1033,6 +1051,7 @@ func_get_detail(List *funcname, Oid *rettype, /* return value */ bool *retset, /* return value */ int *nvargs, /* return value */ + Oid *vatype, /* return value */ Oid **true_typeids, /* return value */ List **argdefaults) /* optional return value */ { @@ -1251,6 +1270,7 @@ func_get_detail(List *funcname, pform = (Form_pg_proc) GETSTRUCT(ftup); *rettype = pform->prorettype; *retset = pform->proretset; + *vatype = pform->provariadic; /* fetch default args if caller wants 'em */ if (argdefaults && best_candidate->ndargs > 0) { -- cgit v1.2.3