Commit f0a9e64a authored by Bruce Momjian's avatar Bruce Momjian

As someone asked for this feature - patch for 1.09 follows.

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
parent 87352726
...@@ -259,16 +259,33 @@ ExecAgg(Agg *node) ...@@ -259,16 +259,33 @@ ExecAgg(Agg *node)
Datum newVal; Datum newVal;
AggFuncInfo *aggfns = &aggFuncInfo[i]; AggFuncInfo *aggfns = &aggFuncInfo[i];
Datum args[2]; Datum args[2];
Node *tagnode;
switch(nodeTag(aggregates[i]->target))
{
case T_Var:
tagnode = NULL;
newVal = aggGetAttr(outerslot, newVal = aggGetAttr(outerslot,
aggregates[i], aggregates[i],
&isNull); &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) if (isNull)
continue; /* ignore this tuple for this agg */ continue; /* ignore this tuple for this agg */
if (aggfns->xfn1) { if (aggfns->xfn1) {
if (noInitValue[i]) { if (noInitValue[i]) {
int byVal;
/* /*
* value1 and value2 has not been initialized. This * value1 and value2 has not been initialized. This
* is the first non-NULL value. We use it as the * is the first non-NULL value. We use it as the
...@@ -278,17 +295,32 @@ ExecAgg(Agg *node) ...@@ -278,17 +295,32 @@ ExecAgg(Agg *node)
to make a copy of it since the tuple from which to make a copy of it since the tuple from which
it came will be freed on the next iteration it came will be freed on the next iteration
of the scan */ 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
{
attnum = ((Var*)aggregates[i]->target)->varattno; attnum = ((Var*)aggregates[i]->target)->varattno;
attlen = outerslot->ttc_tupleDescriptor->attrs[attnum-1]->attlen; attlen = outerslot->ttc_tupleDescriptor->attrs[attnum-1]->attlen;
byVal = outerslot->ttc_tupleDescriptor->attrs[attnum-1]->attbyval;
}
if (attlen == -1) { if (attlen == -1) {
/* variable length */ /* variable length */
attlen = VARSIZE((struct varlena*) newVal); attlen = VARSIZE((struct varlena*) newVal);
} }
value1[i] = (Datum)palloc(attlen); value1[i] = (Datum)palloc(attlen);
if (outerslot->ttc_tupleDescriptor->attrs[attnum-1]->attbyval) if ( byVal )
value1[i] = newVal; value1[i] = newVal;
else else
memmove((char*) (value1[i]), (char*) (newVal), attlen); memmove((char*)(value1[i]), (char*)newVal, attlen);
/* value1[i] = newVal; */ /* value1[i] = newVal; */
noInitValue[i] = 0; noInitValue[i] = 0;
nulls[i] = 0; nulls[i] = 0;
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * 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 * HISTORY
* AUTHOR DATE MAJOR EVENT * AUTHOR DATE MAJOR EVENT
...@@ -521,6 +521,9 @@ fix_opid(Node *clause) ...@@ -521,6 +521,9 @@ fix_opid(Node *clause)
fix_opid((Node*)get_leftop((Expr*)clause)); fix_opid((Node*)get_leftop((Expr*)clause));
fix_opid((Node*)get_rightop((Expr*)clause)); fix_opid((Node*)get_rightop((Expr*)clause));
} }
else if (agg_clause (clause)) {
fix_opid (((Aggreg*)clause)->target);
}
} }
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* *
* *
* IDENTIFICATION * 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) ...@@ -434,13 +434,16 @@ ParseAgg(char *aggname, Oid basetype, Node *target)
fintype = aggform->aggfinaltype; fintype = aggform->aggfinaltype;
xfn1 = aggform->aggtransfn1; xfn1 = aggform->aggtransfn1;
if (nodeTag(target) != T_Var) if (nodeTag(target) != T_Var && nodeTag(target) != T_Expr)
elog(WARN, "parser: aggregate can only be applied on an attribute"); elog(WARN, "parser: aggregate can only be applied on an attribute or expression");
/* only aggregates with transfn1 need a base type */ /* only aggregates with transfn1 need a base type */
if (OidIsValid(xfn1)) { if (OidIsValid(xfn1)) {
basetype = aggform->aggbasetype; basetype = aggform->aggbasetype;
if (nodeTag(target) == T_Var)
vartype = ((Var*)target)->vartype; vartype = ((Var*)target)->vartype;
else
vartype = ((Expr*)target)->typeOid;
if (basetype != vartype) { if (basetype != vartype) {
Type tp1, tp2, get_id_type(); Type tp1, tp2, get_id_type();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment