implementation of transition function invocation for byref types */
| 4551 | |
| 4552 | /* implementation of transition function invocation for byref types */ |
| 4553 | static pg_attribute_always_inline void |
| 4554 | ExecAggPlainTransByRef(AggState *aggstate, AggStatePerTrans pertrans, |
| 4555 | AggStatePerGroup pergroup, |
| 4556 | ExprContext *aggcontext, int setno) |
| 4557 | { |
| 4558 | FunctionCallInfo fcinfo = pertrans->transfn_fcinfo; |
| 4559 | MemoryContext oldContext; |
| 4560 | Datum newVal; |
| 4561 | |
| 4562 | /* cf. select_current_set() */ |
| 4563 | aggstate->curaggcontext = aggcontext; |
| 4564 | aggstate->current_set = setno; |
| 4565 | |
| 4566 | /* set up aggstate->curpertrans for AggGetAggref() */ |
| 4567 | aggstate->curpertrans = pertrans; |
| 4568 | |
| 4569 | /* invoke transition function in per-tuple context */ |
| 4570 | oldContext = MemoryContextSwitchTo(aggstate->tmpcontext->ecxt_per_tuple_memory); |
| 4571 | |
| 4572 | fcinfo->args[0].value = pergroup->transValue; |
| 4573 | fcinfo->args[0].isnull = pergroup->transValueIsNull; |
| 4574 | fcinfo->isnull = false; /* just in case transfn doesn't set it */ |
| 4575 | |
| 4576 | newVal = FunctionCallInvoke(fcinfo); |
| 4577 | |
| 4578 | /* |
| 4579 | * For pass-by-ref datatype, must copy the new value into aggcontext and |
| 4580 | * free the prior transValue. But if transfn returned a pointer to its |
| 4581 | * first input, we don't need to do anything. Also, if transfn returned a |
| 4582 | * pointer to a R/W expanded object that is already a child of the |
| 4583 | * aggcontext, assume we can adopt that value without copying it. |
| 4584 | * |
| 4585 | * It's safe to compare newVal with pergroup->transValue without regard |
| 4586 | * for either being NULL, because ExecAggTransReparent() takes care to set |
| 4587 | * transValue to 0 when NULL. Otherwise we could end up accidentally not |
| 4588 | * reparenting, when the transValue has the same numerical value as |
| 4589 | * newValue, despite being NULL. This is a somewhat hot path, making it |
| 4590 | * undesirable to instead solve this with another branch for the common |
| 4591 | * case of the transition function returning its (modified) input |
| 4592 | * argument. |
| 4593 | */ |
| 4594 | if (DatumGetPointer(newVal) != DatumGetPointer(pergroup->transValue)) |
| 4595 | newVal = ExecAggTransReparent(aggstate, pertrans, |
| 4596 | newVal, fcinfo->isnull, |
| 4597 | pergroup->transValue, |
| 4598 | pergroup->transValueIsNull); |
| 4599 | |
| 4600 | pergroup->transValue = newVal; |
| 4601 | pergroup->transValueIsNull = fcinfo->isnull; |
| 4602 | |
| 4603 | MemoryContextSwitchTo(oldContext); |
| 4604 | } |
no test coverage detected