#include "access/genam.h"
#include "access/heapam.h"
+#include "access/tableam.h"
#include "access/tuptoaster.h"
#include "access/xact.h"
#include "catalog/catalog.h"
sysscan->heap_rel = heapRelation;
sysscan->irel = irel;
- sysscan->slot = MakeSingleTupleTableSlot(RelationGetDescr(heapRelation),
- &TTSOpsBufferHeapTuple);
+ sysscan->slot = table_gimmegimmeslot(heapRelation, NULL);
if (snapshot == NULL)
{
sysscan->heap_rel = heapRelation;
sysscan->irel = indexRelation;
- sysscan->slot = MakeSingleTupleTableSlot(RelationGetDescr(heapRelation),
- &TTSOpsBufferHeapTuple);
+ sysscan->slot = table_gimmegimmeslot(heapRelation, NULL);
if (snapshot == NULL)
{
bool synchronize_seqscans = true;
+const TupleTableSlotOps *
+table_slot_callbacks(Relation relation)
+{
+ const TupleTableSlotOps *tts_cb;
+
+ if (relation->rd_tableam)
+ tts_cb = relation->rd_tableam->slot_callbacks(relation);
+ else
+ {
+ /*
+ * These need to be supported, as some parts of the code (like COPY)
+ * need to create slots for such relations too. It seems better to
+ * centralize the knowledge that a heap slot is the right thing in
+ * that case here.
+ */
+ Assert(relation->rd_rel->relkind == RELKIND_VIEW ||
+ relation->rd_rel->relkind == RELKIND_FOREIGN_TABLE ||
+ relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE);
+ tts_cb = &TTSOpsHeapTuple;
+ }
+
+ return tts_cb;
+}
+
+TupleTableSlot *
+table_gimmegimmeslot(Relation relation, List **reglist)
+{
+ const TupleTableSlotOps *tts_cb;
+ TupleTableSlot *slot;
+
+ tts_cb = table_slot_callbacks(relation);
+ slot = MakeSingleTupleTableSlot(RelationGetDescr(relation), tts_cb);
+
+ if (reglist)
+ *reglist = lappend(*reglist, slot);
+
+ return slot;
+}
+
/* ----------------
* table_beginscan_parallel - join a parallel scan
*
*/
estate = CreateExecutorState();
econtext = GetPerTupleExprContext(estate);
- slot = MakeSingleTupleTableSlot(RelationGetDescr(heapRelation),
- &TTSOpsHeapTuple);
+ slot = table_gimmegimmeslot(heapRelation, NULL);
/* Arrange for econtext's scan tuple to be the tuple under test */
econtext->ecxt_scantuple = slot;
MemoryContextReset(econtext->ecxt_per_tuple_memory);
/* Set up for predicate or expression evaluation */
- ExecStoreHeapTuple(heapTuple, slot, false);
+ ExecStoreBufferHeapTuple(heapTuple, slot, hscan->rs_cbuf);
/*
* In a partial index, discard tuples that don't satisfy the
{
HeapTuple heapTuple;
TableScanDesc scan;
+ HeapScanDesc hscan;
Datum values[INDEX_MAX_KEYS];
bool isnull[INDEX_MAX_KEYS];
ExprState *predicate;
*/
estate = CreateExecutorState();
econtext = GetPerTupleExprContext(estate);
- slot = MakeSingleTupleTableSlot(RelationGetDescr(heapRelation),
- &TTSOpsHeapTuple);
+ slot = table_gimmegimmeslot(heapRelation, NULL);
/* Arrange for econtext's scan tuple to be the tuple under test */
econtext->ecxt_scantuple = slot;
NULL, /* scan key */
true, /* buffer access strategy OK */
true); /* syncscan OK */
+ hscan = (HeapScanDesc) scan;
while ((heapTuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
{
MemoryContextReset(econtext->ecxt_per_tuple_memory);
/* Set up for predicate or expression evaluation */
- ExecStoreHeapTuple(heapTuple, slot, false);
+ ExecStoreBufferHeapTuple(heapTuple, slot, hscan->rs_cbuf);
/*
* In a partial index, ignore tuples that don't satisfy the predicate.
indexScan = NULL;
}
- slot = MakeSingleTupleTableSlot(RelationGetDescr(OldHeap),
- &TTSOpsBufferHeapTuple);
+ slot = table_gimmegimmeslot(OldHeap, NULL);
hslot = (BufferHeapTupleTableSlot *) slot;
/* Log what we're doing */
char *conbin;
Expr *origexpr;
ExprState *exprstate;
- TupleDesc tupdesc;
HeapTuple tuple;
TableScanDesc scan;
+ HeapScanDesc hscan;
ExprContext *econtext;
MemoryContext oldcxt;
TupleTableSlot *slot;
exprstate = ExecPrepareExpr(origexpr, estate);
econtext = GetPerTupleExprContext(estate);
- tupdesc = RelationGetDescr(rel);
- slot = MakeSingleTupleTableSlot(tupdesc, &TTSOpsHeapTuple);
+ slot = table_gimmegimmeslot(rel, NULL);
econtext->ecxt_scantuple = slot;
snapshot = RegisterSnapshot(GetLatestSnapshot());
scan = table_beginscan(rel, snapshot, 0, NULL);
+ hscan = (HeapScanDesc) scan;
/*
* Switch to per-tuple memory context and reset it for each tuple
while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
{
- ExecStoreHeapTuple(tuple, slot, false);
+ ExecStoreBufferHeapTuple(tuple, slot, hscan->rs_cbuf);
+
if (!ExecCheck(exprstate, econtext))
ereport(ERROR,
#include "access/genam.h"
#include "access/relscan.h"
+#include "access/tableam.h"
#include "access/xact.h"
#include "catalog/index.h"
#include "executor/executor.h"
* to this slot. Be sure to save and restore caller's value for
* scantuple.
*/
- existing_slot = MakeSingleTupleTableSlot(RelationGetDescr(heap),
- &TTSOpsBufferHeapTuple);
+ existing_slot = table_gimmegimmeslot(heap, NULL);
econtext = GetPerTupleExprContext(estate);
save_scantuple = econtext->ecxt_scantuple;
#include "access/heapam.h"
#include "access/htup_details.h"
+#include "access/tableam.h"
#include "access/sysattr.h"
#include "access/transam.h"
#include "access/xact.h"
oldcontext = MemoryContextSwitchTo(epqstate->estate->es_query_cxt);
if (relation)
- *slot = ExecAllocTableSlot(&epqstate->estate->es_tupleTable,
- RelationGetDescr(relation),
- &TTSOpsBufferHeapTuple);
+ *slot = table_gimmegimmeslot(relation,
+ &epqstate->estate->es_tupleTable);
else
*slot = ExecAllocTableSlot(&epqstate->estate->es_tupleTable,
epqstate->origslot->tts_tupleDescriptor,
#include "postgres.h"
#include "access/table.h"
+#include "access/tableam.h"
#include "catalog/partition.h"
#include "catalog/pg_inherits.h"
#include "catalog/pg_type.h"
{
TupleConversionMap *map;
TupleDesc leaf_desc;
+ const TupleTableSlotOps *tts_cb;
map = leaf_part_rri->ri_PartitionInfo->pi_RootToPartitionMap;
leaf_desc = RelationGetDescr(leaf_part_rri->ri_RelationDesc);
+ tts_cb = table_slot_callbacks(leaf_part_rri->ri_RelationDesc);
Assert(node->onConflictSet != NIL);
Assert(rootResultRelInfo->ri_onConflict != NULL);
leaf_part_rri->ri_onConflict->oc_Existing =
ExecInitExtraTupleSlot(mtstate->ps.state,
leaf_desc,
- &TTSOpsBufferHeapTuple);
+ tts_cb);
/*
* If the partition's tuple descriptor matches exactly the root
* end of the command.
*/
partrouteinfo->pi_PartitionTupleSlot =
- ExecInitExtraTupleSlot(estate, RelationGetDescr(partrel),
- &TTSOpsHeapTuple);
+ table_gimmegimmeslot(partrel, &estate->es_tupleTable);
}
else
partrouteinfo->pi_PartitionTupleSlot = NULL;
ResultRelInfo *resultRelInfo = estate->es_result_relation_info;
Relation rel = resultRelInfo->ri_RelationDesc;
HeapTupleTableSlot *hsearchslot = (HeapTupleTableSlot *)searchslot;
- HeapTupleTableSlot *hslot = (HeapTupleTableSlot *)slot;
- /* We expect both searchslot and the slot to contain a heap tuple. */
+ /* We expect the searchslot to contain a heap tuple. */
Assert(TTS_IS_HEAPTUPLE(searchslot) || TTS_IS_BUFFERTUPLE(searchslot));
- Assert(TTS_IS_HEAPTUPLE(slot) || TTS_IS_BUFFERTUPLE(slot));
/* For now we support only tables. */
Assert(rel->rd_rel->relkind == RELKIND_RELATION);
tuple = ExecFetchSlotHeapTuple(slot, true, NULL);
/* OK, update the tuple and index entries for it */
- simple_heap_update(rel, &hsearchslot->tuple->t_self, hslot->tuple);
- ItemPointerCopy(&hslot->tuple->t_self, &slot->tts_tid);
+ simple_heap_update(rel, &hsearchslot->tuple->t_self, tuple);
+ ItemPointerCopy(&tuple->t_self, &slot->tts_tid);
if (resultRelInfo->ri_NumIndices > 0 &&
- !HeapTupleIsHeapOnly(hslot->tuple))
+ !HeapTupleIsHeapOnly(tuple))
recheckIndexes = ExecInsertIndexTuples(slot, &(tuple->t_self),
estate, false, NULL,
NIL);
#include "access/parallel.h"
#include "access/relscan.h"
#include "access/table.h"
+#include "access/tableam.h"
#include "access/transam.h"
#include "executor/executor.h"
#include "jit/jit.h"
relInfo->ri_TrigOldSlot =
ExecInitExtraTupleSlot(estate,
RelationGetDescr(rel),
- &TTSOpsBufferHeapTuple);
+ table_slot_callbacks(rel));
MemoryContextSwitchTo(oldcontext);
}
relInfo->ri_TrigNewSlot =
ExecInitExtraTupleSlot(estate,
RelationGetDescr(rel),
- &TTSOpsBufferHeapTuple);
+ table_slot_callbacks(rel));
MemoryContextSwitchTo(oldcontext);
}
relInfo->ri_ReturningSlot =
ExecInitExtraTupleSlot(estate,
RelationGetDescr(rel),
- &TTSOpsBufferHeapTuple);
+ table_slot_callbacks(rel));
MemoryContextSwitchTo(oldcontext);
}
*/
ExecInitScanTupleSlot(estate, &scanstate->ss,
RelationGetDescr(currentRelation),
- &TTSOpsBufferHeapTuple);
-
+ table_slot_callbacks(currentRelation));
/*
* Initialize result type and projection.
#include "access/genam.h"
#include "access/relscan.h"
+#include "access/tableam.h"
#include "access/tupdesc.h"
#include "access/visibilitymap.h"
#include "executor/execdebug.h"
*/
tupDesc = ExecTypeFromTL(node->indextlist);
ExecInitScanTupleSlot(estate, &indexstate->ss, tupDesc,
- &TTSOpsBufferHeapTuple);
+ table_slot_callbacks(currentRelation));
/*
* Initialize result type and projection info. The node's targetlist will
*/
ExecInitScanTupleSlot(estate, &indexstate->ss,
RelationGetDescr(currentRelation),
- &TTSOpsBufferHeapTuple);
+ table_slot_callbacks(currentRelation));
/*
* Initialize result type and projection.
#include "access/heapam.h"
#include "access/htup_details.h"
+#include "access/tableam.h"
#include "access/xact.h"
#include "catalog/catalog.h"
#include "commands/trigger.h"
mtstate->mt_plans[i] = ExecInitNode(subplan, estate, eflags);
mtstate->mt_scans[i] =
ExecInitExtraTupleSlot(mtstate->ps.state, ExecGetResultType(mtstate->mt_plans[i]),
- &TTSOpsHeapTuple);
+ table_slot_callbacks(resultRelInfo->ri_RelationDesc));
/* Also let FDWs init themselves for foreign-table result rels */
if (!resultRelInfo->ri_usesFdwDirectModify &&
if (update_tuple_routing_needed)
{
ExecSetupChildParentMapForSubplan(mtstate);
- mtstate->mt_root_tuple_slot = MakeTupleTableSlot(RelationGetDescr(rel),
- &TTSOpsHeapTuple);
+ mtstate->mt_root_tuple_slot = table_gimmegimmeslot(rel, NULL);
}
/*
ExprContext *econtext;
TupleDesc relationDesc;
TupleDesc tupDesc;
+ const TupleTableSlotOps *tts_cb;
/* insert may only have one plan, inheritance is not expanded */
Assert(nplans == 1);
econtext = mtstate->ps.ps_ExprContext;
relationDesc = resultRelInfo->ri_RelationDesc->rd_att;
+ tts_cb = table_slot_callbacks(resultRelInfo->ri_RelationDesc);
/* carried forward solely for the benefit of explain */
mtstate->mt_excludedtlist = node->exclRelTlist;
/* initialize slot for the existing tuple */
resultRelInfo->ri_onConflict->oc_Existing =
ExecInitExtraTupleSlot(mtstate->ps.state, relationDesc,
- &TTSOpsBufferHeapTuple);
+ tts_cb);
/* create the tuple slot for the UPDATE SET projection */
tupDesc = ExecTypeFromTL((List *) node->onConflictSet);
for (i = 0; i < nplans; i++)
{
JunkFilter *j;
+ TupleTableSlot *junkresslot;
subplan = mtstate->mt_plans[i]->plan;
if (operation == CMD_INSERT || operation == CMD_UPDATE)
ExecCheckPlanOutput(resultRelInfo->ri_RelationDesc,
subplan->targetlist);
+ junkresslot =
+ ExecInitExtraTupleSlot(estate, NULL,
+ table_slot_callbacks(resultRelInfo->ri_RelationDesc));
j = ExecInitJunkFilter(subplan->targetlist,
- ExecInitExtraTupleSlot(estate, NULL,
- &TTSOpsHeapTuple));
+ junkresslot);
if (operation == CMD_UPDATE || operation == CMD_DELETE)
{
/* and create slot with appropriate rowtype */
ExecInitScanTupleSlot(estate, &scanstate->ss,
RelationGetDescr(scanstate->ss.ss_currentRelation),
- &TTSOpsBufferHeapTuple);
+ table_slot_callbacks(scanstate->ss.ss_currentRelation));
/*
* Initialize result type and projection.
/* and create slot with the appropriate rowtype */
ExecInitScanTupleSlot(estate, &scanstate->ss,
RelationGetDescr(scanstate->ss.ss_currentRelation),
- &TTSOpsBufferHeapTuple);
+ table_slot_callbacks(scanstate->ss.ss_currentRelation));
/*
* Initialize result type and projection.
#include "access/heapam.h"
#include "access/sysattr.h"
+#include "access/tableam.h"
#include "catalog/pg_type.h"
#include "executor/execdebug.h"
#include "executor/nodeTidscan.h"
*/
ExecInitScanTupleSlot(estate, &tidstate->ss,
RelationGetDescr(currentRelation),
- &TTSOpsBufferHeapTuple);
+ table_slot_callbacks(currentRelation));
/*
* Initialize result type and projection.
HeapTuple tuple;
ExprState *partqualstate = NULL;
Snapshot snapshot;
- TupleDesc tupdesc;
ExprContext *econtext;
TableScanDesc scan;
+ HeapScanDesc hscan;
MemoryContext oldCxt;
TupleTableSlot *tupslot;
continue;
}
- tupdesc = CreateTupleDescCopy(RelationGetDescr(part_rel));
constr = linitial(def_part_constraints);
partition_constraint = (Expr *)
map_partition_varattnos((List *) constr,
econtext = GetPerTupleExprContext(estate);
snapshot = RegisterSnapshot(GetLatestSnapshot());
- tupslot = MakeSingleTupleTableSlot(tupdesc, &TTSOpsHeapTuple);
+ tupslot = table_gimmegimmeslot(part_rel, &estate->es_tupleTable);
scan = table_beginscan(part_rel, snapshot, 0, NULL);
+ hscan = (HeapScanDesc) scan;
/*
* Switch to per-tuple memory context and reset it for each tuple
while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
{
- ExecStoreHeapTuple(tuple, tupslot, false);
+ ExecStoreBufferHeapTuple(tuple, tupslot, hscan->rs_cbuf);
econtext->ecxt_scantuple = tupslot;
if (!ExecCheck(partqualstate, econtext))
#include "postgres.h"
#include "access/table.h"
+#include "access/tableam.h"
#include "access/xact.h"
#include "access/xlog_internal.h"
#include "catalog/catalog.h"
estate = create_estate_for_relation(rel);
remoteslot = ExecInitExtraTupleSlot(estate,
RelationGetDescr(rel->localrel),
- &TTSOpsHeapTuple);
- localslot = ExecInitExtraTupleSlot(estate,
- RelationGetDescr(rel->localrel),
- &TTSOpsBufferHeapTuple);
+ &TTSOpsVirtual);
+ localslot = table_gimmegimmeslot(rel->localrel, &estate->es_tupleTable);
EvalPlanQualInit(&epqstate, estate, NULL, NIL, -1);
PushActiveSnapshot(GetTransactionSnapshot());
remoteslot = ExecInitExtraTupleSlot(estate,
RelationGetDescr(rel->localrel),
&TTSOpsVirtual);
- localslot = ExecInitExtraTupleSlot(estate,
- RelationGetDescr(rel->localrel),
- &TTSOpsBufferHeapTuple);
+ localslot = table_gimmegimmeslot(rel->localrel, &estate->es_tupleTable);
EvalPlanQualInit(&epqstate, estate, NULL, NIL, -1);
PushActiveSnapshot(GetTransactionSnapshot());
indexInfo = BuildIndexInfo(indexRel);
/* some other stuff */
- slot = MakeSingleTupleTableSlot(RelationGetDescr(heapRel),
- &TTSOpsBufferHeapTuple);
+ slot = table_gimmegimmeslot(heapRel, NULL);
econtext->ecxt_scantuple = slot;
get_typlenbyval(vardata->atttype, &typLen, &typByVal);
InitNonVacuumableSnapshot(SnapshotNonVacuumable, RecentGlobalXmin);
TupleHashTable
TupleQueueReader
TupleTableSlot
+TupleTableSlotOps
TuplesortInstrumentation
TuplesortMethod
TuplesortSpaceType