* Given new input value(s), advance the transition function of one aggregate * state within one grouping set only (already set in aggstate->current_set) * * The new values (and null flags) have been preloaded into argument positions * 1 and up in pertrans->transfn_fcinfo, so that we needn't copy them again to * pass to the transition function. We also expect that the static fields of * the
| 741 | * It doesn't matter which memory context this is called in. |
| 742 | */ |
| 743 | static void |
| 744 | advance_transition_function(AggState *aggstate, |
| 745 | AggStatePerTrans pertrans, |
| 746 | AggStatePerGroup pergroupstate) |
| 747 | { |
| 748 | FunctionCallInfo fcinfo = pertrans->transfn_fcinfo; |
| 749 | MemoryContext oldContext; |
| 750 | Datum newVal; |
| 751 | |
| 752 | if (pertrans->transfn.fn_strict) |
| 753 | { |
| 754 | /* |
| 755 | * For a strict transfn, nothing happens when there's a NULL input; we |
| 756 | * just keep the prior transValue. |
| 757 | */ |
| 758 | int numTransInputs = pertrans->numTransInputs; |
| 759 | int i; |
| 760 | |
| 761 | for (i = 1; i <= numTransInputs; i++) |
| 762 | { |
| 763 | if (fcinfo->args[i].isnull) |
| 764 | return; |
| 765 | } |
| 766 | if (pergroupstate->noTransValue) |
| 767 | { |
| 768 | /* |
| 769 | * transValue has not been initialized. This is the first non-NULL |
| 770 | * input value. We use it as the initial value for transValue. (We |
| 771 | * already checked that the agg's input type is binary-compatible |
| 772 | * with its transtype, so straight copy here is OK.) |
| 773 | * |
| 774 | * We must copy the datum into aggcontext if it is pass-by-ref. We |
| 775 | * do not need to pfree the old transValue, since it's NULL. |
| 776 | */ |
| 777 | oldContext = MemoryContextSwitchTo(aggstate->curaggcontext->ecxt_per_tuple_memory); |
| 778 | pergroupstate->transValue = datumCopy(fcinfo->args[1].value, |
| 779 | pertrans->transtypeByVal, |
| 780 | pertrans->transtypeLen); |
| 781 | pergroupstate->transValueIsNull = false; |
| 782 | pergroupstate->noTransValue = false; |
| 783 | MemoryContextSwitchTo(oldContext); |
| 784 | return; |
| 785 | } |
| 786 | if (pergroupstate->transValueIsNull) |
| 787 | { |
| 788 | /* |
| 789 | * Don't call a strict function with NULL inputs. Note it is |
| 790 | * possible to get here despite the above tests, if the transfn is |
| 791 | * strict *and* returned a NULL on a prior cycle. If that happens |
| 792 | * we will propagate the NULL all the way to the end. |
| 793 | */ |
| 794 | return; |
| 795 | } |
| 796 | } |
| 797 | |
| 798 | /* We run the transition functions in per-input-tuple memory context */ |
| 799 | oldContext = MemoryContextSwitchTo(aggstate->tmpcontext->ecxt_per_tuple_memory); |
| 800 |
no test coverage detected