diff options
author | Andres Freund | 2019-02-28 20:27:58 +0000 |
---|---|---|
committer | Andres Freund | 2019-02-28 20:28:03 +0000 |
commit | f414abd62da7aa3cfd75e9047affd94c029c7c04 (patch) | |
tree | 2706cc9765f596d971be0a77987dd71d20e75a93 /src/backend/executor/execTuples.c | |
parent | 19455c9f5606072a191962271c35ad659fbab526 (diff) |
Allow buffer tuple table slots to materialize after ExecStoreVirtualTuple().
While not common, it can be useful to store a virtual tuple into a
buffer tuple table slot, and then materialize that slot. So far we've
asserted out, which surprisingly wasn't a problem for anything in
core. But that seems fragile, and it also breaks redis_fdw after
ff11e7f4b9.
Thus, allow materializing a virtual tuple stored in a buffer tuple
table slot.
Author: Andres Freund
Discussion:
https://postgr.es/m/[email protected]
https://postgr.es/m/[email protected]
Diffstat (limited to 'src/backend/executor/execTuples.c')
-rw-r--r-- | src/backend/executor/execTuples.c | 48 |
1 files changed, 31 insertions, 17 deletions
diff --git a/src/backend/executor/execTuples.c b/src/backend/executor/execTuples.c index 3a142518214..121649f3435 100644 --- a/src/backend/executor/execTuples.c +++ b/src/backend/executor/execTuples.c @@ -700,25 +700,36 @@ tts_buffer_heap_materialize(TupleTableSlot *slot) slot->tts_flags |= TTS_FLAG_SHOULDFREE; - /* - * A heap tuple stored in a BufferHeapTupleTableSlot should have a buffer - * associated with it, unless it's materialized (which would've returned - * above). - */ - Assert(bslot->base.tuple); - oldContext = MemoryContextSwitchTo(slot->tts_mcxt); - bslot->base.tuple = heap_copytuple(bslot->base.tuple); - MemoryContextSwitchTo(oldContext); - /* - * A heap tuple stored in a BufferHeapTupleTableSlot should have a buffer - * associated with it, unless it's materialized. - */ - Assert(BufferIsValid(bslot->buffer)); - if (likely(BufferIsValid(bslot->buffer))) - ReleaseBuffer(bslot->buffer); - bslot->buffer = InvalidBuffer; + if (!bslot->base.tuple) + { + /* + * Normally BufferHeapTupleTableSlot should have a tuple + buffer + * associated with it, unless it's materialized (which would've + * returned above). But when it's useful to allow storing virtual + * tuples in a buffer slot, which then also needs to be + * materializable. + */ + bslot->base.tuple = heap_form_tuple(slot->tts_tupleDescriptor, + slot->tts_values, + slot->tts_isnull); + + } + else + { + bslot->base.tuple = heap_copytuple(bslot->base.tuple); + + /* + * A heap tuple stored in a BufferHeapTupleTableSlot should have a + * buffer associated with it, unless it's materialized or virtual. + */ + Assert(BufferIsValid(bslot->buffer)); + if (likely(BufferIsValid(bslot->buffer))) + ReleaseBuffer(bslot->buffer); + bslot->buffer = InvalidBuffer; + } + MemoryContextSwitchTo(oldContext); /* * Have to deform from scratch, otherwise tts_values[] entries could point @@ -752,6 +763,9 @@ tts_buffer_heap_copyslot(TupleTableSlot *dstslot, TupleTableSlot *srcslot) } else { + if (!bsrcslot->base.tuple) + tts_buffer_heap_materialize(srcslot); + tts_buffer_heap_store_tuple(dstslot, bsrcslot->base.tuple, bsrcslot->buffer, false); |