* Helper function to call the transition function. * * The caller must load the arguments into fcinfo->args/argnulls already, * and switch to tmpcontext->ecxt_per_tuple_context. */
| 357 | * and switch to tmpcontext->ecxt_per_tuple_context. |
| 358 | */ |
| 359 | static void |
| 360 | call_transfunc(WindowAggState *winstate, |
| 361 | WindowStatePerFunc perfuncstate, |
| 362 | WindowStatePerAgg peraggstate, |
| 363 | FunctionCallInfo fcinfo) |
| 364 | { |
| 365 | int numArguments = perfuncstate->numArguments; |
| 366 | Datum newVal; |
| 367 | int i; |
| 368 | MemoryContext oldContext; |
| 369 | ExprContext *econtext = winstate->tmpcontext; |
| 370 | |
| 371 | /* |
| 372 | * This may seem weird, but it allows us to keep the code that follows unchanged |
| 373 | * from upstream. In the upstream, this is part of advance_windowaggregate(). |
| 374 | */ |
| 375 | Assert(CurrentMemoryContext == econtext->ecxt_per_tuple_memory); |
| 376 | oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory); |
| 377 | |
| 378 | if (peraggstate->transfn.fn_strict) |
| 379 | { |
| 380 | /* |
| 381 | * For a strict transfn, nothing happens when there's a NULL input; we |
| 382 | * just keep the prior transValue. Note transValueCount doesn't |
| 383 | * change either. |
| 384 | */ |
| 385 | for (i = 1; i <= numArguments; i++) |
| 386 | { |
| 387 | if (fcinfo->args[i].isnull) |
| 388 | { |
| 389 | MemoryContextSwitchTo(oldContext); |
| 390 | return; |
| 391 | } |
| 392 | } |
| 393 | |
| 394 | /* |
| 395 | * For strict transition functions with initial value NULL we use the |
| 396 | * first non-NULL input as the initial state. (We already checked |
| 397 | * that the agg's input type is binary-compatible with its transtype, |
| 398 | * so straight copy here is OK.) |
| 399 | * |
| 400 | * We must copy the datum into aggcontext if it is pass-by-ref. We do |
| 401 | * not need to pfree the old transValue, since it's NULL. |
| 402 | */ |
| 403 | if (peraggstate->transValueCount == 0 && peraggstate->transValueIsNull) |
| 404 | { |
| 405 | MemoryContextSwitchTo(peraggstate->aggcontext); |
| 406 | peraggstate->transValue = datumCopy(fcinfo->args[1].value, |
| 407 | peraggstate->transtypeByVal, |
| 408 | peraggstate->transtypeLen); |
| 409 | peraggstate->transValueIsNull = false; |
| 410 | peraggstate->transValueCount = 1; |
| 411 | MemoryContextSwitchTo(oldContext); |
| 412 | return; |
| 413 | } |
| 414 | |
| 415 | if (peraggstate->transValueIsNull) |
| 416 | { |
no test coverage detected