* ExecMakeFunctionResultSet * * Evaluate the arguments to a set-returning function and then call the * function itself. The argument expressions may not contain set-returning * functions (the planner is supposed to have separated evaluation for those). * * This should be called in a short-lived (per-tuple) context, argContext * needs to live until all rows have been returned (i.e. *isDone
| 498 | * This is used by nodeProjectSet.c. |
| 499 | */ |
| 500 | Datum |
| 501 | ExecMakeFunctionResultSet(SetExprState *fcache, |
| 502 | ExprContext *econtext, |
| 503 | MemoryContext argContext, |
| 504 | bool *isNull, |
| 505 | ExprDoneCond *isDone) |
| 506 | { |
| 507 | List *arguments; |
| 508 | Datum result; |
| 509 | FunctionCallInfo fcinfo; |
| 510 | PgStat_FunctionCallUsage fcusage; |
| 511 | ReturnSetInfo rsinfo; |
| 512 | bool callit; |
| 513 | int i; |
| 514 | |
| 515 | restart: |
| 516 | |
| 517 | /* Guard against stack overflow due to overly complex expressions */ |
| 518 | check_stack_depth(); |
| 519 | |
| 520 | /* |
| 521 | * If a previous call of the function returned a set result in the form of |
| 522 | * a tuplestore, continue reading rows from the tuplestore until it's |
| 523 | * empty. |
| 524 | */ |
| 525 | if (fcache->funcResultStore) |
| 526 | { |
| 527 | TupleTableSlot *slot = fcache->funcResultSlot; |
| 528 | MemoryContext oldContext; |
| 529 | bool foundTup; |
| 530 | |
| 531 | /* |
| 532 | * Have to make sure tuple in slot lives long enough, otherwise |
| 533 | * clearing the slot could end up trying to free something already |
| 534 | * freed. |
| 535 | */ |
| 536 | oldContext = MemoryContextSwitchTo(slot->tts_mcxt); |
| 537 | foundTup = tuplestore_gettupleslot(fcache->funcResultStore, true, false, |
| 538 | fcache->funcResultSlot); |
| 539 | MemoryContextSwitchTo(oldContext); |
| 540 | |
| 541 | if (foundTup) |
| 542 | { |
| 543 | *isDone = ExprMultipleResult; |
| 544 | if (fcache->funcReturnsTuple) |
| 545 | { |
| 546 | /* We must return the whole tuple as a Datum. */ |
| 547 | *isNull = false; |
| 548 | return ExecFetchSlotHeapTupleDatum(fcache->funcResultSlot); |
| 549 | } |
| 550 | else |
| 551 | { |
| 552 | /* Extract the first column and return it as a scalar. */ |
| 553 | return slot_getattr(fcache->funcResultSlot, 1, isNull); |
| 554 | } |
| 555 | } |
| 556 | /* Exhausted the tuplestore, so clean up */ |
| 557 | tuplestore_end(fcache->funcResultStore); |
no test coverage detected