ensure_slotdescs_match_in_ExecCopySlot.patch
text/plain
Filename: ensure_slotdescs_match_in_ExecCopySlot.patch
Type: text/plain
Part: 0
Patch
Format: unified
| File | + | − |
|---|---|---|
| src/backend/executor/execTuples.c | 0 | 2 |
| src/include/executor/tuptable.h | 38 | 1 |
diff --git a/src/backend/executor/execTuples.c b/src/backend/executor/execTuples.c
index 2c2712ceac..5a2db83987 100644
--- a/src/backend/executor/execTuples.c
+++ b/src/backend/executor/execTuples.c
@@ -253,8 +253,6 @@ tts_virtual_copyslot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)
{
TupleDesc srcdesc = srcslot->tts_tupleDescriptor;
- Assert(srcdesc->natts <= dstslot->tts_tupleDescriptor->natts);
-
tts_virtual_clear(dstslot);
slot_getallattrs(srcslot);
diff --git a/src/include/executor/tuptable.h b/src/include/executor/tuptable.h
index 4210d6d838..cc32550840 100644
--- a/src/include/executor/tuptable.h
+++ b/src/include/executor/tuptable.h
@@ -174,7 +174,10 @@ struct TupleTableSlotOps
/*
* Copy the contents of the source slot into the destination slot's own
- * context. Invoked using callback of the destination slot.
+ * context. Invoked using callback of the destination slot. 'dstslot' and
+ * 'srcslot' can be assumed to match in terms of attribute count and data
+ * types. However, either TupleDesc may sometimes contain attribute types
+ * of InvalidOid in cases where the attribute refers to a dropped column.
*/
void (*copyslot) (TupleTableSlot *dstslot, TupleTableSlot *srcslot);
@@ -340,6 +343,35 @@ extern void slot_getsomeattrs_int(TupleTableSlot *slot, int attnum);
#ifndef FRONTEND
+
+/*
+ * VerifySlotCompatibility
+ * Ensure the two given slots are compatible with one another in terms of
+ * their number of attributes and attribute types.
+ */
+static void
+VerifySlotCompatibility(TupleTableSlot *slot1, TupleTableSlot *slot2)
+{
+#ifdef USE_ASSERT_CHECKING
+ TupleDesc desc1 = slot1->tts_tupleDescriptor;
+ TupleDesc desc2 = slot2->tts_tupleDescriptor;
+
+ Assert(desc1->natts == desc2->natts);
+
+ for (int i = 0; i < desc1->natts; i++)
+ {
+ Oid type1 = desc1->attrs[i].atttypid;
+ Oid type2 = desc2->attrs[i].atttypid;
+
+ /*
+ * Ensure the attribute types match. InvalidOid is permitted as we can end
+ * up with dropped columns in a TupleDesc
+ */
+ Assert(type1 == type2 || !OidIsValid(type1) || !OidIsValid(type2));
+ }
+#endif
+}
+
/*
* This function forces the entries of the slot's Datum/isnull arrays to be
* valid at least up through the attnum'th entry.
@@ -477,6 +509,9 @@ ExecCopySlotMinimalTuple(TupleTableSlot *slot)
*
* If a source's system attributes are supposed to be accessed in the target
* slot, the target slot and source slot types need to match.
+ *
+ * The source and destination slot's tuple descriptor must match in terms of
+ * attribute types and number of attributes.
*/
static inline TupleTableSlot *
ExecCopySlot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)
@@ -484,6 +519,8 @@ ExecCopySlot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)
Assert(!TTS_EMPTY(srcslot));
Assert(srcslot != dstslot);
+ VerifySlotCompatibility(dstslot, srcslot);
+
dstslot->tts_ops->copyslot(dstslot, srcslot);
return dstslot;