From 13ed2713b82306d32b1bf2265a90386efde677ce Mon Sep 17 00:00:00 2001
From: Hari <haribabuk@fast.au.fujitsu.com>
Date: Fri, 9 Jun 2017 11:15:31 +1000
Subject: [PATCH 07/10] Replace slot functions with storage access methods

Replace all slot_* function with slot storage access
methods
---
 src/backend/access/common/printsimple.c  |  3 ++-
 src/backend/access/common/printtup.c     |  9 +++++----
 src/backend/catalog/index.c              |  2 +-
 src/backend/catalog/partition.c          |  2 +-
 src/backend/commands/copy.c              | 15 +++++++--------
 src/backend/executor/execCurrent.c       |  4 ++--
 src/backend/executor/execExprInterp.c    |  9 ++++++---
 src/backend/executor/execGrouping.c      | 10 +++++-----
 src/backend/executor/execJunk.c          |  4 ++--
 src/backend/executor/execMain.c          |  5 +++--
 src/backend/executor/functions.c         |  2 +-
 src/backend/executor/nodeAgg.c           |  8 ++++----
 src/backend/executor/nodeFunctionscan.c  |  2 +-
 src/backend/executor/nodeMergeAppend.c   |  4 ++--
 src/backend/executor/nodeNestloop.c      |  2 +-
 src/backend/executor/nodeSetOp.c         |  2 +-
 src/backend/executor/nodeSubplan.c       | 12 ++++++------
 src/backend/executor/tqueue.c            |  3 ++-
 src/backend/executor/tstoreReceiver.c    |  3 ++-
 src/backend/replication/logical/worker.c |  8 ++++++--
 src/backend/utils/adt/orderedsetaggs.c   |  4 ++--
 21 files changed, 62 insertions(+), 51 deletions(-)

diff --git a/src/backend/access/common/printsimple.c b/src/backend/access/common/printsimple.c
index 851c3bf..7ab9b43 100644
--- a/src/backend/access/common/printsimple.c
+++ b/src/backend/access/common/printsimple.c
@@ -19,6 +19,7 @@
 #include "postgres.h"
 
 #include "access/printsimple.h"
+#include "access/storageamapi.h"
 #include "catalog/pg_type.h"
 #include "fmgr.h"
 #include "libpq/pqformat.h"
@@ -63,7 +64,7 @@ printsimple(TupleTableSlot *slot, DestReceiver *self)
 	int			i;
 
 	/* Make sure the tuple is fully deconstructed */
-	slot_getallattrs(slot);
+	slot->tts_storageam->slot_getallattrs(slot);
 
 	/* Prepare and send message */
 	pq_beginmessage(&buf, 'D');
diff --git a/src/backend/access/common/printtup.c b/src/backend/access/common/printtup.c
index a2ca2d7..0e5caa9 100644
--- a/src/backend/access/common/printtup.c
+++ b/src/backend/access/common/printtup.c
@@ -16,6 +16,7 @@
 #include "postgres.h"
 
 #include "access/printtup.h"
+#include "access/storageamapi.h"
 #include "libpq/libpq.h"
 #include "libpq/pqformat.h"
 #include "tcop/pquery.h"
@@ -310,7 +311,7 @@ printtup(TupleTableSlot *slot, DestReceiver *self)
 		printtup_prepare_info(myState, typeinfo, natts);
 
 	/* Make sure the tuple is fully deconstructed */
-	slot_getallattrs(slot);
+	slot->tts_storageam->slot_getallattrs(slot);
 
 	/* Switch into per-row context so we can recover memory below */
 	oldcontext = MemoryContextSwitchTo(myState->tmpcontext);
@@ -397,7 +398,7 @@ printtup_20(TupleTableSlot *slot, DestReceiver *self)
 		printtup_prepare_info(myState, typeinfo, natts);
 
 	/* Make sure the tuple is fully deconstructed */
-	slot_getallattrs(slot);
+	slot->tts_storageam->slot_getallattrs(slot);
 
 	/* Switch into per-row context so we can recover memory below */
 	oldcontext = MemoryContextSwitchTo(myState->tmpcontext);
@@ -542,7 +543,7 @@ debugtup(TupleTableSlot *slot, DestReceiver *self)
 
 	for (i = 0; i < natts; ++i)
 	{
-		attr = slot_getattr(slot, i + 1, &isnull);
+		attr = slot->tts_storageam->slot_getattr(slot, i + 1, &isnull);
 		if (isnull)
 			continue;
 		getTypeOutputInfo(typeinfo->attrs[i]->atttypid,
@@ -583,7 +584,7 @@ printtup_internal_20(TupleTableSlot *slot, DestReceiver *self)
 		printtup_prepare_info(myState, typeinfo, natts);
 
 	/* Make sure the tuple is fully deconstructed */
-	slot_getallattrs(slot);
+	slot->tts_storageam->slot_getallattrs(slot);
 
 	/* Switch into per-row context so we can recover memory below */
 	oldcontext = MemoryContextSwitchTo(myState->tmpcontext);
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 2328b92..558dbbc 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -1794,7 +1794,7 @@ FormIndexDatum(IndexInfo *indexInfo,
 			 * Plain index column; get the value we need directly from the
 			 * heap tuple.
 			 */
-			iDatum = slot_getattr(slot, keycol, &isNull);
+			iDatum = slot->tts_storageam->slot_getattr(slot, keycol, &isNull);
 		}
 		else
 		{
diff --git a/src/backend/catalog/partition.c b/src/backend/catalog/partition.c
index 7304f6c..3fe5e0a 100644
--- a/src/backend/catalog/partition.c
+++ b/src/backend/catalog/partition.c
@@ -1884,7 +1884,7 @@ FormPartitionKeyDatum(PartitionDispatch pd,
 		if (keycol != 0)
 		{
 			/* Plain column; get the value directly from the heap tuple */
-			datum = slot_getattr(slot, keycol, &isNull);
+			datum = slot->tts_storageam->slot_getattr(slot, keycol, &isNull);
 		}
 		else
 		{
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index 84b1a54..afa4cb1 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -2297,6 +2297,7 @@ CopyFrom(CopyState cstate)
 	bool	   *nulls;
 	ResultRelInfo *resultRelInfo;
 	ResultRelInfo *saved_resultRelInfo = NULL;
+	StorageAmRoutine *method;
 	EState	   *estate = CreateExecutorState(); /* for ExecConstraints() */
 	ExprContext *econtext;
 	TupleTableSlot *myslot;
@@ -2357,6 +2358,7 @@ CopyFrom(CopyState cstate)
 	}
 
 	tupDesc = RelationGetDescr(cstate->rel);
+	method = cstate->rel->rd_stamroutine;
 
 	/*----------
 	 * Check to see if we can avoid writing WAL
@@ -2626,8 +2628,6 @@ CopyFrom(CopyState cstate)
 
 			if (slot == NULL)	/* "do nothing" */
 				skip_tuple = true;
-			else	/* trigger might have changed tuple */
-				tuple = ExecMaterializeSlot(slot);
 		}
 
 		if (!skip_tuple)
@@ -2675,8 +2675,7 @@ CopyFrom(CopyState cstate)
 					List	   *recheckIndexes = NIL;
 
 					/* OK, store the tuple and create index entries for it */
-					heap_insert(resultRelInfo->ri_RelationDesc, tuple, mycid,
-								hi_options, bistate);
+					method->tuple_insert(resultRelInfo->ri_RelationDesc, slot, mycid, hi_options, bistate, &(tuple->t_self));
 
 					if (resultRelInfo->ri_NumIndices > 0)
 						recheckIndexes = ExecInsertIndexTuples(slot,
@@ -2687,7 +2686,7 @@ CopyFrom(CopyState cstate)
 															   NIL);
 
 					/* AFTER ROW INSERT Triggers */
-					ExecARInsertTriggers(estate, resultRelInfo, tuple,
+					ExecARInsertTriggers(estate, resultRelInfo, slot,
 										 recheckIndexes);
 
 					list_free(recheckIndexes);
@@ -2840,7 +2839,7 @@ CopyFromInsertBatch(CopyState cstate, EState *estate, CommandId mycid,
 				ExecInsertIndexTuples(myslot, &(bufferedTuples[i]->t_self),
 									  estate, false, NULL, NIL);
 			ExecARInsertTriggers(estate, resultRelInfo,
-								 bufferedTuples[i],
+								 myslot,
 								 recheckIndexes);
 			list_free(recheckIndexes);
 		}
@@ -2857,7 +2856,7 @@ CopyFromInsertBatch(CopyState cstate, EState *estate, CommandId mycid,
 		{
 			cstate->cur_lineno = firstBufferedLineNo + i;
 			ExecARInsertTriggers(estate, resultRelInfo,
-								 bufferedTuples[i],
+								 myslot,
 								 NIL);
 		}
 	}
@@ -4708,7 +4707,7 @@ copy_dest_receive(TupleTableSlot *slot, DestReceiver *self)
 	CopyState	cstate = myState->cstate;
 
 	/* Make sure the tuple is fully deconstructed */
-	slot_getallattrs(slot);
+	slot->tts_storageam->slot_getallattrs(slot);
 
 	/* And send the data */
 	CopyOneRowTo(cstate, InvalidOid, slot->tts_values, slot->tts_isnull);
diff --git a/src/backend/executor/execCurrent.c b/src/backend/executor/execCurrent.c
index 3af4a90..350b688 100644
--- a/src/backend/executor/execCurrent.c
+++ b/src/backend/executor/execCurrent.c
@@ -185,12 +185,12 @@ execCurrentOf(CurrentOfExpr *cexpr,
 
 		/* Use slot_getattr to catch any possible mistakes */
 		tuple_tableoid =
-			DatumGetObjectId(slot_getattr(scanstate->ss_ScanTupleSlot,
+			DatumGetObjectId(scanstate->ss_ScanTupleSlot->tts_storageam->slot_getattr(scanstate->ss_ScanTupleSlot,
 										  TableOidAttributeNumber,
 										  &lisnull));
 		Assert(!lisnull);
 		tuple_tid = (ItemPointer)
-			DatumGetPointer(slot_getattr(scanstate->ss_ScanTupleSlot,
+			DatumGetPointer(scanstate->ss_ScanTupleSlot->tts_storageam->slot_getattr(scanstate->ss_ScanTupleSlot,
 										 SelfItemPointerAttributeNumber,
 										 &lisnull));
 		Assert(!lisnull);
diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c
index 1217304..14220dc 100644
--- a/src/backend/executor/execExprInterp.c
+++ b/src/backend/executor/execExprInterp.c
@@ -507,7 +507,8 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
 			Assert(innerslot->tts_tuple != &(innerslot->tts_minhdr));
 			/* heap_getsysattr has sufficient defenses against bad attnums */
 
-			*op->resvalue = heap_getsysattr(innerslot->tts_tuple, attnum,
+			*op->resvalue = heap_getsysattr(innerslot->tts_storageam->slot_get_tuple(innerslot),
+											attnum,
 											innerslot->tts_tupleDescriptor,
 											op->resnull);
 
@@ -523,7 +524,8 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
 			Assert(outerslot->tts_tuple != &(outerslot->tts_minhdr));
 
 			/* heap_getsysattr has sufficient defenses against bad attnums */
-			*op->resvalue = heap_getsysattr(outerslot->tts_tuple, attnum,
+			*op->resvalue = heap_getsysattr(outerslot->tts_storageam->slot_get_tuple(outerslot),
+											attnum,
 											outerslot->tts_tupleDescriptor,
 											op->resnull);
 
@@ -539,7 +541,8 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
 			Assert(scanslot->tts_tuple != &(scanslot->tts_minhdr));
 			/* heap_getsysattr has sufficient defenses against bad attnums */
 
-			*op->resvalue = heap_getsysattr(scanslot->tts_tuple, attnum,
+			*op->resvalue = heap_getsysattr(scanslot->tts_storageam->slot_get_tuple(scanslot),
+											attnum,
 											scanslot->tts_tupleDescriptor,
 											op->resnull);
 
diff --git a/src/backend/executor/execGrouping.c b/src/backend/executor/execGrouping.c
index 07c8852..0d33cfe 100644
--- a/src/backend/executor/execGrouping.c
+++ b/src/backend/executor/execGrouping.c
@@ -97,9 +97,9 @@ execTuplesMatch(TupleTableSlot *slot1,
 		bool		isNull1,
 					isNull2;
 
-		attr1 = slot_getattr(slot1, att, &isNull1);
+		attr1 = slot1->tts_storageam->slot_getattr(slot1, att, &isNull1);
 
-		attr2 = slot_getattr(slot2, att, &isNull2);
+		attr2 = slot2->tts_storageam->slot_getattr(slot2, att, &isNull2);
 
 		if (isNull1 != isNull2)
 		{
@@ -167,12 +167,12 @@ execTuplesUnequal(TupleTableSlot *slot1,
 		bool		isNull1,
 					isNull2;
 
-		attr1 = slot_getattr(slot1, att, &isNull1);
+		attr1 = slot1->tts_storageam->slot_getattr(slot1, att, &isNull1);
 
 		if (isNull1)
 			continue;			/* can't prove anything here */
 
-		attr2 = slot_getattr(slot2, att, &isNull2);
+		attr2 = slot2->tts_storageam->slot_getattr(slot2, att, &isNull2);
 
 		if (isNull2)
 			continue;			/* can't prove anything here */
@@ -498,7 +498,7 @@ TupleHashTableHash(struct tuplehash_hash *tb, const MinimalTuple tuple)
 		/* rotate hashkey left 1 bit at each step */
 		hashkey = (hashkey << 1) | ((hashkey & 0x80000000) ? 1 : 0);
 
-		attr = slot_getattr(slot, att, &isNull);
+		attr = slot->tts_storageam->slot_getattr(slot, att, &isNull);
 
 		if (!isNull)			/* treat nulls as having hash key 0 */
 		{
diff --git a/src/backend/executor/execJunk.c b/src/backend/executor/execJunk.c
index a422327..08f7b7a 100644
--- a/src/backend/executor/execJunk.c
+++ b/src/backend/executor/execJunk.c
@@ -250,7 +250,7 @@ ExecGetJunkAttribute(TupleTableSlot *slot, AttrNumber attno,
 {
 	Assert(attno > 0);
 
-	return slot_getattr(slot, attno, isNull);
+	return slot->tts_storageam->slot_getattr(slot, attno, isNull);
 }
 
 /*
@@ -274,7 +274,7 @@ ExecFilterJunk(JunkFilter *junkfilter, TupleTableSlot *slot)
 	/*
 	 * Extract all the values of the old tuple.
 	 */
-	slot_getallattrs(slot);
+	slot->tts_storageam->slot_getallattrs(slot);
 	old_values = slot->tts_values;
 	old_isnull = slot->tts_isnull;
 
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index 3614513..b519cb0 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -38,6 +38,7 @@
 #include "postgres.h"
 
 #include "access/htup_details.h"
+#include "access/storageamapi.h"
 #include "access/sysattr.h"
 #include "access/transam.h"
 #include "access/xact.h"
@@ -1903,7 +1904,7 @@ ExecConstraints(ResultRelInfo *resultRelInfo,
 		for (attrChk = 1; attrChk <= natts; attrChk++)
 		{
 			if (tupdesc->attrs[attrChk - 1]->attnotnull &&
-				slot_attisnull(slot, attrChk))
+				slot->tts_storageam->slot_attisnull(slot, attrChk))
 			{
 				char	   *val_desc;
 				Relation	orig_rel = rel;
@@ -2220,7 +2221,7 @@ ExecBuildSlotValueDescription(Oid reloid,
 		table_perm = any_perm = true;
 
 	/* Make sure the tuple is fully deconstructed */
-	slot_getallattrs(slot);
+	slot->tts_storageam->slot_getallattrs(slot);
 
 	for (i = 0; i < tupdesc->natts; i++)
 	{
diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c
index e2ab776..e7db610 100644
--- a/src/backend/executor/functions.c
+++ b/src/backend/executor/functions.c
@@ -971,7 +971,7 @@ postquel_get_single_result(TupleTableSlot *slot,
 		 * Returning a scalar, which we have to extract from the first column
 		 * of the SELECT result, and then copy into result context if needed.
 		 */
-		value = slot_getattr(slot, 1, &(fcinfo->isnull));
+		value = slot->tts_storageam->slot_getattr(slot, 1, &(fcinfo->isnull));
 
 		if (!fcinfo->isnull)
 			value = datumCopy(value, fcache->typbyval, fcache->typlen);
diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c
index a412402..1fbd5ad 100644
--- a/src/backend/executor/nodeAgg.c
+++ b/src/backend/executor/nodeAgg.c
@@ -1419,7 +1419,7 @@ process_ordered_aggregate_multi(AggState *aggstate,
 		 * transfn.  (This will help execTuplesMatch too, so we do it
 		 * immediately.)
 		 */
-		slot_getsomeattrs(slot1, numTransInputs);
+		slot1->tts_storageam->slot_getsomeattrs(slot1, numTransInputs);
 
 		if (numDistinctCols == 0 ||
 			!haveOldValue ||
@@ -1683,7 +1683,7 @@ prepare_projection_slot(AggState *aggstate, TupleTableSlot *slot, int currentSet
 			ListCell   *lc;
 
 			/* all_grouped_cols is arranged in desc order */
-			slot_getsomeattrs(slot, linitial_int(aggstate->all_grouped_cols));
+			slot->tts_storageam->slot_getsomeattrs(slot, linitial_int(aggstate->all_grouped_cols));
 
 			foreach(lc, aggstate->all_grouped_cols)
 			{
@@ -2032,7 +2032,7 @@ lookup_hash_entry(AggState *aggstate)
 	int			i;
 
 	/* transfer just the needed columns into hashslot */
-	slot_getsomeattrs(inputslot, perhash->largestGrpColIdx);
+	inputslot->tts_storageam->slot_getsomeattrs(inputslot, perhash->largestGrpColIdx);
 	ExecClearTuple(hashslot);
 
 	for (i = 0; i < perhash->numhashGrpCols; i++)
@@ -2608,7 +2608,7 @@ agg_retrieve_hash_table(AggState *aggstate)
 		 * columns.
 		 */
 		ExecStoreMinimalTuple(entry->firstTuple, hashslot, false);
-		slot_getallattrs(hashslot);
+		hashslot->tts_storageam->slot_getallattrs(hashslot);
 
 		ExecClearTuple(firstSlot);
 		memset(firstSlot->tts_isnull, true,
diff --git a/src/backend/executor/nodeFunctionscan.c b/src/backend/executor/nodeFunctionscan.c
index 426527d..9d2de95 100644
--- a/src/backend/executor/nodeFunctionscan.c
+++ b/src/backend/executor/nodeFunctionscan.c
@@ -207,7 +207,7 @@ FunctionNext(FunctionScanState *node)
 			/*
 			 * we have a result, so just copy it to the result cols.
 			 */
-			slot_getallattrs(fs->func_slot);
+			fs->func_slot->tts_storageam->slot_getallattrs(fs->func_slot);
 
 			for (i = 0; i < fs->colcount; i++)
 			{
diff --git a/src/backend/executor/nodeMergeAppend.c b/src/backend/executor/nodeMergeAppend.c
index fef83db..501e5fc 100644
--- a/src/backend/executor/nodeMergeAppend.c
+++ b/src/backend/executor/nodeMergeAppend.c
@@ -249,8 +249,8 @@ heap_compare_slots(Datum a, Datum b, void *arg)
 					isNull2;
 		int			compare;
 
-		datum1 = slot_getattr(s1, attno, &isNull1);
-		datum2 = slot_getattr(s2, attno, &isNull2);
+		datum1 = s1->tts_storageam->slot_getattr(s1, attno, &isNull1);
+		datum2 = s2->tts_storageam->slot_getattr(s2, attno, &isNull2);
 
 		compare = ApplySortComparator(datum1, isNull1,
 									  datum2, isNull2,
diff --git a/src/backend/executor/nodeNestloop.c b/src/backend/executor/nodeNestloop.c
index 69d2453..5874c74 100644
--- a/src/backend/executor/nodeNestloop.c
+++ b/src/backend/executor/nodeNestloop.c
@@ -133,7 +133,7 @@ ExecNestLoop(NestLoopState *node)
 				Assert(IsA(nlp->paramval, Var));
 				Assert(nlp->paramval->varno == OUTER_VAR);
 				Assert(nlp->paramval->varattno > 0);
-				prm->value = slot_getattr(outerTupleSlot,
+				prm->value = outerTupleSlot->tts_storageam->slot_getattr(outerTupleSlot,
 										  nlp->paramval->varattno,
 										  &(prm->isnull));
 				/* Flag parameter value as changed */
diff --git a/src/backend/executor/nodeSetOp.c b/src/backend/executor/nodeSetOp.c
index 9ae53bb..056e968 100644
--- a/src/backend/executor/nodeSetOp.c
+++ b/src/backend/executor/nodeSetOp.c
@@ -104,7 +104,7 @@ fetch_tuple_flag(SetOpState *setopstate, TupleTableSlot *inputslot)
 	int			flag;
 	bool		isNull;
 
-	flag = DatumGetInt32(slot_getattr(inputslot,
+	flag = DatumGetInt32(inputslot->tts_storageam->slot_getattr(inputslot,
 									  node->flagColIdx,
 									  &isNull));
 	Assert(!isNull);
diff --git a/src/backend/executor/nodeSubplan.c b/src/backend/executor/nodeSubplan.c
index e8fa4c8..4cf6870 100644
--- a/src/backend/executor/nodeSubplan.c
+++ b/src/backend/executor/nodeSubplan.c
@@ -358,7 +358,7 @@ ExecScanSubPlan(SubPlanState *node,
 			found = true;
 			/* stash away current value */
 			Assert(subplan->firstColType == tdesc->attrs[0]->atttypid);
-			dvalue = slot_getattr(slot, 1, &disnull);
+			dvalue = slot->tts_storageam->slot_getattr(slot, 1, &disnull);
 			astate = accumArrayResultAny(astate, dvalue, disnull,
 										 subplan->firstColType, oldcontext);
 			/* keep scanning subplan to collect all values */
@@ -386,7 +386,7 @@ ExecScanSubPlan(SubPlanState *node,
 
 			prmdata = &(econtext->ecxt_param_exec_vals[paramid]);
 			Assert(prmdata->execPlan == NULL);
-			prmdata->value = slot_getattr(slot, col, &(prmdata->isnull));
+			prmdata->value = slot->tts_storageam->slot_getattr(slot, col, &(prmdata->isnull));
 			col++;
 		}
 
@@ -556,7 +556,7 @@ buildSubPlanHash(SubPlanState *node, ExprContext *econtext)
 
 			prmdata = &(innerecontext->ecxt_param_exec_vals[paramid]);
 			Assert(prmdata->execPlan == NULL);
-			prmdata->value = slot_getattr(slot, col,
+			prmdata->value = slot->tts_storageam->slot_getattr(slot, col,
 										  &(prmdata->isnull));
 			col++;
 		}
@@ -646,7 +646,7 @@ slotAllNulls(TupleTableSlot *slot)
 
 	for (i = 1; i <= ncols; i++)
 	{
-		if (!slot_attisnull(slot, i))
+		if (!slot->tts_storageam->slot_attisnull(slot, i))
 			return false;
 	}
 	return true;
@@ -666,7 +666,7 @@ slotNoNulls(TupleTableSlot *slot)
 
 	for (i = 1; i <= ncols; i++)
 	{
-		if (slot_attisnull(slot, i))
+		if (slot->tts_storageam->slot_attisnull(slot, i))
 			return false;
 	}
 	return true;
@@ -988,7 +988,7 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext)
 			found = true;
 			/* stash away current value */
 			Assert(subplan->firstColType == tdesc->attrs[0]->atttypid);
-			dvalue = slot_getattr(slot, 1, &disnull);
+			dvalue = slot->tts_storageam->slot_getattr(slot, 1, &disnull);
 			astate = accumArrayResultAny(astate, dvalue, disnull,
 										 subplan->firstColType, oldcontext);
 			/* keep scanning subplan to collect all values */
diff --git a/src/backend/executor/tqueue.c b/src/backend/executor/tqueue.c
index 16adf26..7bef12e 100644
--- a/src/backend/executor/tqueue.c
+++ b/src/backend/executor/tqueue.c
@@ -35,6 +35,7 @@
 #include "postgres.h"
 
 #include "access/htup_details.h"
+#include "access/storageamapi.h"
 #include "catalog/pg_type.h"
 #include "executor/tqueue.h"
 #include "funcapi.h"
@@ -265,7 +266,7 @@ tqueueReceiveSlot(TupleTableSlot *slot, DestReceiver *self)
 		MemoryContext oldcontext = NULL;
 
 		/* Deform the tuple so we can examine fields, if not done already. */
-		slot_getallattrs(slot);
+		slot->tts_storageam->slot_getallattrs(slot);
 
 		/* Iterate over each attribute and search it for transient typmods. */
 		for (i = 0; i < tupledesc->natts; i++)
diff --git a/src/backend/executor/tstoreReceiver.c b/src/backend/executor/tstoreReceiver.c
index 1e641c9..1ac48b2 100644
--- a/src/backend/executor/tstoreReceiver.c
+++ b/src/backend/executor/tstoreReceiver.c
@@ -20,6 +20,7 @@
 
 #include "postgres.h"
 
+#include "access/storageamapi.h"
 #include "access/tuptoaster.h"
 #include "executor/tstoreReceiver.h"
 
@@ -116,7 +117,7 @@ tstoreReceiveSlot_detoast(TupleTableSlot *slot, DestReceiver *self)
 	MemoryContext oldcxt;
 
 	/* Make sure the tuple is fully deconstructed */
-	slot_getallattrs(slot);
+	slot->tts_storageam->slot_getallattrs(slot);
 
 	/*
 	 * Fetch back any out-of-line datums.  We build the new datums array in
diff --git a/src/backend/replication/logical/worker.c b/src/backend/replication/logical/worker.c
index 7d1787d..dabe87e 100644
--- a/src/backend/replication/logical/worker.c
+++ b/src/backend/replication/logical/worker.c
@@ -366,7 +366,7 @@ slot_modify_cstrings(TupleTableSlot *slot, LogicalRepRelMapEntry *rel,
 	SlotErrCallbackArg errarg;
 	ErrorContextCallback errcallback;
 
-	slot_getallattrs(slot);
+	slot->tts_storageam->slot_getallattrs(slot);
 	ExecClearTuple(slot);
 
 	/* Push callback + info on the error context stack */
@@ -700,6 +700,7 @@ apply_handle_update(StringInfo s)
 		found = RelationFindReplTupleSeq(rel->localrel, LockTupleExclusive,
 										 remoteslot, localslot);
 
+	remoteslot->tts_storageam->slot_clear_tuple(remoteslot);
 	ExecClearTuple(remoteslot);
 
 	/*
@@ -709,9 +710,12 @@ apply_handle_update(StringInfo s)
 	 */
 	if (found)
 	{
+		HeapTuple tuple;
+
 		/* Process and store remote tuple in the slot */
 		oldctx = MemoryContextSwitchTo(GetPerTupleMemoryContext(estate));
-		ExecStoreTuple(localslot->tts_tuple, remoteslot, InvalidBuffer, false);
+		tuple = ExecHeapifySlot(localslot);
+		remoteslot->tts_storageam->slot_store_tuple(remoteslot, tuple, false);
 		slot_modify_cstrings(remoteslot, rel, newtup.values, newtup.changed);
 		MemoryContextSwitchTo(oldctx);
 
diff --git a/src/backend/utils/adt/orderedsetaggs.c b/src/backend/utils/adt/orderedsetaggs.c
index 8502fcf..718b862 100644
--- a/src/backend/utils/adt/orderedsetaggs.c
+++ b/src/backend/utils/adt/orderedsetaggs.c
@@ -1193,7 +1193,7 @@ hypothetical_rank_common(FunctionCallInfo fcinfo, int flag,
 	while (tuplesort_gettupleslot(osastate->sortstate, true, true, slot, NULL))
 	{
 		bool		isnull;
-		Datum		d = slot_getattr(slot, nargs + 1, &isnull);
+		Datum		d = slot->tts_storageam->slot_getattr(slot, nargs + 1, &isnull);
 
 		if (!isnull && DatumGetInt32(d) != 0)
 			break;
@@ -1357,7 +1357,7 @@ hypothetical_dense_rank_final(PG_FUNCTION_ARGS)
 								  &abbrevVal))
 	{
 		bool		isnull;
-		Datum		d = slot_getattr(slot, nargs + 1, &isnull);
+		Datum		d = slot->tts_storageam->slot_getattr(slot, nargs + 1, &isnull);
 		TupleTableSlot *tmpslot;
 
 		if (!isnull && DatumGetInt32(d) != 0)
-- 
2.7.4.windows.1

