aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBruce Momjian <bruce@momjian.us>1996-11-30 17:49:02 +0000
committerBruce Momjian <bruce@momjian.us>1996-11-30 17:49:02 +0000
commitf0a9e64afd1d2401abc269274113e4384bf537b9 (patch)
tree3fe0b2867d2cf54d323dbb3b3f9d2aa429e9a068 /src
parent87352726b2f971a7cddfe155a34f6493fbf81084 (diff)
downloadpostgresql-f0a9e64afd1d2401abc269274113e4384bf537b9.tar.gz
postgresql-f0a9e64afd1d2401abc269274113e4384bf537b9.zip
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
Diffstat (limited to 'src')
-rw-r--r--src/backend/executor/nodeAgg.c50
-rw-r--r--src/backend/optimizer/util/clauses.c5
-rw-r--r--src/backend/parser/parser.c11
3 files changed, 52 insertions, 14 deletions
diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c
index 44e051a3038..bcc6bdebaf7 100644
--- a/src/backend/executor/nodeAgg.c
+++ b/src/backend/executor/nodeAgg.c
@@ -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;
diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c
index 563b6130749..b690b0fdb0f 100644
--- a/src/backend/optimizer/util/clauses.c
+++ b/src/backend/optimizer/util/clauses.c
@@ -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);
+ }
}
diff --git a/src/backend/parser/parser.c b/src/backend/parser/parser.c
index 79bac80c115..a77007c6f4c 100644
--- a/src/backend/parser/parser.c
+++ b/src/backend/parser/parser.c
@@ -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();