* exec_for_query --- execute body of FOR loop for each row from a portal * * Used by exec_stmt_fors, exec_stmt_forc and exec_stmt_dynfors */
| 5780 | * Used by exec_stmt_fors, exec_stmt_forc and exec_stmt_dynfors |
| 5781 | */ |
| 5782 | static int |
| 5783 | exec_for_query(PLpgSQL_execstate *estate, PLpgSQL_stmt_forq *stmt, |
| 5784 | Portal portal, bool prefetch_ok) |
| 5785 | { |
| 5786 | PLpgSQL_variable *var; |
| 5787 | SPITupleTable *tuptab; |
| 5788 | bool found = false; |
| 5789 | int rc = PLPGSQL_RC_OK; |
| 5790 | uint64 previous_id = INVALID_TUPLEDESC_IDENTIFIER; |
| 5791 | bool tupdescs_match = true; |
| 5792 | uint64 n; |
| 5793 | |
| 5794 | /* Fetch loop variable's datum entry */ |
| 5795 | var = (PLpgSQL_variable *) estate->datums[stmt->var->dno]; |
| 5796 | |
| 5797 | /* |
| 5798 | * Make sure the portal doesn't get closed by the user statements we |
| 5799 | * execute. |
| 5800 | */ |
| 5801 | PinPortal(portal); |
| 5802 | |
| 5803 | /* |
| 5804 | * In a non-atomic context, we dare not prefetch, even if it would |
| 5805 | * otherwise be safe. Aside from any semantic hazards that that might |
| 5806 | * create, if we prefetch toasted data and then the user commits the |
| 5807 | * transaction, the toast references could turn into dangling pointers. |
| 5808 | * (Rows we haven't yet fetched from the cursor are safe, because the |
| 5809 | * PersistHoldablePortal mechanism handles this scenario.) |
| 5810 | */ |
| 5811 | if (!estate->atomic) |
| 5812 | prefetch_ok = false; |
| 5813 | |
| 5814 | /* |
| 5815 | * Fetch the initial tuple(s). If prefetching is allowed then we grab a |
| 5816 | * few more rows to avoid multiple trips through executor startup |
| 5817 | * overhead. |
| 5818 | */ |
| 5819 | SPI_cursor_fetch(portal, true, prefetch_ok ? 10 : 1); |
| 5820 | tuptab = SPI_tuptable; |
| 5821 | n = SPI_processed; |
| 5822 | |
| 5823 | /* |
| 5824 | * If the query didn't return any rows, set the target to NULL and fall |
| 5825 | * through with found = false. |
| 5826 | */ |
| 5827 | if (n == 0) |
| 5828 | { |
| 5829 | exec_move_row(estate, var, NULL, tuptab->tupdesc); |
| 5830 | exec_eval_cleanup(estate); |
| 5831 | } |
| 5832 | else |
| 5833 | found = true; /* processed at least one tuple */ |
| 5834 | |
| 5835 | /* |
| 5836 | * Now do the loop |
| 5837 | */ |
| 5838 | while (n > 0) |
| 5839 | { |
no test coverage detected