From 3c993d1f59e89a1b0e537b4bc02e62d482bfe028 Mon Sep 17 00:00:00 2001 From: Hari Date: Fri, 9 Jun 2017 11:07:32 +1000 Subject: [PATCH 06/10] HeapTuple replace with StorageTuple Replace most of the executor flow of HeapTuple with StorageTuple and the necessary code around it. --- src/backend/commands/trigger.c | 39 +++--- src/backend/executor/execAmi.c | 2 +- src/backend/executor/execExprInterp.c | 16 +-- src/backend/executor/execIndexing.c | 10 +- src/backend/executor/execMain.c | 113 ++++++++--------- src/backend/executor/execReplication.c | 50 ++++---- src/backend/executor/functions.c | 4 +- src/backend/executor/nodeAgg.c | 4 +- src/backend/executor/nodeBitmapHeapscan.c | 18 ++- src/backend/executor/nodeForeignscan.c | 7 +- src/backend/executor/nodeGather.c | 8 +- src/backend/executor/nodeGatherMerge.c | 12 +- src/backend/executor/nodeIndexonlyscan.c | 4 +- src/backend/executor/nodeIndexscan.c | 16 +-- src/backend/executor/nodeLockRows.c | 22 ++-- src/backend/executor/nodeModifyTable.c | 193 ++++++++++++++++-------------- src/backend/executor/nodeSamplescan.c | 27 +++-- src/backend/executor/nodeSeqscan.c | 13 +- src/backend/executor/nodeTidscan.c | 16 +-- src/backend/executor/nodeWindowAgg.c | 4 +- src/backend/executor/spi.c | 20 ++-- src/backend/executor/tqueue.c | 22 ++-- src/include/access/htup_details.h | 2 +- src/include/access/relscan.h | 3 +- src/include/commands/trigger.h | 2 +- src/include/executor/executor.h | 7 +- src/include/executor/functions.h | 2 +- src/include/executor/spi.h | 10 +- src/include/executor/tqueue.h | 2 +- src/include/executor/tuptable.h | 6 +- src/include/funcapi.h | 2 +- src/include/nodes/execnodes.h | 4 +- 32 files changed, 337 insertions(+), 323 deletions(-) diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c index 0271788..8fa42d5 100644 --- a/src/backend/commands/trigger.c +++ b/src/backend/commands/trigger.c @@ -17,6 +17,7 @@ #include "access/heapam.h" #include "access/sysattr.h" #include "access/htup_details.h" +#include "access/storageamapi.h" #include "access/xact.h" #include "catalog/catalog.h" #include "catalog/dependency.h" @@ -2200,7 +2201,7 @@ ExecBRInsertTriggers(EState *estate, ResultRelInfo *relinfo, TupleTableSlot *slot) { TriggerDesc *trigdesc = relinfo->ri_TrigDesc; - HeapTuple slottuple = ExecMaterializeSlot(slot); + HeapTuple slottuple = ExecHeapifySlot(slot); HeapTuple newtuple = slottuple; HeapTuple oldtuple; TriggerData LocTriggerData; @@ -2263,14 +2264,18 @@ ExecBRInsertTriggers(EState *estate, ResultRelInfo *relinfo, void ExecARInsertTriggers(EState *estate, ResultRelInfo *relinfo, - HeapTuple trigtuple, List *recheckIndexes) + TupleTableSlot *slot, List *recheckIndexes) { TriggerDesc *trigdesc = relinfo->ri_TrigDesc; if (trigdesc && (trigdesc->trig_insert_after_row || trigdesc->trig_insert_new_table)) + { + HeapTuple trigtuple = ExecHeapifySlot(slot); + AfterTriggerSaveEvent(estate, relinfo, TRIGGER_EVENT_INSERT, true, NULL, trigtuple, recheckIndexes, NULL); + } } TupleTableSlot * @@ -2278,7 +2283,7 @@ ExecIRInsertTriggers(EState *estate, ResultRelInfo *relinfo, TupleTableSlot *slot) { TriggerDesc *trigdesc = relinfo->ri_TrigDesc; - HeapTuple slottuple = ExecMaterializeSlot(slot); + HeapTuple slottuple = ExecHeapifySlot(slot); HeapTuple newtuple = slottuple; HeapTuple oldtuple; TriggerData LocTriggerData; @@ -2621,7 +2626,7 @@ ExecBRUpdateTriggers(EState *estate, EPQState *epqstate, TupleTableSlot *slot) { TriggerDesc *trigdesc = relinfo->ri_TrigDesc; - HeapTuple slottuple = ExecMaterializeSlot(slot); + HeapTuple slottuple = ExecHeapifySlot(slot); HeapTuple newtuple = slottuple; TriggerData LocTriggerData; HeapTuple trigtuple; @@ -2663,7 +2668,7 @@ ExecBRUpdateTriggers(EState *estate, EPQState *epqstate, if (newSlot != NULL) { slot = ExecFilterJunk(relinfo->ri_junkFilter, newSlot); - slottuple = ExecMaterializeSlot(slot); + slottuple = ExecHeapifySlot(slot); newtuple = slottuple; } @@ -2768,7 +2773,7 @@ ExecIRUpdateTriggers(EState *estate, ResultRelInfo *relinfo, HeapTuple trigtuple, TupleTableSlot *slot) { TriggerDesc *trigdesc = relinfo->ri_TrigDesc; - HeapTuple slottuple = ExecMaterializeSlot(slot); + HeapTuple slottuple = ExecHeapifySlot(slot); HeapTuple newtuple = slottuple; TriggerData LocTriggerData; HeapTuple oldtuple; @@ -2920,7 +2925,8 @@ GetTupleForTrigger(EState *estate, */ ltrmark:; tuple.t_self = *tid; - test = heap_lock_tuple(relation, &tuple, + test = relation->rd_stamroutine->tuple_lock(relation, tid, + &tuple, estate->es_output_cid, lockmode, LockWaitBlock, false, &buffer, &hufd); @@ -3742,8 +3748,8 @@ AfterTriggerExecute(AfterTriggerEvent event, AfterTriggerShared evtshared = GetTriggerSharedData(event); Oid tgoid = evtshared->ats_tgoid; TriggerData LocTriggerData; - HeapTupleData tuple1; - HeapTupleData tuple2; + StorageTuple tuple1; + StorageTuple tuple2; HeapTuple rettuple; Buffer buffer1 = InvalidBuffer; Buffer buffer2 = InvalidBuffer; @@ -3804,14 +3810,13 @@ AfterTriggerExecute(AfterTriggerEvent event, * because we start with a minimal tuple that ExecFetchSlotTuple() * must materialize anyway. */ - LocTriggerData.tg_trigtuple = - ExecMaterializeSlot(trig_tuple_slot1); + LocTriggerData.tg_trigtuple = ExecHeapifySlot(trig_tuple_slot1); LocTriggerData.tg_trigtuplebuf = InvalidBuffer; LocTriggerData.tg_newtuple = ((evtshared->ats_event & TRIGGER_EVENT_OPMASK) == TRIGGER_EVENT_UPDATE) ? - ExecMaterializeSlot(trig_tuple_slot2) : NULL; + ExecHeapifySlot(trig_tuple_slot2) : NULL; LocTriggerData.tg_newtuplebuf = InvalidBuffer; break; @@ -3819,10 +3824,9 @@ AfterTriggerExecute(AfterTriggerEvent event, default: if (ItemPointerIsValid(&(event->ate_ctid1))) { - ItemPointerCopy(&(event->ate_ctid1), &(tuple1.t_self)); - if (!heap_fetch(rel, SnapshotAny, &tuple1, &buffer1, false, NULL)) + if (!rel->rd_stamroutine->tuple_fetch(rel, &(event->ate_ctid1), SnapshotAny, &tuple1, &buffer1, false, NULL)) elog(ERROR, "failed to fetch tuple1 for AFTER trigger"); - LocTriggerData.tg_trigtuple = &tuple1; + LocTriggerData.tg_trigtuple = tuple1; LocTriggerData.tg_trigtuplebuf = buffer1; } else @@ -3836,10 +3840,9 @@ AfterTriggerExecute(AfterTriggerEvent event, AFTER_TRIGGER_2CTID && ItemPointerIsValid(&(event->ate_ctid2))) { - ItemPointerCopy(&(event->ate_ctid2), &(tuple2.t_self)); - if (!heap_fetch(rel, SnapshotAny, &tuple2, &buffer2, false, NULL)) + if (!rel->rd_stamroutine->tuple_fetch(rel, &(event->ate_ctid2), SnapshotAny, &tuple2, &buffer2, false, NULL)) elog(ERROR, "failed to fetch tuple2 for AFTER trigger"); - LocTriggerData.tg_newtuple = &tuple2; + LocTriggerData.tg_newtuple = tuple2; LocTriggerData.tg_newtuplebuf = buffer2; } else diff --git a/src/backend/executor/execAmi.c b/src/backend/executor/execAmi.c index 7337d21..953284c 100644 --- a/src/backend/executor/execAmi.c +++ b/src/backend/executor/execAmi.c @@ -539,7 +539,7 @@ static bool IndexSupportsBackwardScan(Oid indexid) { bool result; - HeapTuple ht_idxrel; + StorageTuple ht_idxrel; Form_pg_class idxrelrec; IndexAmRoutine *amroutine; diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c index fed0052..1217304 100644 --- a/src/backend/executor/execExprInterp.c +++ b/src/backend/executor/execExprInterp.c @@ -2057,7 +2057,7 @@ ExecEvalRowNullInt(ExprState *state, ExprEvalStep *op, econtext); /* - * heap_attisnull needs a HeapTuple not a bare HeapTupleHeader. + * heap_attisnull needs a StorageTuple not a bare HeapTupleHeader. */ tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple); tmptup.t_data = tuple; @@ -2368,7 +2368,7 @@ ExecEvalArrayCoerce(ExprState *state, ExprEvalStep *op) void ExecEvalRow(ExprState *state, ExprEvalStep *op) { - HeapTuple tuple; + HeapTuple tuple; //hari /* build tuple from evaluated field values */ tuple = heap_form_tuple(op->d.row.tupdesc, @@ -2497,7 +2497,7 @@ ExecEvalFieldSelect(ExprState *state, ExprEvalStep *op, ExprContext *econtext) format_type_be(attr->atttypid), format_type_be(op->d.fieldselect.resulttype)))); - /* heap_getattr needs a HeapTuple not a bare HeapTupleHeader */ + /* heap_getattr needs a StorageTuple not a bare HeapTupleHeader */ tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple); tmptup.t_data = tuple; @@ -2540,7 +2540,7 @@ ExecEvalFieldStoreDeForm(ExprState *state, ExprEvalStep *op, ExprContext *econte else { /* - * heap_deform_tuple needs a HeapTuple not a bare HeapTupleHeader. We + * heap_deform_tuple needs a StorageTuple not a bare HeapTupleHeader. We * set all the fields in the struct just in case. */ Datum tupDatum = *op->resvalue; @@ -2566,7 +2566,7 @@ ExecEvalFieldStoreDeForm(ExprState *state, ExprEvalStep *op, ExprContext *econte void ExecEvalFieldStoreForm(ExprState *state, ExprEvalStep *op, ExprContext *econtext) { - HeapTuple tuple; + HeapTuple tuple; //hari /* argdesc should already be valid from the DeForm step */ tuple = heap_form_tuple(*op->d.fieldstore.argdesc, @@ -2781,7 +2781,7 @@ void ExecEvalConvertRowtype(ExprState *state, ExprEvalStep *op, ExprContext *econtext) { ConvertRowtypeExpr *convert = op->d.convert_rowtype.convert; - HeapTuple result; + HeapTuple result; //hari Datum tupDatum; HeapTupleHeader tuple; HeapTupleData tmptup; @@ -2840,7 +2840,7 @@ ExecEvalConvertRowtype(ExprState *state, ExprEvalStep *op, ExprContext *econtext MemoryContextSwitchTo(old_cxt); } - /* Following steps need a HeapTuple not a bare HeapTupleHeader */ + /* Following steps need a StorageTuple not a bare HeapTupleHeader */ tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple); tmptup.t_data = tuple; @@ -3345,7 +3345,7 @@ ExecEvalWholeRowVar(ExprState *state, ExprEvalStep *op, ExprContext *econtext) TupleDesc output_tupdesc; MemoryContext oldcontext; HeapTupleHeader dtuple; - HeapTuple tuple; + HeapTuple tuple; //hari /* This was checked by ExecInitExpr */ Assert(variable->varattno == InvalidAttrNumber); diff --git a/src/backend/executor/execIndexing.c b/src/backend/executor/execIndexing.c index 108060a..fe4c873 100644 --- a/src/backend/executor/execIndexing.c +++ b/src/backend/executor/execIndexing.c @@ -650,7 +650,7 @@ check_exclusion_or_unique_constraint(Relation heap, Relation index, Oid *index_collations = index->rd_indcollation; int index_natts = index->rd_index->indnatts; IndexScanDesc index_scan; - HeapTuple tup; + StorageTuple tup; ScanKeyData scankeys[INDEX_MAX_KEYS]; SnapshotData DirtySnapshot; int i; @@ -659,6 +659,7 @@ check_exclusion_or_unique_constraint(Relation heap, Relation index, ExprContext *econtext; TupleTableSlot *existing_slot; TupleTableSlot *save_scantuple; + StorageAmRoutine *method; if (indexInfo->ii_ExclusionOps) { @@ -711,6 +712,7 @@ check_exclusion_or_unique_constraint(Relation heap, Relation index, econtext = GetPerTupleExprContext(estate); save_scantuple = econtext->ecxt_scantuple; econtext->ecxt_scantuple = existing_slot; + method = heap->rd_stamroutine; /* * May have to restart scan from this point if a potential conflict is @@ -737,7 +739,7 @@ retry: * Ignore the entry for the tuple we're trying to check. */ if (ItemPointerIsValid(tupleid) && - ItemPointerEquals(tupleid, &tup->t_self)) + ItemPointerEquals(tupleid, method->tuple_get_itempointer(tup))) { if (found_self) /* should not happen */ elog(ERROR, "found self tuple multiple times in index \"%s\"", @@ -785,7 +787,7 @@ retry: DirtySnapshot.speculativeToken && TransactionIdPrecedes(GetCurrentTransactionId(), xwait)))) { - ctid_wait = tup->t_data->t_ctid; + ctid_wait = method->tuple_get_ctid(tup); reason_wait = indexInfo->ii_ExclusionOps ? XLTW_RecheckExclusionConstr : XLTW_InsertIndex; index_endscan(index_scan); @@ -805,7 +807,7 @@ retry: { conflict = true; if (conflictTid) - *conflictTid = tup->t_self; + *conflictTid = *(method->tuple_get_itempointer(tup)); break; } diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c index 4a899f1..3614513 100644 --- a/src/backend/executor/execMain.c +++ b/src/backend/executor/execMain.c @@ -1918,7 +1918,7 @@ ExecConstraints(ResultRelInfo *resultRelInfo, */ if (resultRelInfo->ri_PartitionRoot) { - HeapTuple tuple = ExecFetchSlotTuple(slot); + StorageTuple tuple = ExecFetchSlotTuple(slot); TupleConversionMap *map; rel = resultRelInfo->ri_PartitionRoot; @@ -1964,7 +1964,7 @@ ExecConstraints(ResultRelInfo *resultRelInfo, /* See the comment above. */ if (resultRelInfo->ri_PartitionRoot) { - HeapTuple tuple = ExecFetchSlotTuple(slot); + StorageTuple tuple = ExecFetchSlotTuple(slot); TupleDesc old_tupdesc = RelationGetDescr(rel); TupleConversionMap *map; @@ -2006,7 +2006,7 @@ ExecConstraints(ResultRelInfo *resultRelInfo, /* See the comment above. */ if (resultRelInfo->ri_PartitionRoot) { - HeapTuple tuple = ExecFetchSlotTuple(slot); + StorageTuple tuple = ExecFetchSlotTuple(slot); TupleDesc old_tupdesc = RelationGetDescr(rel); TupleConversionMap *map; @@ -2437,7 +2437,8 @@ EvalPlanQual(EState *estate, EPQState *epqstate, ItemPointer tid, TransactionId priorXmax) { TupleTableSlot *slot; - HeapTuple copyTuple; + StorageTuple copyTuple; + StorageAmRoutine *method; Assert(rti > 0); @@ -2450,11 +2451,14 @@ EvalPlanQual(EState *estate, EPQState *epqstate, if (copyTuple == NULL) return NULL; + method = relation->rd_stamroutine; + /* * For UPDATE/DELETE we have to return tid of actual row we're executing * PQ for. */ - *tid = copyTuple->t_self; + + *tid = *(method->tuple_get_itempointer(copyTuple)); /* * Need to run a recheck subquery. Initialize or reinitialize EPQ state. @@ -2485,7 +2489,7 @@ EvalPlanQual(EState *estate, EPQState *epqstate, * is to guard against early re-use of the EPQ query. */ if (!TupIsNull(slot)) - (void) ExecMaterializeSlot(slot); + ExecMaterializeSlot(slot); /* * Clear out the test tuple. This is needed in case the EPQ query is @@ -2518,13 +2522,13 @@ EvalPlanQual(EState *estate, EPQState *epqstate, * Note: properly, lockmode should be declared as enum LockTupleMode, * but we use "int" to avoid having to include heapam.h in executor.h. */ -HeapTuple +StorageTuple EvalPlanQualFetch(EState *estate, Relation relation, int lockmode, LockWaitPolicy wait_policy, ItemPointer tid, TransactionId priorXmax) { - HeapTuple copyTuple = NULL; - HeapTupleData tuple; + StorageAmRoutine *method = relation->rd_stamroutine; + StorageTuple tuple = NULL; SnapshotData SnapshotDirty; /* @@ -2533,12 +2537,12 @@ EvalPlanQualFetch(EState *estate, Relation relation, int lockmode, * Loop here to deal with updated or busy tuples */ InitDirtySnapshot(SnapshotDirty); - tuple.t_self = *tid; for (;;) { Buffer buffer; + ItemPointerData ctid; - if (heap_fetch(relation, &SnapshotDirty, &tuple, &buffer, true, NULL)) + if (method->tuple_fetch(relation, tid, &SnapshotDirty, &tuple, &buffer, true, NULL)) { HTSU_Result test; HeapUpdateFailureData hufd; @@ -2552,8 +2556,7 @@ EvalPlanQualFetch(EState *estate, Relation relation, int lockmode, * atomic, and Xmin never changes in an existing tuple, except to * invalid or frozen, and neither of those can match priorXmax.) */ - if (!TransactionIdEquals(HeapTupleHeaderGetXmin(tuple.t_data), - priorXmax)) + if (!TransactionIdEquals(method->tuple_get_xmin(tuple), priorXmax)) { ReleaseBuffer(buffer); return NULL; @@ -2574,7 +2577,8 @@ EvalPlanQualFetch(EState *estate, Relation relation, int lockmode, { case LockWaitBlock: XactLockTableWait(SnapshotDirty.xmax, - relation, &tuple.t_self, + relation, + tid, XLTW_FetchUpdated); break; case LockWaitSkip: @@ -2604,7 +2608,7 @@ EvalPlanQualFetch(EState *estate, Relation relation, int lockmode, * doing HeapTupleHeaderGetXmin again. */ if (TransactionIdIsCurrentTransactionId(priorXmax) && - HeapTupleHeaderGetCmin(tuple.t_data) >= estate->es_output_cid) + method->tuple_get_cmin(tuple) >= estate->es_output_cid) { ReleaseBuffer(buffer); return NULL; @@ -2613,10 +2617,10 @@ EvalPlanQualFetch(EState *estate, Relation relation, int lockmode, /* * This is a live tuple, so now try to lock it. */ - test = heap_lock_tuple(relation, &tuple, - estate->es_output_cid, - lockmode, wait_policy, - false, &buffer, &hufd); + test = method->tuple_lock(relation, tid, tuple, + estate->es_output_cid, + lockmode, wait_policy, + false, &buffer, &hufd); /* We now have two pins on the buffer, get rid of one */ ReleaseBuffer(buffer); @@ -2652,12 +2656,15 @@ EvalPlanQualFetch(EState *estate, Relation relation, int lockmode, (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE), errmsg("could not serialize access due to concurrent update"))); + +#if 0 //hari /* Should not encounter speculative tuple on recheck */ Assert(!HeapTupleHeaderIsSpeculative(tuple.t_data)); - if (!ItemPointerEquals(&hufd.ctid, &tuple.t_self)) +#endif + if (!ItemPointerEquals(&hufd.ctid, method->tuple_get_itempointer(tuple))) { /* it was updated, so look at the updated version */ - tuple.t_self = hufd.ctid; + *tid = hufd.ctid; /* updated row should have xmin matching this xmax */ priorXmax = hufd.xmax; continue; @@ -2679,10 +2686,6 @@ EvalPlanQualFetch(EState *estate, Relation relation, int lockmode, return NULL; /* keep compiler quiet */ } - /* - * We got tuple - now copy it for use by recheck query. - */ - copyTuple = heap_copytuple(&tuple); ReleaseBuffer(buffer); break; } @@ -2691,7 +2694,7 @@ EvalPlanQualFetch(EState *estate, Relation relation, int lockmode, * If the referenced slot was actually empty, the latest version of * the row must have been deleted, so we need do nothing. */ - if (tuple.t_data == NULL) + if (tuple == NULL) { ReleaseBuffer(buffer); return NULL; @@ -2700,7 +2703,7 @@ EvalPlanQualFetch(EState *estate, Relation relation, int lockmode, /* * As above, if xmin isn't what we're expecting, do nothing. */ - if (!TransactionIdEquals(HeapTupleHeaderGetXmin(tuple.t_data), + if (!TransactionIdEquals(method->tuple_get_xmin(tuple), priorXmax)) { ReleaseBuffer(buffer); @@ -2719,7 +2722,8 @@ EvalPlanQualFetch(EState *estate, Relation relation, int lockmode, * As above, it should be safe to examine xmax and t_ctid without the * buffer content lock, because they can't be changing. */ - if (ItemPointerEquals(&tuple.t_self, &tuple.t_data->t_ctid)) + ctid = method->tuple_get_ctid(tuple); + if (ItemPointerEquals(tid, &ctid)) { /* deleted, so forget about it */ ReleaseBuffer(buffer); @@ -2727,17 +2731,18 @@ EvalPlanQualFetch(EState *estate, Relation relation, int lockmode, } /* updated, so look at the updated row */ - tuple.t_self = tuple.t_data->t_ctid; + *tid = ctid; + /* updated row should have xmin matching this xmax */ - priorXmax = HeapTupleHeaderGetUpdateXid(tuple.t_data); + priorXmax = method->tuple_get_updated_xid(tuple); ReleaseBuffer(buffer); /* loop back to fetch next in chain */ } /* - * Return the copied tuple + * Return the tuple */ - return copyTuple; + return tuple; } /* @@ -2783,7 +2788,7 @@ EvalPlanQualSetPlan(EPQState *epqstate, Plan *subplan, List *auxrowmarks) * NB: passed tuple must be palloc'd; it may get freed later */ void -EvalPlanQualSetTuple(EPQState *epqstate, Index rti, HeapTuple tuple) +EvalPlanQualSetTuple(EPQState *epqstate, Index rti, StorageTuple tuple) { EState *estate = epqstate->estate; @@ -2802,7 +2807,7 @@ EvalPlanQualSetTuple(EPQState *epqstate, Index rti, HeapTuple tuple) /* * Fetch back the current test tuple (if any) for the specified RTI */ -HeapTuple +StorageTuple EvalPlanQualGetTuple(EPQState *epqstate, Index rti) { EState *estate = epqstate->estate; @@ -2830,7 +2835,7 @@ EvalPlanQualFetchRowMarks(EPQState *epqstate) ExecRowMark *erm = aerm->rowmark; Datum datum; bool isNull; - HeapTupleData tuple; + StorageTuple tuple; if (RowMarkRequiresRowShareLock(erm->markType)) elog(ERROR, "EvalPlanQual doesn't support locking rowmarks"); @@ -2861,8 +2866,6 @@ EvalPlanQualFetchRowMarks(EPQState *epqstate) if (erm->markType == ROW_MARK_REFERENCE) { - HeapTuple copyTuple; - Assert(erm->relation != NULL); /* fetch the tuple's ctid */ @@ -2886,11 +2889,11 @@ EvalPlanQualFetchRowMarks(EPQState *epqstate) (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("cannot lock rows in foreign table \"%s\"", RelationGetRelationName(erm->relation)))); - copyTuple = fdwroutine->RefetchForeignRow(epqstate->estate, + tuple = fdwroutine->RefetchForeignRow(epqstate->estate, erm, datum, &updated); - if (copyTuple == NULL) + if (tuple == NULL) elog(ERROR, "failed to fetch tuple for EvalPlanQual recheck"); /* @@ -2904,23 +2907,18 @@ EvalPlanQualFetchRowMarks(EPQState *epqstate) /* ordinary table, fetch the tuple */ Buffer buffer; - tuple.t_self = *((ItemPointer) DatumGetPointer(datum)); - if (!heap_fetch(erm->relation, SnapshotAny, &tuple, &buffer, + if (!erm->relation->rd_stamroutine->tuple_fetch(erm->relation, (ItemPointer) DatumGetPointer(datum), SnapshotAny, &tuple, &buffer, false, NULL)) elog(ERROR, "failed to fetch tuple for EvalPlanQual recheck"); - /* successful, copy tuple */ - copyTuple = heap_copytuple(&tuple); ReleaseBuffer(buffer); } /* store tuple */ - EvalPlanQualSetTuple(epqstate, erm->rti, copyTuple); + EvalPlanQualSetTuple(epqstate, erm->rti, tuple); } else { - HeapTupleHeader td; - Assert(erm->markType == ROW_MARK_COPY); /* fetch the whole-row Var for the relation */ @@ -2930,19 +2928,12 @@ EvalPlanQualFetchRowMarks(EPQState *epqstate) /* non-locked rels could be on the inside of outer joins */ if (isNull) continue; - td = DatumGetHeapTupleHeader(datum); - - /* build a temporary HeapTuple control structure */ - tuple.t_len = HeapTupleHeaderGetDatumLength(td); - tuple.t_data = td; - /* relation might be a foreign table, if so provide tableoid */ - tuple.t_tableOid = erm->relid; - /* also copy t_ctid in case there's valid data there */ - tuple.t_self = td->t_ctid; - - /* copy and store tuple */ - EvalPlanQualSetTuple(epqstate, erm->rti, - heap_copytuple(&tuple)); + + tuple = erm->relation->rd_stamroutine->tuple_from_datum(datum, erm->relid); + + /* store tuple */ + EvalPlanQualSetTuple(epqstate, erm->rti, tuple); + } } } @@ -3108,8 +3099,8 @@ EvalPlanQualStart(EPQState *epqstate, EState *parentestate, Plan *planTree) } else { - estate->es_epqTuple = (HeapTuple *) - palloc0(rtsize * sizeof(HeapTuple)); + estate->es_epqTuple = (StorageTuple *) + palloc0(rtsize * sizeof(StorageTuple)); estate->es_epqTupleSet = (bool *) palloc0(rtsize * sizeof(bool)); } diff --git a/src/backend/executor/execReplication.c b/src/backend/executor/execReplication.c index c6a66b6..206238a 100644 --- a/src/backend/executor/execReplication.c +++ b/src/backend/executor/execReplication.c @@ -116,7 +116,7 @@ RelationFindReplTupleByIndex(Relation rel, Oid idxoid, TupleTableSlot *searchslot, TupleTableSlot *outslot) { - HeapTuple scantuple; + StorageTuple scantuple; ScanKeyData skey[INDEX_MAX_KEYS]; IndexScanDesc scan; SnapshotData snap; @@ -169,12 +169,14 @@ retry: HeapUpdateFailureData hufd; HTSU_Result res; HeapTupleData locktup; + ItemPointer tid; - ItemPointerCopy(&outslot->tts_tuple->t_self, &locktup.t_self); + tid = outslot->tts_storageam->tuple_get_itempointer(outslot->tts_storage); + ItemPointerCopy(tid, &locktup.t_self); PushActiveSnapshot(GetLatestSnapshot()); - res = heap_lock_tuple(rel, &locktup, GetCurrentCommandId(false), + res = rel->rd_stamroutine->tuple_lock(rel, tid, &locktup, GetCurrentCommandId(false), lockmode, LockWaitBlock, false /* don't follow updates */ , @@ -219,7 +221,7 @@ retry: * to use. */ static bool -tuple_equals_slot(TupleDesc desc, HeapTuple tup, TupleTableSlot *slot) +tuple_equals_slot(TupleDesc desc, StorageTuple tup, TupleTableSlot *slot) { Datum values[MaxTupleAttributeNumber]; bool isnull[MaxTupleAttributeNumber]; @@ -267,7 +269,7 @@ bool RelationFindReplTupleSeq(Relation rel, LockTupleMode lockmode, TupleTableSlot *searchslot, TupleTableSlot *outslot) { - HeapTuple scantuple; + StorageTuple scantuple; HeapScanDesc scan; SnapshotData snap; TransactionId xwait; @@ -316,12 +318,14 @@ retry: HeapUpdateFailureData hufd; HTSU_Result res; HeapTupleData locktup; + ItemPointer tid; - ItemPointerCopy(&outslot->tts_tuple->t_self, &locktup.t_self); + tid = outslot->tts_storageam->tuple_get_itempointer(outslot->tts_storage); + ItemPointerCopy(tid, &locktup.t_self); PushActiveSnapshot(GetLatestSnapshot()); - res = heap_lock_tuple(rel, &locktup, GetCurrentCommandId(false), + res = rel->rd_stamroutine->tuple_lock(rel, tid, &locktup, GetCurrentCommandId(false), lockmode, LockWaitBlock, false /* don't follow updates */ , @@ -364,7 +368,7 @@ void ExecSimpleRelationInsert(EState *estate, TupleTableSlot *slot) { bool skip_tuple = false; - HeapTuple tuple; + StorageTuple tuple; ResultRelInfo *resultRelInfo = estate->es_result_relation_info; Relation rel = resultRelInfo->ri_RelationDesc; @@ -392,18 +396,18 @@ ExecSimpleRelationInsert(EState *estate, TupleTableSlot *slot) ExecConstraints(resultRelInfo, slot, estate); /* Store the slot into tuple that we can inspect. */ - tuple = ExecMaterializeSlot(slot); + tuple = ExecHeapifySlot(slot); /* OK, store the tuple and create index entries for it */ simple_heap_insert(rel, tuple); if (resultRelInfo->ri_NumIndices > 0) - recheckIndexes = ExecInsertIndexTuples(slot, &(tuple->t_self), + recheckIndexes = ExecInsertIndexTuples(slot, rel->rd_stamroutine->tuple_get_itempointer(tuple), estate, false, NULL, NIL); /* AFTER ROW INSERT Triggers */ - ExecARInsertTriggers(estate, resultRelInfo, tuple, + ExecARInsertTriggers(estate, resultRelInfo, slot, recheckIndexes); list_free(recheckIndexes); @@ -421,9 +425,10 @@ ExecSimpleRelationUpdate(EState *estate, EPQState *epqstate, TupleTableSlot *searchslot, TupleTableSlot *slot) { bool skip_tuple = false; - HeapTuple tuple; + StorageTuple tuple; ResultRelInfo *resultRelInfo = estate->es_result_relation_info; Relation rel = resultRelInfo->ri_RelationDesc; + ItemPointer tid = searchslot->tts_storageam->tuple_get_itempointer(searchslot->tts_storage); /* For now we support only tables. */ Assert(rel->rd_rel->relkind == RELKIND_RELATION); @@ -435,7 +440,7 @@ ExecSimpleRelationUpdate(EState *estate, EPQState *epqstate, resultRelInfo->ri_TrigDesc->trig_update_before_row) { slot = ExecBRUpdateTriggers(estate, epqstate, resultRelInfo, - &searchslot->tts_tuple->t_self, + tid, NULL, slot); if (slot == NULL) /* "do nothing" */ @@ -451,21 +456,19 @@ ExecSimpleRelationUpdate(EState *estate, EPQState *epqstate, ExecConstraints(resultRelInfo, slot, estate); /* Store the slot into tuple that we can write. */ - tuple = ExecMaterializeSlot(slot); + tuple = ExecHeapifySlot(slot); /* OK, update the tuple and index entries for it */ - simple_heap_update(rel, &searchslot->tts_tuple->t_self, - slot->tts_tuple); + simple_heap_update(rel, tid, tuple); - if (resultRelInfo->ri_NumIndices > 0 && - !HeapTupleIsHeapOnly(slot->tts_tuple)) - recheckIndexes = ExecInsertIndexTuples(slot, &(tuple->t_self), + if ((resultRelInfo->ri_NumIndices > 0) && rel->rd_stamroutine->tuple_is_heaponly(tuple)) + recheckIndexes = ExecInsertIndexTuples(slot, rel->rd_stamroutine->tuple_get_itempointer(tuple), estate, false, NULL, NIL); /* AFTER ROW UPDATE Triggers */ ExecARUpdateTriggers(estate, resultRelInfo, - &searchslot->tts_tuple->t_self, + tid, NULL, tuple, recheckIndexes); list_free(recheckIndexes); @@ -485,6 +488,7 @@ ExecSimpleRelationDelete(EState *estate, EPQState *epqstate, bool skip_tuple = false; ResultRelInfo *resultRelInfo = estate->es_result_relation_info; Relation rel = resultRelInfo->ri_RelationDesc; + ItemPointer tid = searchslot->tts_storageam->tuple_get_itempointer(searchslot->tts_storage); /* For now we support only tables. */ Assert(rel->rd_rel->relkind == RELKIND_RELATION); @@ -496,7 +500,7 @@ ExecSimpleRelationDelete(EState *estate, EPQState *epqstate, resultRelInfo->ri_TrigDesc->trig_update_before_row) { skip_tuple = !ExecBRDeleteTriggers(estate, epqstate, resultRelInfo, - &searchslot->tts_tuple->t_self, + tid, NULL); } @@ -505,11 +509,11 @@ ExecSimpleRelationDelete(EState *estate, EPQState *epqstate, List *recheckIndexes = NIL; /* OK, delete the tuple */ - simple_heap_delete(rel, &searchslot->tts_tuple->t_self); + simple_heap_delete(rel, tid); /* AFTER ROW DELETE Triggers */ ExecARDeleteTriggers(estate, resultRelInfo, - &searchslot->tts_tuple->t_self, NULL); + tid, NULL); list_free(recheckIndexes); } diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c index a35ba32..e2ab776 100644 --- a/src/backend/executor/functions.c +++ b/src/backend/executor/functions.c @@ -181,7 +181,7 @@ static void sqlfunction_destroy(DestReceiver *self); * polymorphic arguments. */ SQLFunctionParseInfoPtr -prepare_sql_fn_parse_info(HeapTuple procedureTuple, +prepare_sql_fn_parse_info(StorageTuple procedureTuple, Node *call_expr, Oid inputCollation) { @@ -596,7 +596,7 @@ init_sql_fcache(FmgrInfo *finfo, Oid collation, bool lazyEvalOK) MemoryContext fcontext; MemoryContext oldcontext; Oid rettype; - HeapTuple procedureTuple; + StorageTuple procedureTuple; Form_pg_proc procedureStruct; SQLFunctionCachePtr fcache; List *raw_parsetree_list; diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c index 7eeda95..a412402 100644 --- a/src/backend/executor/nodeAgg.c +++ b/src/backend/executor/nodeAgg.c @@ -3084,7 +3084,7 @@ ExecInitAgg(Agg *node, EState *estate, int eflags) Oid inputTypes[FUNC_MAX_ARGS]; int numArguments; int numDirectArgs; - HeapTuple aggTuple; + StorageTuple aggTuple; Form_pg_aggregate aggform; AclResult aclresult; Oid transfn_oid, @@ -3199,7 +3199,7 @@ ExecInitAgg(Agg *node, EState *estate, int eflags) /* Check that aggregate owner has permission to call component fns */ { - HeapTuple procTuple; + StorageTuple procTuple; Oid aggOwner; procTuple = SearchSysCache1(PROCOID, diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c index c453362..f8a4e7d 100644 --- a/src/backend/executor/nodeBitmapHeapscan.c +++ b/src/backend/executor/nodeBitmapHeapscan.c @@ -215,6 +215,7 @@ BitmapHeapNext(BitmapHeapScanState *node) * least AccessShareLock on the table before performing any of the * indexscans, but let's be safe.) */ + //hari --> need a fix to change the scan if (tbmres->blockno >= scan->rs_nblocks) { node->tbmres = tbmres = NULL; @@ -234,6 +235,7 @@ BitmapHeapNext(BitmapHeapScanState *node) /* * Set rs_cindex to first slot to examine */ + //hari scan->rs_cindex = 0; /* Adjust the prefetch target */ @@ -244,6 +246,7 @@ BitmapHeapNext(BitmapHeapScanState *node) /* * Continuing in previously obtained page; advance rs_cindex */ + //hari scan->rs_cindex++; #ifdef USE_PREFETCH @@ -271,6 +274,7 @@ BitmapHeapNext(BitmapHeapScanState *node) /* * Out of range? If so, nothing more to look at on this page */ + //hari if (scan->rs_cindex < 0 || scan->rs_cindex >= scan->rs_ntuples) { node->tbmres = tbmres = NULL; @@ -289,6 +293,8 @@ BitmapHeapNext(BitmapHeapScanState *node) /* * Okay to fetch the tuple */ + //hari +#if 1 targoffset = scan->rs_vistuples[scan->rs_cindex]; dp = (Page) BufferGetPage(scan->rs_cbuf); lp = PageGetItemId(dp, targoffset); @@ -309,7 +315,7 @@ BitmapHeapNext(BitmapHeapScanState *node) slot, scan->rs_cbuf, false); - +#endif /* * If we are using lossy info, we have to recheck the qual conditions * at every tuple. @@ -352,7 +358,8 @@ bitgetpage(HeapScanDesc scan, TBMIterateResult *tbmres) Buffer buffer; Snapshot snapshot; int ntup; - + //hari +#if 1 /* * Acquire pin on the target heap page, trading in any pin we held before. */ @@ -394,11 +401,11 @@ bitgetpage(HeapScanDesc scan, TBMIterateResult *tbmres) { OffsetNumber offnum = tbmres->offsets[curslot]; ItemPointerData tid; - HeapTupleData heapTuple; + HeapTupleData StorageTuple; ItemPointerSet(&tid, page, offnum); if (heap_hot_search_buffer(&tid, scan->rs_rd, buffer, snapshot, - &heapTuple, NULL, true)) + &StorageTuple, NULL, true)) scan->rs_vistuples[ntup++] = ItemPointerGetOffsetNumber(&tid); } } @@ -440,6 +447,7 @@ bitgetpage(HeapScanDesc scan, TBMIterateResult *tbmres) Assert(ntup <= MaxHeapTuplesPerPage); scan->rs_ntuples = ntup; +#endif } /* @@ -588,6 +596,7 @@ BitmapPrefetch(BitmapHeapScanState *node, HeapScanDesc scan) break; } node->prefetch_pages++; + //hari PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno); } } @@ -630,6 +639,7 @@ BitmapPrefetch(BitmapHeapScanState *node, HeapScanDesc scan) break; } + //hari PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno); } } diff --git a/src/backend/executor/nodeForeignscan.c b/src/backend/executor/nodeForeignscan.c index 9ae1561..424acac 100644 --- a/src/backend/executor/nodeForeignscan.c +++ b/src/backend/executor/nodeForeignscan.c @@ -61,11 +61,8 @@ ForeignNext(ForeignScanState *node) * tableoid, which is the only actually-useful system column. */ if (plan->fsSystemCol && !TupIsNull(slot)) - { - HeapTuple tup = ExecMaterializeSlot(slot); - - tup->t_tableOid = RelationGetRelid(node->ss.ss_currentRelation); - } + slot->tts_storageam->slot_update_tableoid(slot, + RelationGetRelid(node->ss.ss_currentRelation)); return slot; } diff --git a/src/backend/executor/nodeGather.c b/src/backend/executor/nodeGather.c index c1db2e2..cae003b 100644 --- a/src/backend/executor/nodeGather.c +++ b/src/backend/executor/nodeGather.c @@ -44,7 +44,7 @@ static TupleTableSlot *gather_getnext(GatherState *gatherstate); -static HeapTuple gather_readnext(GatherState *gatherstate); +static StorageTuple gather_readnext(GatherState *gatherstate); static void ExecShutdownGatherWorkers(GatherState *node); @@ -243,7 +243,7 @@ gather_getnext(GatherState *gatherstate) TupleTableSlot *outerTupleSlot; TupleTableSlot *fslot = gatherstate->funnel_slot; MemoryContext tupleContext = gatherstate->ps.ps_ExprContext->ecxt_per_tuple_memory; - HeapTuple tup; + StorageTuple tup; while (gatherstate->reader != NULL || gatherstate->need_to_scan_locally) { @@ -284,7 +284,7 @@ gather_getnext(GatherState *gatherstate) /* * Attempt to read a tuple from one of our parallel workers. */ -static HeapTuple +static StorageTuple gather_readnext(GatherState *gatherstate) { int nvisited = 0; @@ -292,7 +292,7 @@ gather_readnext(GatherState *gatherstate) for (;;) { TupleQueueReader *reader; - HeapTuple tup; + StorageTuple tup; bool readerdone; /* Check for async events, particularly messages from workers. */ diff --git a/src/backend/executor/nodeGatherMerge.c b/src/backend/executor/nodeGatherMerge.c index e066574..1f98939 100644 --- a/src/backend/executor/nodeGatherMerge.c +++ b/src/backend/executor/nodeGatherMerge.c @@ -31,7 +31,7 @@ */ typedef struct GMReaderTupleBuffer { - HeapTuple *tuple; + StorageTuple *tuple; int readCounter; int nTuples; bool done; @@ -46,7 +46,7 @@ typedef struct GMReaderTupleBuffer static int32 heap_compare_slots(Datum a, Datum b, void *arg); static TupleTableSlot *gather_merge_getnext(GatherMergeState *gm_state); -static HeapTuple gm_readnext_tuple(GatherMergeState *gm_state, int nreader, +static StorageTuple gm_readnext_tuple(GatherMergeState *gm_state, int nreader, bool nowait, bool *done); static void gather_merge_init(GatherMergeState *gm_state); static void ExecShutdownGatherMergeWorkers(GatherMergeState *node); @@ -369,7 +369,7 @@ gather_merge_init(GatherMergeState *gm_state) { /* Allocate the tuple array with MAX_TUPLE_STORE size */ gm_state->gm_tuple_buffers[i].tuple = - (HeapTuple *) palloc0(sizeof(HeapTuple) * MAX_TUPLE_STORE); + (StorageTuple *) palloc0(sizeof(StorageTuple) * MAX_TUPLE_STORE); /* Initialize slot for worker */ gm_state->gm_slots[i] = ExecInitExtraTupleSlot(gm_state->ps.state); @@ -531,7 +531,7 @@ static bool gather_merge_readnext(GatherMergeState *gm_state, int reader, bool nowait) { GMReaderTupleBuffer *tuple_buffer; - HeapTuple tup = NULL; + StorageTuple tup = NULL; /* * If we're being asked to generate a tuple from the leader, then we just @@ -606,12 +606,12 @@ gather_merge_readnext(GatherMergeState *gm_state, int reader, bool nowait) /* * Attempt to read a tuple from given reader. */ -static HeapTuple +static StorageTuple gm_readnext_tuple(GatherMergeState *gm_state, int nreader, bool nowait, bool *done) { TupleQueueReader *reader; - HeapTuple tup = NULL; + StorageTuple tup = NULL; MemoryContext oldContext; MemoryContext tupleContext; diff --git a/src/backend/executor/nodeIndexonlyscan.c b/src/backend/executor/nodeIndexonlyscan.c index 5550f6c..a5052de 100644 --- a/src/backend/executor/nodeIndexonlyscan.c +++ b/src/backend/executor/nodeIndexonlyscan.c @@ -115,7 +115,7 @@ IndexOnlyNext(IndexOnlyScanState *node) */ while ((tid = index_getnext_tid(scandesc, direction)) != NULL) { - HeapTuple tuple = NULL; + StorageTuple tuple = NULL; /* * We can skip the heap fetch if the TID references a heap page on @@ -182,7 +182,7 @@ IndexOnlyNext(IndexOnlyScanState *node) /* * Fill the scan tuple slot with data from the index. This might be - * provided in either HeapTuple or IndexTuple format. Conceivably an + * provided in either StorageTuple or IndexTuple format. Conceivably an * index AM might fill both fields, in which case we prefer the heap * format, since it's probably a bit cheaper to fill a slot from. */ diff --git a/src/backend/executor/nodeIndexscan.c b/src/backend/executor/nodeIndexscan.c index 5afd02e..b936c13 100644 --- a/src/backend/executor/nodeIndexscan.c +++ b/src/backend/executor/nodeIndexscan.c @@ -49,7 +49,7 @@ typedef struct { pairingheap_node ph_node; - HeapTuple htup; + StorageTuple htup; Datum *orderbyvals; bool *orderbynulls; } ReorderTuple; @@ -63,9 +63,9 @@ static int cmp_orderbyvals(const Datum *adist, const bool *anulls, IndexScanState *node); static int reorderqueue_cmp(const pairingheap_node *a, const pairingheap_node *b, void *arg); -static void reorderqueue_push(IndexScanState *node, HeapTuple tuple, +static void reorderqueue_push(IndexScanState *node, StorageTuple tuple, Datum *orderbyvals, bool *orderbynulls); -static HeapTuple reorderqueue_pop(IndexScanState *node); +static StorageTuple reorderqueue_pop(IndexScanState *node); /* ---------------------------------------------------------------- @@ -82,7 +82,7 @@ IndexNext(IndexScanState *node) ExprContext *econtext; ScanDirection direction; IndexScanDesc scandesc; - HeapTuple tuple; + StorageTuple tuple; TupleTableSlot *slot; /* @@ -181,7 +181,7 @@ IndexNextWithReorder(IndexScanState *node) EState *estate; ExprContext *econtext; IndexScanDesc scandesc; - HeapTuple tuple; + StorageTuple tuple; TupleTableSlot *slot; ReorderTuple *topmost = NULL; bool was_exact; @@ -475,7 +475,7 @@ reorderqueue_cmp(const pairingheap_node *a, const pairingheap_node *b, * Helper function to push a tuple to the reorder queue. */ static void -reorderqueue_push(IndexScanState *node, HeapTuple tuple, +reorderqueue_push(IndexScanState *node, StorageTuple tuple, Datum *orderbyvals, bool *orderbynulls) { IndexScanDesc scandesc = node->iss_ScanDesc; @@ -508,10 +508,10 @@ reorderqueue_push(IndexScanState *node, HeapTuple tuple, /* * Helper function to pop the next tuple from the reorder queue. */ -static HeapTuple +static StorageTuple reorderqueue_pop(IndexScanState *node) { - HeapTuple result; + StorageTuple result; ReorderTuple *topmost; int i; diff --git a/src/backend/executor/nodeLockRows.c b/src/backend/executor/nodeLockRows.c index 5630eae..d628a40 100644 --- a/src/backend/executor/nodeLockRows.c +++ b/src/backend/executor/nodeLockRows.c @@ -70,7 +70,7 @@ lnext: { ExecAuxRowMark *aerm = (ExecAuxRowMark *) lfirst(lc); ExecRowMark *erm = aerm->rowmark; - HeapTuple *testTuple; + StorageTuple *testTuple; Datum datum; bool isNull; HeapTupleData tuple; @@ -78,10 +78,10 @@ lnext: HeapUpdateFailureData hufd; LockTupleMode lockmode; HTSU_Result test; - HeapTuple copyTuple; + StorageTuple copyTuple; /* clear any leftover test tuple for this rel */ - testTuple = &(node->lr_curtuples[erm->rti - 1]); + testTuple = (StorageTuple)(&(node->lr_curtuples[erm->rti - 1])); if (*testTuple != NULL) heap_freetuple(*testTuple); *testTuple = NULL; @@ -176,7 +176,7 @@ lnext: break; } - test = heap_lock_tuple(erm->relation, &tuple, + test = erm->relation->rd_stamroutine->tuple_lock(erm->relation, &tuple.t_self, &tuple, estate->es_output_cid, lockmode, erm->waitPolicy, true, &buffer, &hufd); @@ -234,7 +234,7 @@ lnext: goto lnext; } /* remember the actually locked tuple's TID */ - tuple.t_self = copyTuple->t_self; + tuple.t_self = *(erm->relation->rd_stamroutine->tuple_get_itempointer(copyTuple)); /* Save locked tuple for EvalPlanQual testing below */ *testTuple = copyTuple; @@ -276,7 +276,7 @@ lnext: { ExecAuxRowMark *aerm = (ExecAuxRowMark *) lfirst(lc); ExecRowMark *erm = aerm->rowmark; - HeapTupleData tuple; + StorageTuple tuple; Buffer buffer; /* skip non-active child tables, but clear their test tuples */ @@ -304,14 +304,12 @@ lnext: Assert(ItemPointerIsValid(&(erm->curCtid))); /* okay, fetch the tuple */ - tuple.t_self = erm->curCtid; - if (!heap_fetch(erm->relation, SnapshotAny, &tuple, &buffer, + if (!erm->relation->rd_stamroutine->tuple_fetch(erm->relation, &erm->curCtid, SnapshotAny, &tuple, &buffer, false, NULL)) elog(ERROR, "failed to fetch tuple for EvalPlanQual recheck"); /* successful, copy and store tuple */ - EvalPlanQualSetTuple(&node->lr_epqstate, erm->rti, - heap_copytuple(&tuple)); + EvalPlanQualSetTuple(&node->lr_epqstate, erm->rti, tuple); ReleaseBuffer(buffer); } @@ -389,8 +387,8 @@ ExecInitLockRows(LockRows *node, EState *estate, int eflags) * Create workspace in which we can remember per-RTE locked tuples */ lrstate->lr_ntables = list_length(estate->es_range_table); - lrstate->lr_curtuples = (HeapTuple *) - palloc0(lrstate->lr_ntables * sizeof(HeapTuple)); + lrstate->lr_curtuples = (StorageTuple *) + palloc0(lrstate->lr_ntables * sizeof(StorageTuple)); /* * Locate the ExecRowMark(s) that this node is responsible for, and diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c index cf555fe..58827e0 100644 --- a/src/backend/executor/nodeModifyTable.c +++ b/src/backend/executor/nodeModifyTable.c @@ -38,6 +38,7 @@ #include "postgres.h" #include "access/htup_details.h" +#include "access/storageamapi.h" #include "access/xact.h" #include "commands/trigger.h" #include "executor/executor.h" @@ -163,15 +164,14 @@ ExecProcessReturning(ResultRelInfo *resultRelInfo, econtext->ecxt_scantuple = tupleSlot; else { - HeapTuple tuple; - /* * RETURNING expressions might reference the tableoid column, so * initialize t_tableOid before evaluating them. */ Assert(!TupIsNull(econtext->ecxt_scantuple)); - tuple = ExecMaterializeSlot(econtext->ecxt_scantuple); - tuple->t_tableOid = RelationGetRelid(resultRelInfo->ri_RelationDesc); + econtext->ecxt_scantuple->tts_storageam->slot_update_tableoid( + econtext->ecxt_scantuple, + RelationGetRelid(resultRelInfo->ri_RelationDesc)); } econtext->ecxt_outertuple = planSlot; @@ -189,7 +189,8 @@ ExecProcessReturning(ResultRelInfo *resultRelInfo, */ static void ExecCheckHeapTupleVisible(EState *estate, - HeapTuple tuple, + Relation rel, + StorageTuple tuple, Buffer buffer) { if (!IsolationUsesXactSnapshot()) @@ -208,7 +209,7 @@ ExecCheckHeapTupleVisible(EState *estate, * visible to our snapshot. (This would happen, for example, if * conflicting keys are proposed for insertion in a single command.) */ - if (!TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmin(tuple->t_data))) + if (!TransactionIdIsCurrentTransactionId(rel->rd_stamroutine->tuple_get_xmin(tuple))) ereport(ERROR, (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE), errmsg("could not serialize access due to concurrent update"))); @@ -226,16 +227,15 @@ ExecCheckTIDVisible(EState *estate, { Relation rel = relinfo->ri_RelationDesc; Buffer buffer; - HeapTupleData tuple; + StorageTuple tuple; /* Redundantly check isolation level */ if (!IsolationUsesXactSnapshot()) return; - tuple.t_self = *tid; - if (!heap_fetch(rel, SnapshotAny, &tuple, &buffer, false, NULL)) + if (!rel->rd_stamroutine->tuple_fetch(rel, tid, SnapshotAny, &tuple, &buffer, false, NULL)) elog(ERROR, "failed to fetch conflicting tuple for ON CONFLICT"); - ExecCheckHeapTupleVisible(estate, &tuple, buffer); + ExecCheckHeapTupleVisible(estate, rel, tuple, buffer); ReleaseBuffer(buffer); } @@ -257,21 +257,16 @@ ExecInsert(ModifyTableState *mtstate, EState *estate, bool canSetTag) { - HeapTuple tuple; + StorageTuple tuple; ResultRelInfo *resultRelInfo; ResultRelInfo *saved_resultRelInfo = NULL; Relation resultRelationDesc; + StorageAmRoutine *method; Oid newId; List *recheckIndexes = NIL; TupleTableSlot *result = NULL; /* - * get the heap tuple out of the tuple table slot, making sure we have a - * writable copy - */ - tuple = ExecMaterializeSlot(slot); - - /* * get information on the (current) result relation */ resultRelInfo = estate->es_result_relation_info; @@ -282,6 +277,8 @@ ExecInsert(ModifyTableState *mtstate, int leaf_part_index; TupleConversionMap *map; + tuple = ExecHeapifySlot(slot); + /* * Away we go ... If we end up not finding a partition after all, * ExecFindPartition() does not return and errors out instead. @@ -337,21 +334,35 @@ ExecInsert(ModifyTableState *mtstate, } resultRelationDesc = resultRelInfo->ri_RelationDesc; + method = resultRelationDesc->rd_stamroutine; /* - * If the result relation has OIDs, force the tuple's OID to zero so that - * heap_insert will assign a fresh OID. Usually the OID already will be - * zero at this point, but there are corner cases where the plan tree can - * return a tuple extracted literally from some table with the same - * rowtype. + * get the heap tuple out of the tuple table slot, making sure we have a + * writable copy <-- obsolete comment XXX explain what we really do here + * + * Do we really need to do this here? + */ + ExecMaterializeSlot(slot); + + + /* + * If the result relation uses heapam and has OIDs, force the tuple's OID + * to zero so that heap_insert will assign a fresh OID. Usually the OID + * already will be zero at this point, but there are corner cases where the + * plan tree can return a tuple extracted literally from some table with + * the same rowtype. * * XXX if we ever wanted to allow users to assign their own OIDs to new * rows, this'd be the place to do it. For the moment, we make a point of * doing this before calling triggers, so that a user-supplied trigger * could hack the OID if desired. */ - if (resultRelationDesc->rd_rel->relhasoids) - HeapTupleSetOid(tuple, InvalidOid); + if (resultRelationDesc->rd_rel->relam == HEAPAM_STORAGE_AM_OID && + resultRelationDesc->rd_rel->relhasoids) + { + slot->tts_tupleOid = InvalidOid; + slot->tts_storageam->slot_set_tuple_oid(slot, InvalidOid); + } /* * BEFORE ROW INSERT Triggers. @@ -369,9 +380,6 @@ ExecInsert(ModifyTableState *mtstate, if (slot == NULL) /* "do nothing" */ return NULL; - - /* trigger might have changed tuple */ - tuple = ExecMaterializeSlot(slot); } /* INSTEAD OF ROW INSERT Triggers */ @@ -383,9 +391,6 @@ ExecInsert(ModifyTableState *mtstate, if (slot == NULL) /* "do nothing" */ return NULL; - /* trigger might have changed tuple */ - tuple = ExecMaterializeSlot(slot); - newId = InvalidOid; } else if (resultRelInfo->ri_FdwRoutine) @@ -401,14 +406,12 @@ ExecInsert(ModifyTableState *mtstate, if (slot == NULL) /* "do nothing" */ return NULL; - /* FDW might have changed tuple */ - tuple = ExecMaterializeSlot(slot); - /* * AFTER ROW Triggers or RETURNING expressions might reference the * tableoid column, so initialize t_tableOid before evaluating them. */ - tuple->t_tableOid = RelationGetRelid(resultRelationDesc); + slot->tts_tableOid = RelationGetRelid(resultRelationDesc); + slot->tts_storageam->slot_update_tableoid(slot, slot->tts_tableOid); newId = InvalidOid; } @@ -418,7 +421,8 @@ ExecInsert(ModifyTableState *mtstate, * Constraints might reference the tableoid column, so initialize * t_tableOid before evaluating them. */ - tuple->t_tableOid = RelationGetRelid(resultRelationDesc); + slot->tts_tableOid = RelationGetRelid(resultRelationDesc); + slot->tts_storageam->slot_update_tableoid(slot, slot->tts_tableOid); /* * Check any RLS INSERT WITH CHECK policies @@ -440,6 +444,7 @@ ExecInsert(ModifyTableState *mtstate, { /* Perform a speculative insertion. */ uint32 specToken; + ItemPointerData newtid; ItemPointerData conflictTid; bool specConflict; @@ -502,24 +507,24 @@ ExecInsert(ModifyTableState *mtstate, * waiting for the whole transaction to complete. */ specToken = SpeculativeInsertionLockAcquire(GetCurrentTransactionId()); - HeapTupleHeaderSetSpeculativeToken(tuple->t_data, specToken); + method->tuple_set_speculative_token(slot, specToken); /* insert the tuple, with the speculative token */ - newId = heap_insert(resultRelationDesc, tuple, - estate->es_output_cid, - HEAP_INSERT_SPECULATIVE, - NULL); + newId = method->tuple_insert(resultRelationDesc, slot, + estate->es_output_cid, + HEAP_INSERT_SPECULATIVE, + NULL, &newtid); /* insert index entries for tuple */ - recheckIndexes = ExecInsertIndexTuples(slot, &(tuple->t_self), + recheckIndexes = ExecInsertIndexTuples(slot, &newtid, estate, true, &specConflict, arbiterIndexes); /* adjust the tuple's state accordingly */ if (!specConflict) - heap_finish_speculative(resultRelationDesc, tuple); + method->speculative_finish(resultRelationDesc, slot); else - heap_abort_speculative(resultRelationDesc, tuple); + method->speculative_abort(resultRelationDesc, slot); /* * Wake up anyone waiting for our decision. They will re-check @@ -545,19 +550,18 @@ ExecInsert(ModifyTableState *mtstate, } else { + ItemPointerData iptr; + /* * insert the tuple normally. - * - * Note: heap_insert returns the tid (location) of the new tuple - * in the t_self field. */ - newId = heap_insert(resultRelationDesc, tuple, - estate->es_output_cid, - 0, NULL); + newId = method->tuple_insert(resultRelationDesc, slot, + estate->es_output_cid, + 0, NULL, &iptr); /* insert index entries for tuple */ if (resultRelInfo->ri_NumIndices > 0) - recheckIndexes = ExecInsertIndexTuples(slot, &(tuple->t_self), + recheckIndexes = ExecInsertIndexTuples(slot, &iptr, estate, false, NULL, arbiterIndexes); } @@ -567,11 +571,11 @@ ExecInsert(ModifyTableState *mtstate, { (estate->es_processed)++; estate->es_lastoid = newId; - setLastTid(&(tuple->t_self)); + setLastTid(method->tuple_get_itempointer(tuple)); } /* AFTER ROW INSERT Triggers */ - ExecARInsertTriggers(estate, resultRelInfo, tuple, recheckIndexes); + ExecARInsertTriggers(estate, resultRelInfo, slot, recheckIndexes); list_free(recheckIndexes); @@ -620,7 +624,7 @@ ExecInsert(ModifyTableState *mtstate, */ static TupleTableSlot * ExecDelete(ItemPointer tupleid, - HeapTuple oldtuple, + StorageTuple oldtuple, TupleTableSlot *planSlot, EPQState *epqstate, EState *estate, @@ -631,12 +635,14 @@ ExecDelete(ItemPointer tupleid, HTSU_Result result; HeapUpdateFailureData hufd; TupleTableSlot *slot = NULL; + StorageAmRoutine *method; /* * get information on the (current) result relation */ resultRelInfo = estate->es_result_relation_info; resultRelationDesc = resultRelInfo->ri_RelationDesc; + method = resultRelationDesc->rd_stamroutine; /* BEFORE ROW DELETE Triggers */ if (resultRelInfo->ri_TrigDesc && @@ -665,8 +671,6 @@ ExecDelete(ItemPointer tupleid, } else if (resultRelInfo->ri_FdwRoutine) { - HeapTuple tuple; - /* * delete from foreign table: let the FDW do it * @@ -676,7 +680,8 @@ ExecDelete(ItemPointer tupleid, */ slot = estate->es_trig_tuple_slot; if (slot->tts_tupleDescriptor != RelationGetDescr(resultRelationDesc)) - ExecSetSlotDescriptor(slot, RelationGetDescr(resultRelationDesc)); + ExecSetSlotDescriptor(slot, + RelationGetDescr(resultRelationDesc)); slot = resultRelInfo->ri_FdwRoutine->ExecForeignDelete(estate, resultRelInfo, @@ -692,8 +697,10 @@ ExecDelete(ItemPointer tupleid, */ if (slot->tts_isempty) ExecStoreAllNullTuple(slot); - tuple = ExecMaterializeSlot(slot); - tuple->t_tableOid = RelationGetRelid(resultRelationDesc); + + ExecMaterializeSlot(slot); + + slot->tts_tableOid = RelationGetRelid(resultRelationDesc); } else { @@ -707,11 +714,11 @@ ExecDelete(ItemPointer tupleid, * mode transactions. */ ldelete:; - result = heap_delete(resultRelationDesc, tupleid, - estate->es_output_cid, - estate->es_crosscheck_snapshot, - true /* wait for commit */ , - &hufd); + result = method->tuple_delete(resultRelationDesc, tupleid, + estate->es_output_cid, + estate->es_crosscheck_snapshot, + true /* wait for commit */ , + &hufd); switch (result) { case HeapTupleSelfUpdated: @@ -806,7 +813,7 @@ ldelete:; * gotta fetch it. We can use the trigger tuple slot. */ TupleTableSlot *rslot; - HeapTupleData deltuple; + StorageTuple deltuple = NULL; Buffer delbuffer; if (resultRelInfo->ri_FdwRoutine) @@ -820,20 +827,20 @@ ldelete:; slot = estate->es_trig_tuple_slot; if (oldtuple != NULL) { - deltuple = *oldtuple; + deltuple = heap_copytuple(oldtuple); delbuffer = InvalidBuffer; } else { - deltuple.t_self = *tupleid; - if (!heap_fetch(resultRelationDesc, SnapshotAny, - &deltuple, &delbuffer, false, NULL)) + if (!method->tuple_fetch(resultRelationDesc, tupleid, SnapshotAny, + &deltuple, &delbuffer, false, NULL)) elog(ERROR, "failed to fetch deleted tuple for DELETE RETURNING"); } if (slot->tts_tupleDescriptor != RelationGetDescr(resultRelationDesc)) - ExecSetSlotDescriptor(slot, RelationGetDescr(resultRelationDesc)); - ExecStoreTuple(&deltuple, slot, InvalidBuffer, false); + ExecSetSlotDescriptor(slot, + RelationGetDescr(resultRelationDesc)); + ExecStoreTuple(deltuple, slot, InvalidBuffer, false); } rslot = ExecProcessReturning(resultRelInfo, slot, planSlot); @@ -878,16 +885,17 @@ ldelete:; */ static TupleTableSlot * ExecUpdate(ItemPointer tupleid, - HeapTuple oldtuple, + StorageTuple oldtuple, TupleTableSlot *slot, TupleTableSlot *planSlot, EPQState *epqstate, EState *estate, bool canSetTag) { - HeapTuple tuple; + StorageTuple tuple; ResultRelInfo *resultRelInfo; Relation resultRelationDesc; + StorageAmRoutine *method; HTSU_Result result; HeapUpdateFailureData hufd; List *recheckIndexes = NIL; @@ -902,13 +910,14 @@ ExecUpdate(ItemPointer tupleid, * get the heap tuple out of the tuple table slot, making sure we have a * writable copy */ - tuple = ExecMaterializeSlot(slot); + tuple = ExecHeapifySlot(slot); /* * get information on the (current) result relation */ resultRelInfo = estate->es_result_relation_info; resultRelationDesc = resultRelInfo->ri_RelationDesc; + method = resultRelationDesc->rd_stamroutine; /* BEFORE ROW UPDATE Triggers */ if (resultRelInfo->ri_TrigDesc && @@ -921,7 +930,7 @@ ExecUpdate(ItemPointer tupleid, return NULL; /* trigger might have changed tuple */ - tuple = ExecMaterializeSlot(slot); + tuple = ExecHeapifySlot(slot); } /* INSTEAD OF ROW UPDATE Triggers */ @@ -935,7 +944,7 @@ ExecUpdate(ItemPointer tupleid, return NULL; /* trigger might have changed tuple */ - tuple = ExecMaterializeSlot(slot); + tuple = ExecHeapifySlot(slot); } else if (resultRelInfo->ri_FdwRoutine) { @@ -950,24 +959,25 @@ ExecUpdate(ItemPointer tupleid, if (slot == NULL) /* "do nothing" */ return NULL; - /* FDW might have changed tuple */ - tuple = ExecMaterializeSlot(slot); - /* * AFTER ROW Triggers or RETURNING expressions might reference the * tableoid column, so initialize t_tableOid before evaluating them. */ - tuple->t_tableOid = RelationGetRelid(resultRelationDesc); + slot->tts_storageam->slot_update_tableoid(slot, RelationGetRelid(resultRelationDesc)); + + /* FDW might have changed tuple */ + tuple = ExecHeapifySlot(slot); } else { LockTupleMode lockmode; + ItemPointerData newtid; /* * Constraints might reference the tableoid column, so initialize * t_tableOid before evaluating them. */ - tuple->t_tableOid = RelationGetRelid(resultRelationDesc); + slot->tts_tableOid = RelationGetRelid(resultRelationDesc); /* * Check any RLS UPDATE WITH CHECK policies @@ -1003,11 +1013,11 @@ lreplace:; * needed for referential integrity updates in transaction-snapshot * mode transactions. */ - result = heap_update(resultRelationDesc, tupleid, tuple, - estate->es_output_cid, - estate->es_crosscheck_snapshot, - true /* wait for commit */ , - &hufd, &lockmode); + result = method->tuple_update(resultRelationDesc, tupleid, slot, + estate->es_output_cid, + estate->es_crosscheck_snapshot, + true /* wait for commit */ , + &hufd, &lockmode, &newtid); switch (result) { case HeapTupleSelfUpdated: @@ -1045,6 +1055,7 @@ lreplace:; return NULL; case HeapTupleMayBeUpdated: + ItemPointerCopy(method->tuple_get_itempointer(tuple), &newtid); break; case HeapTupleUpdated: @@ -1067,7 +1078,7 @@ lreplace:; { *tupleid = hufd.ctid; slot = ExecFilterJunk(resultRelInfo->ri_junkFilter, epqslot); - tuple = ExecMaterializeSlot(slot); + tuple = ExecHeapifySlot(slot); goto lreplace; } } @@ -1095,8 +1106,8 @@ lreplace:; * * If it's a HOT update, we mustn't insert new index entries. */ - if (resultRelInfo->ri_NumIndices > 0 && !HeapTupleIsHeapOnly(tuple)) - recheckIndexes = ExecInsertIndexTuples(slot, &(tuple->t_self), + if ((resultRelInfo->ri_NumIndices > 0) && !method->tuple_is_heaponly(tuple)) + recheckIndexes = ExecInsertIndexTuples(slot, method->tuple_get_itempointer(tuple), estate, false, NULL, NIL); } @@ -1168,7 +1179,7 @@ ExecOnConflictUpdate(ModifyTableState *mtstate, * true anymore. */ tuple.t_self = *conflictTid; - test = heap_lock_tuple(relation, &tuple, estate->es_output_cid, + test = relation->rd_stamroutine->tuple_lock(relation, conflictTid, &tuple, estate->es_output_cid, lockmode, LockWaitBlock, false, &buffer, &hufd); switch (test) @@ -1254,7 +1265,7 @@ ExecOnConflictUpdate(ModifyTableState *mtstate, * snapshot. This is in line with the way UPDATE deals with newer tuple * versions. */ - ExecCheckHeapTupleVisible(estate, &tuple, buffer); + ExecCheckHeapTupleVisible(estate, relation, &tuple, buffer); /* Store target's existing tuple in the state's dedicated slot */ ExecStoreTuple(&tuple, mtstate->mt_existing, buffer, false); @@ -1416,7 +1427,7 @@ ExecModifyTable(ModifyTableState *node) ItemPointer tupleid = NULL; ItemPointerData tuple_ctid; HeapTupleData oldtupdata; - HeapTuple oldtuple; + StorageTuple oldtuple; /* * This should NOT get called during EvalPlanQual; we should have passed a diff --git a/src/backend/executor/nodeSamplescan.c b/src/backend/executor/nodeSamplescan.c index 0247bd2..51fb182 100644 --- a/src/backend/executor/nodeSamplescan.c +++ b/src/backend/executor/nodeSamplescan.c @@ -29,9 +29,9 @@ static void InitScanRelation(SampleScanState *node, EState *estate, int eflags); static TupleTableSlot *SampleNext(SampleScanState *node); static void tablesample_init(SampleScanState *scanstate); -static HeapTuple tablesample_getnext(SampleScanState *scanstate); -static bool SampleTupleVisible(HeapTuple tuple, OffsetNumber tupoffset, - HeapScanDesc scan); +static StorageTuple tablesample_getnext(SampleScanState *scanstate); +static bool SampleTupleVisible(StorageTuple tuple, OffsetNumber tupoffset, + HeapScanDesc scan); //hari /* ---------------------------------------------------------------- * Scan Support @@ -47,7 +47,7 @@ static bool SampleTupleVisible(HeapTuple tuple, OffsetNumber tupoffset, static TupleTableSlot * SampleNext(SampleScanState *node) { - HeapTuple tuple; + StorageTuple tuple; TupleTableSlot *slot; /* @@ -66,7 +66,8 @@ SampleNext(SampleScanState *node) if (tuple) ExecStoreTuple(tuple, /* tuple to store */ slot, /* slot to store in */ - node->ss.ss_currentScanDesc->rs_cbuf, /* tuple's buffer */ + //harinode->ss.ss_currentScanDesc->rs_cbuf, /* tuple's buffer */ + InvalidBuffer, false); /* don't pfree this pointer */ else ExecClearTuple(slot); @@ -125,7 +126,7 @@ InitScanRelation(SampleScanState *node, EState *estate, int eflags) node->ss.ss_currentRelation = currentRelation; - /* we won't set up the HeapScanDesc till later */ + /* we won't set up the StorageScanDesc till later */ node->ss.ss_currentScanDesc = NULL; /* and report the scan tuple slot's rowtype */ @@ -342,7 +343,7 @@ tablesample_init(SampleScanState *scanstate) /* We'll use syncscan if there's no NextSampleBlock function */ allow_sync = (tsm->NextSampleBlock == NULL); - /* Now we can create or reset the HeapScanDesc */ + /* Now we can create or reset the StorageScanDesc */ if (scanstate->ss.ss_currentScanDesc == NULL) { scanstate->ss.ss_currentScanDesc = @@ -373,12 +374,12 @@ tablesample_init(SampleScanState *scanstate) * Note: an awful lot of this is copied-and-pasted from heapam.c. It would * perhaps be better to refactor to share more code. */ -static HeapTuple +static StorageTuple tablesample_getnext(SampleScanState *scanstate) { TsmRoutine *tsm = scanstate->tsmroutine; - HeapScanDesc scan = scanstate->ss.ss_currentScanDesc; - HeapTuple tuple = &(scan->rs_ctup); + HeapScanDesc scan = scanstate->ss.ss_currentScanDesc; //hari + HeapTuple tuple = &(scan->rs_ctup); //hari Snapshot snapshot = scan->rs_snapshot; bool pagemode = scan->rs_pageatatime; BlockNumber blockno; @@ -409,7 +410,7 @@ tablesample_getnext(SampleScanState *scanstate) else blockno = scan->rs_startblock; Assert(blockno < scan->rs_nblocks); - heapgetpage(scan, blockno); + //heapgetpage(scan, blockno); //hari scan->rs_inited = true; } else @@ -530,7 +531,7 @@ tablesample_getnext(SampleScanState *scanstate) } Assert(blockno < scan->rs_nblocks); - heapgetpage(scan, blockno); + //heapgetpage(scan, blockno); //hari /* Re-establish state for new page */ if (!pagemode) @@ -551,7 +552,7 @@ tablesample_getnext(SampleScanState *scanstate) * Check visibility of the tuple. */ static bool -SampleTupleVisible(HeapTuple tuple, OffsetNumber tupoffset, HeapScanDesc scan) +SampleTupleVisible(StorageTuple tuple, OffsetNumber tupoffset, HeapScanDesc scan) //hari { if (scan->rs_pageatatime) { diff --git a/src/backend/executor/nodeSeqscan.c b/src/backend/executor/nodeSeqscan.c index 5680464..9cba6b3 100644 --- a/src/backend/executor/nodeSeqscan.c +++ b/src/backend/executor/nodeSeqscan.c @@ -48,8 +48,8 @@ static TupleTableSlot *SeqNext(SeqScanState *node); static TupleTableSlot * SeqNext(SeqScanState *node) { - HeapTuple tuple; - HeapScanDesc scandesc; + void *tuple; + StorageScanDesc scandesc; EState *estate; ScanDirection direction; TupleTableSlot *slot; @@ -90,8 +90,9 @@ SeqNext(SeqScanState *node) if (tuple) ExecStoreTuple(tuple, /* tuple to store */ slot, /* slot to store in */ - scandesc->rs_cbuf, /* buffer associated with this - * tuple */ + //hariscandesc->rs_cbuf, /* buffer associated with this + // * tuple */ + InvalidBuffer, false); /* don't pfree this pointer */ else ExecClearTuple(slot); @@ -221,7 +222,7 @@ void ExecEndSeqScan(SeqScanState *node) { Relation relation; - HeapScanDesc scanDesc; + StorageScanDesc scanDesc; /* * get information from node @@ -266,7 +267,7 @@ ExecEndSeqScan(SeqScanState *node) void ExecReScanSeqScan(SeqScanState *node) { - HeapScanDesc scan; + StorageScanDesc scan; scan = node->ss.ss_currentScanDesc; diff --git a/src/backend/executor/nodeTidscan.c b/src/backend/executor/nodeTidscan.c index 4860ec0..a97993c 100644 --- a/src/backend/executor/nodeTidscan.c +++ b/src/backend/executor/nodeTidscan.c @@ -305,7 +305,7 @@ TidNext(TidScanState *node) ScanDirection direction; Snapshot snapshot; Relation heapRelation; - HeapTuple tuple; + StorageTuple tuple; TupleTableSlot *slot; Buffer buffer = InvalidBuffer; ItemPointerData *tidList; @@ -331,12 +331,6 @@ TidNext(TidScanState *node) numTids = node->tss_NumTids; /* - * We use node->tss_htup as the tuple pointer; note this can't just be a - * local variable here, as the scan tuple slot will keep a pointer to it. - */ - tuple = &(node->tss_htup); - - /* * Initialize or advance scan position, depending on direction. */ bBackward = ScanDirectionIsBackward(direction); @@ -363,7 +357,7 @@ TidNext(TidScanState *node) while (node->tss_TidPtr >= 0 && node->tss_TidPtr < numTids) { - tuple->t_self = tidList[node->tss_TidPtr]; + ItemPointerData tid = tidList[node->tss_TidPtr]; /* * For WHERE CURRENT OF, the tuple retrieved from the cursor might @@ -371,9 +365,9 @@ TidNext(TidScanState *node) * current according to our snapshot. */ if (node->tss_isCurrentOf) - heap_get_latest_tid(heapRelation, snapshot, &tuple->t_self); + heap_get_latest_tid(heapRelation, snapshot, &tid); - if (heap_fetch(heapRelation, snapshot, tuple, &buffer, false, NULL)) + if (heapRelation->rd_stamroutine->tuple_fetch(heapRelation, &tid, snapshot, &tuple, &buffer, false, NULL)) { /* * store the scanned tuple in the scan tuple slot of the scan @@ -385,7 +379,7 @@ TidNext(TidScanState *node) ExecStoreTuple(tuple, /* tuple to store */ slot, /* slot to store in */ buffer, /* buffer associated with tuple */ - false); /* don't pfree */ + true); /* don't pfree */ /* * At this point we have an extra pin on the buffer, because diff --git a/src/backend/executor/nodeWindowAgg.c b/src/backend/executor/nodeWindowAgg.c index 628bc9f..d1d73bf 100644 --- a/src/backend/executor/nodeWindowAgg.c +++ b/src/backend/executor/nodeWindowAgg.c @@ -2087,7 +2087,7 @@ initialize_peragg(WindowAggState *winstate, WindowFunc *wfunc, { Oid inputTypes[FUNC_MAX_ARGS]; int numArguments; - HeapTuple aggTuple; + StorageTuple aggTuple; Form_pg_aggregate aggform; Oid aggtranstype; AttrNumber initvalAttNo; @@ -2155,7 +2155,7 @@ initialize_peragg(WindowAggState *winstate, WindowFunc *wfunc, /* Check that aggregate owner has permission to call component fns */ { - HeapTuple procTuple; + StorageTuple procTuple; Oid aggOwner; procTuple = SearchSysCache1(PROCOID, diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c index 97c3925..996f129 100644 --- a/src/backend/executor/spi.c +++ b/src/backend/executor/spi.c @@ -627,11 +627,11 @@ SPI_freeplan(SPIPlanPtr plan) return 0; } -HeapTuple -SPI_copytuple(HeapTuple tuple) +StorageTuple +SPI_copytuple(StorageTuple tuple) { MemoryContext oldcxt; - HeapTuple ctuple; + StorageTuple ctuple; if (tuple == NULL) { @@ -655,7 +655,7 @@ SPI_copytuple(HeapTuple tuple) } HeapTupleHeader -SPI_returntuple(HeapTuple tuple, TupleDesc tupdesc) +SPI_returntuple(StorageTuple tuple, TupleDesc tupdesc) { MemoryContext oldcxt; HeapTupleHeader dtup; @@ -686,7 +686,7 @@ SPI_returntuple(HeapTuple tuple, TupleDesc tupdesc) return dtup; } -HeapTuple +StorageTuple SPI_modifytuple(Relation rel, HeapTuple tuple, int natts, int *attnum, Datum *Values, const char *Nulls) { @@ -852,7 +852,7 @@ char * SPI_gettype(TupleDesc tupdesc, int fnumber) { Oid typoid; - HeapTuple typeTuple; + StorageTuple typeTuple; char *result; SPI_result = 0; @@ -960,7 +960,7 @@ SPI_datumTransfer(Datum value, bool typByVal, int typLen) } void -SPI_freetuple(HeapTuple tuple) +SPI_freetuple(StorageTuple tuple) { /* No longer need to worry which context tuple was in... */ heap_freetuple(tuple); @@ -1681,7 +1681,7 @@ spi_dest_startup(DestReceiver *self, int operation, TupleDesc typeinfo) /* set up initial allocations */ tuptable->alloced = tuptable->free = 128; - tuptable->vals = (HeapTuple *) palloc(tuptable->alloced * sizeof(HeapTuple)); + tuptable->vals = (StorageTuple *) palloc(tuptable->alloced * sizeof(StorageTuple)); tuptable->tupdesc = CreateTupleDescCopy(typeinfo); MemoryContextSwitchTo(oldcxt); @@ -1712,8 +1712,8 @@ spi_printtup(TupleTableSlot *slot, DestReceiver *self) /* Double the size of the pointer array */ tuptable->free = tuptable->alloced; tuptable->alloced += tuptable->free; - tuptable->vals = (HeapTuple *) repalloc_huge(tuptable->vals, - tuptable->alloced * sizeof(HeapTuple)); + tuptable->vals = (StorageTuple *) repalloc_huge(tuptable->vals, + tuptable->alloced * sizeof(StorageTuple)); } tuptable->vals[tuptable->alloced - tuptable->free] = diff --git a/src/backend/executor/tqueue.c b/src/backend/executor/tqueue.c index 8d7e711..16adf26 100644 --- a/src/backend/executor/tqueue.c +++ b/src/backend/executor/tqueue.c @@ -192,12 +192,12 @@ static void TQSendRecordInfo(TQueueDestReceiver *tqueue, int32 typmod, TupleDesc tupledesc); static void TupleQueueHandleControlMessage(TupleQueueReader *reader, Size nbytes, char *data); -static HeapTuple TupleQueueHandleDataMessage(TupleQueueReader *reader, +static StorageTuple TupleQueueHandleDataMessage(TupleQueueReader *reader, Size nbytes, HeapTupleHeader data); -static HeapTuple TQRemapTuple(TupleQueueReader *reader, +static StorageTuple TQRemapTuple(TupleQueueReader *reader, TupleDesc tupledesc, TupleRemapInfo **field_remapinfo, - HeapTuple tuple); + StorageTuple tuple); static Datum TQRemap(TupleQueueReader *reader, TupleRemapInfo *remapinfo, Datum value, bool *changed); static Datum TQRemapArray(TupleQueueReader *reader, ArrayRemapInfo *remapinfo, @@ -225,7 +225,7 @@ tqueueReceiveSlot(TupleTableSlot *slot, DestReceiver *self) { TQueueDestReceiver *tqueue = (TQueueDestReceiver *) self; TupleDesc tupledesc = slot->tts_tupleDescriptor; - HeapTuple tuple; + HeapTuple tuple; //hari shm_mq_result result; /* @@ -305,7 +305,7 @@ tqueueReceiveSlot(TupleTableSlot *slot, DestReceiver *self) } /* Send the tuple itself. */ - tuple = ExecMaterializeSlot(slot); + tuple = ExecHeapifySlot(slot); result = shm_mq_send(tqueue->queue, tuple->t_len, tuple->t_data, false); /* Check for failure. */ @@ -675,7 +675,7 @@ DestroyTupleQueueReader(TupleQueueReader *reader) * accumulate bytes from a partially-read message, so it's useful to call * this with nowait = true even if nothing is returned. */ -HeapTuple +StorageTuple TupleQueueReaderNext(TupleQueueReader *reader, bool nowait, bool *done) { shm_mq_result result; @@ -730,7 +730,7 @@ TupleQueueReaderNext(TupleQueueReader *reader, bool nowait, bool *done) /* * Handle a data message - that is, a tuple - from the remote side. */ -static HeapTuple +static StorageTuple TupleQueueHandleDataMessage(TupleQueueReader *reader, Size nbytes, HeapTupleHeader data) @@ -759,11 +759,11 @@ TupleQueueHandleDataMessage(TupleQueueReader *reader, /* * Copy the given tuple, remapping any transient typmods contained in it. */ -static HeapTuple +static StorageTuple TQRemapTuple(TupleQueueReader *reader, TupleDesc tupledesc, TupleRemapInfo **field_remapinfo, - HeapTuple tuple) + StorageTuple tuple) { Datum *values; bool *isnull; @@ -1011,7 +1011,7 @@ TQRemapRecord(TupleQueueReader *reader, RecordRemapInfo *remapinfo, if (changed_typmod || remapinfo->field_remap != NULL) { HeapTupleData htup; - HeapTuple atup; + HeapTuple atup; //hari /* For now, assume we always need to change the tuple in this case. */ *changed = true; @@ -1121,7 +1121,7 @@ TupleQueueHandleControlMessage(TupleQueueReader *reader, Size nbytes, static TupleRemapInfo * BuildTupleRemapInfo(Oid typid, MemoryContext mycontext) { - HeapTuple tup; + StorageTuple tup; Form_pg_type typ; /* This is recursive, so it could be driven to stack overflow. */ diff --git a/src/include/access/htup_details.h b/src/include/access/htup_details.h index a8ab945..1802a97 100644 --- a/src/include/access/htup_details.h +++ b/src/include/access/htup_details.h @@ -665,7 +665,7 @@ struct MinimalTupleData /* * GETSTRUCT - given a HeapTuple pointer, return address of the user data */ -#define GETSTRUCT(TUP) ((char *) ((TUP)->t_data) + (TUP)->t_data->t_hoff) +#define GETSTRUCT(TUP) ((char *) (((HeapTuple)(TUP))->t_data) + ((HeapTuple)(TUP))->t_data->t_hoff) /* * Accessor macros to be used with HeapTuple pointers. diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h index f4d4f1e..62013dc 100644 --- a/src/include/access/relscan.h +++ b/src/include/access/relscan.h @@ -18,6 +18,7 @@ #include "access/heapam.h" #include "access/htup_details.h" #include "access/itup.h" +#include "access/storageamapi.h" #include "access/tupdesc.h" #include "storage/spin.h" @@ -75,7 +76,7 @@ typedef struct HeapScanDescData int rs_cindex; /* current tuple's index in vistuples */ int rs_ntuples; /* number of visible tuples on page */ OffsetNumber rs_vistuples[MaxHeapTuplesPerPage]; /* their offsets */ -} HeapScanDescData; +} HeapScanDescData; /* * We use the same IndexScanDescData structure for both amgettuple-based diff --git a/src/include/commands/trigger.h b/src/include/commands/trigger.h index d73969c..5e79ed0 100644 --- a/src/include/commands/trigger.h +++ b/src/include/commands/trigger.h @@ -138,7 +138,7 @@ extern TupleTableSlot *ExecBRInsertTriggers(EState *estate, TupleTableSlot *slot); extern void ExecARInsertTriggers(EState *estate, ResultRelInfo *relinfo, - HeapTuple trigtuple, + TupleTableSlot *slot, List *recheckIndexes); extern TupleTableSlot *ExecIRInsertTriggers(EState *estate, ResultRelInfo *relinfo, diff --git a/src/include/executor/executor.h b/src/include/executor/executor.h index 8cc5f3a..0333df2 100644 --- a/src/include/executor/executor.h +++ b/src/include/executor/executor.h @@ -15,6 +15,7 @@ #define EXECUTOR_H #include "catalog/partition.h" +#include "access/storageamapi.h" #include "executor/execdesc.h" #include "nodes/parsenodes.h" @@ -196,7 +197,7 @@ extern ExecAuxRowMark *ExecBuildAuxRowMark(ExecRowMark *erm, List *targetlist); extern TupleTableSlot *EvalPlanQual(EState *estate, EPQState *epqstate, Relation relation, Index rti, int lockmode, ItemPointer tid, TransactionId priorXmax); -extern HeapTuple EvalPlanQualFetch(EState *estate, Relation relation, +extern StorageTuple EvalPlanQualFetch(EState *estate, Relation relation, int lockmode, LockWaitPolicy wait_policy, ItemPointer tid, TransactionId priorXmax); extern void EvalPlanQualInit(EPQState *epqstate, EState *estate, @@ -204,8 +205,8 @@ extern void EvalPlanQualInit(EPQState *epqstate, EState *estate, extern void EvalPlanQualSetPlan(EPQState *epqstate, Plan *subplan, List *auxrowmarks); extern void EvalPlanQualSetTuple(EPQState *epqstate, Index rti, - HeapTuple tuple); -extern HeapTuple EvalPlanQualGetTuple(EPQState *epqstate, Index rti); + StorageTuple tuple); +extern StorageTuple EvalPlanQualGetTuple(EPQState *epqstate, Index rti); extern void ExecSetupPartitionTupleRouting(Relation rel, PartitionDispatch **pd, ResultRelInfo **partitions, diff --git a/src/include/executor/functions.h b/src/include/executor/functions.h index 7821a63..fe0ce3f 100644 --- a/src/include/executor/functions.h +++ b/src/include/executor/functions.h @@ -22,7 +22,7 @@ typedef struct SQLFunctionParseInfo *SQLFunctionParseInfoPtr; extern Datum fmgr_sql(PG_FUNCTION_ARGS); -extern SQLFunctionParseInfoPtr prepare_sql_fn_parse_info(HeapTuple procedureTuple, +extern SQLFunctionParseInfoPtr prepare_sql_fn_parse_info(StorageTuple procedureTuple, Node *call_expr, Oid inputCollation); diff --git a/src/include/executor/spi.h b/src/include/executor/spi.h index ffb4c28..4031344 100644 --- a/src/include/executor/spi.h +++ b/src/include/executor/spi.h @@ -25,7 +25,7 @@ typedef struct SPITupleTable uint64 alloced; /* # of alloced vals */ uint64 free; /* # of free vals */ TupleDesc tupdesc; /* tuple descriptor */ - HeapTuple *vals; /* tuples */ + StorageTuple *vals; /* tuples */ slist_node next; /* link for internal bookkeeping */ SubTransactionId subid; /* subxact in which tuptable was created */ } SPITupleTable; @@ -117,9 +117,9 @@ extern const char *SPI_result_code_string(int code); extern List *SPI_plan_get_plan_sources(SPIPlanPtr plan); extern CachedPlan *SPI_plan_get_cached_plan(SPIPlanPtr plan); -extern HeapTuple SPI_copytuple(HeapTuple tuple); -extern HeapTupleHeader SPI_returntuple(HeapTuple tuple, TupleDesc tupdesc); -extern HeapTuple SPI_modifytuple(Relation rel, HeapTuple tuple, int natts, +extern StorageTuple SPI_copytuple(StorageTuple tuple); +extern HeapTupleHeader SPI_returntuple(StorageTuple tuple, TupleDesc tupdesc); +extern StorageTuple SPI_modifytuple(Relation rel, HeapTuple tuple, int natts, int *attnum, Datum *Values, const char *Nulls); extern int SPI_fnumber(TupleDesc tupdesc, const char *fname); extern char *SPI_fname(TupleDesc tupdesc, int fnumber); @@ -133,7 +133,7 @@ extern void *SPI_palloc(Size size); extern void *SPI_repalloc(void *pointer, Size size); extern void SPI_pfree(void *pointer); extern Datum SPI_datumTransfer(Datum value, bool typByVal, int typLen); -extern void SPI_freetuple(HeapTuple pointer); +extern void SPI_freetuple(StorageTuple pointer); extern void SPI_freetuptable(SPITupleTable *tuptable); extern Portal SPI_cursor_open(const char *name, SPIPlanPtr plan, diff --git a/src/include/executor/tqueue.h b/src/include/executor/tqueue.h index 892eec8..03282a9 100644 --- a/src/include/executor/tqueue.h +++ b/src/include/executor/tqueue.h @@ -27,7 +27,7 @@ extern DestReceiver *CreateTupleQueueDestReceiver(shm_mq_handle *handle); extern TupleQueueReader *CreateTupleQueueReader(shm_mq_handle *handle, TupleDesc tupledesc); extern void DestroyTupleQueueReader(TupleQueueReader *reader); -extern HeapTuple TupleQueueReaderNext(TupleQueueReader *reader, +extern StorageTuple TupleQueueReaderNext(TupleQueueReader *reader, bool nowait, bool *done); #endif /* TQUEUE_H */ diff --git a/src/include/executor/tuptable.h b/src/include/executor/tuptable.h index 7521739..546d5e3 100644 --- a/src/include/executor/tuptable.h +++ b/src/include/executor/tuptable.h @@ -164,12 +164,12 @@ extern TupleTableSlot *ExecStoreMinimalTuple(MinimalTuple mtup, extern TupleTableSlot *ExecClearTuple(TupleTableSlot *slot); extern TupleTableSlot *ExecStoreVirtualTuple(TupleTableSlot *slot); extern TupleTableSlot *ExecStoreAllNullTuple(TupleTableSlot *slot); -extern HeapTuple ExecCopySlotTuple(TupleTableSlot *slot); +extern StorageTuple ExecCopySlotTuple(TupleTableSlot *slot); extern MinimalTuple ExecCopySlotMinimalTuple(TupleTableSlot *slot); -extern HeapTuple ExecFetchSlotTuple(TupleTableSlot *slot); +extern StorageTuple ExecFetchSlotTuple(TupleTableSlot *slot); extern MinimalTuple ExecFetchSlotMinimalTuple(TupleTableSlot *slot); extern Datum ExecFetchSlotTupleDatum(TupleTableSlot *slot); -extern HeapTuple ExecMaterializeSlot(TupleTableSlot *slot); +extern void ExecMaterializeSlot(TupleTableSlot *slot); extern StorageTuple ExecHeapifySlot(TupleTableSlot *slot); extern TupleTableSlot *ExecCopySlot(TupleTableSlot *dstslot, TupleTableSlot *srcslot); diff --git a/src/include/funcapi.h b/src/include/funcapi.h index 30e66b6..b1593b0 100644 --- a/src/include/funcapi.h +++ b/src/include/funcapi.h @@ -229,7 +229,7 @@ extern TupleDesc TypeGetTupleDesc(Oid typeoid, List *colaliases); /* from execTuples.c */ extern TupleDesc BlessTupleDesc(TupleDesc tupdesc); extern AttInMetadata *TupleDescGetAttInMetadata(TupleDesc tupdesc); -extern HeapTuple BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values); +extern StorageTuple BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values); extern Datum HeapTupleHeaderGetDatum(HeapTupleHeader tuple); extern TupleTableSlot *TupleDescGetSlot(TupleDesc tupdesc); diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h index d33392f..b8b2d6a 100644 --- a/src/include/nodes/execnodes.h +++ b/src/include/nodes/execnodes.h @@ -480,7 +480,7 @@ typedef struct EState * remember if the tuple has been returned already. Arrays are of size * list_length(es_range_table) and are indexed by scan node scanrelid - 1. */ - HeapTuple *es_epqTuple; /* array of EPQ substitute tuples */ + StorageTuple *es_epqTuple; /* array of EPQ substitute tuples */ bool *es_epqTupleSet; /* true if EPQ tuple is provided */ bool *es_epqScanDone; /* true if EPQ tuple has been fetched */ @@ -1967,7 +1967,7 @@ typedef struct LockRowsState PlanState ps; /* its first field is NodeTag */ List *lr_arowMarks; /* List of ExecAuxRowMarks */ EPQState lr_epqstate; /* for evaluating EvalPlanQual rechecks */ - HeapTuple *lr_curtuples; /* locked tuples (one entry per RT entry) */ + StorageTuple *lr_curtuples; /* locked tuples (one entry per RT entry) */ int lr_ntables; /* length of lr_curtuples[] array */ } LockRowsState; -- 2.7.4.windows.1