From feec41723edd21987838080487349e4852d7daa7 Mon Sep 17 00:00:00 2001
From: kommih <haribabuk@fast.au.fujitsu.com>
Date: Wed, 16 Jan 2019 18:43:47 +1100
Subject: [PATCH 1/2] Reduce the use of HeapTuple t_tableOid

Except trigger and where the HeapTuple is generated
and passed from slots, still the t_tableOid is used.
This needs to be replaced when the t_tableOid is stored
as a seperate variable/parameter.
---
 contrib/hstore/hstore_io.c                    |  2 --
 contrib/pg_visibility/pg_visibility.c         |  1 -
 contrib/pgstattuple/pgstatapprox.c            |  1 -
 contrib/pgstattuple/pgstattuple.c             |  3 +-
 contrib/postgres_fdw/postgres_fdw.c           | 11 ++++--
 src/backend/access/common/heaptuple.c         |  7 ----
 src/backend/access/heap/heapam.c              | 35 +++++--------------
 src/backend/access/heap/heapam_handler.c      | 27 +++++++-------
 src/backend/access/heap/heapam_visibility.c   | 20 ++++-------
 src/backend/access/heap/pruneheap.c           |  2 --
 src/backend/access/heap/tuptoaster.c          |  3 --
 src/backend/access/heap/vacuumlazy.c          |  2 --
 src/backend/access/index/genam.c              |  1 -
 src/backend/catalog/indexing.c                |  2 +-
 src/backend/commands/analyze.c                |  2 +-
 src/backend/commands/functioncmds.c           |  3 +-
 src/backend/commands/schemacmds.c             |  1 -
 src/backend/commands/trigger.c                | 21 +++++------
 src/backend/executor/execExprInterp.c         |  1 -
 src/backend/executor/execTuples.c             | 29 +++++++++------
 src/backend/executor/execUtils.c              |  2 --
 src/backend/executor/nodeAgg.c                |  3 +-
 src/backend/executor/nodeGather.c             |  1 +
 src/backend/executor/nodeGatherMerge.c        |  1 +
 src/backend/executor/nodeIndexonlyscan.c      |  4 +--
 src/backend/executor/nodeIndexscan.c          |  3 +-
 src/backend/executor/nodeModifyTable.c        |  6 +---
 src/backend/executor/nodeSetOp.c              |  1 +
 src/backend/executor/spi.c                    |  1 -
 src/backend/executor/tqueue.c                 |  1 -
 src/backend/replication/logical/decode.c      |  9 -----
 .../replication/logical/reorderbuffer.c       |  4 +--
 src/backend/utils/adt/expandedrecord.c        |  1 -
 src/backend/utils/adt/jsonfuncs.c             |  2 --
 src/backend/utils/adt/rowtypes.c              | 10 ------
 src/backend/utils/cache/catcache.c            |  1 -
 src/backend/utils/sort/tuplesort.c            |  7 ++--
 src/include/access/heapam.h                   |  3 +-
 src/include/executor/tuptable.h               |  5 ++-
 src/pl/plpgsql/src/pl_exec.c                  |  2 --
 src/test/regress/regress.c                    |  1 -
 41 files changed, 92 insertions(+), 150 deletions(-)

diff --git a/contrib/hstore/hstore_io.c b/contrib/hstore/hstore_io.c
index 745497c76f..05244e77ef 100644
--- a/contrib/hstore/hstore_io.c
+++ b/contrib/hstore/hstore_io.c
@@ -845,7 +845,6 @@ hstore_from_record(PG_FUNCTION_ARGS)
 		/* Build a temporary HeapTuple control structure */
 		tuple.t_len = HeapTupleHeaderGetDatumLength(rec);
 		ItemPointerSetInvalid(&(tuple.t_self));
-		tuple.t_tableOid = InvalidOid;
 		tuple.t_data = rec;
 
 		values = (Datum *) palloc(ncolumns * sizeof(Datum));
@@ -998,7 +997,6 @@ hstore_populate_record(PG_FUNCTION_ARGS)
 		/* Build a temporary HeapTuple control structure */
 		tuple.t_len = HeapTupleHeaderGetDatumLength(rec);
 		ItemPointerSetInvalid(&(tuple.t_self));
-		tuple.t_tableOid = InvalidOid;
 		tuple.t_data = rec;
 	}
 
diff --git a/contrib/pg_visibility/pg_visibility.c b/contrib/pg_visibility/pg_visibility.c
index c9166730fe..503f00408c 100644
--- a/contrib/pg_visibility/pg_visibility.c
+++ b/contrib/pg_visibility/pg_visibility.c
@@ -657,7 +657,6 @@ collect_corrupt_items(Oid relid, bool all_visible, bool all_frozen)
 			ItemPointerSet(&(tuple.t_self), blkno, offnum);
 			tuple.t_data = (HeapTupleHeader) PageGetItem(page, itemid);
 			tuple.t_len = ItemIdGetLength(itemid);
-			tuple.t_tableOid = relid;
 
 			/*
 			 * If we're checking whether the page is all-visible, we expect
diff --git a/contrib/pgstattuple/pgstatapprox.c b/contrib/pgstattuple/pgstatapprox.c
index 636c8d40ac..6abe22ed61 100644
--- a/contrib/pgstattuple/pgstatapprox.c
+++ b/contrib/pgstattuple/pgstatapprox.c
@@ -152,7 +152,6 @@ statapprox_heap(Relation rel, output_type *stat)
 
 			tuple.t_data = (HeapTupleHeader) PageGetItem(page, itemid);
 			tuple.t_len = ItemIdGetLength(itemid);
-			tuple.t_tableOid = RelationGetRelid(rel);
 
 			/*
 			 * We follow VACUUM's lead in counting INSERT_IN_PROGRESS tuples
diff --git a/contrib/pgstattuple/pgstattuple.c b/contrib/pgstattuple/pgstattuple.c
index 9bcb640884..a0e7abe748 100644
--- a/contrib/pgstattuple/pgstattuple.c
+++ b/contrib/pgstattuple/pgstattuple.c
@@ -344,7 +344,8 @@ pgstat_heap(Relation rel, FunctionCallInfo fcinfo)
 		/* must hold a buffer lock to call HeapTupleSatisfiesVisibility */
 		LockBuffer(hscan->rs_cbuf, BUFFER_LOCK_SHARE);
 
-		if (HeapTupleSatisfiesVisibility(tuple, &SnapshotDirty, hscan->rs_cbuf))
+		if (HeapTupleSatisfiesVisibility(tuple, RelationGetRelid(hscan->rs_scan.rs_rd),
+								&SnapshotDirty, hscan->rs_cbuf))
 		{
 			stat.tuple_len += tuple->t_len;
 			stat.tuple_count++;
diff --git a/contrib/postgres_fdw/postgres_fdw.c b/contrib/postgres_fdw/postgres_fdw.c
index 525629a6cc..1f806a588b 100644
--- a/contrib/postgres_fdw/postgres_fdw.c
+++ b/contrib/postgres_fdw/postgres_fdw.c
@@ -1468,6 +1468,8 @@ postgresIterateForeignScan(ForeignScanState *node)
 	 */
 	ExecStoreHeapTuple(fsstate->tuples[fsstate->next_tuple++],
 					   slot,
+					   fsstate->rel ?
+							   RelationGetRelid(fsstate->rel) : InvalidOid,
 					   false);
 
 	return slot;
@@ -3482,7 +3484,8 @@ store_returning_result(PgFdwModifyState *fmstate,
 		 * The returning slot will currently not necessarily be suitable to
 		 * store heaptuples directly, so allow for conversion.
 		 */
-		ExecForceStoreHeapTuple(newtup, slot);
+		ExecForceStoreHeapTuple(newtup, slot,
+					fmstate->rel ? RelationGetRelid(fmstate->rel) : InvalidOid);
 		ExecMaterializeSlot(slot);
 		pfree(newtup);
 	}
@@ -3756,7 +3759,11 @@ get_returning_data(ForeignScanState *node)
 												dmstate->retrieved_attrs,
 												node,
 												dmstate->temp_cxt);
-			ExecStoreHeapTuple(newtup, slot, false);
+			ExecStoreHeapTuple(newtup,
+								slot,
+								dmstate->rel ?
+								RelationGetRelid(dmstate->rel) : InvalidOid,
+								false);
 		}
 		PG_CATCH();
 		{
diff --git a/src/backend/access/common/heaptuple.c b/src/backend/access/common/heaptuple.c
index ed4549ca57..d4ede6d47a 100644
--- a/src/backend/access/common/heaptuple.c
+++ b/src/backend/access/common/heaptuple.c
@@ -689,7 +689,6 @@ heap_copytuple(HeapTuple tuple)
 	newTuple = (HeapTuple) palloc(HEAPTUPLESIZE + tuple->t_len);
 	newTuple->t_len = tuple->t_len;
 	newTuple->t_self = tuple->t_self;
-	newTuple->t_tableOid = tuple->t_tableOid;
 	newTuple->t_data = (HeapTupleHeader) ((char *) newTuple + HEAPTUPLESIZE);
 	memcpy((char *) newTuple->t_data, (char *) tuple->t_data, tuple->t_len);
 	return newTuple;
@@ -715,7 +714,6 @@ heap_copytuple_with_tuple(HeapTuple src, HeapTuple dest)
 
 	dest->t_len = src->t_len;
 	dest->t_self = src->t_self;
-	dest->t_tableOid = src->t_tableOid;
 	dest->t_data = (HeapTupleHeader) palloc(src->t_len);
 	memcpy((char *) dest->t_data, (char *) src->t_data, src->t_len);
 }
@@ -850,7 +848,6 @@ expand_tuple(HeapTuple *targetHeapTuple,
 			= targetTHeader
 			= (HeapTupleHeader) ((char *) *targetHeapTuple + HEAPTUPLESIZE);
 		(*targetHeapTuple)->t_len = len;
-		(*targetHeapTuple)->t_tableOid = sourceTuple->t_tableOid;
 		(*targetHeapTuple)->t_self = sourceTuple->t_self;
 
 		targetTHeader->t_infomask = sourceTHeader->t_infomask;
@@ -1078,7 +1075,6 @@ heap_form_tuple(TupleDesc tupleDescriptor,
 	 */
 	tuple->t_len = len;
 	ItemPointerSetInvalid(&(tuple->t_self));
-	tuple->t_tableOid = InvalidOid;
 
 	HeapTupleHeaderSetDatumLength(td, len);
 	HeapTupleHeaderSetTypeId(td, tupleDescriptor->tdtypeid);
@@ -1162,7 +1158,6 @@ heap_modify_tuple(HeapTuple tuple,
 	 */
 	newTuple->t_data->t_ctid = tuple->t_data->t_ctid;
 	newTuple->t_self = tuple->t_self;
-	newTuple->t_tableOid = tuple->t_tableOid;
 
 	return newTuple;
 }
@@ -1225,7 +1220,6 @@ heap_modify_tuple_by_cols(HeapTuple tuple,
 	 */
 	newTuple->t_data->t_ctid = tuple->t_data->t_ctid;
 	newTuple->t_self = tuple->t_self;
-	newTuple->t_tableOid = tuple->t_tableOid;
 
 	return newTuple;
 }
@@ -1465,7 +1459,6 @@ heap_tuple_from_minimal_tuple(MinimalTuple mtup)
 	result = (HeapTuple) palloc(HEAPTUPLESIZE + len);
 	result->t_len = len;
 	ItemPointerSetInvalid(&(result->t_self));
-	result->t_tableOid = InvalidOid;
 	result->t_data = (HeapTupleHeader) ((char *) result + HEAPTUPLESIZE);
 	memcpy((char *) result->t_data + MINIMAL_TUPLE_OFFSET, mtup, mtup->t_len);
 	memset(result->t_data, 0, offsetof(HeapTupleHeaderData, t_infomask2));
diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 8837f83292..7f594b3e4f 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -414,7 +414,6 @@ heapgetpage(TableScanDesc sscan, BlockNumber page)
 			HeapTupleData loctup;
 			bool		valid;
 
-			loctup.t_tableOid = RelationGetRelid(scan->rs_scan.rs_rd);
 			loctup.t_data = (HeapTupleHeader) PageGetItem((Page) dp, lpp);
 			loctup.t_len = ItemIdGetLength(lpp);
 			ItemPointerSet(&(loctup.t_self), page, lineoff);
@@ -422,7 +421,8 @@ heapgetpage(TableScanDesc sscan, BlockNumber page)
 			if (all_visible)
 				valid = true;
 			else
-				valid = HeapTupleSatisfiesVisibility(&loctup, snapshot, buffer);
+				valid = HeapTupleSatisfiesVisibility(&loctup, RelationGetRelid(scan->rs_scan.rs_rd),
+									snapshot, buffer);
 
 			CheckForSerializableConflictOut(valid, scan->rs_scan.rs_rd, &loctup,
 											buffer, snapshot);
@@ -640,7 +640,7 @@ heapgettup(HeapScanDesc scan,
 				/*
 				 * if current tuple qualifies, return it.
 				 */
-				valid = HeapTupleSatisfiesVisibility(tuple,
+				valid = HeapTupleSatisfiesVisibility(tuple, RelationGetRelid(scan->rs_scan.rs_rd),
 													 snapshot,
 													 scan->rs_cbuf);
 
@@ -1156,9 +1156,6 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	if (!is_bitmapscan && snapshot)
 		PredicateLockRelation(relation, snapshot);
 
-	/* we only need to set this up once */
-	scan->rs_ctup.t_tableOid = RelationGetRelid(relation);
-
 	/*
 	 * we do this here instead of in initscan() because heap_rescan also calls
 	 * initscan() and we don't want to allocate memory again
@@ -1383,6 +1380,7 @@ heap_getnextslot(TableScanDesc sscan, ScanDirection direction, TupleTableSlot *s
 
 	pgstat_count_heap_getnext(scan->rs_scan.rs_rd);
 
+	slot->tts_tableOid = RelationGetRelid(scan->rs_scan.rs_rd);
 	return ExecStoreBufferHeapTuple(&scan->rs_ctup, slot,
 									scan->rs_cbuf);
 }
@@ -1486,12 +1484,11 @@ heap_fetch(Relation relation,
 	ItemPointerCopy(tid, &(tuple->t_self));
 	tuple->t_data = (HeapTupleHeader) PageGetItem(page, lp);
 	tuple->t_len = ItemIdGetLength(lp);
-	tuple->t_tableOid = RelationGetRelid(relation);
 
 	/*
 	 * check tuple visibility, then release lock
 	 */
-	valid = HeapTupleSatisfiesVisibility(tuple, snapshot, buffer);
+	valid = HeapTupleSatisfiesVisibility(tuple, RelationGetRelid(relation), snapshot, buffer);
 
 	if (valid)
 		PredicateLockTuple(relation, tuple, snapshot);
@@ -1596,7 +1593,6 @@ heap_hot_search_buffer(ItemPointer tid, Relation relation, Buffer buffer,
 
 		heapTuple->t_data = (HeapTupleHeader) PageGetItem(dp, lp);
 		heapTuple->t_len = ItemIdGetLength(lp);
-		heapTuple->t_tableOid = RelationGetRelid(relation);
 		ItemPointerSetOffsetNumber(&heapTuple->t_self, offnum);
 
 		/*
@@ -1633,7 +1629,7 @@ heap_hot_search_buffer(ItemPointer tid, Relation relation, Buffer buffer,
 			ItemPointerSet(&(heapTuple->t_self), BufferGetBlockNumber(buffer), offnum);
 
 			/* If it's visible per the snapshot, we must return it */
-			valid = HeapTupleSatisfiesVisibility(heapTuple, snapshot, buffer);
+			valid = HeapTupleSatisfiesVisibility(heapTuple, RelationGetRelid(relation), snapshot, buffer);
 			CheckForSerializableConflictOut(valid, relation, heapTuple,
 											buffer, snapshot);
 			/* reset to original, non-redirected, tid */
@@ -1790,7 +1786,6 @@ heap_get_latest_tid(Relation relation,
 		tp.t_self = ctid;
 		tp.t_data = (HeapTupleHeader) PageGetItem(page, lp);
 		tp.t_len = ItemIdGetLength(lp);
-		tp.t_tableOid = RelationGetRelid(relation);
 
 		/*
 		 * After following a t_ctid link, we might arrive at an unrelated
@@ -1807,7 +1802,7 @@ heap_get_latest_tid(Relation relation,
 		 * Check tuple visibility; if visible, set it as the new result
 		 * candidate.
 		 */
-		valid = HeapTupleSatisfiesVisibility(&tp, snapshot, buffer);
+		valid = HeapTupleSatisfiesVisibility(&tp, RelationGetRelid(relation), snapshot, buffer);
 		CheckForSerializableConflictOut(valid, relation, &tp, buffer, snapshot);
 		if (valid)
 			*tid = ctid;
@@ -2160,7 +2155,6 @@ heap_prepare_insert(Relation relation, HeapTuple tup, TransactionId xid,
 
 	HeapTupleHeaderSetCmin(tup->t_data, cid);
 	HeapTupleHeaderSetXmax(tup->t_data, 0); /* for cleanliness */
-	tup->t_tableOid = RelationGetRelid(relation);
 
 	/*
 	 * If the new tuple is too big for storage or contains already toasted
@@ -2218,9 +2212,6 @@ heap_multi_insert(Relation relation, TupleTableSlot **slots, int ntuples,
 	{
 		heaptuples[i] = heap_prepare_insert(relation, ExecFetchSlotHeapTuple(slots[i], true, NULL),
 											xid, cid, options);
-
-		if (slots[i]->tts_tableOid != InvalidOid)
-			heaptuples[i]->t_tableOid = slots[i]->tts_tableOid;
 	}
 
 	/*
@@ -2610,7 +2601,6 @@ heap_delete(Relation relation, ItemPointer tid,
 	lp = PageGetItemId(page, ItemPointerGetOffsetNumber(tid));
 	Assert(ItemIdIsNormal(lp));
 
-	tp.t_tableOid = RelationGetRelid(relation);
 	tp.t_data = (HeapTupleHeader) PageGetItem(page, lp);
 	tp.t_len = ItemIdGetLength(lp);
 	tp.t_self = *tid;
@@ -2727,7 +2717,7 @@ l1:
 	if (crosscheck != InvalidSnapshot && result == HeapTupleMayBeUpdated)
 	{
 		/* Perform additional check for transaction-snapshot mode RI updates */
-		if (!HeapTupleSatisfiesVisibility(&tp, crosscheck, buffer))
+		if (!HeapTupleSatisfiesVisibility(&tp, RelationGetRelid(relation), crosscheck, buffer))
 			result = HeapTupleUpdated;
 	}
 
@@ -3130,14 +3120,10 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup,
 	 * Fill in enough data in oldtup for HeapDetermineModifiedColumns to work
 	 * properly.
 	 */
-	oldtup.t_tableOid = RelationGetRelid(relation);
 	oldtup.t_data = (HeapTupleHeader) PageGetItem(page, lp);
 	oldtup.t_len = ItemIdGetLength(lp);
 	oldtup.t_self = *otid;
 
-	/* the new tuple is ready, except for this: */
-	newtup->t_tableOid = RelationGetRelid(relation);
-
 	/* Determine columns modified by the update. */
 	modified_attrs = HeapDetermineModifiedColumns(relation, interesting_attrs,
 												  &oldtup, newtup);
@@ -3368,7 +3354,7 @@ l2:
 	if (crosscheck != InvalidSnapshot && result == HeapTupleMayBeUpdated)
 	{
 		/* Perform additional check for transaction-snapshot mode RI updates */
-		if (!HeapTupleSatisfiesVisibility(&oldtup, crosscheck, buffer))
+		if (!HeapTupleSatisfiesVisibility(&oldtup, RelationGetRelid(relation), crosscheck, buffer))
 			result = HeapTupleUpdated;
 	}
 
@@ -4122,7 +4108,6 @@ heap_lock_tuple(Relation relation, ItemPointer tid,
 
 	tuple->t_data = (HeapTupleHeader) PageGetItem(page, lp);
 	tuple->t_len = ItemIdGetLength(lp);
-	tuple->t_tableOid = RelationGetRelid(relation);
 	tuple->t_self = *tid;
 
 l3:
@@ -5676,7 +5661,6 @@ heap_abort_speculative(Relation relation, HeapTuple tuple)
 	lp = PageGetItemId(page, ItemPointerGetOffsetNumber(tid));
 	Assert(ItemIdIsNormal(lp));
 
-	tp.t_tableOid = RelationGetRelid(relation);
 	tp.t_data = (HeapTupleHeader) PageGetItem(page, lp);
 	tp.t_len = ItemIdGetLength(lp);
 	tp.t_self = *tid;
@@ -7508,7 +7492,6 @@ log_heap_new_cid(Relation relation, HeapTuple tup)
 	HeapTupleHeader hdr = tup->t_data;
 
 	Assert(ItemPointerIsValid(&tup->t_self));
-	Assert(tup->t_tableOid != InvalidOid);
 
 	xlrec.top_xid = GetTopTransactionId();
 	xlrec.target_node = relation->rd_node;
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 1f6bcf1c51..62c5f9fa9f 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -119,8 +119,6 @@ heapam_heap_insert(Relation relation, TupleTableSlot *slot, CommandId cid,
 
 	/* Update the tuple with table oid */
 	slot->tts_tableOid = RelationGetRelid(relation);
-	if (slot->tts_tableOid != InvalidOid)
-		tuple->t_tableOid = slot->tts_tableOid;
 
 	/* Perform the insertion, and copy the resulting ItemPointer */
 	heap_insert(relation, tuple, cid, options, bistate);
@@ -139,8 +137,6 @@ heapam_heap_insert_speculative(Relation relation, TupleTableSlot *slot, CommandI
 
 	/* Update the tuple with table oid */
 	slot->tts_tableOid = RelationGetRelid(relation);
-	if (slot->tts_tableOid != InvalidOid)
-		tuple->t_tableOid = slot->tts_tableOid;
 
 	HeapTupleHeaderSetSpeculativeToken(tuple->t_data, specToken);
 
@@ -567,7 +563,9 @@ heapam_tuple_satisfies_snapshot(Relation rel, TupleTableSlot *slot, Snapshot sna
 	 * Caller should be holding pin, but not lock.
 	 */
 	LockBuffer(bslot->buffer, BUFFER_LOCK_SHARE);
-	res = HeapTupleSatisfiesVisibility(bslot->base.tuple, snapshot,
+	res = HeapTupleSatisfiesVisibility(bslot->base.tuple,
+									   RelationGetRelid(rel),
+									   snapshot,
 									   bslot->buffer);
 	LockBuffer(bslot->buffer, BUFFER_LOCK_UNLOCK);
 
@@ -733,7 +731,6 @@ heapam_scan_analyze_next_tuple(TableScanDesc sscan, TransactionId OldestXmin, do
 
 		ItemPointerSet(&targtuple->t_self, scan->rs_cblock, scan->rs_cindex);
 
-		targtuple->t_tableOid = RelationGetRelid(scan->rs_scan.rs_rd);
 		targtuple->t_data = (HeapTupleHeader) PageGetItem(targpage, itemid);
 		targtuple->t_len = ItemIdGetLength(itemid);
 
@@ -818,6 +815,7 @@ heapam_scan_analyze_next_tuple(TableScanDesc sscan, TransactionId OldestXmin, do
 		if (sample_it)
 		{
 			ExecStoreBufferHeapTuple(targtuple, slot, scan->rs_cbuf);
+			slot->tts_tableOid = RelationGetRelid(scan->rs_scan.rs_rd);
 			scan->rs_cindex++;
 
 			/* note that we leave the buffer locked here! */
@@ -1478,7 +1476,7 @@ heapam_index_build_range_scan(Relation heapRelation,
 		MemoryContextReset(econtext->ecxt_per_tuple_memory);
 
 		/* Set up for predicate or expression evaluation */
-		ExecStoreHeapTuple(heapTuple, slot, false);
+		ExecStoreHeapTuple(heapTuple, slot, RelationGetRelid(sscan->rs_rd), false);
 
 		/*
 		 * In a partial index, discard tuples that don't satisfy the
@@ -1732,7 +1730,7 @@ heapam_index_validate_scan(Relation heapRelation,
 			MemoryContextReset(econtext->ecxt_per_tuple_memory);
 
 			/* Set up for predicate or expression evaluation */
-			ExecStoreHeapTuple(heapTuple, slot, false);
+			ExecStoreHeapTuple(heapTuple, slot, RelationGetRelid(sscan->rs_rd), false);
 
 			/*
 			 * In a partial index, discard tuples that don't satisfy the
@@ -1885,9 +1883,9 @@ heapam_scan_bitmap_pagescan(TableScanDesc sscan,
 				continue;
 			loctup.t_data = (HeapTupleHeader) PageGetItem((Page) dp, lp);
 			loctup.t_len = ItemIdGetLength(lp);
-			loctup.t_tableOid = scan->rs_scan.rs_rd->rd_id;
 			ItemPointerSet(&loctup.t_self, page, offnum);
-			valid = HeapTupleSatisfiesVisibility(&loctup, snapshot, buffer);
+			valid = HeapTupleSatisfiesVisibility(&loctup, 
+					RelationGetRelid(scan->rs_scan.rs_rd), snapshot, buffer);
 			if (valid)
 			{
 				scan->rs_vistuples[ntup++] = offnum;
@@ -1924,7 +1922,6 @@ heapam_scan_bitmap_pagescan_next(TableScanDesc sscan, TupleTableSlot *slot)
 
 	scan->rs_ctup.t_data = (HeapTupleHeader) PageGetItem((Page) dp, lp);
 	scan->rs_ctup.t_len = ItemIdGetLength(lp);
-	scan->rs_ctup.t_tableOid = scan->rs_scan.rs_rd->rd_id;
 	ItemPointerSet(&scan->rs_ctup.t_self, scan->rs_cblock, targoffset);
 
 	pgstat_count_heap_fetch(scan->rs_scan.rs_rd);
@@ -1936,6 +1933,7 @@ heapam_scan_bitmap_pagescan_next(TableScanDesc sscan, TupleTableSlot *slot)
 	ExecStoreBufferHeapTuple(&scan->rs_ctup,
 							 slot,
 							 scan->rs_cbuf);
+	slot->tts_tableOid = RelationGetRelid(scan->rs_scan.rs_rd);
 
 	scan->rs_cindex++;
 
@@ -1982,8 +1980,10 @@ SampleHeapTupleVisible(HeapScanDesc scan, Buffer buffer,
 	else
 	{
 		/* Otherwise, we have to check the tuple individually. */
-		return HeapTupleSatisfiesVisibility(tuple, scan->rs_scan.rs_snapshot,
-											buffer);
+		return HeapTupleSatisfiesVisibility(tuple, 
+				RelationGetRelid(scan->rs_scan.rs_rd), 
+				scan->rs_scan.rs_snapshot,
+				buffer);
 	}
 }
 
@@ -2132,6 +2132,7 @@ heapam_scan_sample_next_tuple(TableScanDesc sscan, struct SampleScanState *scans
 				LockBuffer(scan->rs_cbuf, BUFFER_LOCK_UNLOCK);
 
 			ExecStoreBufferHeapTuple(tuple, slot, scan->rs_cbuf);
+			slot->tts_tableOid = RelationGetRelid(scan->rs_scan.rs_rd);
 
 			/* Count successfully-fetched tuples as heap fetches */
 			pgstat_count_heap_getnext(scan->rs_scan.rs_rd);
diff --git a/src/backend/access/heap/heapam_visibility.c b/src/backend/access/heap/heapam_visibility.c
index cf9aa5c126..8c298f08e4 100644
--- a/src/backend/access/heap/heapam_visibility.c
+++ b/src/backend/access/heap/heapam_visibility.c
@@ -176,7 +176,6 @@ HeapTupleSatisfiesSelf(HeapTuple htup, Snapshot snapshot, Buffer buffer)
 	HeapTupleHeader tuple = htup->t_data;
 
 	Assert(ItemPointerIsValid(&htup->t_self));
-	Assert(htup->t_tableOid != InvalidOid);
 
 	if (!HeapTupleHeaderXminCommitted(tuple))
 	{
@@ -367,7 +366,6 @@ HeapTupleSatisfiesToast(HeapTuple htup, Snapshot snapshot,
 	HeapTupleHeader tuple = htup->t_data;
 
 	Assert(ItemPointerIsValid(&htup->t_self));
-	Assert(htup->t_tableOid != InvalidOid);
 
 	if (!HeapTupleHeaderXminCommitted(tuple))
 	{
@@ -461,7 +459,6 @@ HeapTupleSatisfiesUpdate(HeapTuple htup, CommandId curcid,
 	HeapTupleHeader tuple = htup->t_data;
 
 	Assert(ItemPointerIsValid(&htup->t_self));
-	Assert(htup->t_tableOid != InvalidOid);
 
 	if (!HeapTupleHeaderXminCommitted(tuple))
 	{
@@ -754,7 +751,6 @@ HeapTupleSatisfiesDirty(HeapTuple htup, Snapshot snapshot,
 	HeapTupleHeader tuple = htup->t_data;
 
 	Assert(ItemPointerIsValid(&htup->t_self));
-	Assert(htup->t_tableOid != InvalidOid);
 
 	snapshot->xmin = snapshot->xmax = InvalidTransactionId;
 	snapshot->speculativeToken = 0;
@@ -978,7 +974,6 @@ HeapTupleSatisfiesMVCC(HeapTuple htup, Snapshot snapshot,
 	HeapTupleHeader tuple = htup->t_data;
 
 	Assert(ItemPointerIsValid(&htup->t_self));
-	Assert(htup->t_tableOid != InvalidOid);
 
 	if (!HeapTupleHeaderXminCommitted(tuple))
 	{
@@ -1179,7 +1174,6 @@ HeapTupleSatisfiesVacuum(HeapTuple htup, TransactionId OldestXmin,
 	HeapTupleHeader tuple = htup->t_data;
 
 	Assert(ItemPointerIsValid(&htup->t_self));
-	Assert(htup->t_tableOid != InvalidOid);
 
 	/*
 	 * Has inserting transaction committed?
@@ -1434,7 +1428,6 @@ HeapTupleIsSurelyDead(HeapTuple htup, TransactionId OldestXmin)
 	HeapTupleHeader tuple = htup->t_data;
 
 	Assert(ItemPointerIsValid(&htup->t_self));
-	Assert(htup->t_tableOid != InvalidOid);
 
 	/*
 	 * If the inserting transaction is marked invalid, then it aborted, and
@@ -1550,7 +1543,7 @@ TransactionIdInArray(TransactionId xid, TransactionId *xip, Size num)
  * complicated than when dealing "only" with the present.
  */
 static bool
-HeapTupleSatisfiesHistoricMVCC(HeapTuple htup, Snapshot snapshot,
+HeapTupleSatisfiesHistoricMVCC(HeapTuple htup, Oid relid, Snapshot snapshot,
 							   Buffer buffer)
 {
 	HeapTupleHeader tuple = htup->t_data;
@@ -1558,7 +1551,6 @@ HeapTupleSatisfiesHistoricMVCC(HeapTuple htup, Snapshot snapshot,
 	TransactionId xmax = HeapTupleHeaderGetRawXmax(tuple);
 
 	Assert(ItemPointerIsValid(&htup->t_self));
-	Assert(htup->t_tableOid != InvalidOid);
 
 	/* inserting transaction aborted */
 	if (HeapTupleHeaderXminInvalid(tuple))
@@ -1579,7 +1571,7 @@ HeapTupleSatisfiesHistoricMVCC(HeapTuple htup, Snapshot snapshot,
 		 * values externally.
 		 */
 		resolved = ResolveCminCmaxDuringDecoding(HistoricSnapshotGetTupleCids(), snapshot,
-												 htup, buffer,
+												 htup, relid, buffer,
 												 &cmin, &cmax);
 
 		if (!resolved)
@@ -1650,7 +1642,7 @@ HeapTupleSatisfiesHistoricMVCC(HeapTuple htup, Snapshot snapshot,
 
 		/* Lookup actual cmin/cmax values */
 		resolved = ResolveCminCmaxDuringDecoding(HistoricSnapshotGetTupleCids(), snapshot,
-												 htup, buffer,
+												 htup, relid, buffer,
 												 &cmin, &cmax);
 
 		if (!resolved)
@@ -1698,8 +1690,10 @@ HeapTupleSatisfiesHistoricMVCC(HeapTuple htup, Snapshot snapshot,
  *	if so, the indicated buffer is marked dirty.
  */
 bool
-HeapTupleSatisfiesVisibility(HeapTuple tup, Snapshot snapshot, Buffer buffer)
+HeapTupleSatisfiesVisibility(HeapTuple tup, Oid relid, Snapshot snapshot, Buffer buffer)
 {
+	Assert(relid != InvalidOid);
+	
 	switch (snapshot->snapshot_type)
 	{
 		case SNAPSHOT_MVCC:
@@ -1718,7 +1712,7 @@ HeapTupleSatisfiesVisibility(HeapTuple tup, Snapshot snapshot, Buffer buffer)
 			return HeapTupleSatisfiesDirty(tup, snapshot, buffer);
 			break;
 		case SNAPSHOT_HISTORIC_MVCC:
-			return HeapTupleSatisfiesHistoricMVCC(tup, snapshot, buffer);
+			return HeapTupleSatisfiesHistoricMVCC(tup, relid, snapshot, buffer);
 			break;
 		case SNAPSHOT_NON_VACUUMABLE:
 			return HeapTupleSatisfiesNonVacuumable(tup, snapshot, buffer);
diff --git a/src/backend/access/heap/pruneheap.c b/src/backend/access/heap/pruneheap.c
index a3e51922d8..e09a9d7340 100644
--- a/src/backend/access/heap/pruneheap.c
+++ b/src/backend/access/heap/pruneheap.c
@@ -366,8 +366,6 @@ heap_prune_chain(Relation relation, Buffer buffer, OffsetNumber rootoffnum,
 				i;
 	HeapTupleData tup;
 
-	tup.t_tableOid = RelationGetRelid(relation);
-
 	rootlp = PageGetItemId(dp, rootoffnum);
 
 	/*
diff --git a/src/backend/access/heap/tuptoaster.c b/src/backend/access/heap/tuptoaster.c
index 7ea964c493..257ae9761b 100644
--- a/src/backend/access/heap/tuptoaster.c
+++ b/src/backend/access/heap/tuptoaster.c
@@ -1022,7 +1022,6 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup,
 		result_tuple = (HeapTuple) palloc0(HEAPTUPLESIZE + new_tuple_len);
 		result_tuple->t_len = new_tuple_len;
 		result_tuple->t_self = newtup->t_self;
-		result_tuple->t_tableOid = newtup->t_tableOid;
 		new_data = (HeapTupleHeader) ((char *) result_tuple + HEAPTUPLESIZE);
 		result_tuple->t_data = new_data;
 
@@ -1123,7 +1122,6 @@ toast_flatten_tuple(HeapTuple tup, TupleDesc tupleDesc)
 	 * a syscache entry.
 	 */
 	new_tuple->t_self = tup->t_self;
-	new_tuple->t_tableOid = tup->t_tableOid;
 
 	new_tuple->t_data->t_choice = tup->t_data->t_choice;
 	new_tuple->t_data->t_ctid = tup->t_data->t_ctid;
@@ -1194,7 +1192,6 @@ toast_flatten_tuple_to_datum(HeapTupleHeader tup,
 	/* Build a temporary HeapTuple control structure */
 	tmptup.t_len = tup_len;
 	ItemPointerSetInvalid(&(tmptup.t_self));
-	tmptup.t_tableOid = InvalidOid;
 	tmptup.t_data = tup;
 
 	/*
diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c
index 85680ab6db..860ea42cba 100644
--- a/src/backend/access/heap/vacuumlazy.c
+++ b/src/backend/access/heap/vacuumlazy.c
@@ -1003,7 +1003,6 @@ lazy_scan_heap(Relation onerel, int options, LVRelStats *vacrelstats,
 
 			tuple.t_data = (HeapTupleHeader) PageGetItem(page, itemid);
 			tuple.t_len = ItemIdGetLength(itemid);
-			tuple.t_tableOid = RelationGetRelid(onerel);
 
 			tupgone = false;
 
@@ -2236,7 +2235,6 @@ heap_page_is_all_visible(Relation rel, Buffer buf,
 
 		tuple.t_data = (HeapTupleHeader) PageGetItem(page, itemid);
 		tuple.t_len = ItemIdGetLength(itemid);
-		tuple.t_tableOid = RelationGetRelid(rel);
 
 		switch (HeapTupleSatisfiesVacuum(&tuple, OldestXmin, buf))
 		{
diff --git a/src/backend/access/index/genam.c b/src/backend/access/index/genam.c
index f4a527b126..250c746971 100644
--- a/src/backend/access/index/genam.c
+++ b/src/backend/access/index/genam.c
@@ -510,7 +510,6 @@ systable_recheck_tuple(SysScanDesc sysscan, HeapTuple tup)
 	result = table_tuple_satisfies_snapshot(sysscan->heap_rel,
 											sysscan->slot,
 											freshsnap);
-
 	return result;
 }
 
diff --git a/src/backend/catalog/indexing.c b/src/backend/catalog/indexing.c
index 0c994122d8..7d443f8fe7 100644
--- a/src/backend/catalog/indexing.c
+++ b/src/backend/catalog/indexing.c
@@ -99,7 +99,7 @@ CatalogIndexInsert(CatalogIndexState indstate, HeapTuple heapTuple)
 	/* Need a slot to hold the tuple being examined */
 	slot = MakeSingleTupleTableSlot(RelationGetDescr(heapRelation),
 									&TTSOpsHeapTuple);
-	ExecStoreHeapTuple(heapTuple, slot, false);
+	ExecStoreHeapTuple(heapTuple, slot, RelationGetRelid(heapRelation), false);
 
 	/*
 	 * for each index, form and insert the index tuple
diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c
index fb4384d556..a71d7b658e 100644
--- a/src/backend/commands/analyze.c
+++ b/src/backend/commands/analyze.c
@@ -760,7 +760,7 @@ compute_index_stats(Relation onerel, double totalrows,
 			ResetExprContext(econtext);
 
 			/* Set up for predicate or expression evaluation */
-			ExecStoreHeapTuple(heapTuple, slot, false);
+			ExecStoreHeapTuple(heapTuple, slot, RelationGetRelid(onerel), false);
 
 			/* If index is partial, check predicate */
 			if (predicate != NULL)
diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c
index eae2b09830..734b5165dd 100644
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -2359,10 +2359,9 @@ ExecuteCallStmt(CallStmt *stmt, ParamListInfo params, bool atomic, DestReceiver
 
 		rettupdata.t_len = HeapTupleHeaderGetDatumLength(td);
 		ItemPointerSetInvalid(&(rettupdata.t_self));
-		rettupdata.t_tableOid = InvalidOid;
 		rettupdata.t_data = td;
 
-		slot = ExecStoreHeapTuple(&rettupdata, tstate->slot, false);
+		slot = ExecStoreHeapTuple(&rettupdata, tstate->slot, InvalidOid, false);
 		tstate->dest->receiveSlot(slot, tstate->dest);
 
 		end_tup_output(tstate);
diff --git a/src/backend/commands/schemacmds.c b/src/backend/commands/schemacmds.c
index 6cf94a3140..4492ae2b0e 100644
--- a/src/backend/commands/schemacmds.c
+++ b/src/backend/commands/schemacmds.c
@@ -355,7 +355,6 @@ AlterSchemaOwner_internal(HeapTuple tup, Relation rel, Oid newOwnerId)
 {
 	Form_pg_namespace nspForm;
 
-	Assert(tup->t_tableOid == NamespaceRelationId);
 	Assert(RelationGetRelid(rel) == NamespaceRelationId);
 
 	nspForm = (Form_pg_namespace) GETSTRUCT(tup);
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index ced31bf552..ddc804af29 100644
--- a/src/backend/commands/trigger.c
+++ b/src/backend/commands/trigger.c
@@ -2570,7 +2570,7 @@ ExecBRInsertTriggers(EState *estate, ResultRelInfo *relinfo,
 		}
 		if (newtuple != oldtuple)
 		{
-			ExecForceStoreHeapTuple(newtuple, slot);
+			ExecForceStoreHeapTuple(newtuple, slot, RelationGetRelid(relinfo->ri_RelationDesc));
 			newtuple = ExecFetchSlotHeapTuple(slot, true, NULL);
 		}
 	}
@@ -2647,7 +2647,8 @@ ExecIRInsertTriggers(EState *estate, ResultRelInfo *relinfo,
 		}
 		if (oldtuple != newtuple)
 		{
-			ExecForceStoreHeapTuple(newtuple, LocTriggerData.tg_trigslot);
+			ExecForceStoreHeapTuple(newtuple, LocTriggerData.tg_trigslot,
+									RelationGetRelid(relinfo->ri_RelationDesc));
 			newtuple = ExecFetchSlotHeapTuple(slot, true, NULL);
 		}
 	}
@@ -2770,7 +2771,7 @@ ExecBRDeleteTriggers(EState *estate, EPQState *epqstate,
 	else
 	{
 		trigtuple = fdw_trigtuple;
-		ExecForceStoreHeapTuple(trigtuple, slot);
+		ExecForceStoreHeapTuple(trigtuple, slot, RelationGetRelid(relinfo->ri_RelationDesc));
 	}
 
 	LocTriggerData.type = T_TriggerData;
@@ -2846,7 +2847,7 @@ ExecARDeleteTriggers(EState *estate, ResultRelInfo *relinfo,
 		}
 		else
 		{
-			ExecForceStoreHeapTuple(fdw_trigtuple, slot);
+			ExecForceStoreHeapTuple(fdw_trigtuple, slot, RelationGetRelid(relinfo->ri_RelationDesc));
 		}
 
 		AfterTriggerSaveEvent(estate, relinfo, TRIGGER_EVENT_DELETE,
@@ -2876,7 +2877,7 @@ ExecIRDeleteTriggers(EState *estate, ResultRelInfo *relinfo,
 	LocTriggerData.tg_oldtable = NULL;
 	LocTriggerData.tg_newtable = NULL;
 
-	ExecForceStoreHeapTuple(trigtuple, slot);
+	ExecForceStoreHeapTuple(trigtuple, slot, RelationGetRelid(relinfo->ri_RelationDesc));
 
 	for (i = 0; i < trigdesc->numtriggers; i++)
 	{
@@ -3036,7 +3037,7 @@ ExecBRUpdateTriggers(EState *estate, EPQState *epqstate,
 	}
 	else
 	{
-		ExecForceStoreHeapTuple(fdw_trigtuple, oldslot);
+		ExecForceStoreHeapTuple(fdw_trigtuple, oldslot, RelationGetRelid(relinfo->ri_RelationDesc));
 		trigtuple = fdw_trigtuple;
 	}
 
@@ -3082,7 +3083,7 @@ ExecBRUpdateTriggers(EState *estate, EPQState *epqstate,
 		}
 
 		if (newtuple != oldtuple)
-			ExecForceStoreHeapTuple(newtuple, newslot);
+			ExecForceStoreHeapTuple(newtuple, newslot, RelationGetRelid(relinfo->ri_RelationDesc));
 	}
 	if (false && trigtuple != fdw_trigtuple && trigtuple != newtuple)
 		heap_freetuple(trigtuple);
@@ -3124,7 +3125,7 @@ ExecARUpdateTriggers(EState *estate, ResultRelInfo *relinfo,
 							   NULL,
 							   NULL);
 		else if (fdw_trigtuple != NULL)
-			ExecForceStoreHeapTuple(fdw_trigtuple, oldslot);
+			ExecForceStoreHeapTuple(fdw_trigtuple, oldslot, RelationGetRelid(relinfo->ri_RelationDesc));
 
 		AfterTriggerSaveEvent(estate, relinfo, TRIGGER_EVENT_UPDATE,
 							  true, oldslot, newslot, recheckIndexes,
@@ -3153,7 +3154,7 @@ ExecIRUpdateTriggers(EState *estate, ResultRelInfo *relinfo,
 	LocTriggerData.tg_oldtable = NULL;
 	LocTriggerData.tg_newtable = NULL;
 
-	ExecForceStoreHeapTuple(trigtuple, oldslot);
+	ExecForceStoreHeapTuple(trigtuple, oldslot, RelationGetRelid(relinfo->ri_RelationDesc));
 
 	for (i = 0; i < trigdesc->numtriggers; i++)
 	{
@@ -3185,7 +3186,7 @@ ExecIRUpdateTriggers(EState *estate, ResultRelInfo *relinfo,
 			return false;		/* "do nothing" */
 
 		if (oldtuple != newtuple)
-			ExecForceStoreHeapTuple(newtuple, newslot);
+			ExecForceStoreHeapTuple(newtuple, newslot, RelationGetRelid(relinfo->ri_RelationDesc));
 	}
 
 	return true;
diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c
index d793efdd9c..928052b1ae 100644
--- a/src/backend/executor/execExprInterp.c
+++ b/src/backend/executor/execExprInterp.c
@@ -3003,7 +3003,6 @@ ExecEvalFieldStoreDeForm(ExprState *state, ExprEvalStep *op, ExprContext *econte
 		tuphdr = DatumGetHeapTupleHeader(tupDatum);
 		tmptup.t_len = HeapTupleHeaderGetDatumLength(tuphdr);
 		ItemPointerSetInvalid(&(tmptup.t_self));
-		tmptup.t_tableOid = InvalidOid;
 		tmptup.t_data = tuphdr;
 
 		heap_deform_tuple(&tmptup, tupDesc,
diff --git a/src/backend/executor/execTuples.c b/src/backend/executor/execTuples.c
index 9afea31e6a..7c48d50784 100644
--- a/src/backend/executor/execTuples.c
+++ b/src/backend/executor/execTuples.c
@@ -387,7 +387,7 @@ tts_heap_copyslot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)
 	tuple = ExecCopySlotHeapTuple(srcslot);
 	MemoryContextSwitchTo(oldcontext);
 
-	ExecStoreHeapTuple(tuple, dstslot, true);
+	ExecStoreHeapTuple(tuple, dstslot, srcslot->tts_tableOid, true);
 }
 
 static HeapTuple
@@ -1117,6 +1117,7 @@ MakeTupleTableSlot(TupleDesc tupleDesc,
 	slot->tts_tupleDescriptor = tupleDesc;
 	slot->tts_mcxt = CurrentMemoryContext;
 	slot->tts_nvalid = 0;
+	slot->tts_tableOid = InvalidOid;
 
 	if (tupleDesc != NULL)
 	{
@@ -1329,6 +1330,7 @@ ExecSetSlotDescriptor(TupleTableSlot *slot, /* slot to change */
 TupleTableSlot *
 ExecStoreHeapTuple(HeapTuple tuple,
 				   TupleTableSlot *slot,
+				   Oid relid,
 				   bool shouldFree)
 {
 	/*
@@ -1342,7 +1344,7 @@ ExecStoreHeapTuple(HeapTuple tuple,
 		elog(ERROR, "trying to store a heap tuple into wrong type of slot");
 	tts_heap_store_tuple(slot, tuple, shouldFree);
 
-	slot->tts_tableOid = tuple->t_tableOid;
+	slot->tts_tableOid = relid;
 
 	return slot;
 }
@@ -1364,6 +1366,8 @@ ExecStoreHeapTuple(HeapTuple tuple,
  *
  * If the target slot is not guaranteed to be TTSOpsBufferHeapTuple type slot,
  * use the, more expensive, ExecForceStoreHeapTuple().
+ *
+ * NOTE: Don't set the tts_tableOid from tuple t_tableOid.
  * --------------------------------
  */
 TupleTableSlot *
@@ -1383,8 +1387,6 @@ ExecStoreBufferHeapTuple(HeapTuple tuple,
 		elog(ERROR, "trying to store an on-disk heap tuple into wrong type of slot");
 	tts_buffer_heap_store_tuple(slot, tuple, buffer, false);
 
-	slot->tts_tableOid = tuple->t_tableOid;
-
 	return slot;
 }
 
@@ -1409,8 +1411,6 @@ ExecStorePinnedBufferHeapTuple(HeapTuple tuple,
 		elog(ERROR, "trying to store an on-disk heap tuple into wrong type of slot");
 	tts_buffer_heap_store_tuple(slot, tuple, buffer, true);
 
-	slot->tts_tableOid = tuple->t_tableOid;
-
 	return slot;
 }
 
@@ -1445,11 +1445,12 @@ ExecStoreMinimalTuple(MinimalTuple mtup,
  */
 void
 ExecForceStoreHeapTuple(HeapTuple tuple,
-						TupleTableSlot *slot)
+						TupleTableSlot *slot,
+						Oid relid)
 {
 	if (TTS_IS_HEAPTUPLE(slot))
 	{
-		ExecStoreHeapTuple(tuple, slot, false);
+		ExecStoreHeapTuple(tuple, slot, relid, false);
 	}
 	else if (TTS_IS_BUFFERTUPLE(slot))
 	{
@@ -1462,6 +1463,7 @@ ExecForceStoreHeapTuple(HeapTuple tuple,
 		oldContext = MemoryContextSwitchTo(slot->tts_mcxt);
 		bslot->base.tuple = heap_copytuple(tuple);
 		MemoryContextSwitchTo(oldContext);
+		slot->tts_tableOid = relid;
 	}
 	else
 	{
@@ -1469,6 +1471,7 @@ ExecForceStoreHeapTuple(HeapTuple tuple,
 		heap_deform_tuple(tuple, slot->tts_tupleDescriptor,
 						  slot->tts_values, slot->tts_isnull);
 		ExecStoreVirtualTuple(slot);
+		slot->tts_tableOid = relid;
 	}
 }
 
@@ -1602,6 +1605,8 @@ ExecStoreAllNullTuple(TupleTableSlot *slot)
 HeapTuple
 ExecFetchSlotHeapTuple(TupleTableSlot *slot, bool materialize, bool *shouldFree)
 {
+	HeapTuple htup;
+
 	/*
 	 * sanity checks
 	 */
@@ -1616,14 +1621,18 @@ ExecFetchSlotHeapTuple(TupleTableSlot *slot, bool materialize, bool *shouldFree)
 	{
 		if (shouldFree)
 			*shouldFree = true;
-		return slot->tts_ops->copy_heap_tuple(slot);
+		htup = slot->tts_ops->copy_heap_tuple(slot);
 	}
 	else
 	{
 		if (shouldFree)
 			*shouldFree = false;
-		return slot->tts_ops->get_heap_tuple(slot);
+		htup = slot->tts_ops->get_heap_tuple(slot);
 	}
+
+	htup->t_tableOid = slot->tts_tableOid;
+
+	return htup;
 }
 
 /* --------------------------------
diff --git a/src/backend/executor/execUtils.c b/src/backend/executor/execUtils.c
index 60928d3f80..b0bccb78ae 100644
--- a/src/backend/executor/execUtils.c
+++ b/src/backend/executor/execUtils.c
@@ -1011,7 +1011,6 @@ GetAttributeByName(HeapTupleHeader tuple, const char *attname, bool *isNull)
 	 */
 	tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple);
 	ItemPointerSetInvalid(&(tmptup.t_self));
-	tmptup.t_tableOid = InvalidOid;
 	tmptup.t_data = tuple;
 
 	result = heap_getattr(&tmptup,
@@ -1059,7 +1058,6 @@ GetAttributeByNum(HeapTupleHeader tuple,
 	 */
 	tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple);
 	ItemPointerSetInvalid(&(tmptup.t_self));
-	tmptup.t_tableOid = InvalidOid;
 	tmptup.t_data = tuple;
 
 	result = heap_getattr(&tmptup,
diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c
index 508c919574..36d86bfdae 100644
--- a/src/backend/executor/nodeAgg.c
+++ b/src/backend/executor/nodeAgg.c
@@ -1801,7 +1801,8 @@ agg_retrieve_direct(AggState *aggstate)
 				 * cleared from the slot.
 				 */
 				ExecForceStoreHeapTuple(aggstate->grp_firstTuple,
-								   firstSlot);
+								   firstSlot,
+								   InvalidOid);
 				aggstate->grp_firstTuple = NULL;	/* don't keep two pointers */
 
 				/* set up for first advance_aggregates call */
diff --git a/src/backend/executor/nodeGather.c b/src/backend/executor/nodeGather.c
index 70a4e90a05..37bce93cc3 100644
--- a/src/backend/executor/nodeGather.c
+++ b/src/backend/executor/nodeGather.c
@@ -280,6 +280,7 @@ gather_getnext(GatherState *gatherstate)
 			{
 				ExecStoreHeapTuple(tup, /* tuple to store */
 								   fslot,	/* slot to store the tuple */
+								   InvalidOid,
 								   true);	/* pfree tuple when done with it */
 				return fslot;
 			}
diff --git a/src/backend/executor/nodeGatherMerge.c b/src/backend/executor/nodeGatherMerge.c
index 8635865d1e..827578ca8d 100644
--- a/src/backend/executor/nodeGatherMerge.c
+++ b/src/backend/executor/nodeGatherMerge.c
@@ -703,6 +703,7 @@ gather_merge_readnext(GatherMergeState *gm_state, int reader, bool nowait)
 	ExecStoreHeapTuple(tup,			/* tuple to store */
 					   gm_state->gm_slots[reader],	/* slot in which to store
 													 * the tuple */
+					   InvalidOid,
 					   true);		/* pfree tuple when done with it */
 
 	return true;
diff --git a/src/backend/executor/nodeIndexonlyscan.c b/src/backend/executor/nodeIndexonlyscan.c
index 08527d527c..ab3e3a6c60 100644
--- a/src/backend/executor/nodeIndexonlyscan.c
+++ b/src/backend/executor/nodeIndexonlyscan.c
@@ -206,8 +206,8 @@ IndexOnlyNext(IndexOnlyScanState *node)
 			 */
 			Assert(slot->tts_tupleDescriptor->natts ==
 				   scandesc->xs_hitupdesc->natts);
-			ExecForceStoreHeapTuple(scandesc->xs_hitup, slot);
-			slot->tts_tableOid = RelationGetRelid(scandesc->heapRelation);
+			ExecForceStoreHeapTuple(scandesc->xs_hitup, slot,
+					RelationGetRelid(scandesc->heapRelation));
 		}
 		else if (scandesc->xs_itup)
 			StoreIndexTuple(slot, scandesc->xs_itup, scandesc->xs_itupdesc);
diff --git a/src/backend/executor/nodeIndexscan.c b/src/backend/executor/nodeIndexscan.c
index b8580a896a..6e26d16f35 100644
--- a/src/backend/executor/nodeIndexscan.c
+++ b/src/backend/executor/nodeIndexscan.c
@@ -247,8 +247,7 @@ IndexNextWithReorder(IndexScanState *node)
 				tuple = reorderqueue_pop(node);
 
 				/* Pass 'true', as the tuple in the queue is a palloc'd copy */
-				slot->tts_tableOid = RelationGetRelid(scandesc->heapRelation);
-				ExecStoreHeapTuple(tuple, slot, true);
+				ExecStoreHeapTuple(tuple, slot, RelationGetRelid(scandesc->heapRelation), true);
 				return slot;
 			}
 		}
diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c
index 20e77db4a8..6440c4ed69 100644
--- a/src/backend/executor/nodeModifyTable.c
+++ b/src/backend/executor/nodeModifyTable.c
@@ -847,7 +847,7 @@ ldelete:;
 			slot = ExecTriggerGetReturnSlot(estate, resultRelInfo);
 			if (oldtuple != NULL)
 			{
-				ExecForceStoreHeapTuple(oldtuple, slot);
+				ExecForceStoreHeapTuple(oldtuple, slot, RelationGetRelid(resultRelationDesc));
 			}
 			else
 			{
@@ -2036,10 +2036,6 @@ ExecModifyTable(PlanState *pstate)
 					oldtupdata.t_len =
 						HeapTupleHeaderGetDatumLength(oldtupdata.t_data);
 					ItemPointerSetInvalid(&(oldtupdata.t_self));
-					/* Historically, view triggers see invalid t_tableOid. */
-					oldtupdata.t_tableOid =
-						(relkind == RELKIND_VIEW) ? InvalidOid :
-						RelationGetRelid(resultRelInfo->ri_RelationDesc);
 
 					oldtuple = &oldtupdata;
 				}
diff --git a/src/backend/executor/nodeSetOp.c b/src/backend/executor/nodeSetOp.c
index 5d8c8b8b02..1c063f6a7b 100644
--- a/src/backend/executor/nodeSetOp.c
+++ b/src/backend/executor/nodeSetOp.c
@@ -269,6 +269,7 @@ setop_retrieve_direct(SetOpState *setopstate)
 		 */
 		ExecStoreHeapTuple(setopstate->grp_firstTuple,
 						   resultTupleSlot,
+						   InvalidOid,
 						   true);
 		setopstate->grp_firstTuple = NULL;	/* don't keep two pointers */
 
diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c
index 94a53e0e3f..0fb406c64f 100644
--- a/src/backend/executor/spi.c
+++ b/src/backend/executor/spi.c
@@ -870,7 +870,6 @@ SPI_modifytuple(Relation rel, HeapTuple tuple, int natts, int *attnum,
 		 */
 		mtuple->t_data->t_ctid = tuple->t_data->t_ctid;
 		mtuple->t_self = tuple->t_self;
-		mtuple->t_tableOid = tuple->t_tableOid;
 	}
 	else
 	{
diff --git a/src/backend/executor/tqueue.c b/src/backend/executor/tqueue.c
index 6e2eaa5dcf..3ebf1e347e 100644
--- a/src/backend/executor/tqueue.c
+++ b/src/backend/executor/tqueue.c
@@ -208,7 +208,6 @@ TupleQueueReaderNext(TupleQueueReader *reader, bool nowait, bool *done)
 	 * (which had better be sufficiently aligned).
 	 */
 	ItemPointerSetInvalid(&htup.t_self);
-	htup.t_tableOid = InvalidOid;
 	htup.t_len = nbytes;
 	htup.t_data = data;
 
diff --git a/src/backend/replication/logical/decode.c b/src/backend/replication/logical/decode.c
index eec3a22842..f26dac0f70 100644
--- a/src/backend/replication/logical/decode.c
+++ b/src/backend/replication/logical/decode.c
@@ -940,12 +940,6 @@ DecodeMultiInsert(LogicalDecodingContext *ctx, XLogRecordBuffer *buf)
 			/* not a disk based tuple */
 			ItemPointerSetInvalid(&tuple->tuple.t_self);
 
-			/*
-			 * We can only figure this out after reassembling the
-			 * transactions.
-			 */
-			tuple->tuple.t_tableOid = InvalidOid;
-
 			tuple->tuple.t_len = datalen + SizeofHeapTupleHeader;
 
 			memset(header, 0, SizeofHeapTupleHeader);
@@ -1033,9 +1027,6 @@ DecodeXLogTuple(char *data, Size len, ReorderBufferTupleBuf *tuple)
 	/* not a disk based tuple */
 	ItemPointerSetInvalid(&tuple->tuple.t_self);
 
-	/* we can only figure this out after reassembling the transactions */
-	tuple->tuple.t_tableOid = InvalidOid;
-
 	/* data is not stored aligned, copy to aligned storage */
 	memcpy((char *) &xlhdr,
 		   data,
diff --git a/src/backend/replication/logical/reorderbuffer.c b/src/backend/replication/logical/reorderbuffer.c
index a49e226967..a2a3c4760e 100644
--- a/src/backend/replication/logical/reorderbuffer.c
+++ b/src/backend/replication/logical/reorderbuffer.c
@@ -3482,7 +3482,7 @@ UpdateLogicalMappings(HTAB *tuplecid_data, Oid relid, Snapshot snapshot)
 bool
 ResolveCminCmaxDuringDecoding(HTAB *tuplecid_data,
 							  Snapshot snapshot,
-							  HeapTuple htup, Buffer buffer,
+							  HeapTuple htup, Oid relid, Buffer buffer,
 							  CommandId *cmin, CommandId *cmax)
 {
 	ReorderBufferTupleCidKey key;
@@ -3524,7 +3524,7 @@ restart:
 	 */
 	if (ent == NULL && !updated_mapping)
 	{
-		UpdateLogicalMappings(tuplecid_data, htup->t_tableOid, snapshot);
+		UpdateLogicalMappings(tuplecid_data, relid, snapshot);
 		/* now check but don't update for a mapping again */
 		updated_mapping = true;
 		goto restart;
diff --git a/src/backend/utils/adt/expandedrecord.c b/src/backend/utils/adt/expandedrecord.c
index 9971abd71f..a49cf9b467 100644
--- a/src/backend/utils/adt/expandedrecord.c
+++ b/src/backend/utils/adt/expandedrecord.c
@@ -610,7 +610,6 @@ make_expanded_record_from_datum(Datum recorddatum, MemoryContext parentcontext)
 
 	tmptup.t_len = HeapTupleHeaderGetDatumLength(tuphdr);
 	ItemPointerSetInvalid(&(tmptup.t_self));
-	tmptup.t_tableOid = InvalidOid;
 	tmptup.t_data = tuphdr;
 
 	oldcxt = MemoryContextSwitchTo(objcxt);
diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c
index dd88c09e6d..314777909d 100644
--- a/src/backend/utils/adt/jsonfuncs.c
+++ b/src/backend/utils/adt/jsonfuncs.c
@@ -3147,7 +3147,6 @@ populate_record(TupleDesc tupdesc,
 		/* Build a temporary HeapTuple control structure */
 		tuple.t_len = HeapTupleHeaderGetDatumLength(defaultval);
 		ItemPointerSetInvalid(&(tuple.t_self));
-		tuple.t_tableOid = InvalidOid;
 		tuple.t_data = defaultval;
 
 		/* Break down the tuple into fields */
@@ -3546,7 +3545,6 @@ populate_recordset_record(PopulateRecordsetState *state, JsObject *obj)
 	/* ok, save into tuplestore */
 	tuple.t_len = HeapTupleHeaderGetDatumLength(tuphead);
 	ItemPointerSetInvalid(&(tuple.t_self));
-	tuple.t_tableOid = InvalidOid;
 	tuple.t_data = tuphead;
 
 	tuplestore_puttuple(state->tuple_store, &tuple);
diff --git a/src/backend/utils/adt/rowtypes.c b/src/backend/utils/adt/rowtypes.c
index 0467f97dc3..2fd3f49e7e 100644
--- a/src/backend/utils/adt/rowtypes.c
+++ b/src/backend/utils/adt/rowtypes.c
@@ -324,7 +324,6 @@ record_out(PG_FUNCTION_ARGS)
 	/* Build a temporary HeapTuple control structure */
 	tuple.t_len = HeapTupleHeaderGetDatumLength(rec);
 	ItemPointerSetInvalid(&(tuple.t_self));
-	tuple.t_tableOid = InvalidOid;
 	tuple.t_data = rec;
 
 	/*
@@ -671,7 +670,6 @@ record_send(PG_FUNCTION_ARGS)
 	/* Build a temporary HeapTuple control structure */
 	tuple.t_len = HeapTupleHeaderGetDatumLength(rec);
 	ItemPointerSetInvalid(&(tuple.t_self));
-	tuple.t_tableOid = InvalidOid;
 	tuple.t_data = rec;
 
 	/*
@@ -821,11 +819,9 @@ record_cmp(FunctionCallInfo fcinfo)
 	/* Build temporary HeapTuple control structures */
 	tuple1.t_len = HeapTupleHeaderGetDatumLength(record1);
 	ItemPointerSetInvalid(&(tuple1.t_self));
-	tuple1.t_tableOid = InvalidOid;
 	tuple1.t_data = record1;
 	tuple2.t_len = HeapTupleHeaderGetDatumLength(record2);
 	ItemPointerSetInvalid(&(tuple2.t_self));
-	tuple2.t_tableOid = InvalidOid;
 	tuple2.t_data = record2;
 
 	/*
@@ -1063,11 +1059,9 @@ record_eq(PG_FUNCTION_ARGS)
 	/* Build temporary HeapTuple control structures */
 	tuple1.t_len = HeapTupleHeaderGetDatumLength(record1);
 	ItemPointerSetInvalid(&(tuple1.t_self));
-	tuple1.t_tableOid = InvalidOid;
 	tuple1.t_data = record1;
 	tuple2.t_len = HeapTupleHeaderGetDatumLength(record2);
 	ItemPointerSetInvalid(&(tuple2.t_self));
-	tuple2.t_tableOid = InvalidOid;
 	tuple2.t_data = record2;
 
 	/*
@@ -1326,11 +1320,9 @@ record_image_cmp(FunctionCallInfo fcinfo)
 	/* Build temporary HeapTuple control structures */
 	tuple1.t_len = HeapTupleHeaderGetDatumLength(record1);
 	ItemPointerSetInvalid(&(tuple1.t_self));
-	tuple1.t_tableOid = InvalidOid;
 	tuple1.t_data = record1;
 	tuple2.t_len = HeapTupleHeaderGetDatumLength(record2);
 	ItemPointerSetInvalid(&(tuple2.t_self));
-	tuple2.t_tableOid = InvalidOid;
 	tuple2.t_data = record2;
 
 	/*
@@ -1570,11 +1562,9 @@ record_image_eq(PG_FUNCTION_ARGS)
 	/* Build temporary HeapTuple control structures */
 	tuple1.t_len = HeapTupleHeaderGetDatumLength(record1);
 	ItemPointerSetInvalid(&(tuple1.t_self));
-	tuple1.t_tableOid = InvalidOid;
 	tuple1.t_data = record1;
 	tuple2.t_len = HeapTupleHeaderGetDatumLength(record2);
 	ItemPointerSetInvalid(&(tuple2.t_self));
-	tuple2.t_tableOid = InvalidOid;
 	tuple2.t_data = record2;
 
 	/*
diff --git a/src/backend/utils/cache/catcache.c b/src/backend/utils/cache/catcache.c
index 258a1d64cc..3e165af707 100644
--- a/src/backend/utils/cache/catcache.c
+++ b/src/backend/utils/cache/catcache.c
@@ -1846,7 +1846,6 @@ CatalogCacheCreateEntry(CatCache *cache, HeapTuple ntp, Datum *arguments,
 								MAXIMUM_ALIGNOF + dtp->t_len);
 		ct->tuple.t_len = dtp->t_len;
 		ct->tuple.t_self = dtp->t_self;
-		ct->tuple.t_tableOid = dtp->t_tableOid;
 		ct->tuple.t_data = (HeapTupleHeader)
 			MAXALIGN(((char *) ct) + sizeof(CatCTup));
 		/* copy tuple contents */
diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index 60b96df8f9..a3ed15214a 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -3792,11 +3792,11 @@ comparetup_cluster(const SortTuple *a, const SortTuple *b,
 
 		ecxt_scantuple = GetPerTupleExprContext(state->estate)->ecxt_scantuple;
 
-		ExecStoreHeapTuple(ltup, ecxt_scantuple, false);
+		ExecStoreHeapTuple(ltup, ecxt_scantuple, InvalidOid, false);
 		FormIndexDatum(state->indexInfo, ecxt_scantuple, state->estate,
 					   l_index_values, l_index_isnull);
 
-		ExecStoreHeapTuple(rtup, ecxt_scantuple, false);
+		ExecStoreHeapTuple(rtup, ecxt_scantuple, InvalidOid, false);
 		FormIndexDatum(state->indexInfo, ecxt_scantuple, state->estate,
 					   r_index_values, r_index_isnull);
 
@@ -3926,8 +3926,7 @@ readtup_cluster(Tuplesortstate *state, SortTuple *stup,
 	tuple->t_len = t_len;
 	LogicalTapeReadExact(state->tapeset, tapenum,
 						 &tuple->t_self, sizeof(ItemPointerData));
-	/* We don't currently bother to reconstruct t_tableOid */
-	tuple->t_tableOid = InvalidOid;
+
 	/* Read in the tuple body */
 	LogicalTapeReadExact(state->tapeset, tapenum,
 						 tuple->t_data, tuple->t_len);
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 2bb170e708..7c9c4f5e98 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -211,7 +211,7 @@ extern void heap_vacuum_rel(Relation onerel, int options,
 				struct VacuumParams *params, BufferAccessStrategy bstrategy);
 
 /* in heap/heapam_visibility.c */
-extern bool HeapTupleSatisfiesVisibility(HeapTuple stup, Snapshot snapshot,
+extern bool HeapTupleSatisfiesVisibility(HeapTuple stup, Oid relid, Snapshot snapshot,
 										 Buffer buffer);
 extern HTSU_Result HeapTupleSatisfiesUpdate(HeapTuple stup, CommandId curcid,
 						 Buffer buffer);
@@ -231,6 +231,7 @@ struct HTAB;
 extern bool ResolveCminCmaxDuringDecoding(struct HTAB *tuplecid_data,
 							  Snapshot snapshot,
 							  HeapTuple htup,
+							  Oid relid,
 							  Buffer buffer,
 							  CommandId *cmin, CommandId *cmax);
 
diff --git a/src/include/executor/tuptable.h b/src/include/executor/tuptable.h
index fe8630e67a..996153e03f 100644
--- a/src/include/executor/tuptable.h
+++ b/src/include/executor/tuptable.h
@@ -306,9 +306,8 @@ extern TupleTableSlot *MakeSingleTupleTableSlot(TupleDesc tupdesc,
 extern void ExecDropSingleTupleTableSlot(TupleTableSlot *slot);
 extern void ExecSetSlotDescriptor(TupleTableSlot *slot, TupleDesc tupdesc);
 extern TupleTableSlot *ExecStoreHeapTuple(HeapTuple tuple,
-				   TupleTableSlot *slot,
-				   bool shouldFree);
-extern void ExecForceStoreHeapTuple(HeapTuple tuple, TupleTableSlot *slot);
+				   TupleTableSlot *slot, Oid relid, bool shouldFree);
+extern void ExecForceStoreHeapTuple(HeapTuple tuple, TupleTableSlot *slot, Oid relid);
 /* FIXME: Remove */
 extern void ExecForceStoreHeapTupleDatum(Datum data, TupleTableSlot *slot);
 extern TupleTableSlot *ExecStoreBufferHeapTuple(HeapTuple tuple,
diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c
index 5c6dbe4c5f..1a61eb85b1 100644
--- a/src/pl/plpgsql/src/pl_exec.c
+++ b/src/pl/plpgsql/src/pl_exec.c
@@ -7236,7 +7236,6 @@ deconstruct_composite_datum(Datum value, HeapTupleData *tmptup)
 	/* Build a temporary HeapTuple control structure */
 	tmptup->t_len = HeapTupleHeaderGetDatumLength(td);
 	ItemPointerSetInvalid(&(tmptup->t_self));
-	tmptup->t_tableOid = InvalidOid;
 	tmptup->t_data = td;
 
 	/* Extract rowtype info and find a tupdesc */
@@ -7405,7 +7404,6 @@ exec_move_row_from_datum(PLpgSQL_execstate *estate,
 		/* Build a temporary HeapTuple control structure */
 		tmptup.t_len = HeapTupleHeaderGetDatumLength(td);
 		ItemPointerSetInvalid(&(tmptup.t_self));
-		tmptup.t_tableOid = InvalidOid;
 		tmptup.t_data = td;
 
 		/* Extract rowtype info */
diff --git a/src/test/regress/regress.c b/src/test/regress/regress.c
index 70727286ca..924bd85ce1 100644
--- a/src/test/regress/regress.c
+++ b/src/test/regress/regress.c
@@ -524,7 +524,6 @@ make_tuple_indirect(PG_FUNCTION_ARGS)
 	/* Build a temporary HeapTuple control structure */
 	tuple.t_len = HeapTupleHeaderGetDatumLength(rec);
 	ItemPointerSetInvalid(&(tuple.t_self));
-	tuple.t_tableOid = InvalidOid;
 	tuple.t_data = rec;
 
 	values = (Datum *) palloc(ncolumns * sizeof(Datum));
-- 
2.18.0.windows.1

