Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit f0a9e64

Browse files
committed
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
1 parent 8735272 commit f0a9e64

File tree

3 files changed

+52
-14
lines changed

3 files changed

+52
-14
lines changed

src/backend/executor/nodeAgg.c

+41-9
Original file line numberDiff line numberDiff line change
@@ -259,16 +259,33 @@ ExecAgg(Agg *node)
259259
Datum newVal;
260260
AggFuncInfo *aggfns = &aggFuncInfo[i];
261261
Datum args[2];
262-
263-
newVal = aggGetAttr(outerslot,
262+
Node *tagnode;
263+
264+
switch(nodeTag(aggregates[i]->target))
265+
{
266+
case T_Var:
267+
tagnode = NULL;
268+
newVal = aggGetAttr(outerslot,
264269
aggregates[i],
265270
&isNull);
271+
break;
272+
case T_Expr:
273+
tagnode = ((Expr*)aggregates[i]->target)->oper;
274+
econtext->ecxt_scantuple = outerslot;
275+
newVal = ExecEvalExpr (aggregates[i]->target, econtext,
276+
&isNull, NULL);
277+
break;
278+
default:
279+
elog(WARN, "ExecAgg: Bad Agg->Target for Agg %d", i);
280+
}
266281

267282
if (isNull)
268283
continue; /* ignore this tuple for this agg */
269284

270285
if (aggfns->xfn1) {
271286
if (noInitValue[i]) {
287+
int byVal;
288+
272289
/*
273290
* value1 and value2 has not been initialized. This
274291
* is the first non-NULL value. We use it as the
@@ -278,17 +295,32 @@ ExecAgg(Agg *node)
278295
to make a copy of it since the tuple from which
279296
it came will be freed on the next iteration
280297
of the scan */
281-
attnum = ((Var*)aggregates[i]->target)->varattno;
282-
attlen = outerslot->ttc_tupleDescriptor->attrs[attnum-1]->attlen;
298+
if ( tagnode != NULL )
299+
{
300+
FunctionCachePtr fcache_ptr;
301+
302+
if ( nodeTag(tagnode) == T_Func )
303+
fcache_ptr = ((Func*)tagnode)->func_fcache;
304+
else
305+
fcache_ptr = ((Oper*)tagnode)->op_fcache;
306+
attlen = fcache_ptr->typlen;
307+
byVal = fcache_ptr->typbyval;
308+
}
309+
else
310+
{
311+
attnum = ((Var*)aggregates[i]->target)->varattno;
312+
attlen = outerslot->ttc_tupleDescriptor->attrs[attnum-1]->attlen;
313+
byVal = outerslot->ttc_tupleDescriptor->attrs[attnum-1]->attbyval;
314+
}
283315
if (attlen == -1) {
284-
/* variable length */
316+
/* variable length */
285317
attlen = VARSIZE((struct varlena*) newVal);
286318
}
287319
value1[i] = (Datum)palloc(attlen);
288-
if (outerslot->ttc_tupleDescriptor->attrs[attnum-1]->attbyval)
289-
value1[i] = newVal;
290-
else
291-
memmove((char*) (value1[i]), (char*) (newVal), attlen);
320+
if ( byVal )
321+
value1[i] = newVal;
322+
else
323+
memmove((char*)(value1[i]), (char*)newVal, attlen);
292324
/* value1[i] = newVal; */
293325
noInitValue[i] = 0;
294326
nulls[i] = 0;

src/backend/optimizer/util/clauses.c

+4-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.4 1996/11/06 09:29:22 scrappy Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.5 1996/11/30 17:48:52 momjian Exp $
1111
*
1212
* HISTORY
1313
* AUTHOR DATE MAJOR EVENT
@@ -521,6 +521,9 @@ fix_opid(Node *clause)
521521
fix_opid((Node*)get_leftop((Expr*)clause));
522522
fix_opid((Node*)get_rightop((Expr*)clause));
523523
}
524+
else if (agg_clause (clause)) {
525+
fix_opid (((Aggreg*)clause)->target);
526+
}
524527

525528
}
526529

src/backend/parser/parser.c

+7-4
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
*
77
*
88
* IDENTIFICATION
9-
* $Header: /cvsroot/pgsql/src/backend/parser/parser.c,v 1.12 1996/11/25 03:03:48 momjian Exp $
9+
* $Header: /cvsroot/pgsql/src/backend/parser/parser.c,v 1.13 1996/11/30 17:49:02 momjian Exp $
1010
*
1111
*-------------------------------------------------------------------------
1212
*/
@@ -434,13 +434,16 @@ ParseAgg(char *aggname, Oid basetype, Node *target)
434434
fintype = aggform->aggfinaltype;
435435
xfn1 = aggform->aggtransfn1;
436436

437-
if (nodeTag(target) != T_Var)
438-
elog(WARN, "parser: aggregate can only be applied on an attribute");
437+
if (nodeTag(target) != T_Var && nodeTag(target) != T_Expr)
438+
elog(WARN, "parser: aggregate can only be applied on an attribute or expression");
439439

440440
/* only aggregates with transfn1 need a base type */
441441
if (OidIsValid(xfn1)) {
442442
basetype = aggform->aggbasetype;
443-
vartype = ((Var*)target)->vartype;
443+
if (nodeTag(target) == T_Var)
444+
vartype = ((Var*)target)->vartype;
445+
else
446+
vartype = ((Expr*)target)->typeOid;
444447

445448
if (basetype != vartype) {
446449
Type tp1, tp2, get_id_type();

0 commit comments

Comments
 (0)