]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
heapam: Move logic to handle HEAP_MOVED into a helper function
authorAndres Freund <andres@anarazel.de>
Fri, 19 Dec 2025 18:28:34 +0000 (13:28 -0500)
committerAndres Freund <andres@anarazel.de>
Fri, 19 Dec 2025 18:28:34 +0000 (13:28 -0500)
Before we dealt with this in 6 near identical and one very similar copy.

The helper function errors out when encountering a
HEAP_MOVED_IN/HEAP_MOVED_OUT tuple with xvac considered current or
in-progress. It'd be preferrable to do that change separately, but otherwise
it'd not be possible to deduplicate the handling in
HeapTupleSatisfiesVacuum().

Reviewed-by: Heikki Linnakangas <hlinnaka@iki.fi>
Discussion: https://postgr.es/m/lxzj26ga6ippdeunz6kuncectr5gfuugmm2ry22qu6hcx6oid6@lzx3sjsqhmt6
Discussion: https://postgr.es/m/6rgb2nvhyvnszz4ul3wfzlf5rheb2kkwrglthnna7qhe24onwr@vw27225tkyar

src/backend/access/heap/heapam_visibility.c

index 05f6946fe60d274597735fae982d78dc9be538da..bf899c2d2c698dc69ae867127cc1a27000d37bf9 100644 (file)
@@ -144,6 +144,55 @@ HeapTupleSetHintBits(HeapTupleHeader tuple, Buffer buffer,
        SetHintBits(tuple, buffer, infomask, xid);
 }
 
+/*
+ * If HEAP_MOVED_OFF or HEAP_MOVED_IN are set on the tuple, remove them and
+ * adjust hint bits. See the comment for SetHintBits() for more background.
+ *
+ * This helper returns false if the row ought to be invisible, true otherwise.
+ */
+static inline bool
+HeapTupleCleanMoved(HeapTupleHeader tuple, Buffer buffer)
+{
+       TransactionId xvac;
+
+       /* only used by pre-9.0 binary upgrades */
+       if (likely(!(tuple->t_infomask & (HEAP_MOVED_OFF | HEAP_MOVED_IN))))
+               return true;
+
+       xvac = HeapTupleHeaderGetXvac(tuple);
+
+       if (TransactionIdIsCurrentTransactionId(xvac))
+               elog(ERROR, "encountered tuple with HEAP_MOVED considered current");
+
+       if (TransactionIdIsInProgress(xvac))
+               elog(ERROR, "encountered tuple with HEAP_MOVED considered in-progress");
+
+       if (tuple->t_infomask & HEAP_MOVED_OFF)
+       {
+               if (TransactionIdDidCommit(xvac))
+               {
+                       SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
+                                               InvalidTransactionId);
+                       return false;
+               }
+               SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
+                                       InvalidTransactionId);
+       }
+       else if (tuple->t_infomask & HEAP_MOVED_IN)
+       {
+               if (TransactionIdDidCommit(xvac))
+                       SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
+                                               InvalidTransactionId);
+               else
+               {
+                       SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
+                                               InvalidTransactionId);
+                       return false;
+               }
+       }
+
+       return true;
+}
 
 /*
  * HeapTupleSatisfiesSelf
@@ -179,45 +228,8 @@ HeapTupleSatisfiesSelf(HeapTuple htup, Snapshot snapshot, Buffer buffer)
                if (HeapTupleHeaderXminInvalid(tuple))
                        return false;
 
-               /* Used by pre-9.0 binary upgrades */
-               if (tuple->t_infomask & HEAP_MOVED_OFF)
-               {
-                       TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
-
-                       if (TransactionIdIsCurrentTransactionId(xvac))
-                               return false;
-                       if (!TransactionIdIsInProgress(xvac))
-                       {
-                               if (TransactionIdDidCommit(xvac))
-                               {
-                                       SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
-                                                               InvalidTransactionId);
-                                       return false;
-                               }
-                               SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
-                                                       InvalidTransactionId);
-                       }
-               }
-               /* Used by pre-9.0 binary upgrades */
-               else if (tuple->t_infomask & HEAP_MOVED_IN)
-               {
-                       TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
-
-                       if (!TransactionIdIsCurrentTransactionId(xvac))
-                       {
-                               if (TransactionIdIsInProgress(xvac))
-                                       return false;
-                               if (TransactionIdDidCommit(xvac))
-                                       SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
-                                                               InvalidTransactionId);
-                               else
-                               {
-                                       SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
-                                                               InvalidTransactionId);
-                                       return false;
-                               }
-                       }
-               }
+               if (!HeapTupleCleanMoved(tuple, buffer))
+                       return false;
                else if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetRawXmin(tuple)))
                {
                        if (tuple->t_infomask & HEAP_XMAX_INVALID)      /* xid invalid */
@@ -372,45 +384,8 @@ HeapTupleSatisfiesToast(HeapTuple htup, Snapshot snapshot,
                if (HeapTupleHeaderXminInvalid(tuple))
                        return false;
 
-               /* Used by pre-9.0 binary upgrades */
-               if (tuple->t_infomask & HEAP_MOVED_OFF)
-               {
-                       TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
-
-                       if (TransactionIdIsCurrentTransactionId(xvac))
-                               return false;
-                       if (!TransactionIdIsInProgress(xvac))
-                       {
-                               if (TransactionIdDidCommit(xvac))
-                               {
-                                       SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
-                                                               InvalidTransactionId);
-                                       return false;
-                               }
-                               SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
-                                                       InvalidTransactionId);
-                       }
-               }
-               /* Used by pre-9.0 binary upgrades */
-               else if (tuple->t_infomask & HEAP_MOVED_IN)
-               {
-                       TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
-
-                       if (!TransactionIdIsCurrentTransactionId(xvac))
-                       {
-                               if (TransactionIdIsInProgress(xvac))
-                                       return false;
-                               if (TransactionIdDidCommit(xvac))
-                                       SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
-                                                               InvalidTransactionId);
-                               else
-                               {
-                                       SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
-                                                               InvalidTransactionId);
-                                       return false;
-                               }
-                       }
-               }
+               if (!HeapTupleCleanMoved(tuple, buffer))
+                       return false;
 
                /*
                 * An invalid Xmin can be left behind by a speculative insertion that
@@ -468,45 +443,8 @@ HeapTupleSatisfiesUpdate(HeapTuple htup, CommandId curcid,
                if (HeapTupleHeaderXminInvalid(tuple))
                        return TM_Invisible;
 
-               /* Used by pre-9.0 binary upgrades */
-               if (tuple->t_infomask & HEAP_MOVED_OFF)
-               {
-                       TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
-
-                       if (TransactionIdIsCurrentTransactionId(xvac))
-                               return TM_Invisible;
-                       if (!TransactionIdIsInProgress(xvac))
-                       {
-                               if (TransactionIdDidCommit(xvac))
-                               {
-                                       SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
-                                                               InvalidTransactionId);
-                                       return TM_Invisible;
-                               }
-                               SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
-                                                       InvalidTransactionId);
-                       }
-               }
-               /* Used by pre-9.0 binary upgrades */
-               else if (tuple->t_infomask & HEAP_MOVED_IN)
-               {
-                       TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
-
-                       if (!TransactionIdIsCurrentTransactionId(xvac))
-                       {
-                               if (TransactionIdIsInProgress(xvac))
-                                       return TM_Invisible;
-                               if (TransactionIdDidCommit(xvac))
-                                       SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
-                                                               InvalidTransactionId);
-                               else
-                               {
-                                       SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
-                                                               InvalidTransactionId);
-                                       return TM_Invisible;
-                               }
-                       }
-               }
+               else if (!HeapTupleCleanMoved(tuple, buffer))
+                       return TM_Invisible;
                else if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetRawXmin(tuple)))
                {
                        if (HeapTupleHeaderGetCmin(tuple) >= curcid)
@@ -756,45 +694,8 @@ HeapTupleSatisfiesDirty(HeapTuple htup, Snapshot snapshot,
                if (HeapTupleHeaderXminInvalid(tuple))
                        return false;
 
-               /* Used by pre-9.0 binary upgrades */
-               if (tuple->t_infomask & HEAP_MOVED_OFF)
-               {
-                       TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
-
-                       if (TransactionIdIsCurrentTransactionId(xvac))
-                               return false;
-                       if (!TransactionIdIsInProgress(xvac))
-                       {
-                               if (TransactionIdDidCommit(xvac))
-                               {
-                                       SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
-                                                               InvalidTransactionId);
-                                       return false;
-                               }
-                               SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
-                                                       InvalidTransactionId);
-                       }
-               }
-               /* Used by pre-9.0 binary upgrades */
-               else if (tuple->t_infomask & HEAP_MOVED_IN)
-               {
-                       TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
-
-                       if (!TransactionIdIsCurrentTransactionId(xvac))
-                       {
-                               if (TransactionIdIsInProgress(xvac))
-                                       return false;
-                               if (TransactionIdDidCommit(xvac))
-                                       SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
-                                                               InvalidTransactionId);
-                               else
-                               {
-                                       SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
-                                                               InvalidTransactionId);
-                                       return false;
-                               }
-                       }
-               }
+               if (!HeapTupleCleanMoved(tuple, buffer))
+                       return false;
                else if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetRawXmin(tuple)))
                {
                        if (tuple->t_infomask & HEAP_XMAX_INVALID)      /* xid invalid */
@@ -979,45 +880,8 @@ HeapTupleSatisfiesMVCC(HeapTuple htup, Snapshot snapshot,
                if (HeapTupleHeaderXminInvalid(tuple))
                        return false;
 
-               /* Used by pre-9.0 binary upgrades */
-               if (tuple->t_infomask & HEAP_MOVED_OFF)
-               {
-                       TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
-
-                       if (TransactionIdIsCurrentTransactionId(xvac))
-                               return false;
-                       if (!XidInMVCCSnapshot(xvac, snapshot))
-                       {
-                               if (TransactionIdDidCommit(xvac))
-                               {
-                                       SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
-                                                               InvalidTransactionId);
-                                       return false;
-                               }
-                               SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
-                                                       InvalidTransactionId);
-                       }
-               }
-               /* Used by pre-9.0 binary upgrades */
-               else if (tuple->t_infomask & HEAP_MOVED_IN)
-               {
-                       TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
-
-                       if (!TransactionIdIsCurrentTransactionId(xvac))
-                       {
-                               if (XidInMVCCSnapshot(xvac, snapshot))
-                                       return false;
-                               if (TransactionIdDidCommit(xvac))
-                                       SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
-                                                               InvalidTransactionId);
-                               else
-                               {
-                                       SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
-                                                               InvalidTransactionId);
-                                       return false;
-                               }
-                       }
-               }
+               if (!HeapTupleCleanMoved(tuple, buffer))
+                       return false;
                else if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetRawXmin(tuple)))
                {
                        if (HeapTupleHeaderGetCmin(tuple) >= snapshot->curcid)
@@ -1222,43 +1086,8 @@ HeapTupleSatisfiesVacuumHorizon(HeapTuple htup, Buffer buffer, TransactionId *de
        {
                if (HeapTupleHeaderXminInvalid(tuple))
                        return HEAPTUPLE_DEAD;
-               /* Used by pre-9.0 binary upgrades */
-               else if (tuple->t_infomask & HEAP_MOVED_OFF)
-               {
-                       TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
-
-                       if (TransactionIdIsCurrentTransactionId(xvac))
-                               return HEAPTUPLE_DELETE_IN_PROGRESS;
-                       if (TransactionIdIsInProgress(xvac))
-                               return HEAPTUPLE_DELETE_IN_PROGRESS;
-                       if (TransactionIdDidCommit(xvac))
-                       {
-                               SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
-                                                       InvalidTransactionId);
-                               return HEAPTUPLE_DEAD;
-                       }
-                       SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
-                                               InvalidTransactionId);
-               }
-               /* Used by pre-9.0 binary upgrades */
-               else if (tuple->t_infomask & HEAP_MOVED_IN)
-               {
-                       TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
-
-                       if (TransactionIdIsCurrentTransactionId(xvac))
-                               return HEAPTUPLE_INSERT_IN_PROGRESS;
-                       if (TransactionIdIsInProgress(xvac))
-                               return HEAPTUPLE_INSERT_IN_PROGRESS;
-                       if (TransactionIdDidCommit(xvac))
-                               SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
-                                                       InvalidTransactionId);
-                       else
-                       {
-                               SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
-                                                       InvalidTransactionId);
-                               return HEAPTUPLE_DEAD;
-                       }
-               }
+               else if (!HeapTupleCleanMoved(tuple, buffer))
+                       return HEAPTUPLE_DEAD;
                else if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetRawXmin(tuple)))
                {
                        if (tuple->t_infomask & HEAP_XMAX_INVALID)      /* xid invalid */