WIP: Fix tuple extension logic.
authorAndres Freund <andres@anarazel.de>
Mon, 3 Dec 2018 20:56:23 +0000 (12:56 -0800)
committerAndres Freund <andres@anarazel.de>
Tue, 11 Dec 2018 00:48:56 +0000 (16:48 -0800)
Author:
Reviewed-By:
Discussion: https://postgr.es/m/
Backpatch:

src/backend/executor/execTuples.c

index 37c46543cdd5b7e296341a51dc739ebbb825155f..ac5d76bd417b0563972274a6d6a9e71bb0b97216 100644 (file)
@@ -394,6 +394,27 @@ tts_heap_get_heap_tuple(TupleTableSlot *slot)
    Assert(!TTS_EMPTY(slot));
    if (!hslot->tuple)
        tts_heap_materialize(slot);
+   else if (HeapTupleHeaderGetNatts(hslot->tuple->t_data)
+            < slot->tts_tupleDescriptor->natts)
+   {
+       MemoryContext oldContext;
+       HeapTuple oldtuple;
+
+       oldContext = MemoryContextSwitchTo(slot->tts_mcxt);
+
+       oldtuple = hslot->tuple;
+       hslot->tuple = heap_expand_tuple(hslot->tuple,
+                                        slot->tts_tupleDescriptor);
+       MemoryContextSwitchTo(oldContext);
+
+       if (slot->tts_flags & TTS_FLAG_SHOULDFREE)
+           heap_freetuple(oldtuple);
+       slot->tts_flags |= TTS_FLAG_SHOULDFREE;
+
+       slot->tts_nvalid = 0;
+       hslot->off = 0;
+       slot_getallattrs(slot);
+   }
 
    return hslot->tuple;
 }
@@ -762,6 +783,33 @@ tts_buffer_heap_get_heap_tuple(TupleTableSlot *slot)
 
    if (!bslot->base.tuple)
        tts_buffer_heap_materialize(slot);
+   else if (HeapTupleHeaderGetNatts(bslot->base.tuple->t_data)
+            < slot->tts_tupleDescriptor->natts)
+   {
+       MemoryContext oldContext;
+       HeapTuple oldtuple;
+
+       oldContext = MemoryContextSwitchTo(slot->tts_mcxt);
+
+       oldtuple = bslot->base.tuple;
+       bslot->base.tuple = heap_expand_tuple(bslot->base.tuple,
+                                        slot->tts_tupleDescriptor);
+       MemoryContextSwitchTo(oldContext);
+
+       if (slot->tts_flags & TTS_FLAG_SHOULDFREE)
+           heap_freetuple(oldtuple);
+       slot->tts_flags |= TTS_FLAG_SHOULDFREE;
+
+       if (BufferIsValid(bslot->buffer))
+       {
+           ReleaseBuffer(bslot->buffer);
+           bslot->buffer = InvalidBuffer;
+       }
+
+       slot->tts_nvalid = 0;
+       bslot->base.off = 0;
+       slot_getallattrs(slot);
+   }
 
    return bslot->base.tuple;
 }