From 8bba4b4e0eaa16fbbddbf0631ea295a6953eec85 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Fri, 26 May 2000 03:56:40 +0000 Subject: [PATCH] Generate a reasonable error message when an aggregate function is applied to an undecorated relation name (cf. example from Ed Loehr, 5/25/00). --- src/backend/parser/parse_func.c | 55 ++++++++++++++++++++------------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c index 3b543c3d61..ed6a910f27 100644 --- a/src/backend/parser/parse_func.c +++ b/src/backend/parser/parse_func.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.78 2000/04/12 17:15:26 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.79 2000/05/26 03:56:40 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -271,6 +271,7 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs, Node *retval; bool retset; bool must_be_agg = agg_star || agg_distinct; + bool could_be_agg; bool attisset = false; Oid toid = InvalidOid; Expr *expr; @@ -291,7 +292,7 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs, if (nargs == 1 && !must_be_agg) { /* Is it a plain Relation name from the parser? */ - if (IsA(first_arg, Ident) &&((Ident *) first_arg)->isRel) + if (IsA(first_arg, Ident) && ((Ident *) first_arg)->isRel) { Ident *ident = (Ident *) first_arg; RangeTblEntry *rte; @@ -413,28 +414,31 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs, } } - if (nargs == 1 || must_be_agg) + /* + * See if it's an aggregate. + */ + if (must_be_agg) { - - /* - * See if it's an aggregate. - */ - Oid basetype; - int ncandidates; - CandidateList candidates; - /* We don't presently cope with, eg, foo(DISTINCT x,y) */ if (nargs != 1) elog(ERROR, "Aggregate functions may only have one parameter"); + /* Agg's argument can't be a relation name, either */ + if (IsA(first_arg, Ident) && ((Ident *) first_arg)->isRel) + elog(ERROR, "Aggregate functions cannot be applied to relation names"); + could_be_agg = true; + } + else + { + /* Try to parse as an aggregate if above-mentioned checks are OK */ + could_be_agg = (nargs == 1) && + !(IsA(first_arg, Ident) && ((Ident *) first_arg)->isRel); + } - /* - * the aggregate COUNT is a special case, ignore its base type. - * Treat it as zero. XXX mighty ugly --- FIXME - */ - if (strcmp(funcname, "count") == 0) - basetype = 0; - else - basetype = exprType(lfirst(fargs)); + if (could_be_agg) + { + Oid basetype = exprType(lfirst(fargs)); + int ncandidates; + CandidateList candidates; /* try for exact match first... */ if (SearchSysCacheTuple(AGGNAME, @@ -445,9 +449,18 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs, fargs, agg_star, agg_distinct, precedence); + /* check for aggregate-that-accepts-any-type (eg, COUNT) */ + if (SearchSysCacheTuple(AGGNAME, + PointerGetDatum(funcname), + ObjectIdGetDatum(0), + 0, 0)) + return (Node *) ParseAgg(pstate, funcname, 0, + fargs, agg_star, agg_distinct, + precedence); + /* * No exact match yet, so see if there is another entry in the - * aggregate table which is compatible. - thomas 1998-12-05 + * aggregate table that is compatible. - thomas 1998-12-05 */ ncandidates = agg_get_candidates(funcname, basetype, &candidates); if (ncandidates > 0) @@ -497,7 +510,7 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs, { Node *arg = lfirst(i); - if (IsA(arg, Ident) &&((Ident *) arg)->isRel) + if (IsA(arg, Ident) && ((Ident *) arg)->isRel) { RangeTblEntry *rte; int vnum;