Make plpgsql complain about conflicting IN and OUT parameter names.

The core CREATE FUNCTION code only enforces that IN parameter names are
non-duplicate, and that OUT parameter names are separately non-duplicate.
This is because some function languages might not have any confusion
between the two.  But in plpgsql, such names are all in the same namespace,
so we'd better disallow it.

Per a recent complaint from Dan S.  Not back-patching since this is a small
issue and the change could cause unexpected failures if we started to
enforce it in a minor release.
This commit is contained in:
Tom Lane 2011-05-23 16:34:27 -04:00
parent 34be83b7e1
commit 59a4a571d3

View File

@ -95,6 +95,7 @@ static PLpgSQL_function *do_compile(FunctionCallInfo fcinfo,
PLpgSQL_func_hashkey *hashkey,
bool forValidator);
static void plpgsql_compile_error_callback(void *arg);
static void add_parameter_name(int itemtype, int itemno, const char *name);
static void add_dummy_return(PLpgSQL_function *function);
static Node *plpgsql_pre_column_ref(ParseState *pstate, ColumnRef *cref);
static Node *plpgsql_post_column_ref(ParseState *pstate, ColumnRef *cref, Node *var);
@ -451,11 +452,11 @@ do_compile(FunctionCallInfo fcinfo,
out_arg_variables[num_out_args++] = argvariable;
/* Add to namespace under the $n name */
plpgsql_ns_additem(argitemtype, argvariable->dno, buf);
add_parameter_name(argitemtype, argvariable->dno, buf);
/* If there's a name for the argument, make an alias */
if (argnames && argnames[i][0] != '\0')
plpgsql_ns_additem(argitemtype, argvariable->dno,
add_parameter_name(argitemtype, argvariable->dno,
argnames[i]);
}
@ -913,6 +914,31 @@ plpgsql_compile_error_callback(void *arg)
}
/*
* Add a name for a function parameter to the function's namespace
*/
static void
add_parameter_name(int itemtype, int itemno, const char *name)
{
/*
* Before adding the name, check for duplicates. We need this even though
* functioncmds.c has a similar check, because that code explicitly
* doesn't complain about conflicting IN and OUT parameter names. In
* plpgsql, such names are in the same namespace, so there is no way to
* disambiguate.
*/
if (plpgsql_ns_lookup(plpgsql_ns_top(), true,
name, NULL, NULL,
NULL) != NULL)
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("parameter name \"%s\" used more than once",
name)));
/* OK, add the name */
plpgsql_ns_additem(itemtype, itemno, name);
}
/*
* Add a dummy RETURN statement to the given function's body
*/