Line data Source code
1 : /*------------------------------------------------------------------------- 2 : * 3 : * itemptr.c 4 : * POSTGRES disk item pointer code. 5 : * 6 : * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group 7 : * Portions Copyright (c) 1994, Regents of the University of California 8 : * 9 : * 10 : * IDENTIFICATION 11 : * src/backend/storage/page/itemptr.c 12 : * 13 : *------------------------------------------------------------------------- 14 : */ 15 : #include "postgres.h" 16 : 17 : #include "storage/itemptr.h" 18 : 19 : 20 : /* 21 : * We really want ItemPointerData to be exactly 6 bytes. 22 : */ 23 : StaticAssertDecl(sizeof(ItemPointerData) == 3 * sizeof(uint16), 24 : "ItemPointerData struct is improperly padded"); 25 : 26 : /* 27 : * ItemPointerEquals 28 : * Returns true if both item pointers point to the same item, 29 : * otherwise returns false. 30 : * 31 : * Note: 32 : * Asserts that the disk item pointers are both valid! 33 : */ 34 : bool 35 13880114 : ItemPointerEquals(ItemPointer pointer1, ItemPointer pointer2) 36 : { 37 27760228 : if (ItemPointerGetBlockNumber(pointer1) == 38 18364584 : ItemPointerGetBlockNumber(pointer2) && 39 4484470 : ItemPointerGetOffsetNumber(pointer1) == 40 4484470 : ItemPointerGetOffsetNumber(pointer2)) 41 1795616 : return true; 42 : else 43 12084498 : return false; 44 : } 45 : 46 : /* 47 : * ItemPointerCompare 48 : * Generic btree-style comparison for item pointers. 49 : */ 50 : int32 51 26179818 : ItemPointerCompare(ItemPointer arg1, ItemPointer arg2) 52 : { 53 : /* 54 : * Use ItemPointerGet{Offset,Block}NumberNoCheck to avoid asserting 55 : * ip_posid != 0, which may not be true for a user-supplied TID. 56 : */ 57 26179818 : BlockNumber b1 = ItemPointerGetBlockNumberNoCheck(arg1); 58 26179818 : BlockNumber b2 = ItemPointerGetBlockNumberNoCheck(arg2); 59 : 60 26179818 : if (b1 < b2) 61 310846 : return -1; 62 25868972 : else if (b1 > b2) 63 19636952 : return 1; 64 12464040 : else if (ItemPointerGetOffsetNumberNoCheck(arg1) < 65 6232020 : ItemPointerGetOffsetNumberNoCheck(arg2)) 66 805424 : return -1; 67 10853192 : else if (ItemPointerGetOffsetNumberNoCheck(arg1) > 68 5426596 : ItemPointerGetOffsetNumberNoCheck(arg2)) 69 4028230 : return 1; 70 : else 71 1398366 : return 0; 72 : } 73 : 74 : /* 75 : * ItemPointerInc 76 : * Increment 'pointer' by 1 only paying attention to the ItemPointer's 77 : * type's range limits and not MaxOffsetNumber and FirstOffsetNumber. 78 : * This may result in 'pointer' becoming !OffsetNumberIsValid. 79 : * 80 : * If the pointer is already the maximum possible values permitted by the 81 : * range of the ItemPointer's types, then do nothing. 82 : */ 83 : void 84 46 : ItemPointerInc(ItemPointer pointer) 85 : { 86 46 : BlockNumber blk = ItemPointerGetBlockNumberNoCheck(pointer); 87 46 : OffsetNumber off = ItemPointerGetOffsetNumberNoCheck(pointer); 88 : 89 46 : if (off == PG_UINT16_MAX) 90 : { 91 12 : if (blk != InvalidBlockNumber) 92 : { 93 6 : off = 0; 94 6 : blk++; 95 : } 96 : } 97 : else 98 34 : off++; 99 : 100 46 : ItemPointerSet(pointer, blk, off); 101 46 : } 102 : 103 : /* 104 : * ItemPointerDec 105 : * Decrement 'pointer' by 1 only paying attention to the ItemPointer's 106 : * type's range limits and not MaxOffsetNumber and FirstOffsetNumber. 107 : * This may result in 'pointer' becoming !OffsetNumberIsValid. 108 : * 109 : * If the pointer is already the minimum possible values permitted by the 110 : * range of the ItemPointer's types, then do nothing. This does rely on 111 : * FirstOffsetNumber being 1 rather than 0. 112 : */ 113 : void 114 60 : ItemPointerDec(ItemPointer pointer) 115 : { 116 60 : BlockNumber blk = ItemPointerGetBlockNumberNoCheck(pointer); 117 60 : OffsetNumber off = ItemPointerGetOffsetNumberNoCheck(pointer); 118 : 119 60 : if (off == 0) 120 : { 121 60 : if (blk != 0) 122 : { 123 42 : off = PG_UINT16_MAX; 124 42 : blk--; 125 : } 126 : } 127 : else 128 0 : off--; 129 : 130 60 : ItemPointerSet(pointer, blk, off); 131 60 : }