Skip to content

Commit d16a0c1

Browse files
committed
Verify that attribute counts match in ExecCopySlot
tts_virtual_copyslot() contained an Assert that checked that the srcslot contained <= attributes than the dstslot. This seems to be backwards as if the srcslot contained fewer attributes then the dstslot could be left with stale Datum values from the previously stored tuple. It might make more sense to allow the source to contain additional attributes and only copy the leading ones that also exist in the destination, however, that's not what we're doing here. Here we just remove the Assert from tts_virtual_copyslot() and add an Assert to ExecCopySlot() to verify the attribute counts match. There does not seem to be any places where the destination contains fewer attributes, so instead of going to the trouble of making the code properly handle this, let's just ensure the attribute counts match. If this Assert fails then that will indicate that we do have cases that require us to handle the srcslot with more attributes than the dstslot. It seems better to only write this code if there's a genuine requirement for it rather than write it now only to leave it untested. Thanks to Andres Freund for helping with the analysis of this. Discussion: https://postgr.es/m/CAApHDvpMAvBL0T+TRORquyx1iqFQKMVTXtqNocOw0Pa2uh1heg@mail.gmail.com
1 parent d43bd09 commit d16a0c1

File tree

2 files changed

+9
-3
lines changed

2 files changed

+9
-3
lines changed

src/backend/executor/execTuples.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -253,8 +253,6 @@ tts_virtual_copyslot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)
253253
{
254254
TupleDesc srcdesc = srcslot->tts_tupleDescriptor;
255255

256-
Assert(srcdesc->natts <= dstslot->tts_tupleDescriptor->natts);
257-
258256
tts_virtual_clear(dstslot);
259257

260258
slot_getallattrs(srcslot);

src/include/executor/tuptable.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,8 @@ struct TupleTableSlotOps
174174

175175
/*
176176
* Copy the contents of the source slot into the destination slot's own
177-
* context. Invoked using callback of the destination slot.
177+
* context. Invoked using callback of the destination slot. 'dstslot' and
178+
* 'srcslot' can be assumed to have the same number of attributes.
178179
*/
179180
void (*copyslot) (TupleTableSlot *dstslot, TupleTableSlot *srcslot);
180181

@@ -477,12 +478,19 @@ ExecCopySlotMinimalTuple(TupleTableSlot *slot)
477478
*
478479
* If a source's system attributes are supposed to be accessed in the target
479480
* slot, the target slot and source slot types need to match.
481+
*
482+
* Currently, 'dstslot' and 'srcslot' must have the same number of attributes.
483+
* Future work could see this relaxed to allow the source to contain
484+
* additional attributes and have the code here only copy over the leading
485+
* attributes.
480486
*/
481487
static inline TupleTableSlot *
482488
ExecCopySlot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)
483489
{
484490
Assert(!TTS_EMPTY(srcslot));
485491
Assert(srcslot != dstslot);
492+
Assert(dstslot->tts_tupleDescriptor->natts ==
493+
srcslot->tts_tupleDescriptor->natts);
486494

487495
dstslot->tts_ops->copyslot(dstslot, srcslot);
488496

0 commit comments

Comments
 (0)