* Run the transition function for a DISTINCT or ORDER BY aggregate * with more than one input. This is called after we have completed * entering all the input values into the sort object. We complete the * sort, read out the values in sorted order, and run the transition * function on each value (applying DISTINCT if appropriate). * * This function handles only one grouping set (already se
| 977 | * When called, CurrentMemoryContext should be the per-query context. |
| 978 | */ |
| 979 | static void |
| 980 | process_ordered_aggregate_multi(AggState *aggstate, |
| 981 | AggStatePerTrans pertrans, |
| 982 | AggStatePerGroup pergroupstate) |
| 983 | { |
| 984 | ExprContext *tmpcontext = aggstate->tmpcontext; |
| 985 | FunctionCallInfo fcinfo = pertrans->transfn_fcinfo; |
| 986 | TupleTableSlot *slot1 = pertrans->sortslot; |
| 987 | TupleTableSlot *slot2 = pertrans->uniqslot; |
| 988 | int numTransInputs = pertrans->numTransInputs; |
| 989 | int numDistinctCols = pertrans->numDistinctCols; |
| 990 | Datum newAbbrevVal = (Datum) 0; |
| 991 | Datum oldAbbrevVal = (Datum) 0; |
| 992 | bool haveOldValue = false; |
| 993 | TupleTableSlot *save = aggstate->tmpcontext->ecxt_outertuple; |
| 994 | int i; |
| 995 | |
| 996 | tuplesort_performsort(pertrans->sortstates[aggstate->current_set]); |
| 997 | |
| 998 | ExecClearTuple(slot1); |
| 999 | if (slot2) |
| 1000 | ExecClearTuple(slot2); |
| 1001 | |
| 1002 | while (tuplesort_gettupleslot(pertrans->sortstates[aggstate->current_set], |
| 1003 | true, true, slot1, &newAbbrevVal)) |
| 1004 | { |
| 1005 | CHECK_FOR_INTERRUPTS(); |
| 1006 | |
| 1007 | tmpcontext->ecxt_outertuple = slot1; |
| 1008 | tmpcontext->ecxt_innertuple = slot2; |
| 1009 | |
| 1010 | if (numDistinctCols == 0 || |
| 1011 | !haveOldValue || |
| 1012 | newAbbrevVal != oldAbbrevVal || |
| 1013 | !ExecQual(pertrans->equalfnMulti, tmpcontext)) |
| 1014 | { |
| 1015 | /* |
| 1016 | * Extract the first numTransInputs columns as datums to pass to |
| 1017 | * the transfn. |
| 1018 | */ |
| 1019 | slot_getsomeattrs(slot1, numTransInputs); |
| 1020 | |
| 1021 | /* Load values into fcinfo */ |
| 1022 | /* Start from 1, since the 0th arg will be the transition value */ |
| 1023 | for (i = 0; i < numTransInputs; i++) |
| 1024 | { |
| 1025 | fcinfo->args[i + 1].value = slot1->tts_values[i]; |
| 1026 | fcinfo->args[i + 1].isnull = slot1->tts_isnull[i]; |
| 1027 | } |
| 1028 | |
| 1029 | advance_transition_function(aggstate, pertrans, pergroupstate); |
| 1030 | |
| 1031 | if (numDistinctCols > 0) |
| 1032 | { |
| 1033 | /* swap the slot pointers to retain the current tuple */ |
| 1034 | TupleTableSlot *tmpslot = slot2; |
| 1035 | |
| 1036 | slot2 = slot1; |
no test coverage detected