| 873 | } |
| 874 | |
| 875 | static inline void |
| 876 | tts_buffer_heap_store_tuple(TupleTableSlot *slot, HeapTuple tuple, |
| 877 | Buffer buffer, bool transfer_pin) |
| 878 | { |
| 879 | BufferHeapTupleTableSlot *bslot = (BufferHeapTupleTableSlot *) slot; |
| 880 | |
| 881 | if (TTS_SHOULDFREE(slot)) |
| 882 | { |
| 883 | /* materialized slot shouldn't have a buffer to release */ |
| 884 | Assert(!BufferIsValid(bslot->buffer)); |
| 885 | |
| 886 | heap_freetuple(bslot->base.tuple); |
| 887 | slot->tts_flags &= ~TTS_FLAG_SHOULDFREE; |
| 888 | } |
| 889 | |
| 890 | slot->tts_flags &= ~TTS_FLAG_EMPTY; |
| 891 | slot->tts_nvalid = 0; |
| 892 | bslot->base.tuple = tuple; |
| 893 | bslot->base.off = 0; |
| 894 | slot->tts_tid = tuple->t_self; |
| 895 | |
| 896 | /* |
| 897 | * If tuple is on a disk page, keep the page pinned as long as we hold a |
| 898 | * pointer into it. We assume the caller already has such a pin. If |
| 899 | * transfer_pin is true, we'll transfer that pin to this slot, if not |
| 900 | * we'll pin it again ourselves. |
| 901 | * |
| 902 | * This is coded to optimize the case where the slot previously held a |
| 903 | * tuple on the same disk page: in that case releasing and re-acquiring |
| 904 | * the pin is a waste of cycles. This is a common situation during |
| 905 | * seqscans, so it's worth troubling over. |
| 906 | */ |
| 907 | if (bslot->buffer != buffer) |
| 908 | { |
| 909 | if (BufferIsValid(bslot->buffer)) |
| 910 | ReleaseBuffer(bslot->buffer); |
| 911 | |
| 912 | bslot->buffer = buffer; |
| 913 | |
| 914 | if (!transfer_pin && BufferIsValid(buffer)) |
| 915 | IncrBufferRefCount(buffer); |
| 916 | } |
| 917 | else if (transfer_pin && BufferIsValid(buffer)) |
| 918 | { |
| 919 | /* |
| 920 | * In transfer_pin mode the caller won't know about the same-page |
| 921 | * optimization, so we gotta release its pin. |
| 922 | */ |
| 923 | ReleaseBuffer(buffer); |
| 924 | } |
| 925 | } |
| 926 | |
| 927 | /* |
| 928 | * slot_deform_heap_tuple |
no test coverage detected