@@ -61,6 +61,9 @@ typedef struct
61
61
{
62
62
PlannerInfo * root ;
63
63
AggClauseCosts * costs ;
64
+ bool finalizeAggs ;
65
+ bool combineStates ;
66
+ bool serialStates ;
64
67
} count_agg_clauses_context ;
65
68
66
69
typedef struct
@@ -540,12 +543,16 @@ contain_agg_clause_walker(Node *node, void *context)
540
543
* are no subqueries. There mustn't be outer-aggregate references either.
541
544
*/
542
545
void
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 )
544
548
{
545
549
count_agg_clauses_context context ;
546
550
547
551
context .root = root ;
548
552
context .costs = costs ;
553
+ context .finalizeAggs = finalizeAggs ;
554
+ context .combineStates = combineStates ;
555
+ context .serialStates = serialStates ;
549
556
(void ) count_agg_clauses_walker (clause , & context );
550
557
}
551
558
@@ -562,6 +569,9 @@ count_agg_clauses_walker(Node *node, count_agg_clauses_context *context)
562
569
Form_pg_aggregate aggform ;
563
570
Oid aggtransfn ;
564
571
Oid aggfinalfn ;
572
+ Oid aggcombinefn ;
573
+ Oid aggserialfn ;
574
+ Oid aggdeserialfn ;
565
575
Oid aggtranstype ;
566
576
int32 aggtransspace ;
567
577
QualCost argcosts ;
@@ -583,6 +593,9 @@ count_agg_clauses_walker(Node *node, count_agg_clauses_context *context)
583
593
aggform = (Form_pg_aggregate ) GETSTRUCT (aggTuple );
584
594
aggtransfn = aggform -> aggtransfn ;
585
595
aggfinalfn = aggform -> aggfinalfn ;
596
+ aggcombinefn = aggform -> aggcombinefn ;
597
+ aggserialfn = aggform -> aggserialfn ;
598
+ aggdeserialfn = aggform -> aggdeserialfn ;
586
599
aggtranstype = aggform -> aggtranstype ;
587
600
aggtransspace = aggform -> aggtransspace ;
588
601
ReleaseSysCache (aggTuple );
@@ -592,28 +605,58 @@ count_agg_clauses_walker(Node *node, count_agg_clauses_context *context)
592
605
if (aggref -> aggorder != NIL || aggref -> aggdistinct != NIL )
593
606
costs -> numOrderedAggs ++ ;
594
607
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 ;
599
616
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
+ }
604
634
605
635
/*
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.
610
638
*/
611
- if (aggref -> aggfilter )
639
+ if (! context -> combineStates )
612
640
{
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 );
615
643
costs -> transCost .startup += argcosts .startup ;
616
644
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
+ }
617
660
}
618
661
619
662
/*
0 commit comments