* (Re)Initialize an individual aggregate. * * This function handles only one grouping set, already set in * aggstate->current_set. * * When called, CurrentMemoryContext should be the per-query context. */
| 612 | * When called, CurrentMemoryContext should be the per-query context. |
| 613 | */ |
| 614 | static void |
| 615 | initialize_aggregate(AggState *aggstate, AggStatePerTrans pertrans, |
| 616 | AggStatePerGroup pergroupstate) |
| 617 | { |
| 618 | /* |
| 619 | * Start a fresh sort operation for each DISTINCT/ORDER BY aggregate. |
| 620 | */ |
| 621 | if (pertrans->numSortCols > 0) |
| 622 | { |
| 623 | /* |
| 624 | * In case of rescan, maybe there could be an uncompleted sort |
| 625 | * operation? Clean it up if so. |
| 626 | */ |
| 627 | if (pertrans->sortstates[aggstate->current_set]) |
| 628 | tuplesort_end(pertrans->sortstates[aggstate->current_set]); |
| 629 | |
| 630 | |
| 631 | /* |
| 632 | * We use a plain Datum sorter when there's a single input column; |
| 633 | * otherwise sort the full tuple. (See comments for |
| 634 | * process_ordered_aggregate_single.) |
| 635 | */ |
| 636 | if (pertrans->numInputs == 1) |
| 637 | { |
| 638 | Form_pg_attribute attr = TupleDescAttr(pertrans->sortdesc, 0); |
| 639 | |
| 640 | pertrans->sortstates[aggstate->current_set] = |
| 641 | tuplesort_begin_datum(attr->atttypid, |
| 642 | pertrans->sortOperators[0], |
| 643 | pertrans->sortCollations[0], |
| 644 | pertrans->sortNullsFirst[0], |
| 645 | PlanStateOperatorMemKB((PlanState *) aggstate), NULL, false); |
| 646 | } |
| 647 | else |
| 648 | pertrans->sortstates[aggstate->current_set] = |
| 649 | tuplesort_begin_heap(pertrans->sortdesc, |
| 650 | pertrans->numSortCols, |
| 651 | pertrans->sortColIdx, |
| 652 | pertrans->sortOperators, |
| 653 | pertrans->sortCollations, |
| 654 | pertrans->sortNullsFirst, |
| 655 | PlanStateOperatorMemKB((PlanState *) aggstate), NULL, false); |
| 656 | } |
| 657 | |
| 658 | /* |
| 659 | * (Re)set transValue to the initial value. |
| 660 | * |
| 661 | * Note that when the initial value is pass-by-ref, we must copy it (into |
| 662 | * the aggcontext) since we will pfree the transValue later. |
| 663 | */ |
| 664 | if (pertrans->initValueIsNull) |
| 665 | pergroupstate->transValue = pertrans->initValue; |
| 666 | else |
| 667 | { |
| 668 | MemoryContext oldContext; |
| 669 | |
| 670 | oldContext = MemoryContextSwitchTo(aggstate->curaggcontext->ecxt_per_tuple_memory); |
| 671 | pergroupstate->transValue = datumCopy(pertrans->initValue, |
no test coverage detected