As someone asked for this feature - patch for 1.09 follows.
authorBruce Momjian
Sat, 30 Nov 1996 17:49:02 +0000 (17:49 +0000)
committerBruce Momjian
Sat, 30 Nov 1996 17:49:02 +0000 (17:49 +0000)
Now You can do queries like

select sum(some_func(x)) from ...
select min(table1.x + table2.y) from table1, table2 where ...

and so on.

Vadim

src/backend/executor/nodeAgg.c
src/backend/optimizer/util/clauses.c
src/backend/parser/parser.c

index 44e051a3038db9ac1569600df43efd568b7a2763..bcc6bdebaf779cbf8b6316ad211da710f0aaa641 100644 (file)
@@ -259,16 +259,33 @@ ExecAgg(Agg *node)
        Datum newVal;
        AggFuncInfo *aggfns = &aggFuncInfo[i];
        Datum args[2];
-
-       newVal = aggGetAttr(outerslot,
+       Node *tagnode;
+       
+       switch(nodeTag(aggregates[i]->target))
+       {
+           case T_Var:
+               tagnode = NULL;
+           newVal = aggGetAttr(outerslot,
                aggregates[i],
                &isNull);
+           break;
+       case T_Expr:
+           tagnode = ((Expr*)aggregates[i]->target)->oper;
+           econtext->ecxt_scantuple = outerslot;
+           newVal = ExecEvalExpr (aggregates[i]->target, econtext,
+                   &isNull, NULL);
+           break;
+       default:
+           elog(WARN, "ExecAgg: Bad Agg->Target for Agg %d", i);
+       }
 
        if (isNull)
        continue;   /* ignore this tuple for this agg */
 
        if (aggfns->xfn1) {
        if (noInitValue[i]) {
+           int byVal;
+           
            /*
             * value1 and value2 has not been initialized. This
             * is the first non-NULL value. We use it as the
@@ -278,17 +295,32 @@ ExecAgg(Agg *node)
            to make a copy of it since the tuple from which
            it came will be freed on the next iteration 
            of the scan */
-           attnum = ((Var*)aggregates[i]->target)->varattno;
-           attlen = outerslot->ttc_tupleDescriptor->attrs[attnum-1]->attlen;
+           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
+           {
+               attnum = ((Var*)aggregates[i]->target)->varattno;
+               attlen = outerslot->ttc_tupleDescriptor->attrs[attnum-1]->attlen;
+               byVal = outerslot->ttc_tupleDescriptor->attrs[attnum-1]->attbyval;
+           }
            if (attlen == -1)  {
-           /* variable length */
+           /* variable length */
            attlen = VARSIZE((struct varlena*) newVal);
            }
            value1[i] = (Datum)palloc(attlen);
-                 if (outerslot->ttc_tupleDescriptor->attrs[attnum-1]->attbyval)
-                        value1[i] = newVal;
-                    else
-                        memmove((char*) (value1[i]), (char*) (newVal), attlen);
+           if ( byVal )
+               value1[i] = newVal;
+           else
+               memmove((char*)(value1[i]), (char*)newVal, attlen);
            /* value1[i] = newVal; */
            noInitValue[i] = 0;
            nulls[i] = 0;
index 563b6130749feae4bfd38f77fca30adcfaeff389..b690b0fdb0f4ab9e6a3928bf1dd6f692e5d4cb4f 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *    $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.4 1996/11/06 09:29:22 scrappy Exp $
+ *    $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.5 1996/11/30 17:48:52 momjian Exp $
  *
  * HISTORY
  *    AUTHOR       DATE        MAJOR EVENT
@@ -521,6 +521,9 @@ fix_opid(Node *clause)
    fix_opid((Node*)get_leftop((Expr*)clause));
    fix_opid((Node*)get_rightop((Expr*)clause));
     }
+    else if (agg_clause (clause)) {
+       fix_opid (((Aggreg*)clause)->target);
+    }
 
 }
 
index 79bac80c11532d0562d648c4d0d13058d8aaa0bb..a77007c6f4c53fe98353098f5cc6a19d7a56328e 100644 (file)
@@ -6,7 +6,7 @@
  *
  *
  * IDENTIFICATION
- *    $Header: /cvsroot/pgsql/src/backend/parser/parser.c,v 1.12 1996/11/25 03:03:48 momjian Exp $
+ *    $Header: /cvsroot/pgsql/src/backend/parser/parser.c,v 1.13 1996/11/30 17:49:02 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -434,13 +434,16 @@ ParseAgg(char *aggname, Oid basetype, Node *target)
     fintype = aggform->aggfinaltype;
     xfn1 = aggform->aggtransfn1;
     
-    if (nodeTag(target) != T_Var)
-   elog(WARN, "parser: aggregate can only be applied on an attribute");
+    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;
-   vartype = ((Var*)target)->vartype;
+   if (nodeTag(target) == T_Var)
+       vartype = ((Var*)target)->vartype;
+   else
+       vartype = ((Expr*)target)->typeOid;
 
    if (basetype != vartype) {
        Type tp1, tp2, get_id_type();