/src/postgres/src/backend/storage/page/itemptr.c
Line | Count | Source |
1 | | /*------------------------------------------------------------------------- |
2 | | * |
3 | | * itemptr.c |
4 | | * POSTGRES disk item pointer code. |
5 | | * |
6 | | * Portions Copyright (c) 1996-2026, 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 | | ItemPointerEquals(const ItemPointerData *pointer1, const ItemPointerData *pointer2) |
36 | 0 | { |
37 | 0 | if (ItemPointerGetBlockNumber(pointer1) == |
38 | 0 | ItemPointerGetBlockNumber(pointer2) && |
39 | 0 | ItemPointerGetOffsetNumber(pointer1) == |
40 | 0 | ItemPointerGetOffsetNumber(pointer2)) |
41 | 0 | return true; |
42 | 0 | else |
43 | 0 | return false; |
44 | 0 | } |
45 | | |
46 | | /* |
47 | | * ItemPointerCompare |
48 | | * Generic btree-style comparison for item pointers. |
49 | | */ |
50 | | int32 |
51 | | ItemPointerCompare(const ItemPointerData *arg1, const ItemPointerData *arg2) |
52 | 0 | { |
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 | 0 | BlockNumber b1 = ItemPointerGetBlockNumberNoCheck(arg1); |
58 | 0 | BlockNumber b2 = ItemPointerGetBlockNumberNoCheck(arg2); |
59 | |
|
60 | 0 | if (b1 < b2) |
61 | 0 | return -1; |
62 | 0 | else if (b1 > b2) |
63 | 0 | return 1; |
64 | 0 | else if (ItemPointerGetOffsetNumberNoCheck(arg1) < |
65 | 0 | ItemPointerGetOffsetNumberNoCheck(arg2)) |
66 | 0 | return -1; |
67 | 0 | else if (ItemPointerGetOffsetNumberNoCheck(arg1) > |
68 | 0 | ItemPointerGetOffsetNumberNoCheck(arg2)) |
69 | 0 | return 1; |
70 | 0 | else |
71 | 0 | return 0; |
72 | 0 | } |
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 | | ItemPointerInc(ItemPointer pointer) |
85 | 0 | { |
86 | 0 | BlockNumber blk = ItemPointerGetBlockNumberNoCheck(pointer); |
87 | 0 | OffsetNumber off = ItemPointerGetOffsetNumberNoCheck(pointer); |
88 | |
|
89 | 0 | if (off == PG_UINT16_MAX) |
90 | 0 | { |
91 | 0 | if (blk != InvalidBlockNumber) |
92 | 0 | { |
93 | 0 | off = 0; |
94 | 0 | blk++; |
95 | 0 | } |
96 | 0 | } |
97 | 0 | else |
98 | 0 | off++; |
99 | |
|
100 | 0 | ItemPointerSet(pointer, blk, off); |
101 | 0 | } |
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 | | ItemPointerDec(ItemPointer pointer) |
115 | 0 | { |
116 | 0 | BlockNumber blk = ItemPointerGetBlockNumberNoCheck(pointer); |
117 | 0 | OffsetNumber off = ItemPointerGetOffsetNumberNoCheck(pointer); |
118 | |
|
119 | 0 | if (off == 0) |
120 | 0 | { |
121 | 0 | if (blk != 0) |
122 | 0 | { |
123 | 0 | off = PG_UINT16_MAX; |
124 | 0 | blk--; |
125 | 0 | } |
126 | 0 | } |
127 | 0 | else |
128 | 0 | off--; |
129 | |
|
130 | 0 | ItemPointerSet(pointer, blk, off); |
131 | 0 | } |