tableam: Add fetch_row_version.
authorAndres Freund <[email protected]>
Tue, 5 Feb 2019 08:58:40 +0000 (00:58 -0800)
committerAndres Freund <[email protected]>
Wed, 6 Mar 2019 06:59:31 +0000 (22:59 -0800)
Author:
Reviewed-By:
Discussion: https://postgr.es/m/
Backpatch:

src/backend/access/heap/heapam_handler.c
src/backend/commands/trigger.c
src/backend/executor/execMain.c
src/backend/executor/nodeLockRows.c
src/backend/executor/nodeModifyTable.c
src/backend/executor/nodeTidscan.c
src/include/access/tableam.h

index f9b5053972fc661028640bf0e918d3d1ba131fdb..f1b6be712737ce746a8816dede7cdd4ed316586e 100644 (file)
@@ -426,6 +426,33 @@ retry:
    return result;
 }
 
+static bool
+heapam_fetch_row_version(Relation relation,
+                        ItemPointer tid,
+                        Snapshot snapshot,
+                        TupleTableSlot *slot,
+                        Relation stats_relation)
+{
+   BufferHeapTupleTableSlot *bslot = (BufferHeapTupleTableSlot *) slot;
+   Buffer      buffer;
+
+   Assert(TTS_IS_BUFFERTUPLE(slot));
+
+   if (heap_fetch(relation, tid, snapshot, &bslot->base.tupdata, &buffer, stats_relation))
+   {
+       /* store in slot, transferring existing pin */
+       ExecStorePinnedBufferHeapTuple(&bslot->base.tupdata, slot, buffer);
+
+       slot->tts_tableOid = RelationGetRelid(relation);
+
+       return true;
+   }
+
+   slot->tts_tableOid = RelationGetRelid(relation);
+
+   return false;
+}
+
 static bool
 heapam_fetch_follow(struct IndexFetchTableData *scan,
                    ItemPointer tid,
@@ -536,6 +563,7 @@ static const TableAmRoutine heapam_methods = {
    .tuple_update = heapam_heap_update,
    .tuple_lock = heapam_lock_tuple,
 
+   .tuple_fetch_row_version = heapam_fetch_row_version,
    .tuple_fetch_follow = heapam_fetch_follow,
    .tuple_satisfies_snapshot = heapam_tuple_satisfies_snapshot,
 };
index 5cc15bcfef0ffc376e229a53f3eaae0c09cc742a..6fbf0c2b81e190acc91da89e664d023c962b2974 100644 (file)
 #include "postgres.h"
 
 #include "access/genam.h"
-#include "access/heapam.h"
-#include "access/tableam.h"
-#include "access/sysattr.h"
 #include "access/htup_details.h"
+#include "access/relation.h"
+#include "access/sysattr.h"
+#include "access/table.h"
+#include "access/tableam.h"
 #include "access/xact.h"
 #include "catalog/catalog.h"
 #include "catalog/dependency.h"
@@ -3382,43 +3383,8 @@ GetTupleForTrigger(EState *estate,
    }
    else
    {
-
-       Page        page;
-       ItemId      lp;
-       Buffer      buffer;
-       BufferHeapTupleTableSlot *boldslot;
-       HeapTuple tuple;
-
-       Assert(TTS_IS_BUFFERTUPLE(oldslot));
-       ExecClearTuple(oldslot);
-       boldslot = (BufferHeapTupleTableSlot *) oldslot;
-       tuple = &boldslot->base.tupdata;
-
-       buffer = ReadBuffer(relation, ItemPointerGetBlockNumber(tid));
-
-       /*
-        * Although we already know this tuple is valid, we must lock the
-        * buffer to ensure that no one has a buffer cleanup lock; otherwise
-        * they might move the tuple while we try to copy it.  But we can
-        * release the lock before actually doing the heap_copytuple call,
-        * since holding pin is sufficient to prevent anyone from getting a
-        * cleanup lock they don't already hold.
-        */
-       LockBuffer(buffer, BUFFER_LOCK_SHARE);
-
-       page = BufferGetPage(buffer);
-       lp = PageGetItemId(page, ItemPointerGetOffsetNumber(tid));
-
-       Assert(ItemIdIsNormal(lp));
-
-       tuple->t_data = (HeapTupleHeader) PageGetItem(page, lp);
-       tuple->t_len = ItemIdGetLength(lp);
-       tuple->t_self = *tid;
-       tuple->t_tableOid = RelationGetRelid(relation);
-
-       LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
-
-       ExecStorePinnedBufferHeapTuple(tuple, oldslot, buffer);
+       if (!table_fetch_row_version(relation, tid, SnapshotAny, oldslot, NULL))
+           elog(ERROR, "couldn't fetch tuple");
    }
 
    return true;
@@ -4197,8 +4163,6 @@ AfterTriggerExecute(EState *estate,
    AfterTriggerShared evtshared = GetTriggerSharedData(event);
    Oid         tgoid = evtshared->ats_tgoid;
    TriggerData LocTriggerData;
-   HeapTupleData tuple1;
-   HeapTupleData tuple2;
    HeapTuple   rettuple;
    int         tgindx;
    bool        should_free_trig = false;
@@ -4275,19 +4239,12 @@ AfterTriggerExecute(EState *estate,
        default:
            if (ItemPointerIsValid(&(event->ate_ctid1)))
            {
-               Buffer buffer;
-
                LocTriggerData.tg_trigslot = ExecGetTriggerOldSlot(estate, relInfo);
 
-               ItemPointerCopy(&(event->ate_ctid1), &(tuple1.t_self));
-               if (!heap_fetch(rel, &(tuple1.t_self), SnapshotAny, &tuple1, &buffer, NULL))
+               if (!table_fetch_row_version(rel, &(event->ate_ctid1), SnapshotAny, LocTriggerData.tg_trigslot, NULL))
                    elog(ERROR, "failed to fetch tuple1 for AFTER trigger");
-               ExecStorePinnedBufferHeapTuple(&tuple1,
-                                              LocTriggerData.tg_trigslot,
-                                              buffer);
                LocTriggerData.tg_trigtuple =
-                   ExecFetchSlotHeapTuple(LocTriggerData.tg_trigslot, false,
-                                          &should_free_trig);
+                   ExecFetchSlotHeapTuple(LocTriggerData.tg_trigslot, false, &should_free_trig);
            }
            else
            {
@@ -4299,19 +4256,12 @@ AfterTriggerExecute(EState *estate,
                AFTER_TRIGGER_2CTID &&
                ItemPointerIsValid(&(event->ate_ctid2)))
            {
-               Buffer buffer;
-
                LocTriggerData.tg_newslot = ExecGetTriggerNewSlot(estate, relInfo);
 
-               ItemPointerCopy(&(event->ate_ctid2), &(tuple2.t_self));
-               if (!heap_fetch(rel, &(tuple2.t_self), SnapshotAny, &tuple2, &buffer, NULL))
+               if (!table_fetch_row_version(rel, &(event->ate_ctid2), SnapshotAny, LocTriggerData.tg_newslot, NULL))
                    elog(ERROR, "failed to fetch tuple2 for AFTER trigger");
-               ExecStorePinnedBufferHeapTuple(&tuple2,
-                                              LocTriggerData.tg_newslot,
-                                              buffer);
                LocTriggerData.tg_newtuple =
-                   ExecFetchSlotHeapTuple(LocTriggerData.tg_newslot, false,
-                                          &should_free_new);
+                   ExecFetchSlotHeapTuple(LocTriggerData.tg_newslot, false, &should_free_new);
            }
            else
            {
index d1db75af919e427a4a91b06f6574bcd23e9c0be3..053ef683f7af8b97ad2c00b5b71ec4d81e5921a8 100644 (file)
@@ -2638,17 +2638,9 @@ EvalPlanQualFetchRowMarks(EPQState *epqstate)
            else
            {
                /* ordinary table, fetch the tuple */
-               HeapTupleData tuple;
-               Buffer      buffer;
-
-               tuple.t_self = *((ItemPointer) DatumGetPointer(datum));
-               if (!heap_fetch(erm->relation, &tuple.t_self, SnapshotAny,
-                               &tuple, &buffer, NULL))
+               if (!table_fetch_row_version(erm->relation, (ItemPointer) DatumGetPointer(datum),
+                                            SnapshotAny, slot, NULL))
                    elog(ERROR, "failed to fetch tuple for EvalPlanQual recheck");
-
-               /* successful, store tuple */
-               ExecStorePinnedBufferHeapTuple(&tuple, slot, buffer);
-               ExecMaterializeSlot(slot);
            }
        }
        else
index 91f46b88ed8e7c984982653bb02aa85cb09ef602..aedc5297e3bada0bf900a32bcc093ecb2f56c29e 100644 (file)
@@ -21,7 +21,6 @@
 
 #include "postgres.h"
 
-#include "access/heapam.h"
 #include "access/htup_details.h"
 #include "access/tableam.h"
 #include "access/xact.h"
@@ -275,8 +274,6 @@ lnext:
            ExecAuxRowMark *aerm = (ExecAuxRowMark *) lfirst(lc);
            ExecRowMark *erm = aerm->rowmark;
            TupleTableSlot *markSlot;
-           HeapTupleData tuple;
-           Buffer buffer;
 
            markSlot = EvalPlanQualSlot(&node->lr_epqstate, erm->relation, erm->rti);
 
@@ -297,12 +294,9 @@ lnext:
            Assert(ItemPointerIsValid(&(erm->curCtid)));
 
            /* okay, fetch the tuple */
-           tuple.t_self = erm->curCtid;
-           if (!heap_fetch(erm->relation, &tuple.t_self, SnapshotAny, &tuple, &buffer,
-                           NULL))
+           if (!table_fetch_row_version(erm->relation, &erm->curCtid, SnapshotAny, markSlot,
+                              NULL))
                elog(ERROR, "failed to fetch tuple for EvalPlanQual recheck");
-           ExecStorePinnedBufferHeapTuple(&tuple, markSlot, buffer);
-           ExecMaterializeSlot(markSlot);
            /* successful, use tuple in slot */
        }
 
index 2dd37a84d06d5b8afcd28246aa068217d5688663..f4f95428af0bd32174963ec5aa20eb43478a4313 100644 (file)
@@ -230,18 +230,15 @@ ExecCheckTIDVisible(EState *estate,
                    TupleTableSlot *tempSlot)
 {
    Relation    rel = relinfo->ri_RelationDesc;
-   Buffer      buffer;
-   HeapTupleData tuple;
 
    /* Redundantly check isolation level */
    if (!IsolationUsesXactSnapshot())
        return;
 
-   tuple.t_self = *tid;
-   if (!heap_fetch(rel, &tuple.t_self, SnapshotAny, &tuple, &buffer, NULL))
+   if (!table_fetch_row_version(rel, tid, SnapshotAny, tempSlot, NULL))
        elog(ERROR, "failed to fetch conflicting tuple for ON CONFLICT");
-   ExecStorePinnedBufferHeapTuple(&tuple, tempSlot, buffer);
    ExecCheckHeapTupleVisible(estate, rel, tempSlot);
+   ExecClearTuple(tempSlot);
 }
 
 /* ----------------------------------------------------------------
@@ -851,21 +848,9 @@ ldelete:;
            }
            else
            {
-               BufferHeapTupleTableSlot *bslot;
-               HeapTuple deltuple;
-               Buffer buffer;
-
-               Assert(TTS_IS_BUFFERTUPLE(slot));
-               ExecClearTuple(slot);
-               bslot = (BufferHeapTupleTableSlot *) slot;
-               deltuple = &bslot->base.tupdata;
-
-               deltuple->t_self = *tupleid;
-               if (!heap_fetch(resultRelationDesc, &deltuple->t_self, SnapshotAny,
-                               deltuple, &buffer, NULL))
+               if (!table_fetch_row_version(resultRelationDesc, tupleid, SnapshotAny,
+                                            slot, NULL))
                    elog(ERROR, "failed to fetch deleted tuple for DELETE RETURNING");
-
-               ExecStorePinnedBufferHeapTuple(deltuple, slot, buffer);
            }
        }
 
index b819cf2383e63c9af988a0fb0eec7729bf969e29..7d496cc4105465919181251460370a2f4abde018 100644 (file)
@@ -310,7 +310,6 @@ TidNext(TidScanState *node)
    Relation    heapRelation;
    HeapTuple   tuple;
    TupleTableSlot *slot;
-   Buffer      buffer = InvalidBuffer;
    ItemPointerData *tidList;
    int         numTids;
    bool        bBackward;
@@ -376,19 +375,9 @@ TidNext(TidScanState *node)
        if (node->tss_isCurrentOf)
            heap_get_latest_tid(heapRelation, snapshot, &tuple->t_self);
 
-       if (heap_fetch(heapRelation, &tuple->t_self, snapshot, tuple, &buffer, NULL))
-       {
-           /*
-            * Store the scanned tuple in the scan tuple slot of the scan
-            * state, transferring the pin to the slot.
-            */
-           ExecStorePinnedBufferHeapTuple(tuple, /* tuple to store */
-                                          slot,    /* slot to store in */
-                                          buffer); /* buffer associated with
-                                                    * tuple */
-
+       if (table_fetch_row_version(heapRelation, &tuple->t_self, snapshot, slot, NULL))
            return slot;
-       }
+
        /* Bad TID or failed snapshot qual; try next */
        if (bBackward)
            node->tss_TidPtr--;
index 22e15506ec1eafb5440f4266b565e37408b9d056..fa5ea9c6680e95ad72f06832602fdab4f23e66af 100644 (file)
@@ -160,6 +160,11 @@ typedef struct TableAmRoutine
     * ------------------------------------------------------------------------
     */
 
+   bool        (*tuple_fetch_row_version) (Relation rel,
+                                           ItemPointer tid,
+                                           Snapshot snapshot,
+                                           TupleTableSlot *slot,
+                                           Relation stats_relation);
    bool        (*tuple_fetch_follow) (struct IndexFetchTableData *scan,
                                       ItemPointer tid,
                                       Snapshot snapshot,
@@ -429,6 +434,23 @@ table_lock_tuple(Relation rel, ItemPointer tid, Snapshot snapshot,
  * ----------------------------------------------------------------------------
  */
 
+/*
+ * table_fetch_row_version     - retrieve tuple with given tid
+ *
+ *  XXX: This shouldn't just take a tid, but tid + additional information
+ */
+static inline bool
+table_fetch_row_version(Relation rel,
+                       ItemPointer tid,
+                       Snapshot snapshot,
+                       TupleTableSlot *slot,
+                       Relation stats_relation)
+{
+   return rel->rd_tableam->tuple_fetch_row_version(rel, tid,
+                                                   snapshot, slot,
+                                                   stats_relation);
+}
+
 static inline bool
 table_fetch_follow(struct IndexFetchTableData *scan,
                   ItemPointer tid,