diff options
Diffstat (limited to 'src/backend/commands')
-rw-r--r-- | src/backend/commands/aggregatecmds.c | 37 | ||||
-rw-r--r-- | src/backend/commands/functioncmds.c | 7 |
2 files changed, 43 insertions, 1 deletions
diff --git a/src/backend/commands/aggregatecmds.c b/src/backend/commands/aggregatecmds.c index 6fc3e045492..b570d3e5fa5 100644 --- a/src/backend/commands/aggregatecmds.c +++ b/src/backend/commands/aggregatecmds.c @@ -45,7 +45,10 @@ * * "oldstyle" signals the old (pre-8.2) style where the aggregate input type * is specified by a BASETYPE element in the parameters. Otherwise, - * "args" is a list of FunctionParameter structs defining the agg's arguments. + * "args" is a pair, whose first element is a list of FunctionParameter structs + * defining the agg's arguments (both direct and aggregated), and whose second + * element is an Integer node with the number of direct args, or -1 if this + * isn't an ordered-set aggregate. * "parameters" is a list of DefElem representing the agg's definition clauses. */ Oid @@ -55,6 +58,7 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters, char *aggName; Oid aggNamespace; AclResult aclresult; + char aggKind = AGGKIND_NORMAL; List *transfuncName = NIL; List *finalfuncName = NIL; List *sortoperatorName = NIL; @@ -63,11 +67,13 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters, int32 transSpace = 0; char *initval = NULL; int numArgs; + int numDirectArgs = 0; oidvector *parameterTypes; ArrayType *allParameterTypes; ArrayType *parameterModes; ArrayType *parameterNames; List *parameterDefaults; + Oid variadicArgType; Oid transTypeId; char transTypeType; ListCell *pl; @@ -81,6 +87,19 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters, aclcheck_error(aclresult, ACL_KIND_NAMESPACE, get_namespace_name(aggNamespace)); + /* Deconstruct the output of the aggr_args grammar production */ + if (!oldstyle) + { + Assert(list_length(args) == 2); + numDirectArgs = intVal(lsecond(args)); + if (numDirectArgs >= 0) + aggKind = AGGKIND_ORDERED_SET; + else + numDirectArgs = 0; + args = (List *) linitial(args); + } + + /* Examine aggregate's definition clauses */ foreach(pl, parameters) { DefElem *defel = (DefElem *) lfirst(pl); @@ -99,6 +118,17 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters, sortoperatorName = defGetQualifiedName(defel); else if (pg_strcasecmp(defel->defname, "basetype") == 0) baseType = defGetTypeName(defel); + else if (pg_strcasecmp(defel->defname, "hypothetical") == 0) + { + if (defGetBoolean(defel)) + { + if (aggKind == AGGKIND_NORMAL) + ereport(ERROR, + (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), + errmsg("only ordered-set aggregates can be hypothetical"))); + aggKind = AGGKIND_HYPOTHETICAL; + } + } else if (pg_strcasecmp(defel->defname, "stype") == 0) transType = defGetTypeName(defel); else if (pg_strcasecmp(defel->defname, "stype1") == 0) @@ -162,6 +192,7 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters, parameterModes = NULL; parameterNames = NULL; parameterDefaults = NIL; + variadicArgType = InvalidOid; } else { @@ -186,6 +217,7 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters, ¶meterModes, ¶meterNames, ¶meterDefaults, + &variadicArgType, &requiredResultType); /* Parameter defaults are not currently allowed by the grammar */ Assert(parameterDefaults == NIL); @@ -241,12 +273,15 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters, */ return AggregateCreate(aggName, /* aggregate name */ aggNamespace, /* namespace */ + aggKind, numArgs, + numDirectArgs, parameterTypes, PointerGetDatum(allParameterTypes), PointerGetDatum(parameterModes), PointerGetDatum(parameterNames), parameterDefaults, + variadicArgType, 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 ca754b47ff9..49b046597cf 100644 --- a/src/backend/commands/functioncmds.c +++ b/src/backend/commands/functioncmds.c @@ -168,6 +168,8 @@ compute_return_type(TypeName *returnType, Oid languageOid, * * Results are stored into output parameters. parameterTypes must always * be created, but the other arrays are set to NULL if not needed. + * variadicArgType is set to the variadic array type if there's a VARIADIC + * parameter (there can be only one); or to InvalidOid if not. * requiredResultType is set to InvalidOid if there are no OUT parameters, * else it is set to the OID of the implied result type. */ @@ -181,6 +183,7 @@ interpret_function_parameter_list(List *parameters, ArrayType **parameterModes, ArrayType **parameterNames, List **parameterDefaults, + Oid *variadicArgType, Oid *requiredResultType) { int parameterCount = list_length(parameters); @@ -197,6 +200,7 @@ interpret_function_parameter_list(List *parameters, int i; ParseState *pstate; + *variadicArgType = InvalidOid; /* default result */ *requiredResultType = InvalidOid; /* default result */ inTypes = (Oid *) palloc(parameterCount * sizeof(Oid)); @@ -293,6 +297,7 @@ interpret_function_parameter_list(List *parameters, if (fp->mode == FUNC_PARAM_VARIADIC) { + *variadicArgType = toid; varCount++; /* validate variadic parameter type */ switch (toid) @@ -823,6 +828,7 @@ CreateFunction(CreateFunctionStmt *stmt, const char *queryString) ArrayType *parameterModes; ArrayType *parameterNames; List *parameterDefaults; + Oid variadicArgType; Oid requiredResultType; bool isWindowFunc, isStrict, @@ -920,6 +926,7 @@ CreateFunction(CreateFunctionStmt *stmt, const char *queryString) ¶meterModes, ¶meterNames, ¶meterDefaults, + &variadicArgType, &requiredResultType); if (stmt->returnType) |