diff options
author | Heikki Linnakangas <heikki.linnakangas@iki.fi> | 2015-08-04 17:53:10 +0300 |
---|---|---|
committer | Heikki Linnakangas <heikki.linnakangas@iki.fi> | 2015-08-04 17:53:10 +0300 |
commit | 804163bc25e979fcd91b02e58fa2d1c6b587cc65 (patch) | |
tree | 841c63e6356df2bc42b3729cb05ba2f9834bdd78 /src/backend/parser/parse_agg.c | |
parent | dee0200f0276c0f9da930a2c926f90f5615f2d64 (diff) | |
download | postgresql-804163bc25e979fcd91b02e58fa2d1c6b587cc65.tar.gz postgresql-804163bc25e979fcd91b02e58fa2d1c6b587cc65.zip |
Share transition state between different aggregates when possible.
If there are two different aggregates in the query with same inputs, and
the aggregates have the same initial condition and transition function,
only calculate the state value once, and only call the final functions
separately. For example, AVG(x) and SUM(x) aggregates have the same
transition function, which accumulates the sum and number of input tuples.
For a query like "SELECT AVG(x), SUM(x) FROM x", we can therefore
accumulate the state function only once, which gives a nice speedup.
David Rowley, reviewed and edited by me.
Diffstat (limited to 'src/backend/parser/parse_agg.c')
-rw-r--r-- | src/backend/parser/parse_agg.c | 75 |
1 files changed, 41 insertions, 34 deletions
diff --git a/src/backend/parser/parse_agg.c b/src/backend/parser/parse_agg.c index 3846b569d6f..5b0d568478b 100644 --- a/src/backend/parser/parse_agg.c +++ b/src/backend/parser/parse_agg.c @@ -1829,44 +1829,40 @@ resolve_aggregate_transtype(Oid aggfuncid, } /* - * Create expression trees for the transition and final functions - * of an aggregate. These are needed so that polymorphic functions - * can be used within an aggregate --- without the expression trees, - * such functions would not know the datatypes they are supposed to use. - * (The trees will never actually be executed, however, so we can skimp - * a bit on correctness.) + * Create an expression tree for the transition function of an aggregate. + * This is needed so that polymorphic functions can be used within an + * aggregate --- without the expression tree, such functions would not know + * the datatypes they are supposed to use. (The trees will never actually + * be executed, however, so we can skimp a bit on correctness.) * - * agg_input_types, agg_state_type, agg_result_type identify the input, - * transition, and result types of the aggregate. These should all be - * resolved to actual types (ie, none should ever be ANYELEMENT etc). + * agg_input_types and agg_state_type identifies the input types of the + * aggregate. These should be resolved to actual types (ie, none should + * ever be ANYELEMENT etc). * agg_input_collation is the aggregate function's input collation. * * For an ordered-set aggregate, remember that agg_input_types describes * the direct arguments followed by the aggregated arguments. * - * transfn_oid, invtransfn_oid and finalfn_oid identify the funcs to be - * called; the latter two may be InvalidOid. + * transfn_oid and invtransfn_oid identify the funcs to be called; the + * latter may be InvalidOid, however if invtransfn_oid is set then + * transfn_oid must also be set. * * Pointers to the constructed trees are returned into *transfnexpr, - * *invtransfnexpr and *finalfnexpr. If there is no invtransfn or finalfn, - * the respective pointers are set to NULL. Since use of the invtransfn is - * optional, NULL may be passed for invtransfnexpr. + * *invtransfnexpr. If there is no invtransfn, the respective pointer is set + * to NULL. Since use of the invtransfn is optional, NULL may be passed for + * invtransfnexpr. */ void -build_aggregate_fnexprs(Oid *agg_input_types, - int agg_num_inputs, - int agg_num_direct_inputs, - int num_finalfn_inputs, - bool agg_variadic, - Oid agg_state_type, - Oid agg_result_type, - Oid agg_input_collation, - Oid transfn_oid, - Oid invtransfn_oid, - Oid finalfn_oid, - Expr **transfnexpr, - Expr **invtransfnexpr, - Expr **finalfnexpr) +build_aggregate_transfn_expr(Oid *agg_input_types, + int agg_num_inputs, + int agg_num_direct_inputs, + bool agg_variadic, + Oid agg_state_type, + Oid agg_input_collation, + Oid transfn_oid, + Oid invtransfn_oid, + Expr **transfnexpr, + Expr **invtransfnexpr) { Param *argp; List *args; @@ -1929,13 +1925,24 @@ build_aggregate_fnexprs(Oid *agg_input_types, else *invtransfnexpr = NULL; } +} - /* see if we have a final function */ - if (!OidIsValid(finalfn_oid)) - { - *finalfnexpr = NULL; - return; - } +/* + * Like build_aggregate_transfn_expr, but creates an expression tree for the + * final function of an aggregate, rather than the transition function. + */ +void +build_aggregate_finalfn_expr(Oid *agg_input_types, + int num_finalfn_inputs, + Oid agg_state_type, + Oid agg_result_type, + Oid agg_input_collation, + Oid finalfn_oid, + Expr **finalfnexpr) +{ + Param *argp; + List *args; + int i; /* * Build expr tree for final function |