Coverage Report

Created: 2025-06-13 06:06

/src/postgres/src/backend/utils/misc/pg_controldata.c
Line
Count
Source (jump to first uncovered line)
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-2025, 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[18];
73
0
  bool    nulls[18];
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] = CStringGetTextDatum(psprintf("%u:%u",
120
0
                       EpochFromFullTransactionId(ControlFile->checkPointCopy.nextXid),
121
0
                       XidFromFullTransactionId(ControlFile->checkPointCopy.nextXid)));
122
0
  nulls[6] = false;
123
124
0
  values[7] = ObjectIdGetDatum(ControlFile->checkPointCopy.nextOid);
125
0
  nulls[7] = false;
126
127
0
  values[8] = TransactionIdGetDatum(ControlFile->checkPointCopy.nextMulti);
128
0
  nulls[8] = false;
129
130
0
  values[9] = TransactionIdGetDatum(ControlFile->checkPointCopy.nextMultiOffset);
131
0
  nulls[9] = false;
132
133
0
  values[10] = TransactionIdGetDatum(ControlFile->checkPointCopy.oldestXid);
134
0
  nulls[10] = false;
135
136
0
  values[11] = ObjectIdGetDatum(ControlFile->checkPointCopy.oldestXidDB);
137
0
  nulls[11] = false;
138
139
0
  values[12] = TransactionIdGetDatum(ControlFile->checkPointCopy.oldestActiveXid);
140
0
  nulls[12] = false;
141
142
0
  values[13] = TransactionIdGetDatum(ControlFile->checkPointCopy.oldestMulti);
143
0
  nulls[13] = false;
144
145
0
  values[14] = ObjectIdGetDatum(ControlFile->checkPointCopy.oldestMultiDB);
146
0
  nulls[14] = false;
147
148
0
  values[15] = TransactionIdGetDatum(ControlFile->checkPointCopy.oldestCommitTsXid);
149
0
  nulls[15] = false;
150
151
0
  values[16] = TransactionIdGetDatum(ControlFile->checkPointCopy.newestCommitTsXid);
152
0
  nulls[16] = false;
153
154
0
  values[17] = TimestampTzGetDatum(time_t_to_timestamptz(ControlFile->checkPointCopy.time));
155
0
  nulls[17] = false;
156
157
0
  htup = heap_form_tuple(tupdesc, values, nulls);
158
159
0
  PG_RETURN_DATUM(HeapTupleGetDatum(htup));
160
0
}
161
162
Datum
163
pg_control_recovery(PG_FUNCTION_ARGS)
164
0
{
165
0
  Datum   values[5];
166
0
  bool    nulls[5];
167
0
  TupleDesc tupdesc;
168
0
  HeapTuple htup;
169
0
  ControlFileData *ControlFile;
170
0
  bool    crc_ok;
171
172
0
  if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
173
0
    elog(ERROR, "return type must be a row type");
174
175
  /* read the control file */
176
0
  LWLockAcquire(ControlFileLock, LW_SHARED);
177
0
  ControlFile = get_controlfile(DataDir, &crc_ok);
178
0
  LWLockRelease(ControlFileLock);
179
0
  if (!crc_ok)
180
0
    ereport(ERROR,
181
0
        (errmsg("calculated CRC checksum does not match value stored in file")));
182
183
0
  values[0] = LSNGetDatum(ControlFile->minRecoveryPoint);
184
0
  nulls[0] = false;
185
186
0
  values[1] = Int32GetDatum(ControlFile->minRecoveryPointTLI);
187
0
  nulls[1] = false;
188
189
0
  values[2] = LSNGetDatum(ControlFile->backupStartPoint);
190
0
  nulls[2] = false;
191
192
0
  values[3] = LSNGetDatum(ControlFile->backupEndPoint);
193
0
  nulls[3] = false;
194
195
0
  values[4] = BoolGetDatum(ControlFile->backupEndRequired);
196
0
  nulls[4] = false;
197
198
0
  htup = heap_form_tuple(tupdesc, values, nulls);
199
200
0
  PG_RETURN_DATUM(HeapTupleGetDatum(htup));
201
0
}
202
203
Datum
204
pg_control_init(PG_FUNCTION_ARGS)
205
0
{
206
0
  Datum   values[12];
207
0
  bool    nulls[12];
208
0
  TupleDesc tupdesc;
209
0
  HeapTuple htup;
210
0
  ControlFileData *ControlFile;
211
0
  bool    crc_ok;
212
213
0
  if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
214
0
    elog(ERROR, "return type must be a row type");
215
216
  /* read the control file */
217
0
  LWLockAcquire(ControlFileLock, LW_SHARED);
218
0
  ControlFile = get_controlfile(DataDir, &crc_ok);
219
0
  LWLockRelease(ControlFileLock);
220
0
  if (!crc_ok)
221
0
    ereport(ERROR,
222
0
        (errmsg("calculated CRC checksum does not match value stored in file")));
223
224
0
  values[0] = Int32GetDatum(ControlFile->maxAlign);
225
0
  nulls[0] = false;
226
227
0
  values[1] = Int32GetDatum(ControlFile->blcksz);
228
0
  nulls[1] = false;
229
230
0
  values[2] = Int32GetDatum(ControlFile->relseg_size);
231
0
  nulls[2] = false;
232
233
0
  values[3] = Int32GetDatum(ControlFile->xlog_blcksz);
234
0
  nulls[3] = false;
235
236
0
  values[4] = Int32GetDatum(ControlFile->xlog_seg_size);
237
0
  nulls[4] = false;
238
239
0
  values[5] = Int32GetDatum(ControlFile->nameDataLen);
240
0
  nulls[5] = false;
241
242
0
  values[6] = Int32GetDatum(ControlFile->indexMaxKeys);
243
0
  nulls[6] = false;
244
245
0
  values[7] = Int32GetDatum(ControlFile->toast_max_chunk_size);
246
0
  nulls[7] = false;
247
248
0
  values[8] = Int32GetDatum(ControlFile->loblksize);
249
0
  nulls[8] = false;
250
251
0
  values[9] = BoolGetDatum(ControlFile->float8ByVal);
252
0
  nulls[9] = false;
253
254
0
  values[10] = Int32GetDatum(ControlFile->data_checksum_version);
255
0
  nulls[10] = false;
256
257
0
  values[11] = BoolGetDatum(ControlFile->default_char_signedness);
258
0
  nulls[11] = false;
259
260
0
  htup = heap_form_tuple(tupdesc, values, nulls);
261
262
0
  PG_RETURN_DATUM(HeapTupleGetDatum(htup));
263
0
}