Coverage Report

Created: 2026-08-14 06:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}