aboutsummaryrefslogtreecommitdiff
path: root/src/backend/parser/parse_func.c
diff options
context:
space:
mode:
authorAndrew Dunstan <andrew@dunslane.net>2013-07-18 11:52:12 -0400
committerAndrew Dunstan <andrew@dunslane.net>2013-07-18 11:52:12 -0400
commitd26888bc4d1e539a82f21382b0000fe5bbf889d9 (patch)
tree45971c200f11e8b55af421cdadf012b4071f8ce1 /src/backend/parser/parse_func.c
parent405a468b02dd80a069b95c4eb9838cb6a562eddd (diff)
downloadpostgresql-d26888bc4d1e539a82f21382b0000fe5bbf889d9.tar.gz
postgresql-d26888bc4d1e539a82f21382b0000fe5bbf889d9.zip
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.
Diffstat (limited to 'src/backend/parser/parse_func.c')
-rw-r--r--src/backend/parser/parse_func.c22
1 files changed, 21 insertions, 1 deletions
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)
{