summaryrefslogtreecommitdiff
path: root/src/backend/commands/functioncmds.c
diff options
context:
space:
mode:
authorTom Lane2008-07-16 01:30:23 +0000
committerTom Lane2008-07-16 01:30:23 +0000
commit9da84d1c6cf8c37a46b3f85c054404ebf7b695d0 (patch)
tree5f83702ad8d86ebf3a5429d695a6f528ad9a65b2 /src/backend/commands/functioncmds.c
parent105bece010aff2f8a6b3127fc1ffad112c440d25 (diff)
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
Diffstat (limited to 'src/backend/commands/functioncmds.c')
-rw-r--r--src/backend/commands/functioncmds.c31
1 files changed, 29 insertions, 2 deletions
diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c
index 0e5804cb33..9f010d479d 100644
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -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');