diff --git a/src/include/access/htup_details.h b/src/include/access/htup_details.h index cf56d4ace43..1867a70f6f3 100644 --- a/src/include/access/htup_details.h +++ b/src/include/access/htup_details.h @@ -83,13 +83,15 @@ * * A word about t_ctid: whenever a new tuple is stored on disk, its t_ctid * is initialized with its own TID (location). If the tuple is ever updated, - * its t_ctid is changed to point to the replacement version of the tuple or - * the block number (ip_blkid) is invalidated if the tuple is moved from one - * partition to another partition relation due to an update of the partition - * key. Thus, a tuple is the latest version of its row iff XMAX is invalid or + * its t_ctid is changed to point to the replacement version of the tuple. Or + * if the tuple is moved from one partition to another, due to an update of + * the partition key, t_ctid is set to a special value to indicate that + * (see ItemPointerSetMovedPartitions). Thus, a tuple is the latest version + * of its row iff XMAX is invalid or * t_ctid points to itself (in which case, if XMAX is valid, the tuple is * either locked or deleted). One can follow the chain of t_ctid links - * to find the newest version of the row. Beware however that VACUUM might + * to find the newest version of the row, unless it was moved to a different + * partition. Beware however that VACUUM might * erase the pointed-to (newer) tuple before erasing the pointing (older) * tuple. Hence, when following a t_ctid link, it is necessary to check * to see if the referenced slot is empty or contains an unrelated tuple. @@ -287,14 +289,6 @@ struct HeapTupleHeaderData */ #define HEAP_TUPLE_HAS_MATCH HEAP_ONLY_TUPLE /* tuple has a join match */ -/* - * Special value used in t_ctid.ip_posid, to indicate that it holds a - * speculative insertion token rather than a real TID. This must be higher - * than MaxOffsetNumber, so that it can be distinguished from a valid - * offset number in a regular item pointer. - */ -#define SpecTokenOffsetNumber 0xfffe - /* * HeapTupleHeader accessor macros * @@ -447,11 +441,12 @@ do { \ ItemPointerSet(&(tup)->t_ctid, token, SpecTokenOffsetNumber) \ ) -#define HeapTupleHeaderSetMovedPartitions(tup) \ - ItemPointerSetMovedPartitions(&(tup)->t_ctid) - #define HeapTupleHeaderIndicatesMovedPartitions(tup) \ - ItemPointerIndicatesMovedPartitions(&tup->t_ctid) + (ItemPointerGetOffsetNumber(&(tup)->t_ctid) == MovedPartitionsOffsetNumber && \ + ItemPointerGetBlockNumberNoCheck(&(tup)->t_ctid) == MovedPartitionsBlockNumber) + +#define HeapTupleHeaderSetMovedPartitions(tup) \ + ItemPointerSet(&(tup)->t_ctid, MovedPartitionsBlockNumber, MovedPartitionsOffsetNumber) #define HeapTupleHeaderGetDatumLength(tup) \ VARSIZE(tup) diff --git a/src/include/storage/itemptr.h b/src/include/storage/itemptr.h index 626c98f9691..d87101f2701 100644 --- a/src/include/storage/itemptr.h +++ b/src/include/storage/itemptr.h @@ -48,6 +48,28 @@ ItemPointerData; typedef ItemPointerData *ItemPointer; +/* ---------------- + * special values used in heap tuples (t_ctid) + * ---------------- + */ + +/* + * If a heap tuple holds a speculative insertion token rather than a real + * TID, ip_posid is set to SpecTokenOffsetNumber, and the token is stored in + * ip_blkid. SpecTokenOffsetNumber must be higher than MaxOffsetNumber, so + * that it can be distinguished from a valid offset number in a regular item + * pointer. + */ +#define SpecTokenOffsetNumber 0xfffe + +/* + * When a tuple is moved to a different partition by UPDATE, the t_ctid of + * the old tuple version is set to this magic value. + */ +#define MovedPartitionsOffsetNumber 0xfffd +#define MovedPartitionsBlockNumber InvalidBlockNumber + + /* ---------------- * support macros * ---------------- @@ -160,7 +182,10 @@ typedef ItemPointerData *ItemPointer; * partition. */ #define ItemPointerIndicatesMovedPartitions(pointer) \ - !BlockNumberIsValid(ItemPointerGetBlockNumberNoCheck(pointer)) +( \ + ItemPointerGetOffsetNumber(pointer) == MovedPartitionsOffsetNumber && \ + ItemPointerGetBlockNumberNoCheck(pointer) == MovedPartitionsBlockNumber \ +) /* * ItemPointerSetMovedPartitions @@ -168,7 +193,7 @@ typedef ItemPointerData *ItemPointer; * different partition. */ #define ItemPointerSetMovedPartitions(pointer) \ - ItemPointerSetBlockNumber((pointer), InvalidBlockNumber) + ItemPointerSet((pointer), MovedPartitionsBlockNumber, MovedPartitionsOffsetNumber) /* ---------------- * externs