Coverage Report

Created: 2026-09-28 06:55

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/postgres/src/backend/utils/misc/pg_controldata.c
Line
Count
Source
1
/*-------------------------------------------------------------------------
2
 *
3
 * pg_controldata.c
4
 *
5
 * Routines to expose the contents of the control data file via
6
 * a set of SQL functions.
7
 *
8
 * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
9
 * Portions Copyright (c) 1994, Regents of the University of California
10
 *
11
 * IDENTIFICATION
12
 *    src/backend/utils/misc/pg_controldata.c
13
 *-------------------------------------------------------------------------
14
 */
15
16
#include "postgres.h"
17
18
#include "access/htup_details.h"
19
#include "access/transam.h"
20
#include "access/xlog.h"
21
#include "access/xlog_internal.h"
22
#include "catalog/pg_control.h"
23
#include "common/controldata_utils.h"
24
#include "funcapi.h"
25
#include "miscadmin.h"
26
#include "storage/lwlock.h"
27
#include "utils/builtins.h"
28
#include "utils/pg_lsn.h"
29
#include "utils/timestamp.h"
30
31
Datum
32
pg_control_system(PG_FUNCTION_ARGS)
33
0
{
34
0
  Datum   values[4];
35
0
  bool    nulls[4];
36
0
  TupleDesc tupdesc;
37
0
  HeapTuple htup;
38
0
  ControlFileData *ControlFile;
39
0
  bool    crc_ok;
40
41
0
  if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
42
0
    elog(ERROR, "return type must be a row type");
43
44
  /* read the control file */
45
0
  LWLockAcquire(ControlFileLock, LW_SHARED);
46
0
  ControlFile = get_controlfile(DataDir, &crc_ok);
47
0
  LWLockRelease(ControlFileLock);
48
0
  if (!crc_ok)
49
0
    ereport(ERROR,
50
0
        (errmsg("calculated CRC checksum does not match value stored in file")));
51
52
0
  values[0] = Int32GetDatum(ControlFile->pg_control_version);
53
0
  nulls[0] = false;
54
55
0
  values[1] = Int32GetDatum(ControlFile->catalog_version_no);
56
0
  nulls[1] = false;
57
58
0
  values[2] = Int64GetDatum(ControlFile->system_identifier);
59
0
  nulls[2] = false;
60
61
0
  values[3] = TimestampTzGetDatum(time_t_to_timestamptz(ControlFile->time));
62
0
  nulls[3] = false;
63
64
0
  htup = heap_form_tuple(tupdesc, values, nulls);
65
66
0
  PG_RETURN_DATUM(HeapTupleGetDatum(htup));
67
0
}
68
69
Datum
70
pg_control_checkpoint(PG_FUNCTION_ARGS)
71
0
{
72
0
  Datum   values[20];
73
0
  bool    nulls[20];
74
0
  TupleDesc tupdesc;
75
0
  HeapTuple htup;
76
0
  ControlFileData *ControlFile;
77
0
  XLogSegNo segno;
78
0
  char    xlogfilename[MAXFNAMELEN];
79
0
  bool    crc_ok;
80
81
0
  if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
82
0
    elog(ERROR, "return type must be a row type");
83
84
  /* Read the control file. */
85
0
  LWLockAcquire(ControlFileLock, LW_SHARED);
86
0
  ControlFile = get_controlfile(DataDir, &crc_ok);
87
0
  LWLockRelease(ControlFileLock);
88
0
  if (!crc_ok)
89
0
    ereport(ERROR,
90
0
        (errmsg("calculated CRC checksum does not match value stored in file")));
91
92
  /*
93
   * Calculate name of the WAL file containing the latest checkpoint's REDO
94
   * start point.
95
   */
96
0
  XLByteToSeg(ControlFile->checkPointCopy.redo, segno, wal_segment_size);
97
0
  XLogFileName(xlogfilename, ControlFile->checkPointCopy.ThisTimeLineID,
98
0
         segno, wal_segment_size);
99
100
  /* Populate the values and null arrays */
101
0
  values[0] = LSNGetDatum(ControlFile->checkPoint);
102
0
  nulls[0] = false;
103
104
0
  values[1] = LSNGetDatum(ControlFile->checkPointCopy.redo);
105
0
  nulls[1] = false;
106
107
0
  values[2] = CStringGetTextDatum(xlogfilename);
108
0
  nulls[2] = false;
109
110
0
  values[3] = Int32GetDatum(ControlFile->checkPointCopy.ThisTimeLineID);
111
0
  nulls[3] = false;
112
113
0
  values[4] = Int32GetDatum(ControlFile->checkPointCopy.PrevTimeLineID);
114
0
  nulls[4] = false;
115
116
0
  values[5] = BoolGetDatum(ControlFile->checkPointCopy.fullPageWrites);
117
0
  nulls[5] = false;
118
119
0
  values[6] = BoolGetDatum(ControlFile->checkPointCopy.logicalDecodingEnabled);
120
0
  nulls[6] = false;
121
122
0
  values[7] = CStringGetTextDatum(psprintf("%u:%u",
123
0
                       EpochFromFullTransactionId(ControlFile->checkPointCopy.nextXid),
124
0
                       XidFromFullTransactionId(ControlFile->checkPointCopy.nextXid)));
125
0
  nulls[7] = false;
126
127
0
  values[8] = ObjectId8GetDatum(ControlFile->checkPointCopy.nextOid);
128
0
  nulls[8] = false;
129
130
0
  values[9] = TransactionIdGetDatum(ControlFile->checkPointCopy.nextMulti);
131
0
  nulls[9] = false;
132
133
0
  values[10] = Int64GetDatum(ControlFile->checkPointCopy.nextMultiOffset);
134
0
  nulls[10] = false;
135
136
0
  values[11] = TransactionIdGetDatum(ControlFile->checkPointCopy.oldestXid);
137
0
  nulls[11] = false;
138
139
0
  values[12] = ObjectIdGetDatum(ControlFile->checkPointCopy.oldestXidDB);
140
0
  nulls[12] = false;
141
142
0
  values[13] = TransactionIdGetDatum(ControlFile->checkPointCopy.oldestActiveXid);
143
0
  nulls[13] = false;
144
145
0
  values[14] = TransactionIdGetDatum(ControlFile->checkPointCopy.oldestMulti);
146
0
  nulls[14] = false;
147
148
0
  values[15] = ObjectIdGetDatum(ControlFile->checkPointCopy.oldestMultiDB);
149
0
  nulls[15] = false;
150
151
0
  values[16] = TransactionIdGetDatum(ControlFile->checkPointCopy.oldestCommitTsXid);
152
0
  nulls[16] = false;
153
154
0
  values[17] = TransactionIdGetDatum(ControlFile->checkPointCopy.newestCommitTsXid);
155
0
  nulls[17] = false;
156
157
0
  values[18] = Int32GetDatum(ControlFile->checkPointCopy.dataChecksumState);
158
0
  nulls[18] = false;
159
160
0
  values[19] = TimestampTzGetDatum(time_t_to_timestamptz(ControlFile->checkPointCopy.time));
161
0
  nulls[19] = false;
162
163
0
  htup = heap_form_tuple(tupdesc, values, nulls);
164
165
0
  PG_RETURN_DATUM(HeapTupleGetDatum(htup));
166
0
}
167
168
Datum
169
pg_control_recovery(PG_FUNCTION_ARGS)
170
0
{
171
0
  Datum   values[5];
172
0
  bool    nulls[5];
173
0
  TupleDesc tupdesc;
174
0
  HeapTuple htup;
175
0
  ControlFileData *ControlFile;
176
0
  bool    crc_ok;
177
178
0
  if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
179
0
    elog(ERROR, "return type must be a row type");
180
181
  /* read the control file */
182
0
  LWLockAcquire(ControlFileLock, LW_SHARED);
183
0
  ControlFile = get_controlfile(DataDir, &crc_ok);
184
0
  LWLockRelease(ControlFileLock);
185
0
  if (!crc_ok)
186
0
    ereport(ERROR,
187
0
        (errmsg("calculated CRC checksum does not match value stored in file")));
188
189
0
  values[0] = LSNGetDatum(ControlFile->minRecoveryPoint);
190
0
  nulls[0] = false;
191
192
0
  values[1] = Int32GetDatum(ControlFile->minRecoveryPointTLI);
193
0
  nulls[1] = false;
194
195
0
  values[2] = LSNGetDatum(ControlFile->backupStartPoint);
196
0
  nulls[2] = false;
197
198
0
  values[3] = LSNGetDatum(ControlFile->backupEndPoint);
199
0
  nulls[3] = false;
200
201
0
  values[4] = BoolGetDatum(ControlFile->backupEndRequired);
202
0
  nulls[4] = false;
203
204
0
  htup = heap_form_tuple(tupdesc, values, nulls);
205
206
0
  PG_RETURN_DATUM(HeapTupleGetDatum(htup));
207
0
}
208
209
Datum
210
pg_control_init(PG_FUNCTION_ARGS)
211
0
{
212
0
  Datum   values[12];
213
0
  bool    nulls[12];
214
0
  TupleDesc tupdesc;
215
0
  HeapTuple htup;
216
0
  ControlFileData *ControlFile;
217
0
  bool    crc_ok;
218
219
0
  if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
220
0
    elog(ERROR, "return type must be a row type");
221
222
  /* read the control file */
223
0
  LWLockAcquire(ControlFileLock, LW_SHARED);
224
0
  ControlFile = get_controlfile(DataDir, &crc_ok);
225
0
  LWLockRelease(ControlFileLock);
226
0
  if (!crc_ok)
227
0
    ereport(ERROR,
228
0
        (errmsg("calculated CRC checksum does not match value stored in file")));
229
230
0
  values[0] = Int32GetDatum(ControlFile->maxAlign);
231
0
  nulls[0] = false;
232
233
0
  values[1] = Int32GetDatum(ControlFile->blcksz);
234
0
  nulls[1] = false;
235
236
0
  values[2] = Int32GetDatum(ControlFile->relseg_size);
237
0
  nulls[2] = false;
238
239
0
  values[3] = Int32GetDatum(ControlFile->xlog_blcksz);
240
0
  nulls[3] = false;
241
242
0
  values[4] = Int32GetDatum(ControlFile->xlog_seg_size);
243
0
  nulls[4] = false;
244
245
0
  values[5] = Int32GetDatum(ControlFile->nameDataLen);
246
0
  nulls[5] = false;
247
248
0
  values[6] = Int32GetDatum(ControlFile->indexMaxKeys);
249
0
  nulls[6] = false;
250
251
0
  values[7] = Int32GetDatum(ControlFile->toast_max_chunk_size);
252
0
  nulls[7] = false;
253
254
0
  values[8] = Int32GetDatum(ControlFile->loblksize);
255
0
  nulls[8] = false;
256
257
0
  values[9] = BoolGetDatum(ControlFile->float8ByVal);
258
0
  nulls[9] = false;
259
260
0
  values[10] = Int32GetDatum(ControlFile->data_checksum_version_init);
261
0
  nulls[10] = false;
262
263
0
  values[11] = BoolGetDatum(ControlFile->default_char_signedness);
264
0
  nulls[11] = false;
265
266
0
  htup = heap_form_tuple(tupdesc, values, nulls);
267
268
0
  PG_RETURN_DATUM(HeapTupleGetDatum(htup));
269
0
}