aboutsummaryrefslogtreecommitdiff
path: root/src/backend/commands
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/commands')
-rw-r--r--src/backend/commands/aggregatecmds.c55
-rw-r--r--src/backend/commands/functioncmds.c66
2 files changed, 84 insertions, 37 deletions
diff --git a/src/backend/commands/aggregatecmds.c b/src/backend/commands/aggregatecmds.c
index 4a03786210a..78af0924654 100644
--- a/src/backend/commands/aggregatecmds.c
+++ b/src/backend/commands/aggregatecmds.c
@@ -45,10 +45,12 @@
*
* "oldstyle" signals the old (pre-8.2) style where the aggregate input type
* is specified by a BASETYPE element in the parameters. Otherwise,
- * "args" defines the input type(s).
+ * "args" is a list of FunctionParameter structs defining the agg's arguments.
+ * "parameters" is a list of DefElem representing the agg's definition clauses.
*/
Oid
-DefineAggregate(List *name, List *args, bool oldstyle, List *parameters)
+DefineAggregate(List *name, List *args, bool oldstyle, List *parameters,
+ const char *queryString)
{
char *aggName;
Oid aggNamespace;
@@ -59,8 +61,12 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters)
TypeName *baseType = NULL;
TypeName *transType = NULL;
char *initval = NULL;
- Oid *aggArgTypes;
int numArgs;
+ oidvector *parameterTypes;
+ ArrayType *allParameterTypes;
+ ArrayType *parameterModes;
+ ArrayType *parameterNames;
+ List *parameterDefaults;
Oid transTypeId;
char transTypeType;
ListCell *pl;
@@ -131,6 +137,8 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters)
* Historically we allowed the command to look like basetype = 'ANY'
* so we must do a case-insensitive comparison for the name ANY. Ugh.
*/
+ Oid aggArgTypes[1];
+
if (baseType == NULL)
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
@@ -139,22 +147,26 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters)
if (pg_strcasecmp(TypeNameToString(baseType), "ANY") == 0)
{
numArgs = 0;
- aggArgTypes = NULL;
+ aggArgTypes[0] = InvalidOid;
}
else
{
numArgs = 1;
- aggArgTypes = (Oid *) palloc(sizeof(Oid));
aggArgTypes[0] = typenameTypeId(NULL, baseType);
}
+ parameterTypes = buildoidvector(aggArgTypes, numArgs);
+ allParameterTypes = NULL;
+ parameterModes = NULL;
+ parameterNames = NULL;
+ parameterDefaults = NIL;
}
else
{
/*
- * New style: args is a list of TypeNames (possibly zero of 'em).
+ * New style: args is a list of FunctionParameters (possibly zero of
+ * 'em). We share functioncmds.c's code for processing them.
*/
- ListCell *lc;
- int i = 0;
+ Oid requiredResultType;
if (baseType != NULL)
ereport(ERROR,
@@ -162,13 +174,20 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters)
errmsg("basetype is redundant with aggregate input type specification")));
numArgs = list_length(args);
- aggArgTypes = (Oid *) palloc(sizeof(Oid) * numArgs);
- foreach(lc, args)
- {
- TypeName *curTypeName = (TypeName *) lfirst(lc);
-
- aggArgTypes[i++] = typenameTypeId(NULL, curTypeName);
- }
+ interpret_function_parameter_list(args,
+ InvalidOid,
+ true, /* is an aggregate */
+ queryString,
+ &parameterTypes,
+ &allParameterTypes,
+ &parameterModes,
+ &parameterNames,
+ &parameterDefaults,
+ &requiredResultType);
+ /* Parameter defaults are not currently allowed by the grammar */
+ Assert(parameterDefaults == NIL);
+ /* There shouldn't have been any OUT parameters, either */
+ Assert(requiredResultType == InvalidOid);
}
/*
@@ -219,8 +238,12 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters)
*/
return AggregateCreate(aggName, /* aggregate name */
aggNamespace, /* namespace */
- aggArgTypes, /* input data type(s) */
numArgs,
+ parameterTypes,
+ PointerGetDatum(allParameterTypes),
+ PointerGetDatum(parameterModes),
+ PointerGetDatum(parameterNames),
+ parameterDefaults,
transfuncName, /* step function name */
finalfuncName, /* final function name */
sortoperatorName, /* sort operator name */
diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c
index 0a9facfbaaa..ca754b47ff9 100644
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -88,7 +88,6 @@ compute_return_type(TypeName *returnType, Oid languageOid,
typtup = LookupTypeName(NULL, returnType, NULL);
-
if (typtup)
{
if (!((Form_pg_type) GETSTRUCT(typtup))->typisdefined)
@@ -158,22 +157,31 @@ compute_return_type(TypeName *returnType, Oid languageOid,
}
/*
- * Interpret the parameter list of the CREATE FUNCTION statement.
+ * Interpret the function parameter list of a CREATE FUNCTION or
+ * CREATE AGGREGATE statement.
+ *
+ * Input parameters:
+ * parameters: list of FunctionParameter structs
+ * languageOid: OID of function language (InvalidOid if it's CREATE AGGREGATE)
+ * is_aggregate: needed only to determine error handling
+ * queryString: likewise, needed only for error handling
*
* Results are stored into output parameters. parameterTypes must always
* be created, but the other arrays are set to NULL if not needed.
* requiredResultType is set to InvalidOid if there are no OUT parameters,
* else it is set to the OID of the implied result type.
*/
-static void
-examine_parameter_list(List *parameters, Oid languageOid,
- const char *queryString,
- oidvector **parameterTypes,
- ArrayType **allParameterTypes,
- ArrayType **parameterModes,
- ArrayType **parameterNames,
- List **parameterDefaults,
- Oid *requiredResultType)
+void
+interpret_function_parameter_list(List *parameters,
+ Oid languageOid,
+ bool is_aggregate,
+ const char *queryString,
+ oidvector **parameterTypes,
+ ArrayType **allParameterTypes,
+ ArrayType **parameterModes,
+ ArrayType **parameterNames,
+ List **parameterDefaults,
+ Oid *requiredResultType)
{
int parameterCount = list_length(parameters);
Oid *inTypes;
@@ -223,6 +231,12 @@ examine_parameter_list(List *parameters, Oid languageOid,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("SQL function cannot accept shell type %s",
TypeNameToString(t))));
+ /* We don't allow creating aggregates on shell types either */
+ else if (is_aggregate)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
+ errmsg("aggregate cannot accept shell type %s",
+ TypeNameToString(t))));
else
ereport(NOTICE,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
@@ -246,9 +260,16 @@ examine_parameter_list(List *parameters, Oid languageOid,
aclcheck_error_type(aclresult, toid);
if (t->setof)
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
- errmsg("functions cannot accept set arguments")));
+ {
+ if (is_aggregate)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
+ errmsg("aggregates cannot accept set arguments")));
+ else
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
+ errmsg("functions cannot accept set arguments")));
+ }
/* handle input parameters */
if (fp->mode != FUNC_PARAM_OUT && fp->mode != FUNC_PARAM_TABLE)
@@ -890,13 +911,16 @@ CreateFunction(CreateFunctionStmt *stmt, const char *queryString)
* Convert remaining parameters of CREATE to form wanted by
* ProcedureCreate.
*/
- examine_parameter_list(stmt->parameters, languageOid, queryString,
- &parameterTypes,
- &allParameterTypes,
- &parameterModes,
- &parameterNames,
- &parameterDefaults,
- &requiredResultType);
+ interpret_function_parameter_list(stmt->parameters,
+ languageOid,
+ false, /* not an aggregate */
+ queryString,
+ &parameterTypes,
+ &allParameterTypes,
+ &parameterModes,
+ &parameterNames,
+ &parameterDefaults,
+ &requiredResultType);
if (stmt->returnType)
{