aboutsummaryrefslogtreecommitdiff
path: root/src/backend/parser/parse_func.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2006-04-15 17:45:46 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2006-04-15 17:45:46 +0000
commit3651a3e6fb41121f2262577774382e84bf9a3177 (patch)
treee09fb8fcf6851e4625f4eb5595ede6f16367056f /src/backend/parser/parse_func.c
parentebd5257d493ac8a6f20eea667409cf9b06ac3202 (diff)
downloadpostgresql-3651a3e6fb41121f2262577774382e84bf9a3177.tar.gz
postgresql-3651a3e6fb41121f2262577774382e84bf9a3177.zip
Support the syntax
CREATE AGGREGATE aggname (input_type) (parameter_list) along with the old syntax where the input type was named in the parameter list. This fits more naturally with the way that the aggregate is identified in DROP AGGREGATE and other utility commands; furthermore it has a natural extension to handle multiple-input aggregates, where the basetype-parameter method would get ugly. In fact, this commit fixes the grammar and all the utility commands to support multiple-input aggregates; but DefineAggregate rejects it because the executor isn't fixed yet. I didn't do anything about treating agg(*) as a zero-input aggregate instead of artificially making it a one-input aggregate, but that should be considered in combination with supporting multi-input aggregates.
Diffstat (limited to 'src/backend/parser/parse_func.c')
-rw-r--r--src/backend/parser/parse_func.c159
1 files changed, 99 insertions, 60 deletions
diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c
index 35e826881fd..d7c04620b28 100644
--- a/src/backend/parser/parse_func.c
+++ b/src/backend/parser/parse_func.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/parser/parse_func.c,v 1.185 2006/03/14 22:48:21 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/parser/parse_func.c,v 1.186 2006/04/15 17:45:40 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1116,65 +1116,6 @@ func_signature_string(List *funcname, int nargs, const Oid *argtypes)
}
/*
- * find_aggregate_func
- * Convenience routine to check that a function exists and is an
- * aggregate.
- *
- * Note: basetype is ANYOID if we are looking for an aggregate on
- * all types.
- */
-Oid
-find_aggregate_func(List *aggname, Oid basetype, bool noError)
-{
- Oid oid;
- HeapTuple ftup;
- Form_pg_proc pform;
-
- oid = LookupFuncName(aggname, 1, &basetype, true);
-
- if (!OidIsValid(oid))
- {
- if (noError)
- return InvalidOid;
- if (basetype == ANYOID)
- ereport(ERROR,
- (errcode(ERRCODE_UNDEFINED_FUNCTION),
- errmsg("aggregate %s(*) does not exist",
- NameListToString(aggname))));
- else
- ereport(ERROR,
- (errcode(ERRCODE_UNDEFINED_FUNCTION),
- errmsg("aggregate %s(%s) does not exist",
- NameListToString(aggname),
- format_type_be(basetype))));
- }
-
- /* Make sure it's an aggregate */
- ftup = SearchSysCache(PROCOID,
- ObjectIdGetDatum(oid),
- 0, 0, 0);
- if (!HeapTupleIsValid(ftup)) /* should not happen */
- elog(ERROR, "cache lookup failed for function %u", oid);
- pform = (Form_pg_proc) GETSTRUCT(ftup);
-
- if (!pform->proisagg)
- {
- ReleaseSysCache(ftup);
- if (noError)
- return InvalidOid;
- /* we do not use the (*) notation for functions... */
- ereport(ERROR,
- (errcode(ERRCODE_WRONG_OBJECT_TYPE),
- errmsg("function %s(%s) is not an aggregate",
- NameListToString(aggname), format_type_be(basetype))));
- }
-
- ReleaseSysCache(ftup);
-
- return oid;
-}
-
-/*
* LookupFuncName
* Given a possibly-qualified function name and a set of argument types,
* look up the function.
@@ -1246,3 +1187,101 @@ LookupFuncNameTypeNames(List *funcname, List *argtypes, bool noError)
return LookupFuncName(funcname, argcount, argoids, noError);
}
+
+/*
+ * LookupAggNameTypeNames
+ * Find an aggregate function given a name and list of TypeName nodes.
+ *
+ * This is almost like LookupFuncNameTypeNames, but the error messages refer
+ * to aggregates rather than plain functions, and we verify that the found
+ * function really is an aggregate, and we recognize the convention used by
+ * the grammar that agg(*) translates to a NIL list, which we have to treat
+ * as one ANY argument. (XXX this ought to be changed)
+ */
+Oid
+LookupAggNameTypeNames(List *aggname, List *argtypes, bool noError)
+{
+ Oid argoids[FUNC_MAX_ARGS];
+ int argcount;
+ int i;
+ ListCell *args_item;
+ Oid oid;
+ HeapTuple ftup;
+ Form_pg_proc pform;
+
+ argcount = list_length(argtypes);
+ if (argcount > FUNC_MAX_ARGS)
+ ereport(ERROR,
+ (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
+ errmsg("functions cannot have more than %d arguments",
+ FUNC_MAX_ARGS)));
+
+ if (argcount == 0)
+ {
+ /* special case for agg(*) */
+ argoids[0] = ANYOID;
+ argcount = 1;
+ }
+ else
+ {
+ args_item = list_head(argtypes);
+ for (i = 0; i < argcount; i++)
+ {
+ TypeName *t = (TypeName *) lfirst(args_item);
+
+ argoids[i] = LookupTypeName(NULL, t);
+
+ if (!OidIsValid(argoids[i]))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("type \"%s\" does not exist",
+ TypeNameToString(t))));
+
+ args_item = lnext(args_item);
+ }
+ }
+
+ oid = LookupFuncName(aggname, argcount, argoids, true);
+
+ if (!OidIsValid(oid))
+ {
+ if (noError)
+ return InvalidOid;
+ if (argcount == 1 && argoids[0] == ANYOID)
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_FUNCTION),
+ errmsg("aggregate %s(*) does not exist",
+ NameListToString(aggname))));
+ else
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_FUNCTION),
+ errmsg("aggregate %s does not exist",
+ func_signature_string(aggname,
+ argcount, argoids))));
+ }
+
+ /* Make sure it's an aggregate */
+ ftup = SearchSysCache(PROCOID,
+ ObjectIdGetDatum(oid),
+ 0, 0, 0);
+ if (!HeapTupleIsValid(ftup)) /* should not happen */
+ elog(ERROR, "cache lookup failed for function %u", oid);
+ pform = (Form_pg_proc) GETSTRUCT(ftup);
+
+ if (!pform->proisagg)
+ {
+ ReleaseSysCache(ftup);
+ if (noError)
+ return InvalidOid;
+ /* we do not use the (*) notation for functions... */
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("function %s is not an aggregate",
+ func_signature_string(aggname,
+ argcount, argoids))));
+ }
+
+ ReleaseSysCache(ftup);
+
+ return oid;
+}