aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/executor/execTuples.c19
1 files changed, 11 insertions, 8 deletions
diff --git a/src/backend/executor/execTuples.c b/src/backend/executor/execTuples.c
index 121649f3435..e1948670490 100644
--- a/src/backend/executor/execTuples.c
+++ b/src/backend/executor/execTuples.c
@@ -747,10 +747,12 @@ tts_buffer_heap_copyslot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)
/*
* If the source slot is of a different kind, or is a buffer slot that has
- * been materialized, make a new copy of the tuple.
+ * been materialized / is virtual, make a new copy of the tuple. Otherwise
+ * make a new reference to the in-buffer tuple.
*/
if (dstslot->tts_ops != srcslot->tts_ops ||
- TTS_SHOULDFREE(srcslot))
+ TTS_SHOULDFREE(srcslot) ||
+ !bsrcslot->base.tuple)
{
MemoryContext oldContext;
@@ -763,18 +765,19 @@ tts_buffer_heap_copyslot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)
}
else
{
- if (!bsrcslot->base.tuple)
- tts_buffer_heap_materialize(srcslot);
+ Assert(BufferIsValid(bsrcslot->buffer));
tts_buffer_heap_store_tuple(dstslot, bsrcslot->base.tuple,
bsrcslot->buffer, false);
/*
- * Need to materialize because the HeapTupleData portion of the tuple
- * might be in a foreign memory context. That's annoying, but until
- * that's moved into the slot, unavoidable.
+ * The HeapTupleData portion of the source tuple might be shorter
+ * lived than the destination slot. Therefore copy the HeapTuple into
+ * our slot's tupdata, which is guaranteed to live long enough (but
+ * will still point into the buffer).
*/
- tts_buffer_heap_materialize(dstslot);
+ memcpy(&bdstslot->base.tupdata, bdstslot->base.tuple, sizeof(HeapTupleData));
+ bdstslot->base.tuple = &bdstslot->base.tupdata;
}
}