Fix for count(*), aggs with views and multiple tables and sum(3).
authorBruce Momjian
Sun, 4 Jan 1998 04:31:43 +0000 (04:31 +0000)
committerBruce Momjian
Sun, 4 Jan 1998 04:31:43 +0000 (04:31 +0000)
15 files changed:
src/backend/executor/nodeAgg.c
src/backend/nodes/copyfuncs.c
src/backend/parser/gram.y
src/backend/parser/parse_agg.c
src/backend/parser/parse_func.c
src/backend/parser/parse_relation.c
src/backend/parser/parse_target.c
src/backend/rewrite/locks.c
src/backend/rewrite/rewriteHandler.c
src/backend/rewrite/rewriteManip.c
src/include/nodes/primnodes.h
src/include/parser/parse_agg.h
src/include/parser/parse_expr.h
src/include/parser/parse_func.h
src/include/parser/parse_relation.h

index 59c18ab158c2d0490b73a8d36288d0ab3624c063..2037994027a800290e84284df5c65d5afaa39861 100644 (file)
@@ -278,7 +278,7 @@ ExecAgg(Agg *node)
        for (i = 0; i < nagg; i++)
        {
            AttrNumber  attnum;
-           int2        attlen;
+           int2        attlen = 0;
            Datum       newVal = (Datum) NULL;
            AggFuncInfo *aggfns = &aggFuncInfo[i];
            Datum       args[2];
@@ -298,18 +298,24 @@ ExecAgg(Agg *node)
                    newVal = ExecEvalExpr(aggregates[i]->target, econtext,
                                          &isNull, &isDone);
                    break;
+               case T_Const:
+                   tagnode = NULL;
+                   econtext->ecxt_scantuple = outerslot;
+                   newVal = ExecEvalExpr(aggregates[i]->target, econtext,
+                                         &isNull, &isDone);
+                   break;
                default:
                    elog(WARN, "ExecAgg: Bad Agg->Target for Agg %d", i);
            }
 
-           if (isNull)
+           if (isNull && !aggregates[i]->usenulls)
                continue;       /* ignore this tuple for this agg */
 
            if (aggfns->xfn1)
            {
                if (noInitValue[i])
                {
-                   int         byVal;
+                   int         byVal = 0;
 
                    /*
                     * value1 and value2 has not been initialized. This is
@@ -322,22 +328,34 @@ ExecAgg(Agg *node)
                     * a copy of it since the tuple from which it came
                     * will be freed on the next iteration of the scan
                     */
-                   if (tagnode != NULL)
-                   {
-                       FunctionCachePtr fcache_ptr;
-
-                       if (nodeTag(tagnode) == T_Func)
-                           fcache_ptr = ((Func *) tagnode)->func_fcache;
-                       else
-                           fcache_ptr = ((Oper *) tagnode)->op_fcache;
-                       attlen = fcache_ptr->typlen;
-                       byVal = fcache_ptr->typbyval;
-                   }
-                   else
+                   switch (nodeTag(aggregates[i]->target))
                    {
-                       attnum = ((Var *) aggregates[i]->target)->varattno;
-                       attlen = outerslot->ttc_tupleDescriptor->attrs[attnum - 1]->attlen;
-                       byVal = outerslot->ttc_tupleDescriptor->attrs[attnum - 1]->attbyval;
+                       case T_Var:
+                           attnum = ((Var *) aggregates[i]->target)->varattno;
+                           attlen = outerslot->ttc_tupleDescriptor->attrs[attnum - 1]->attlen;
+                           byVal = outerslot->ttc_tupleDescriptor->attrs[attnum - 1]->attbyval;
+
+                           break;
+                       case T_Expr:
+                       {
+                           FunctionCachePtr fcache_ptr;
+       
+                           if (nodeTag(tagnode) == T_Func)
+                               fcache_ptr = ((Func *) tagnode)->func_fcache;
+                           else
+                               fcache_ptr = ((Oper *) tagnode)->op_fcache;
+                           attlen = fcache_ptr->typlen;
+                           byVal = fcache_ptr->typbyval;
+
+                           break;
+                       }
+                       case T_Const:
+                           attlen = ((Const *) aggregates[i]->target)->constlen;
+                           byVal = ((Const *) aggregates[i]->target)->constbyval;
+
+                           break;
+                       default:
+                           elog(WARN, "ExecAgg: Bad Agg->Target for Agg %d", i);
                    }
                    if (attlen == -1)
                    {
@@ -349,7 +367,6 @@ ExecAgg(Agg *node)
                        value1[i] = newVal;
                    else
                        memmove((char *) (value1[i]), (char *) newVal, attlen);
-                   /* value1[i] = newVal; */
                    noInitValue[i] = 0;
                    nulls[i] = 0;
                }
index 96dc5097e1020dda46a6206800f6f3b0c5261ae5..edc055dfdb0d1770656f231458748d51fc447279 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.26 1997/12/24 06:05:52 momjian Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.27 1998/01/04 04:31:02 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -899,6 +899,7 @@ _copyAggreg(Aggreg *from)
    newnode->aggname = pstrdup(from->aggname);
    newnode->basetype = from->basetype;
    newnode->aggtype = from->aggtype;
+   newnode->usenulls = from->usenulls;
 
    Node_Copy(from, newnode, target);
 
index c64c8d41d25dfd2366973210c4fe6fc750ae1e5f..963d5adf0dc569798affb69d8b0fa2386cf45caf 100644 (file)
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 1.82 1998/01/01 05:44:53 thomas Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 1.83 1998/01/04 04:31:08 momjian Exp $
  *
  * HISTORY
  *   AUTHOR            DATE            MAJOR EVENT
@@ -2381,8 +2381,6 @@ OptUseOp:  USING Op                               { $$ = $2; }
  *
  * ...however, recursive addattr and rename supported.  make special
  * cases for these.
- *
- * XXX i believe '*' should be the default behavior, but...
  */
 opt_inh_star:  '*'                             { $$ = TRUE; }
        | /*EMPTY*/                             { $$ = FALSE; }
@@ -2978,11 +2976,12 @@ a_expr:  attr opt_indirection
                }
        | name '(' '*' ')'
                {
+                   /* cheap hack for aggregate (eg. count) */
                    FuncCall *n = makeNode(FuncCall);
-                   Ident *star = makeNode(Ident);
+                   A_Const *star = makeNode(A_Const);
 
-                   /* cheap hack for aggregate (eg. count) */
-                   star->name = "oid";
+                   star->val.type = T_String;
+                   star->val.val.str = "";
                    n->funcname = $1;
                    n->args = lcons(star, NIL);
                    $$ = (Node *)n;
index e776f695000bbd0bb808ef476a44907f6816b509..a244d0398ce54eb80f507b5238b5fd8f5ae90b26 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/parser/parse_agg.c,v 1.4 1997/12/22 05:42:19 momjian Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/parser/parse_agg.c,v 1.5 1998/01/04 04:31:14 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
 #include "postgres.h"
 #include "access/heapam.h"
 #include "catalog/pg_aggregate.h"
+#include "catalog/pg_type.h"
 #include "nodes/nodeFuncs.h"
 #include "nodes/primnodes.h"
 #include "nodes/relation.h"
 #include "optimizer/clauses.h"
 #include "parser/parse_agg.h"
+#include "parser/parse_expr.h"
 #include "parser/parse_node.h"
 #include "parser/parse_target.h"
 #include "utils/syscache.h"
+#include "utils/lsyscache.h"
 
 static bool contain_agg_clause(Node *clause);
 static bool exprIsAggOrGroupCol(Node *expr, List *groupClause);
@@ -276,7 +279,8 @@ parseCheckAggregates(ParseState *pstate, Query *qry)
 
 
 Aggreg    *
-ParseAgg(char *aggname, Oid basetype, Node *target)
+ParseAgg(ParseState *pstate, char *aggname, Oid basetype,
+           List *target, int precedence)
 {
    Oid         fintype;
    Oid         vartype;
@@ -284,7 +288,8 @@ ParseAgg(char *aggname, Oid basetype, Node *target)
    Form_pg_aggregate aggform;
    Aggreg     *aggreg;
    HeapTuple   theAggTuple;
-
+   bool        usenulls = false;
+   
    theAggTuple = SearchSysCacheTuple(AGGNAME, PointerGetDatum(aggname),
                                      ObjectIdGetDatum(basetype),
                                      0, 0);
@@ -293,21 +298,78 @@ ParseAgg(char *aggname, Oid basetype, Node *target)
        elog(WARN, "aggregate %s does not exist", aggname);
    }
 
+   /*
+    *  We do a major hack for count(*) here.
+    *
+    *  Count(*) poses several problems.  First, we need a field that is
+    *  guaranteed to be in the range table, and unique.  Using a constant
+    *  causes the optimizer to properly remove the aggragate from any
+    *  elements of the query.
+    *  Using just 'oid', which can not be null, in the parser fails on:
+    *
+    *      select count(*) from tab1, tab2     -- oid is not unique
+    *      select count(*) from viewtable      -- views don't have real oids
+    *
+    *  So, for an aggregate with parameter '*', we use the first valid
+    *  range table entry, and pick the first column from the table.
+    *  We set a flag to count nulls, because we could have nulls in
+    *  that column.
+   */
+       
+   if (nodeTag(lfirst(target)) == T_Const)
+   {
+       Const *con = (Const *)lfirst(target);
+       
+       if (con->consttype == UNKNOWNOID && VARSIZE(con->constvalue) == VARHDRSZ)
+       {
+           Attr *attr = makeNode(Attr);
+           List       *rtable, *rlist;
+           RangeTblEntry *first_valid_rte;
+
+           Assert(lnext(target) == NULL);
+
+           if (pstate->p_is_rule)
+               rtable = lnext(lnext(pstate->p_rtable));
+           else
+               rtable = pstate->p_rtable;
+       
+           first_valid_rte = NULL;
+           foreach(rlist, rtable)
+           {
+               RangeTblEntry *rte = lfirst(rlist);
+       
+               /* only entries on outer(non-function?) scope */
+               if (!rte->inFromCl && rte != pstate->p_target_rangetblentry)
+                   continue;
+
+               first_valid_rte =rte;
+               break;
+           }
+           if (first_valid_rte == NULL)
+               elog(WARN, "Can't find column to do aggregate(*) on.");
+               
+           attr->relname = first_valid_rte->refname;
+           attr->attrs = lcons(makeString(
+                           get_attname(first_valid_rte->relid,1)),NIL);
+
+           lfirst(target) = transformExpr(pstate, (Node *) attr, precedence);
+           usenulls = true;
+       }
+   }
+   
    aggform = (Form_pg_aggregate) GETSTRUCT(theAggTuple);
    fintype = aggform->aggfinaltype;
    xfn1 = aggform->aggtransfn1;
 
-   if (nodeTag(target) != T_Var && nodeTag(target) != T_Expr)
-       elog(WARN, "parser: aggregate can only be applied on an attribute or expression");
-
+   
    /* only aggregates with transfn1 need a base type */
    if (OidIsValid(xfn1))
    {
        basetype = aggform->aggbasetype;
-       if (nodeTag(target) == T_Var)
-           vartype = ((Var *) target)->vartype;
+       if (nodeTag(lfirst(target)) == T_Var)
+           vartype = ((Var *) lfirst(target))->vartype;
        else
-           vartype = ((Expr *) target)->typeOid;
+           vartype = ((Expr *) lfirst(target))->typeOid;
 
        if (basetype != vartype)
        {
@@ -327,7 +389,9 @@ ParseAgg(char *aggname, Oid basetype, Node *target)
    aggreg->basetype = aggform->aggbasetype;
    aggreg->aggtype = fintype;
 
-   aggreg->target = target;
+   aggreg->target = lfirst(target);
+   if (usenulls)
+       aggreg->usenulls = true;
 
    return aggreg;
 }
index 4d1017b54a0735e22bdbc231f2e84a1b0eff7176..43c78e299de626cd854fb8ccc927c4c7a648de0d 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.3 1997/11/26 03:42:42 momjian Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.4 1998/01/04 04:31:18 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -87,7 +87,8 @@ typedef struct _SuperQE
  */
 
 Node *
-ParseFunc(ParseState *pstate, char *funcname, List *fargs, int *curr_resno)
+ParseFunc(ParseState *pstate, char *funcname, List *fargs,
+       int *curr_resno, int precedence)
 {
    Oid         rettype = (Oid) 0;
    Oid         argrelid = (Oid) 0;
@@ -194,9 +195,7 @@ ParseFunc(ParseState *pstate, char *funcname, List *fargs, int *curr_resno)
                 */
                if ((get_attnum(argrelid, funcname) == InvalidAttrNumber)
                    && strcmp(funcname, "*"))
-               {
                    elog(WARN, "Functions on sets are not yet supported");
-               }
            }
 
            if (retval)
@@ -223,7 +222,8 @@ ParseFunc(ParseState *pstate, char *funcname, List *fargs, int *curr_resno)
                                    ObjectIdGetDatum(basetype),
                                    0, 0))
            {
-               Aggreg     *aggreg = ParseAgg(funcname, basetype, lfirst(fargs));
+               Aggreg     *aggreg = ParseAgg(pstate, funcname, basetype,
+                                       fargs, precedence);
 
                AddAggToParseState(pstate, aggreg);
                return (Node *) aggreg;
@@ -368,7 +368,7 @@ ParseFunc(ParseState *pstate, char *funcname, List *fargs, int *curr_resno)
        else
        {
            funcnode->func_tlist = setup_tlist(funcname, argrelid);
-           rettype = attnameTypeId(argrelid, funcname);
+           rettype = get_atttype(argrelid, get_attnum(argrelid, funcname));
        }
    }
 
@@ -1031,7 +1031,7 @@ setup_tlist(char *attname, Oid relid)
    if (attno < 0)
        elog(WARN, "cannot reference attribute '%s' of tuple params/return values for functions", attname);
 
-   typeid = attnameTypeId(relid, attname);
+   typeid = get_atttype(relid, attno);
    resnode = makeResdom(1,
                         typeid,
                         typeLen(typeidType(typeid)),
index 2b880213d7d4a9f908b93080f9230bc42810a4d4..e2c53ed15230abf98c6187940a54ca3e919d2ee3 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.3 1997/11/26 03:42:48 momjian Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.4 1998/01/04 04:31:19 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -346,34 +346,6 @@ attnumAttNelems(Relation rd, int attid)
    return (rd->rd_att->attrs[attid - 1]->attnelems);
 }
 
-Oid
-attnameTypeId(Oid relid, char *attrname)
-{
-   int         attid;
-   Oid         vartype;
-   Relation    rd;
-
-   rd = heap_open(relid);
-   if (!RelationIsValid(rd))
-   {
-       rd = heap_openr(typeidTypeName(relid));
-       if (!RelationIsValid(rd))
-           elog(WARN, "cannot compute type of att %s for relid %d",
-                attrname, relid);
-   }
-
-   attid = attnameAttNum(rd, attrname); /* could elog(WARN) and never return */
-
-   vartype = attnumTypeId(rd, attid);
-
-   /*
-    * close relation we're done with it now
-    */
-   heap_close(rd);
-
-   return (vartype);
-}
-
 /* given attribute id, return type of that attribute */
 /* XXX Special case for pseudo-attributes is a hack */
 Oid
index 04739fe5503593bf7b5136d8a916713b6569682f..a7049b0b3f73f2a0d1ba8f410e5d42b2239a68f7 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.3 1997/11/26 03:42:49 momjian Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.4 1998/01/04 04:31:22 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -255,7 +255,7 @@ transformTargetList(ParseState *pstate, List *targetlist)
                     * Target item is fully specified: ie.
                     * relation.attribute
                     */
-                   result = handleNestedDots(pstate, att, &pstate->p_last_resno);
+                   result = handleNestedDots(pstate, att, &pstate->p_last_resno,EXPR_COLUMN_FIRST);
                    handleTargetColname(pstate, &res->name, att->relname, attrname);
                    if (att->indirection != NIL)
                    {
@@ -467,7 +467,8 @@ make_targetlist_expr(ParseState *pstate,
            att->relname = pstrdup(RelationGetRelationName(rd)->data);
            att->attrs = lcons(makeString(colname), NIL);
            target_expr = (Expr *) handleNestedDots(pstate, att,
-                                                 &pstate->p_last_resno);
+                                                 &pstate->p_last_resno,
+                                                 EXPR_COLUMN_FIRST);
            while (ar != NIL)
            {
                A_Indices  *ind = lfirst(ar);
index d446da653cc3672075c9d483f76b4bf0d7607c92..70dc37080e2a5d098accbc08d17d3d5d7fdec8c9 100644 (file)
@@ -6,7 +6,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/rewrite/Attic/locks.c,v 1.5 1997/09/08 21:46:33 momjian Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/rewrite/Attic/locks.c,v 1.6 1998/01/04 04:31:27 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -58,6 +58,14 @@ nodeThisLockWasTriggered(Node *node, int varno, AttrNumber attnum)
                    nodeThisLockWasTriggered(tle->expr, varno, attnum);
            }
            break;
+       case T_Aggreg:
+           {
+               Aggreg *agg = (Aggreg *) node;
+
+               return
+                   nodeThisLockWasTriggered(agg->target, varno, attnum);
+           }
+           break;
        case T_List:
            {
                List       *l;
@@ -87,10 +95,20 @@ thisLockWasTriggered(int varno,
                     AttrNumber attnum,
                     Query *parsetree)
 {
-   return
-   (nodeThisLockWasTriggered(parsetree->qual, varno, attnum) ||
-    nodeThisLockWasTriggered((Node *) parsetree->targetList,
-                             varno, attnum));
+   int i;
+   
+   if (nodeThisLockWasTriggered(parsetree->qual, varno, attnum))
+       return true;
+
+   if (nodeThisLockWasTriggered((Node *) parsetree->targetList, varno, attnum))
+       return true;
+
+   for(i=0; i < parsetree->qry_numAgg; i++)
+       if (nodeThisLockWasTriggered(parsetree->qry_aggs[i]->target,
+                   varno, attnum))
+           return true;
+   return false;
+       
 }
 
 /*
index d6dc95e387d7c0f39513065ead9e7599002b35db..1f6bd86343cc9c57835cee1b301c5d912fda15b6 100644 (file)
@@ -6,7 +6,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.6 1997/09/08 21:46:38 momjian Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.7 1998/01/04 04:31:28 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -225,6 +225,7 @@ FireRetrieveRulesAtQuery(Query *parsetree,
            {
                *instead_flag = TRUE;
                FixResdomTypes(parsetree->targetList);
+
                return lcons(parsetree, NIL);
            }
        }
index f7e3896040c2ba9bb04f8efbb15eb662bb6c5888..122067a2424feb91ef9ca3a877656131b869cfce 100644 (file)
@@ -6,7 +6,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteManip.c,v 1.8 1997/09/18 20:21:11 momjian Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteManip.c,v 1.9 1998/01/04 04:31:29 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -46,6 +46,13 @@ OffsetVarNodes(Node *node, int offset)
                OffsetVarNodes(tle->expr, offset);
            }
            break;
+       case T_Aggreg:
+           {
+               Aggreg *agg = (Aggreg *) node;
+
+               OffsetVarNodes(agg->target, offset);
+           }
+           break;
        case T_Expr:
            {
                Expr       *expr = (Expr *) node;
@@ -91,6 +98,13 @@ ChangeVarNodes(Node *node, int old_varno, int new_varno)
                ChangeVarNodes(tle->expr, old_varno, new_varno);
            }
            break;
+       case T_Aggreg:
+           {
+               Aggreg *agg = (Aggreg *) node;
+
+               ChangeVarNodes(agg->target, old_varno, new_varno);
+           }
+           break;
        case T_Expr:
            {
                Expr       *expr = (Expr *) node;
@@ -235,6 +249,9 @@ ResolveNew(RewriteInfo *info, List *targetlist, Node **nodePtr)
        case T_TargetEntry:
            ResolveNew(info, targetlist, &((TargetEntry *) node)->expr);
            break;
+       case T_Aggreg:
+           ResolveNew(info, targetlist, &((Aggreg *) node)->target);
+           break;
        case T_Expr:
            ResolveNew(info, targetlist, (Node **) (&(((Expr *) node)->args)));
            break;
@@ -325,6 +342,14 @@ nodeHandleRIRAttributeRule(Node **nodePtr,
                                   rt_index, attr_num, modified, badsql);
            }
            break;
+       case T_Aggreg:
+           {
+               Aggreg *agg = (Aggreg *) node;
+
+               nodeHandleRIRAttributeRule(&agg->target, rtable, targetlist,
+                                  rt_index, attr_num, modified, badsql);
+           }
+           break;
        case T_Expr:
            {
                Expr       *expr = (Expr *) node;
@@ -395,11 +420,16 @@ HandleRIRAttributeRule(Query *parsetree,
                       int *modified,
                       int *badsql)
 {
+   int i;
+   
    nodeHandleRIRAttributeRule((Node **) (&(parsetree->targetList)), rtable,
                               targetlist, rt_index, attr_num,
                               modified, badsql);
    nodeHandleRIRAttributeRule(&parsetree->qual, rtable, targetlist,
                               rt_index, attr_num, modified, badsql);
+   for(i=0; i < parsetree->qry_numAgg; i++)
+       nodeHandleRIRAttributeRule(&parsetree->qry_aggs[i]->target, rtable,
+                   targetlist, rt_index, attr_num, modified, badsql);
 }
 
 
@@ -437,6 +467,14 @@ nodeHandleViewRule(Node **nodePtr,
                                   rt_index, modified);
            }
            break;
+       case T_Aggreg:
+           {
+               Aggreg *agg = (Aggreg *) node;
+
+               nodeHandleViewRule(&(agg->target), rtable, targetlist,
+                                  rt_index, modified);
+           }
+           break;
        case T_Expr:
            {
                Expr       *expr = (Expr *) node;
@@ -483,8 +521,13 @@ HandleViewRule(Query *parsetree,
               int rt_index,
               int *modified)
 {
+   int i;
+   
    nodeHandleViewRule(&parsetree->qual, rtable, targetlist, rt_index,
                       modified);
    nodeHandleViewRule((Node **) (&(parsetree->targetList)), rtable, targetlist,
                       rt_index, modified);
+   for(i=0; i < parsetree->qry_numAgg; i++)
+       nodeHandleViewRule(&parsetree->qry_aggs[i]->target, rtable, targetlist, rt_index,
+                      modified);
 }
index f0706d1392e04c6699d48985d91c1172cb8efed5..1e896e5e1365fe7b3dc06d49225b97c18dbce922 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: primnodes.h,v 1.11 1997/09/08 21:52:58 momjian Exp $
+ * $Id: primnodes.h,v 1.12 1998/01/04 04:31:37 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -255,18 +255,19 @@ typedef struct Func
  *     aggname         - name of the aggregate
  *     basetype        - base type Oid of the aggregate
  *     aggtype         - type Oid of final result of the aggregate
- *     query           - XXX comment me
- *     target          - XXX comment me
+ *     target          - attribute or expression we are aggregating on
+ *     aggno           - index to ecxt_values
  * ----------------
  */
 typedef struct Aggreg
 {
    NodeTag     type;
    char       *aggname;
-   Oid         basetype;       /* base type of the aggregate */
-   Oid         aggtype;        /* type of final result */
-   Node       *target;         /* attribute to aggreg on */
-   int         aggno;          /* index to ecxt_values */
+   Oid         basetype;
+   Oid         aggtype;
+   Node       *target; 
+   int         aggno;
+   bool        usenulls;
 } Aggreg;
 
 /* ----------------
index 9761aa94e17ed46485540c53161cb036a03f856d..8d1e0fb31fd426731430b8b6765a3df5f93c38f8 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: parse_agg.h,v 1.3 1997/11/26 03:43:08 momjian Exp $
+ * $Id: parse_agg.h,v 1.4 1998/01/04 04:31:39 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -21,7 +21,8 @@
 extern void AddAggToParseState(ParseState *pstate, Aggreg *aggreg);
 extern void finalizeAggregates(ParseState *pstate, Query *qry);
 extern void parseCheckAggregates(ParseState *pstate, Query *qry);
-extern Aggreg *ParseAgg(char *aggname, Oid basetype, Node *target);
+extern Aggreg *ParseAgg(ParseState *pstate, char *aggname, Oid basetype,
+           List *target, int precedence);
 extern void agg_error(char *caller, char *aggname, Oid basetypeID);
 
 #endif                         /* PARSE_AGG_H */
index f26bf34acb994bbd85c756ffe519ed0d53ade68f..ba8eed9c814b7d33ec4106e184f5349c52d92106 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: parse_expr.h,v 1.3 1997/11/26 03:43:11 momjian Exp $
+ * $Id: parse_expr.h,v 1.4 1998/01/04 04:31:41 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -21,7 +21,8 @@
 extern Node *transformExpr(ParseState *pstate, Node *expr, int precedence);
 extern Node *transformIdent(ParseState *pstate, Node *expr, int precedence);
 extern Oid exprType(Node *expr);
-extern Node *handleNestedDots(ParseState *pstate, Attr *attr, int *curr_resno);
+extern Node *handleNestedDots(ParseState *pstate, Attr *attr,
+       int *curr_resno, int precedence);
 extern Node *parser_typecast2(Node *expr, Oid exprType, Type tp, int typlen);
 
 #endif                         /* PARSE_EXPR_H */
index 9ff6ee91b80579bca8b52037bc11c634400111ad..12d6ba16b88c097c02d0434d64a6279822a3592b 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: parse_func.h,v 1.3 1997/11/26 03:43:12 momjian Exp $
+ * $Id: parse_func.h,v 1.4 1998/01/04 04:31:42 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -43,7 +43,7 @@ typedef struct _CandidateList
 }         *CandidateList;
 
 extern Node *ParseFunc(ParseState *pstate, char *funcname, List *fargs,
-   int *curr_resno);
+   int *curr_resno, int precedence);
 
 extern void func_error(char *caller, char *funcname, int nargs, Oid *argtypes);
 
index 7c78757ac32e55003edcef50f40c7d98fea6509a..e379b92932f5fd9e6f746ba0585a285140b5656e 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: parse_relation.h,v 1.3 1997/11/26 03:43:16 momjian Exp $
+ * $Id: parse_relation.h,v 1.4 1998/01/04 04:31:43 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -34,7 +34,6 @@ extern int attnameAttNum(Relation rd, char *a);
 extern bool attnameIsSet(Relation rd, char *name);
 extern char *attnumAttName(Relation rd, int attrno);
 extern int attnumAttNelems(Relation rd, int attid);
-extern Oid attnameTypeId(Oid relid, char *attrname);
 extern Oid attnumTypeId(Relation rd, int attid);
 extern void handleTargetColname(ParseState *pstate, char **resname,
                    char *refname, char *colname);