1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-14 18:42:34 +03:00

Support "variadic" functions, which can accept a variable number of arguments

so long as all the trailing arguments are of the same (non-array) type.
The function receives them as a single array argument (which is why they
have to all be the same type).

It might be useful to extend this facility to aggregates, but this patch
doesn't do that.

This patch imposes a noticeable slowdown on function lookup --- a follow-on
patch will fix that by adding a redundant column to pg_proc.

Pavel Stehule
This commit is contained in:
Tom Lane
2008-07-16 01:30:23 +00:00
parent 2c773296f8
commit d89737d31c
38 changed files with 915 additions and 170 deletions

View File

@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/functioncmds.c,v 1.95 2008/07/12 10:44:56 petere Exp $
* $PostgreSQL: pgsql/src/backend/commands/functioncmds.c,v 1.96 2008/07/16 01:30:22 tgl Exp $
*
* DESCRIPTION
* These routines take the parse tree and pick out the
@ -173,6 +173,7 @@ examine_parameter_list(List *parameters, Oid languageOid,
Datum *paramModes;
Datum *paramNames;
int outCount = 0;
int varCount = 0;
bool have_names = false;
ListCell *x;
int i;
@ -228,15 +229,41 @@ examine_parameter_list(List *parameters, Oid languageOid,
errmsg("functions cannot accept set arguments")));
if (fp->mode != FUNC_PARAM_OUT)
{
/* only OUT parameters can follow a VARIADIC parameter */
if (varCount > 0)
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("VARIADIC parameter must be the last input parameter")));
inTypes[inCount++] = toid;
}
if (fp->mode != FUNC_PARAM_IN)
if (fp->mode != FUNC_PARAM_IN && fp->mode != FUNC_PARAM_VARIADIC)
{
if (outCount == 0) /* save first OUT param's type */
*requiredResultType = toid;
outCount++;
}
if (fp->mode == FUNC_PARAM_VARIADIC)
{
varCount++;
/* validate variadic parameter type */
switch (toid)
{
case ANYARRAYOID:
case ANYOID:
/* okay */
break;
default:
if (!OidIsValid(get_element_type(toid)))
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("VARIADIC parameter must be an array")));
break;
}
}
allTypes[i] = ObjectIdGetDatum(toid);
paramModes[i] = CharGetDatum(fp->mode);
@ -253,7 +280,7 @@ examine_parameter_list(List *parameters, Oid languageOid,
/* Now construct the proper outputs as needed */
*parameterTypes = buildoidvector(inTypes, inCount);
if (outCount > 0)
if (outCount > 0 || varCount > 0)
{
*allParameterTypes = construct_array(allTypes, parameterCount, OIDOID,
sizeof(Oid), true, 'i');