@@ -61,6 +61,9 @@ typedef struct
6161{
6262 PlannerInfo * root ;
6363 AggClauseCosts * costs ;
64+ bool finalizeAggs ;
65+ bool combineStates ;
66+ bool serialStates ;
6467} count_agg_clauses_context ;
6568
6669typedef struct
@@ -540,12 +543,16 @@ contain_agg_clause_walker(Node *node, void *context)
540543 * are no subqueries. There mustn't be outer-aggregate references either.
541544 */
542545void
543- count_agg_clauses (PlannerInfo * root , Node * clause , AggClauseCosts * costs )
546+ count_agg_clauses (PlannerInfo * root , Node * clause , AggClauseCosts * costs ,
547+ bool finalizeAggs , bool combineStates , bool serialStates )
544548{
545549 count_agg_clauses_context context ;
546550
547551 context .root = root ;
548552 context .costs = costs ;
553+ context .finalizeAggs = finalizeAggs ;
554+ context .combineStates = combineStates ;
555+ context .serialStates = serialStates ;
549556 (void ) count_agg_clauses_walker (clause , & context );
550557}
551558
@@ -562,6 +569,9 @@ count_agg_clauses_walker(Node *node, count_agg_clauses_context *context)
562569 Form_pg_aggregate aggform ;
563570 Oid aggtransfn ;
564571 Oid aggfinalfn ;
572+ Oid aggcombinefn ;
573+ Oid aggserialfn ;
574+ Oid aggdeserialfn ;
565575 Oid aggtranstype ;
566576 int32 aggtransspace ;
567577 QualCost argcosts ;
@@ -583,6 +593,9 @@ count_agg_clauses_walker(Node *node, count_agg_clauses_context *context)
583593 aggform = (Form_pg_aggregate ) GETSTRUCT (aggTuple );
584594 aggtransfn = aggform -> aggtransfn ;
585595 aggfinalfn = aggform -> aggfinalfn ;
596+ aggcombinefn = aggform -> aggcombinefn ;
597+ aggserialfn = aggform -> aggserialfn ;
598+ aggdeserialfn = aggform -> aggdeserialfn ;
586599 aggtranstype = aggform -> aggtranstype ;
587600 aggtransspace = aggform -> aggtransspace ;
588601 ReleaseSysCache (aggTuple );
@@ -592,28 +605,58 @@ count_agg_clauses_walker(Node *node, count_agg_clauses_context *context)
592605 if (aggref -> aggorder != NIL || aggref -> aggdistinct != NIL )
593606 costs -> numOrderedAggs ++ ;
594607
595- /* add component function execution costs to appropriate totals */
596- costs -> transCost .per_tuple += get_func_cost (aggtransfn ) * cpu_operator_cost ;
597- if (OidIsValid (aggfinalfn ))
598- costs -> finalCost += get_func_cost (aggfinalfn ) * cpu_operator_cost ;
608+ /*
609+ * Add the appropriate component function execution costs to
610+ * appropriate totals.
611+ */
612+ if (context -> combineStates )
613+ {
614+ /* charge for combining previously aggregated states */
615+ costs -> transCost .per_tuple += get_func_cost (aggcombinefn ) * cpu_operator_cost ;
599616
600- /* also add the input expressions' cost to per-input-row costs */
601- cost_qual_eval_node (& argcosts , (Node * ) aggref -> args , context -> root );
602- costs -> transCost .startup += argcosts .startup ;
603- costs -> transCost .per_tuple += argcosts .per_tuple ;
617+ /* charge for deserialization, when appropriate */
618+ if (context -> serialStates && OidIsValid (aggdeserialfn ))
619+ costs -> transCost .per_tuple += get_func_cost (aggdeserialfn ) * cpu_operator_cost ;
620+ }
621+ else
622+ costs -> transCost .per_tuple += get_func_cost (aggtransfn ) * cpu_operator_cost ;
623+
624+ if (context -> finalizeAggs )
625+ {
626+ if (OidIsValid (aggfinalfn ))
627+ costs -> finalCost += get_func_cost (aggfinalfn ) * cpu_operator_cost ;
628+ }
629+ else if (context -> serialStates )
630+ {
631+ if (OidIsValid (aggserialfn ))
632+ costs -> finalCost += get_func_cost (aggserialfn ) * cpu_operator_cost ;
633+ }
604634
605635 /*
606- * Add any filter's cost to per-input-row costs.
607- *
608- * XXX Ideally we should reduce input expression costs according to
609- * filter selectivity, but it's not clear it's worth the trouble.
636+ * Some costs will already have been incurred by the initial aggregate
637+ * node, so we mustn't include these again.
610638 */
611- if (aggref -> aggfilter )
639+ if (! context -> combineStates )
612640 {
613- cost_qual_eval_node ( & argcosts , ( Node * ) aggref -> aggfilter ,
614- context -> root );
641+ /* add the input expressions' cost to per-input-row costs */
642+ cost_qual_eval_node ( & argcosts , ( Node * ) aggref -> args , context -> root );
615643 costs -> transCost .startup += argcosts .startup ;
616644 costs -> transCost .per_tuple += argcosts .per_tuple ;
645+
646+ /*
647+ * Add any filter's cost to per-input-row costs.
648+ *
649+ * XXX Ideally we should reduce input expression costs according
650+ * to filter selectivity, but it's not clear it's worth the
651+ * trouble.
652+ */
653+ if (aggref -> aggfilter )
654+ {
655+ cost_qual_eval_node (& argcosts , (Node * ) aggref -> aggfilter ,
656+ context -> root );
657+ costs -> transCost .startup += argcosts .startup ;
658+ costs -> transCost .per_tuple += argcosts .per_tuple ;
659+ }
617660 }
618661
619662 /*
0 commit comments