]> granicus.if.org Git - postgresql/commitdiff
Fix off-by-one error in txid_status().
authorThomas Munro <tmunro@postgresql.org>
Wed, 27 Mar 2019 08:16:50 +0000 (21:16 +1300)
committerThomas Munro <tmunro@postgresql.org>
Wed, 27 Mar 2019 08:31:29 +0000 (21:31 +1300)
The transaction ID returned by GetNextXidAndEpoch() is in the future,
so we can't attempt to access its status or we might try to read a
CLOG page that doesn't exist.  The > vs >= confusion probably stemmed
from the choice of a variable name containing the word "last" instead
of "next", so fix that too.

Back-patch to 10 where the function arrived.

Author: Thomas Munro
Discussion: https://postgr.es/m/CA%2BhUKG%2Buua_BV5cyfsioKVN2d61Lukg28ECsWTXKvh%3DBtN2DPA%40mail.gmail.com

src/backend/utils/adt/txid.c

index 1e38ca2aa5e68f2da5b77f0538fd5b4faa5e7a36..f48a98f02d64802d85f0930410d4ac7fbaa1dc84 100644 (file)
@@ -113,9 +113,9 @@ TransactionIdInRecentPast(uint64 xid_with_epoch, TransactionId *extracted_xid)
        uint32          xid_epoch = (uint32) (xid_with_epoch >> 32);
        TransactionId xid = (TransactionId) xid_with_epoch;
        uint32          now_epoch;
-       TransactionId now_epoch_last_xid;
+       TransactionId now_epoch_next_xid;
 
-       GetNextXidAndEpoch(&now_epoch_last_xid, &now_epoch);
+       GetNextXidAndEpoch(&now_epoch_next_xid, &now_epoch);
 
        if (extracted_xid != NULL)
                *extracted_xid = xid;
@@ -129,7 +129,7 @@ TransactionIdInRecentPast(uint64 xid_with_epoch, TransactionId *extracted_xid)
 
        /* If the transaction ID is in the future, throw an error. */
        if (xid_epoch > now_epoch
-               || (xid_epoch == now_epoch && xid > now_epoch_last_xid))
+               || (xid_epoch == now_epoch && xid >= now_epoch_next_xid))
                ereport(ERROR,
                                (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                 errmsg("transaction ID %s is in the future",
@@ -151,7 +151,7 @@ TransactionIdInRecentPast(uint64 xid_with_epoch, TransactionId *extracted_xid)
         * CLOG entry is guaranteed to still exist.
         */
        if (xid_epoch + 1 < now_epoch
-               || (xid_epoch + 1 == now_epoch && xid < now_epoch_last_xid)
+               || (xid_epoch + 1 == now_epoch && xid < now_epoch_next_xid)
                || TransactionIdPrecedes(xid, ShmemVariableCache->oldestClogXid))
                return false;