From c3f827a729f457c8b3bf760553b6c85d5b0a0db1 Mon Sep 17 00:00:00 2001
From: Amit Khandekar <amit.khandekar@enterprisedb.com>
Date: Mon, 19 Nov 2018 12:09:20 +0530
Subject: [PATCH 1/2] Populate &slot->tts_tid wherever tuple->t_self changes.

Author: Andres Freund.
---
 src/backend/commands/copy.c            | 4 +++-
 src/backend/commands/createas.c        | 1 +
 src/backend/commands/matview.c         | 1 +
 src/backend/commands/tablecmds.c       | 3 +++
 src/backend/executor/execReplication.c | 1 +
 src/backend/executor/execTuples.c      | 2 ++
 src/backend/executor/nodeModifyTable.c | 4 ++++
 src/include/executor/tuptable.h        | 1 +
 8 files changed, 16 insertions(+), 1 deletion(-)

diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index a61f3bc..93badf7 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -2953,9 +2953,11 @@ CopyFrom(CopyState cstate)
 						tuple->t_tableOid = RelationGetRelid(resultRelInfo->ri_RelationDesc);
 					}
 					else
+					{
 						heap_insert(resultRelInfo->ri_RelationDesc, tuple,
 									mycid, hi_options, bistate);
-
+						ItemPointerCopy(&tuple->t_self, &slot->tts_tid);
+					}
 					/* And create index entries for it */
 					if (resultRelInfo->ri_NumIndices > 0)
 						recheckIndexes = ExecInsertIndexTuples(slot,
diff --git a/src/backend/commands/createas.c b/src/backend/commands/createas.c
index 7b60aa9..7df40c6 100644
--- a/src/backend/commands/createas.c
+++ b/src/backend/commands/createas.c
@@ -602,6 +602,7 @@ intorel_receive(TupleTableSlot *slot, DestReceiver *self)
 				myState->output_cid,
 				myState->hi_options,
 				myState->bistate);
+	ItemPointerCopy(&tuple->t_self, &slot->tts_tid);
 
 	/* We know this is a newly created relation, so there are no indexes */
 
diff --git a/src/backend/commands/matview.c b/src/backend/commands/matview.c
index fd12288..f0120e4 100644
--- a/src/backend/commands/matview.c
+++ b/src/backend/commands/matview.c
@@ -491,6 +491,7 @@ transientrel_receive(TupleTableSlot *slot, DestReceiver *self)
 				myState->output_cid,
 				myState->hi_options,
 				myState->bistate);
+	ItemPointerCopy(&tuple->t_self, &slot->tts_tid);
 
 	/* We know this is a newly created relation, so there are no indexes */
 
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index a15e604..dfa15a5 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -4875,7 +4875,10 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode)
 
 			/* Write the tuple out to the new relation */
 			if (newrel)
+			{
 				heap_insert(newrel, tuple, mycid, hi_options, bistate);
+				ItemPointerCopy(&tuple->t_self, &newslot->tts_tid);
+			}
 
 			ResetExprContext(econtext);
 
diff --git a/src/backend/executor/execReplication.c b/src/backend/executor/execReplication.c
index 5bd3bbc..fc00b49 100644
--- a/src/backend/executor/execReplication.c
+++ b/src/backend/executor/execReplication.c
@@ -500,6 +500,7 @@ ExecSimpleRelationUpdate(EState *estate, EPQState *epqstate,
 
 		/* OK, update the tuple and index entries for it */
 		simple_heap_update(rel, &hsearchslot->tuple->t_self, hslot->tuple);
+		ItemPointerCopy(&hslot->tuple->t_self, &hslot->base.tts_tid);
 
 		if (resultRelInfo->ri_NumIndices > 0 &&
 			!HeapTupleIsHeapOnly(hslot->tuple))
diff --git a/src/backend/executor/execTuples.c b/src/backend/executor/execTuples.c
index c9523c5..47aed0a 100644
--- a/src/backend/executor/execTuples.c
+++ b/src/backend/executor/execTuples.c
@@ -432,6 +432,7 @@ tts_heap_store_tuple(TupleTableSlot *slot, HeapTuple tuple, bool shouldFree)
 	hslot->tuple = tuple;
 	hslot->off = 0;
 	slot->tts_flags &= ~TTS_FLAG_EMPTY;
+	slot->tts_tid = tuple->t_self;
 
 	if (shouldFree)
 		slot->tts_flags |= TTS_FLAG_SHOULDFREE;
@@ -810,6 +811,7 @@ tts_buffer_heap_store_tuple(TupleTableSlot *slot, HeapTuple tuple, Buffer buffer
 	slot->tts_nvalid = 0;
 	bslot->base.tuple = tuple;
 	bslot->base.off = 0;
+	slot->tts_tid = tuple->t_self;
 
 	/*
 	 * If tuple is on a disk page, keep the page pinned as long as we hold a
diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c
index 7e05c15..9786d95 100644
--- a/src/backend/executor/nodeModifyTable.c
+++ b/src/backend/executor/nodeModifyTable.c
@@ -477,6 +477,7 @@ ExecInsert(ModifyTableState *mtstate,
 								estate->es_output_cid,
 								HEAP_INSERT_SPECULATIVE,
 								NULL);
+			ItemPointerCopy(&tuple->t_self, &slot->tts_tid);
 
 			/* insert index entries for tuple */
 			recheckIndexes = ExecInsertIndexTuples(slot, &(tuple->t_self),
@@ -522,6 +523,7 @@ ExecInsert(ModifyTableState *mtstate,
 			newId = heap_insert(resultRelationDesc, tuple,
 								estate->es_output_cid,
 								0, NULL);
+			ItemPointerCopy(&tuple->t_self, &slot->tts_tid);
 
 			/* insert index entries for tuple */
 			if (resultRelInfo->ri_NumIndices > 0)
@@ -1204,6 +1206,8 @@ lreplace:;
 							 estate->es_crosscheck_snapshot,
 							 true /* wait for commit */ ,
 							 &hufd, &lockmode);
+		ItemPointerCopy(&tuple->t_self, &slot->tts_tid);
+
 		switch (result)
 		{
 			case HeapTupleSelfUpdated:
diff --git a/src/include/executor/tuptable.h b/src/include/executor/tuptable.h
index db5031f..6990f6e 100644
--- a/src/include/executor/tuptable.h
+++ b/src/include/executor/tuptable.h
@@ -125,6 +125,7 @@ typedef struct TupleTableSlot
 #define FIELDNO_TUPLETABLESLOT_ISNULL 6
 	bool	   *tts_isnull;		/* current per-attribute isnull flags */
 	MemoryContext tts_mcxt;		/* slot itself is in this context */
+	ItemPointerData tts_tid;	/* tid of the underlying tuple */
 } TupleTableSlot;
 
 /* routines for a TupleTableSlot implementation */
-- 
2.1.4

