diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index 789faad772c739468bd9feec0d0c147867da54f5..78bda61b30fc72e4e2e8f674ab5860e8d274dc68 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -5,7 +5,7 @@ * * Copyright (c) 1994, Regents of the University of California * - * $Id: outfuncs.c,v 1.98 1999/11/23 20:06:53 momjian Exp $ + * $Id: outfuncs.c,v 1.99 1999/12/10 07:37:31 tgl Exp $ * * NOTES * Every (plan) node in POSTGRES has an associated "out" routine which @@ -114,8 +114,12 @@ _outSelectStmt(StringInfo str, SelectStmt *node) static void _outFuncCall(StringInfo str, FuncCall *node) { - appendStringInfo(str, "FUNCTION %s :args ", stringStringInfo(node->funcname)); + appendStringInfo(str, "FUNCTION %s :args ", + stringStringInfo(node->funcname)); _outNode(str, node->args); + appendStringInfo(str, " :agg_star %s :agg_distinct %s ", + node->agg_star ? "true" : "false", + node->agg_distinct ? "true" : "false"); } static void diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c index e93bd13d9a11c6842c64782f5c2224141494d1ed..2162bbff315c77b8121e422b38567be9b54be411 100644 --- a/src/backend/parser/analyze.c +++ b/src/backend/parser/analyze.c @@ -5,7 +5,7 @@ * * Copyright (c) 1994, Regents of the University of California * - * $Id: analyze.c,v 1.125 1999/12/06 18:02:42 wieck Exp $ + * $Id: analyze.c,v 1.126 1999/12/10 07:37:35 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -624,6 +624,8 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt) funccallnode = makeNode(FuncCall); funccallnode->funcname = "nextval"; funccallnode->args = lcons(snamenode, NIL); + funccallnode->agg_star = false; + funccallnode->agg_distinct = false; constraint = makeNode(Constraint); constraint->contype = CONSTR_DEFAULT; diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 4352bb327a75ce9ead948e9232fccf57730c0d43..d3fb6291806aaa7652c05705cd0850a128b299aa 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.120 1999/12/10 05:17:13 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.121 1999/12/10 07:37:35 tgl Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -246,7 +246,7 @@ static Node *doNegate(Node *n); %type <str> TypeId %type <node> TableConstraint -%type <list> ColPrimaryKey, ColQualifier +%type <list> ColPrimaryKey, ColConstraintList %type <node> ColConstraint, ColConstraintElem %type <ival> key_actions, key_action, key_reference %type <str> key_match @@ -912,7 +912,7 @@ OptTableElement: columnDef { $$ = $1; } | TableConstraint { $$ = $1; } ; -columnDef: ColId Typename ColQualifier +columnDef: ColId Typename ColConstraintList { ColumnDef *n = makeNode(ColumnDef); n->colname = $1; @@ -939,14 +939,15 @@ columnDef: ColId Typename ColQualifier } ; -ColQualifier: ColQualifier ColConstraint +ColConstraintList: ColConstraintList ColConstraint { if ($2 != NULL) $$ = lappend($1, $2); else $$ = $1; } - | /*EMPTY*/ { $$ = NULL; } + | /*EMPTY*/ + { $$ = NIL; } ; ColPrimaryKey: PRIMARY KEY @@ -3792,6 +3793,8 @@ a_expr: com_expr FuncCall *n = makeNode(FuncCall); n->funcname = $3->name; n->args = lcons($1,NIL); + n->agg_star = false; + n->agg_distinct = false; $$ = (Node *)n; } } @@ -4037,6 +4040,8 @@ b_expr: com_expr FuncCall *n = makeNode(FuncCall); n->funcname = $3->name; n->args = lcons($1,NIL); + n->agg_star = false; + n->agg_distinct = false; $$ = (Node *)n; } } @@ -4129,6 +4134,8 @@ com_expr: attr FuncCall *n = makeNode(FuncCall); n->funcname = $5->name; n->args = lcons($3,NIL); + n->agg_star = false; + n->agg_distinct = false; $$ = (Node *)n; } } @@ -4139,6 +4146,8 @@ com_expr: attr FuncCall *n = makeNode(FuncCall); n->funcname = $1; n->args = NIL; + n->agg_star = false; + n->agg_distinct = false; $$ = (Node *)n; } | func_name '(' expr_list ')' @@ -4146,6 +4155,17 @@ com_expr: attr FuncCall *n = makeNode(FuncCall); n->funcname = $1; n->args = $3; + n->agg_star = false; + n->agg_distinct = false; + $$ = (Node *)n; + } + | func_name '(' DISTINCT expr_list ')' + { + FuncCall *n = makeNode(FuncCall); + n->funcname = $1; + n->args = $4; + n->agg_star = false; + n->agg_distinct = true; $$ = (Node *)n; } | func_name '(' '*' ')' @@ -4158,12 +4178,9 @@ com_expr: attr * and there are no other aggregates in SQL92 that accept * '*' as parameter. * - * XXX really, the '*' ought to be transformed to some - * special construct that wouldn't be acceptable as the - * input of a non-aggregate function, in case the given - * func_name matches a plain function. This would also - * support a possible extension to let user-defined - * aggregates do something special with '*' as input. + * The FuncCall node is also marked agg_star = true, + * so that later processing can detect what the argument + * really was. */ FuncCall *n = makeNode(FuncCall); A_Const *star = makeNode(A_Const); @@ -4172,6 +4189,8 @@ com_expr: attr star->val.val.ival = 1; n->funcname = $1; n->args = lcons(star, NIL); + n->agg_star = true; + n->agg_distinct = false; $$ = (Node *)n; } | CURRENT_DATE @@ -4203,6 +4222,8 @@ com_expr: attr n->funcname = xlateSqlType("date"); n->args = lcons(s, NIL); + n->agg_star = false; + n->agg_distinct = false; $$ = (Node *)n; } @@ -4226,6 +4247,8 @@ com_expr: attr n->funcname = xlateSqlType("time"); n->args = lcons(s, NIL); + n->agg_star = false; + n->agg_distinct = false; $$ = (Node *)n; } @@ -4249,6 +4272,8 @@ com_expr: attr n->funcname = xlateSqlType("time"); n->args = lcons(s, NIL); + n->agg_star = false; + n->agg_distinct = false; if ($3 != 0) elog(NOTICE,"CURRENT_TIME(%d) precision not implemented; zero used instead",$3); @@ -4275,6 +4300,8 @@ com_expr: attr n->funcname = xlateSqlType("timestamp"); n->args = lcons(s, NIL); + n->agg_star = false; + n->agg_distinct = false; $$ = (Node *)n; } @@ -4298,6 +4325,8 @@ com_expr: attr n->funcname = xlateSqlType("timestamp"); n->args = lcons(s, NIL); + n->agg_star = false; + n->agg_distinct = false; if ($3 != 0) elog(NOTICE,"CURRENT_TIMESTAMP(%d) precision not implemented; zero used instead",$3); @@ -4309,6 +4338,8 @@ com_expr: attr FuncCall *n = makeNode(FuncCall); n->funcname = "getpgusername"; n->args = NIL; + n->agg_star = false; + n->agg_distinct = false; $$ = (Node *)n; } | USER @@ -4316,6 +4347,8 @@ com_expr: attr FuncCall *n = makeNode(FuncCall); n->funcname = "getpgusername"; n->args = NIL; + n->agg_star = false; + n->agg_distinct = false; $$ = (Node *)n; } | EXTRACT '(' extract_list ')' @@ -4323,6 +4356,8 @@ com_expr: attr FuncCall *n = makeNode(FuncCall); n->funcname = "date_part"; n->args = $3; + n->agg_star = false; + n->agg_distinct = false; $$ = (Node *)n; } | POSITION '(' position_list ')' @@ -4330,6 +4365,8 @@ com_expr: attr FuncCall *n = makeNode(FuncCall); n->funcname = "strpos"; n->args = $3; + n->agg_star = false; + n->agg_distinct = false; $$ = (Node *)n; } | SUBSTRING '(' substr_list ')' @@ -4337,6 +4374,8 @@ com_expr: attr FuncCall *n = makeNode(FuncCall); n->funcname = "substr"; n->args = $3; + n->agg_star = false; + n->agg_distinct = false; $$ = (Node *)n; } /* various trim expressions are defined in SQL92 - thomas 1997-07-19 */ @@ -4345,6 +4384,8 @@ com_expr: attr FuncCall *n = makeNode(FuncCall); n->funcname = "btrim"; n->args = $4; + n->agg_star = false; + n->agg_distinct = false; $$ = (Node *)n; } | TRIM '(' LEADING trim_list ')' @@ -4352,6 +4393,8 @@ com_expr: attr FuncCall *n = makeNode(FuncCall); n->funcname = "ltrim"; n->args = $4; + n->agg_star = false; + n->agg_distinct = false; $$ = (Node *)n; } | TRIM '(' TRAILING trim_list ')' @@ -4359,6 +4402,8 @@ com_expr: attr FuncCall *n = makeNode(FuncCall); n->funcname = "rtrim"; n->args = $4; + n->agg_star = false; + n->agg_distinct = false; $$ = (Node *)n; } | TRIM '(' trim_list ')' @@ -4366,6 +4411,8 @@ com_expr: attr FuncCall *n = makeNode(FuncCall); n->funcname = "btrim"; n->args = $3; + n->agg_star = false; + n->agg_distinct = false; $$ = (Node *)n; } | '(' SubSelect ')' diff --git a/src/backend/parser/parse_agg.c b/src/backend/parser/parse_agg.c index 4e30e60ca65a7b01b11ae5c2fa69c0066f7e1674..68280f7f4a0a9ea8d75ce25951921d4fdb0428c6 100644 --- a/src/backend/parser/parse_agg.c +++ b/src/backend/parser/parse_agg.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_agg.c,v 1.30 1999/12/09 05:58:54 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_agg.c,v 1.31 1999/12/10 07:37:35 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -203,7 +203,8 @@ parseCheckAggregates(ParseState *pstate, Query *qry) Aggref * ParseAgg(ParseState *pstate, char *aggname, Oid basetype, - List *target, int precedence) + List *args, bool agg_star, bool agg_distinct, + int precedence) { HeapTuple theAggTuple; Form_pg_aggregate aggform; @@ -242,7 +243,7 @@ ParseAgg(ParseState *pstate, char *aggname, Oid basetype, if (OidIsValid(xfn1)) { basetype = aggform->aggbasetype; - vartype = exprType(lfirst(target)); + vartype = exprType(lfirst(args)); if ((basetype != vartype) && (!IS_BINARY_COMPATIBLE(basetype, vartype))) { @@ -261,9 +262,17 @@ ParseAgg(ParseState *pstate, char *aggname, Oid basetype, aggref->aggname = pstrdup(aggname); aggref->basetype = aggform->aggbasetype; aggref->aggtype = fintype; - aggref->target = lfirst(target); + aggref->target = lfirst(args); aggref->usenulls = usenulls; + /* + * We should store agg_star and agg_distinct into the Aggref node, + * and let downstream processing deal with them. Currently, agg_star + * is ignored and agg_distinct is not implemented... + */ + if (agg_distinct) + elog(ERROR, "aggregate(DISTINCT ...) is not implemented yet"); + pstate->p_hasAggs = true; return aggref; diff --git a/src/backend/parser/parse_coerce.c b/src/backend/parser/parse_coerce.c index 0d51f2ae0565ebb1bd718a76a2021fad5b463d8c..95315d6c8244c17a6c7163269f9818b7fe5d088c 100644 --- a/src/backend/parser/parse_coerce.c +++ b/src/backend/parser/parse_coerce.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.25 1999/11/22 17:56:20 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.26 1999/12/10 07:37:35 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -99,6 +99,8 @@ coerce_type(ParseState *pstate, Node *node, Oid inputTypeId, Oid targetTypeId, n->funcname = typeTypeName(targetType); n->args = lcons(node, NIL); + n->agg_star = false; + n->agg_distinct = false; result = transformExpr(pstate, (Node *) n, EXPR_COLUMN_FIRST); diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c index 76e5f91f1a8978247d8e92f44c585196149a3e72..ee43be4195068c7c5e0e483974ac3cddc8731016 100644 --- a/src/backend/parser/parse_expr.c +++ b/src/backend/parser/parse_expr.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.59 1999/11/15 02:00:10 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.60 1999/12/10 07:37:35 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -106,8 +106,10 @@ transformExpr(ParseState *pstate, Node *expr, int precedence) Node *lexpr = transformExpr(pstate, a->lexpr, precedence); result = ParseFuncOrColumn(pstate, - "nullvalue", lcons(lexpr, NIL), - &pstate->p_last_resno, + "nullvalue", + lcons(lexpr, NIL), + false, false, + &pstate->p_last_resno, precedence); } break; @@ -116,8 +118,10 @@ transformExpr(ParseState *pstate, Node *expr, int precedence) Node *lexpr = transformExpr(pstate, a->lexpr, precedence); result = ParseFuncOrColumn(pstate, - "nonnullvalue", lcons(lexpr, NIL), - &pstate->p_last_resno, + "nonnullvalue", + lcons(lexpr, NIL), + false, false, + &pstate->p_last_resno, precedence); } break; @@ -192,6 +196,8 @@ transformExpr(ParseState *pstate, Node *expr, int precedence) result = ParseFuncOrColumn(pstate, fn->funcname, fn->args, + fn->agg_star, + fn->agg_distinct, &pstate->p_last_resno, precedence); break; diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c index aafa4e4c9cb057a25113e61b34fa1f2a3b05656b..42143746b815c77cfa5c7964eaa01e439af49308 100644 --- a/src/backend/parser/parse_func.c +++ b/src/backend/parser/parse_func.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.63 1999/12/07 04:09:39 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.64 1999/12/10 07:37:35 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -87,6 +87,7 @@ ParseNestedFuncOrColumn(ParseState *pstate, Attr *attr, int *curr_resno, int pre retval = ParseFuncOrColumn(pstate, strVal(lfirst(attr->attrs)), lcons(param, NIL), + false, false, curr_resno, precedence); } @@ -98,6 +99,7 @@ ParseNestedFuncOrColumn(ParseState *pstate, Attr *attr, int *curr_resno, int pre ident->isRel = TRUE; retval = ParseFuncOrColumn(pstate, strVal(lfirst(attr->attrs)), lcons(ident, NIL), + false, false, curr_resno, precedence); } @@ -107,6 +109,7 @@ ParseNestedFuncOrColumn(ParseState *pstate, Attr *attr, int *curr_resno, int pre { retval = ParseFuncOrColumn(pstate, strVal(lfirst(mutator_iter)), lcons(retval, NIL), + false, false, curr_resno, precedence); } @@ -219,6 +222,7 @@ agg_select_candidate(Oid typeid, CandidateList candidates) */ Node * ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs, + bool agg_star, bool agg_distinct, int *curr_resno, int precedence) { Oid rettype = InvalidOid; @@ -230,12 +234,13 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs, char *refname = NULL; Relation rd; Oid relid; - int nargs; + int nargs = length(fargs); Func *funcnode; Oid oid_array[MAXFARGS]; Oid *true_oid_array; Node *retval; bool retset; + bool must_be_agg = agg_star || agg_distinct; bool attisset = false; Oid toid = InvalidOid; Expr *expr; @@ -252,11 +257,11 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs, * that argument is a relation, param, or PQ function returning a * complex * type, then the function could be a projection. */ - /* We only have one parameter */ - if (length(fargs) == 1) + /* We only have one parameter, and it's not got aggregate decoration */ + if (nargs == 1 && !must_be_agg) { - /* Is is a plain Relation name from the parser? */ - if (nodeTag(first_arg) == T_Ident && ((Ident *) first_arg)->isRel) + /* Is it a plain Relation name from the parser? */ + if (IsA(first_arg, Ident) && ((Ident *) first_arg)->isRel) { RangeTblEntry *rte; Ident *ident = (Ident *) first_arg; @@ -292,15 +297,10 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs, refname, funcname); } - else - { - /* drop through - attr is a set */ - ; - } + /* else drop through - attr is a set */ } else if (ISCOMPLEX(exprType(first_arg))) { - /* * Attempt to handle projection of a complex argument. If * ParseComplexProjection can't handle the projection, we have @@ -325,8 +325,7 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs, argrelid = typeidTypeRelid(toid); /* - * A projection contains either an attribute name or the - * "*". + * A projection contains either an attribute name or "*". */ if ((get_attnum(argrelid, funcname) == InvalidAttrNumber) && strcmp(funcname, "*")) @@ -336,76 +335,99 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs, if (retval) return retval; } - else - { + } - /* - * Parsing aggregates. - */ - Type tp; - Oid basetype; - int ncandidates; - CandidateList candidates; + if (nargs == 1 || must_be_agg) + { + /* + * See if it's an aggregate. + */ + Oid basetype; + int ncandidates; + CandidateList candidates; - /* - * the aggregate COUNT is a special case, ignore its base - * type. Treat it as zero - */ - if (strcmp(funcname, "count") == 0) - basetype = 0; - else - basetype = exprType(lfirst(fargs)); + /* We don't presently cope with, eg, foo(DISTINCT x,y) */ + if (nargs != 1) + elog(ERROR, "Aggregate functions may only have one parameter"); - /* try for exact match first... */ - if (SearchSysCacheTuple(AGGNAME, - PointerGetDatum(funcname), - ObjectIdGetDatum(basetype), - 0, 0)) - return (Node *) ParseAgg(pstate, funcname, basetype, - fargs, precedence); + /* + * 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)); - /* - * No exact match yet, so see if there is another entry in the - * aggregate table which is compatible. - thomas 1998-12-05 - */ - ncandidates = agg_get_candidates(funcname, basetype, &candidates); - if (ncandidates > 0) - { - Oid type; + /* try for exact match first... */ + if (SearchSysCacheTuple(AGGNAME, + PointerGetDatum(funcname), + ObjectIdGetDatum(basetype), + 0, 0)) + return (Node *) ParseAgg(pstate, funcname, basetype, + fargs, agg_star, agg_distinct, + precedence); - type = agg_select_candidate(basetype, candidates); - if (OidIsValid(type)) - { - lfirst(fargs) = coerce_type(pstate, lfirst(fargs), - basetype, type, -1); - basetype = type; + /* + * No exact match yet, so see if there is another entry in the + * aggregate table which is compatible. - thomas 1998-12-05 + */ + ncandidates = agg_get_candidates(funcname, basetype, &candidates); + if (ncandidates > 0) + { + Oid type; - return (Node *) ParseAgg(pstate, funcname, basetype, - fargs, precedence); - } - else - { - elog(ERROR, "Unable to select an aggregate function %s(%s)", - funcname, typeidTypeName(basetype)); - } + type = agg_select_candidate(basetype, candidates); + if (OidIsValid(type)) + { + lfirst(fargs) = coerce_type(pstate, lfirst(fargs), + basetype, type, -1); + basetype = type; + return (Node *) ParseAgg(pstate, funcname, basetype, + fargs, agg_star, agg_distinct, + precedence); + } + else + { + /* Multiple possible matches --- give up */ + elog(ERROR, "Unable to select an aggregate function %s(%s)", + funcname, typeidTypeName(basetype)); } + } + if (must_be_agg) + { /* - * See if this is a single argument function with the function - * name also a type name and the input argument and type name - * binary compatible... This means that you are trying for a - * type conversion which does not need to take place, so we'll - * just pass through the argument itself. (make this clearer - * with some extra brackets - thomas 1998-12-05) + * No matching agg, but we had '*' or DISTINCT, so a plain + * function could not have been meant. */ - if ((HeapTupleIsValid(tp = SearchSysCacheTuple(TYPENAME, - PointerGetDatum(funcname), - 0, 0, 0))) - && IS_BINARY_COMPATIBLE(typeTypeId(tp), basetype)) - return ((Node *) lfirst(fargs)); + elog(ERROR, "There is no aggregate function %s(%s)", + funcname, typeidTypeName(basetype)); } } + /* + * See if this is a single argument function with the function + * name also a type name and the input argument and type name + * binary compatible... This means that you are trying for a + * type conversion which does not need to take place, so we'll + * just pass through the argument itself. (make this clearer + * with some extra brackets - thomas 1998-12-05) + */ + if (nargs == 1) + { + Type tp; + + tp = SearchSysCacheTuple(TYPENAME, + PointerGetDatum(funcname), + 0, 0, 0); + if (HeapTupleIsValid(tp) && + IS_BINARY_COMPATIBLE(typeTypeId(tp), exprType(lfirst(fargs)))) + { + /* XXX FIXME: probably need to change expression's marked type? */ + return (Node *) lfirst(fargs); + } + } /* * If we dropped through to here it's really a function (or a set, @@ -461,14 +483,14 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs, { /* set functions don't have parameters */ /* - * any functiona args which are typed "unknown", but aren't + * any function args which are typed "unknown", but aren't * constants, we don't know what to do with, because we can't * cast them - jolly */ if (exprType(pair) == UNKNOWNOID && !IsA(pair, Const)) elog(ERROR, "There is no function '%s'" " with argument #%d of type UNKNOWN", - funcname, nargs); + funcname, nargs+1); else toid = exprType(pair); } @@ -572,7 +594,7 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs, text *seqname; int32 aclcheck_result = -1; - Assert(length(fargs) == ((funcid == F_SETVAL) ? 2 : 1)); + Assert(nargs == ((funcid == F_SETVAL) ? 2 : 1)); seq = (Const *) lfirst(fargs); if (!IsA((Node *) seq, Const)) elog(ERROR, "Only constant sequence names are acceptable for function '%s'", funcname); diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c index 8cac8b417cdc9b29d4ae1580fbb3243cee8d93fc..a5e130b85431c90be6a4894dcb928a1bf87ff18f 100644 --- a/src/backend/parser/parse_target.c +++ b/src/backend/parser/parse_target.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.49 1999/11/22 17:56:21 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.50 1999/12/10 07:37:35 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -337,16 +337,16 @@ SizeTargetExpr(ParseState *pstate, if (HeapTupleIsValid(ftup)) { - FuncCall *func; - A_Const *cons; + A_Const *cons = makeNode(A_Const); + FuncCall *func = makeNode(FuncCall); - func = makeNode(FuncCall); - func->funcname = funcname; - - cons = makeNode(A_Const); cons->val.type = T_Integer; cons->val.val.ival = attrtypmod; + + func->funcname = funcname; func->args = lappend(lcons(expr, NIL), cons); + func->agg_star = false; + func->agg_distinct = false; expr = transformExpr(pstate, (Node *) func, EXPR_COLUMN_FIRST); } diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index bcff7aa30066fe23b813c8570eb1ee6dcc0d55e8..df0cb5c4e54cacbc597d4530b723e9f6ce0c5b32 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -6,7 +6,7 @@ * * Copyright (c) 1994, Regents of the University of California * - * $Id: parsenodes.h,v 1.89 1999/12/10 03:56:09 momjian Exp $ + * $Id: parsenodes.h,v 1.90 1999/12/10 07:37:32 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -758,6 +758,10 @@ typedef struct SelectStmt /**************************************************************************** * Supporting data structures for Parse Trees + * + * Most of these node types appear in raw parsetrees output by the grammar, + * and get transformed to something else by the analyzer. A few of them + * are used as-is in transformed querytrees. ****************************************************************************/ /* @@ -889,13 +893,20 @@ typedef struct Ident } Ident; /* - * FuncCall - a function/aggregate invocation + * FuncCall - a function or aggregate invocation + * + * agg_star indicates we saw a 'foo(*)' construct, while agg_distinct + * indicates we saw 'foo(DISTINCT ...)'. In either case, the construct + * *must* be an aggregate call. Otherwise, it might be either an + * aggregate or some other kind of function. */ typedef struct FuncCall { NodeTag type; char *funcname; /* name of function */ List *args; /* the arguments (list of exprs) */ + bool agg_star; /* argument was really '*' */ + bool agg_distinct; /* arguments were labeled DISTINCT */ } FuncCall; /* diff --git a/src/include/parser/parse_agg.h b/src/include/parser/parse_agg.h index f1b400e9c9ac5df7590943ab991c60e0edea0c9a..cd149e1517b81898e5a08acc4738a71ec432a593 100644 --- a/src/include/parser/parse_agg.h +++ b/src/include/parser/parse_agg.h @@ -6,7 +6,7 @@ * * Copyright (c) 1994, Regents of the University of California * - * $Id: parse_agg.h,v 1.12 1999/07/15 23:04:01 momjian Exp $ + * $Id: parse_agg.h,v 1.13 1999/12/10 07:37:33 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -18,7 +18,8 @@ extern void AddAggToParseState(ParseState *pstate, Aggref *aggref); extern void parseCheckAggregates(ParseState *pstate, Query *qry); extern Aggref *ParseAgg(ParseState *pstate, char *aggname, Oid basetype, - List *target, int precedence); + List *args, bool agg_star, bool agg_distinct, + int precedence); extern void agg_error(char *caller, char *aggname, Oid basetypeID); #endif /* PARSE_AGG_H */ diff --git a/src/include/parser/parse_func.h b/src/include/parser/parse_func.h index 1fdb8f9890da004a3da3b2283b0f2e4b91bb4715..04b9c44ec0e1890c3043f2b0f2ea928472ce7778 100644 --- a/src/include/parser/parse_func.h +++ b/src/include/parser/parse_func.h @@ -6,7 +6,7 @@ * * Copyright (c) 1994, Regents of the University of California * - * $Id: parse_func.h,v 1.19 1999/08/21 03:49:17 tgl Exp $ + * $Id: parse_func.h,v 1.20 1999/12/10 07:37:33 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -42,8 +42,10 @@ typedef struct _CandidateList extern Node *ParseNestedFuncOrColumn(ParseState *pstate, Attr *attr, int *curr_resno, int precedence); -extern Node *ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs, - int *curr_resno, int precedence); +extern Node *ParseFuncOrColumn(ParseState *pstate, + char *funcname, List *fargs, + bool agg_star, bool agg_distinct, + int *curr_resno, int precedence); extern List *setup_base_tlist(Oid typeid);