diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2006-07-27 19:52:07 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2006-07-27 19:52:07 +0000 |
commit | 108fe4730152058f9b576969d08898b39bf7fc38 (patch) | |
tree | 15a7d14be8267612cdfed4de8af86993b37f9997 /src/backend/parser/parse_func.c | |
parent | c2d1138351f89d0705f71cf935a56b9a2e28ed24 (diff) | |
download | postgresql-108fe4730152058f9b576969d08898b39bf7fc38.tar.gz postgresql-108fe4730152058f9b576969d08898b39bf7fc38.zip |
Aggregate functions now support multiple input arguments. I also took
the opportunity to treat COUNT(*) as a zero-argument aggregate instead
of the old hack that equated it to COUNT(1); this is materially cleaner
(no more weird ANYOID cases) and ought to be at least a tiny bit faster.
Original patch by Sergey Koposov; review, documentation, simple regression
tests, pg_dump and psql support by moi.
Diffstat (limited to 'src/backend/parser/parse_func.c')
-rw-r--r-- | src/backend/parser/parse_func.c | 54 |
1 files changed, 26 insertions, 28 deletions
diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c index aa0632a3898..b1b53164f80 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.188 2006/07/14 14:52:22 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/parser/parse_func.c,v 1.189 2006/07/27 19:52:05 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -259,10 +259,21 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs, aggref->aggfnoid = funcid; aggref->aggtype = rettype; - aggref->target = linitial(fargs); + aggref->args = fargs; aggref->aggstar = agg_star; aggref->aggdistinct = agg_distinct; + /* + * Reject attempt to call a parameterless aggregate without (*) + * syntax. This is mere pedantry but some folks insisted ... + */ + if (fargs == NIL && !agg_star) + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("%s(*) must be used to call a parameterless aggregate function", + NameListToString(funcname)), + parser_errposition(pstate, location))); + /* parse_agg.c does additional aggregate-specific processing */ transformAggregateCall(pstate, aggref); @@ -1194,9 +1205,7 @@ LookupFuncNameTypeNames(List *funcname, List *argtypes, bool noError) * * 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) + * function really is an aggregate. */ Oid LookupAggNameTypeNames(List *aggname, List *argtypes, bool noError) @@ -1204,7 +1213,7 @@ LookupAggNameTypeNames(List *aggname, List *argtypes, bool noError) Oid argoids[FUNC_MAX_ARGS]; int argcount; int i; - ListCell *args_item; + ListCell *lc; Oid oid; HeapTuple ftup; Form_pg_proc pform; @@ -1216,29 +1225,18 @@ LookupAggNameTypeNames(List *aggname, List *argtypes, bool noError) errmsg("functions cannot have more than %d arguments", FUNC_MAX_ARGS))); - if (argcount == 0) - { - /* special case for agg(*) */ - argoids[0] = ANYOID; - argcount = 1; - } - else + i = 0; + foreach(lc, argtypes) { - 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)))); + TypeName *t = (TypeName *) lfirst(lc); - args_item = lnext(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)))); + i++; } oid = LookupFuncName(aggname, argcount, argoids, true); @@ -1247,7 +1245,7 @@ LookupAggNameTypeNames(List *aggname, List *argtypes, bool noError) { if (noError) return InvalidOid; - if (argcount == 1 && argoids[0] == ANYOID) + if (argcount == 0) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_FUNCTION), errmsg("aggregate %s(*) does not exist", |