Line data Source code
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 15 : pg_control_system(PG_FUNCTION_ARGS)
33 : {
34 : Datum values[4];
35 : bool nulls[4];
36 : TupleDesc tupdesc;
37 : HeapTuple htup;
38 : ControlFileData *ControlFile;
39 : bool crc_ok;
40 :
41 15 : 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 15 : LWLockAcquire(ControlFileLock, LW_SHARED);
46 15 : ControlFile = get_controlfile(DataDir, &crc_ok);
47 15 : LWLockRelease(ControlFileLock);
48 15 : if (!crc_ok)
49 0 : ereport(ERROR,
50 : (errmsg("calculated CRC checksum does not match value stored in file")));
51 :
52 15 : values[0] = Int32GetDatum(ControlFile->pg_control_version);
53 15 : nulls[0] = false;
54 :
55 15 : values[1] = Int32GetDatum(ControlFile->catalog_version_no);
56 15 : nulls[1] = false;
57 :
58 15 : values[2] = Int64GetDatum(ControlFile->system_identifier);
59 15 : nulls[2] = false;
60 :
61 15 : values[3] = TimestampTzGetDatum(time_t_to_timestamptz(ControlFile->time));
62 15 : nulls[3] = false;
63 :
64 15 : htup = heap_form_tuple(tupdesc, values, nulls);
65 :
66 15 : PG_RETURN_DATUM(HeapTupleGetDatum(htup));
67 : }
68 :
69 : Datum
70 9 : pg_control_checkpoint(PG_FUNCTION_ARGS)
71 : {
72 : Datum values[18];
73 : bool nulls[18];
74 : TupleDesc tupdesc;
75 : HeapTuple htup;
76 : ControlFileData *ControlFile;
77 : XLogSegNo segno;
78 : char xlogfilename[MAXFNAMELEN];
79 : bool crc_ok;
80 :
81 9 : 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 9 : LWLockAcquire(ControlFileLock, LW_SHARED);
86 9 : ControlFile = get_controlfile(DataDir, &crc_ok);
87 9 : LWLockRelease(ControlFileLock);
88 9 : if (!crc_ok)
89 0 : ereport(ERROR,
90 : (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 9 : XLByteToSeg(ControlFile->checkPointCopy.redo, segno, wal_segment_size);
97 9 : XLogFileName(xlogfilename, ControlFile->checkPointCopy.ThisTimeLineID,
98 : segno, wal_segment_size);
99 :
100 : /* Populate the values and null arrays */
101 9 : values[0] = LSNGetDatum(ControlFile->checkPoint);
102 9 : nulls[0] = false;
103 :
104 9 : values[1] = LSNGetDatum(ControlFile->checkPointCopy.redo);
105 9 : nulls[1] = false;
106 :
107 9 : values[2] = CStringGetTextDatum(xlogfilename);
108 9 : nulls[2] = false;
109 :
110 9 : values[3] = Int32GetDatum(ControlFile->checkPointCopy.ThisTimeLineID);
111 9 : nulls[3] = false;
112 :
113 9 : values[4] = Int32GetDatum(ControlFile->checkPointCopy.PrevTimeLineID);
114 9 : nulls[4] = false;
115 :
116 9 : values[5] = BoolGetDatum(ControlFile->checkPointCopy.fullPageWrites);
117 9 : nulls[5] = false;
118 :
119 9 : values[6] = CStringGetTextDatum(psprintf("%u:%u",
120 : EpochFromFullTransactionId(ControlFile->checkPointCopy.nextXid),
121 : XidFromFullTransactionId(ControlFile->checkPointCopy.nextXid)));
122 9 : nulls[6] = false;
123 :
124 9 : values[7] = ObjectIdGetDatum(ControlFile->checkPointCopy.nextOid);
125 9 : nulls[7] = false;
126 :
127 9 : values[8] = TransactionIdGetDatum(ControlFile->checkPointCopy.nextMulti);
128 9 : nulls[8] = false;
129 :
130 9 : values[9] = TransactionIdGetDatum(ControlFile->checkPointCopy.nextMultiOffset);
131 9 : nulls[9] = false;
132 :
133 9 : values[10] = TransactionIdGetDatum(ControlFile->checkPointCopy.oldestXid);
134 9 : nulls[10] = false;
135 :
136 9 : values[11] = ObjectIdGetDatum(ControlFile->checkPointCopy.oldestXidDB);
137 9 : nulls[11] = false;
138 :
139 9 : values[12] = TransactionIdGetDatum(ControlFile->checkPointCopy.oldestActiveXid);
140 9 : nulls[12] = false;
141 :
142 9 : values[13] = TransactionIdGetDatum(ControlFile->checkPointCopy.oldestMulti);
143 9 : nulls[13] = false;
144 :
145 9 : values[14] = ObjectIdGetDatum(ControlFile->checkPointCopy.oldestMultiDB);
146 9 : nulls[14] = false;
147 :
148 9 : values[15] = TransactionIdGetDatum(ControlFile->checkPointCopy.oldestCommitTsXid);
149 9 : nulls[15] = false;
150 :
151 9 : values[16] = TransactionIdGetDatum(ControlFile->checkPointCopy.newestCommitTsXid);
152 9 : nulls[16] = false;
153 :
154 9 : values[17] = TimestampTzGetDatum(time_t_to_timestamptz(ControlFile->checkPointCopy.time));
155 9 : nulls[17] = false;
156 :
157 9 : htup = heap_form_tuple(tupdesc, values, nulls);
158 :
159 9 : PG_RETURN_DATUM(HeapTupleGetDatum(htup));
160 : }
161 :
162 : Datum
163 3 : pg_control_recovery(PG_FUNCTION_ARGS)
164 : {
165 : Datum values[5];
166 : bool nulls[5];
167 : TupleDesc tupdesc;
168 : HeapTuple htup;
169 : ControlFileData *ControlFile;
170 : bool crc_ok;
171 :
172 3 : 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 3 : LWLockAcquire(ControlFileLock, LW_SHARED);
177 3 : ControlFile = get_controlfile(DataDir, &crc_ok);
178 3 : LWLockRelease(ControlFileLock);
179 3 : if (!crc_ok)
180 0 : ereport(ERROR,
181 : (errmsg("calculated CRC checksum does not match value stored in file")));
182 :
183 3 : values[0] = LSNGetDatum(ControlFile->minRecoveryPoint);
184 3 : nulls[0] = false;
185 :
186 3 : values[1] = Int32GetDatum(ControlFile->minRecoveryPointTLI);
187 3 : nulls[1] = false;
188 :
189 3 : values[2] = LSNGetDatum(ControlFile->backupStartPoint);
190 3 : nulls[2] = false;
191 :
192 3 : values[3] = LSNGetDatum(ControlFile->backupEndPoint);
193 3 : nulls[3] = false;
194 :
195 3 : values[4] = BoolGetDatum(ControlFile->backupEndRequired);
196 3 : nulls[4] = false;
197 :
198 3 : htup = heap_form_tuple(tupdesc, values, nulls);
199 :
200 3 : PG_RETURN_DATUM(HeapTupleGetDatum(htup));
201 : }
202 :
203 : Datum
204 4 : pg_control_init(PG_FUNCTION_ARGS)
205 : {
206 : Datum values[12];
207 : bool nulls[12];
208 : TupleDesc tupdesc;
209 : HeapTuple htup;
210 : ControlFileData *ControlFile;
211 : bool crc_ok;
212 :
213 4 : 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 4 : LWLockAcquire(ControlFileLock, LW_SHARED);
218 4 : ControlFile = get_controlfile(DataDir, &crc_ok);
219 4 : LWLockRelease(ControlFileLock);
220 4 : if (!crc_ok)
221 0 : ereport(ERROR,
222 : (errmsg("calculated CRC checksum does not match value stored in file")));
223 :
224 4 : values[0] = Int32GetDatum(ControlFile->maxAlign);
225 4 : nulls[0] = false;
226 :
227 4 : values[1] = Int32GetDatum(ControlFile->blcksz);
228 4 : nulls[1] = false;
229 :
230 4 : values[2] = Int32GetDatum(ControlFile->relseg_size);
231 4 : nulls[2] = false;
232 :
233 4 : values[3] = Int32GetDatum(ControlFile->xlog_blcksz);
234 4 : nulls[3] = false;
235 :
236 4 : values[4] = Int32GetDatum(ControlFile->xlog_seg_size);
237 4 : nulls[4] = false;
238 :
239 4 : values[5] = Int32GetDatum(ControlFile->nameDataLen);
240 4 : nulls[5] = false;
241 :
242 4 : values[6] = Int32GetDatum(ControlFile->indexMaxKeys);
243 4 : nulls[6] = false;
244 :
245 4 : values[7] = Int32GetDatum(ControlFile->toast_max_chunk_size);
246 4 : nulls[7] = false;
247 :
248 4 : values[8] = Int32GetDatum(ControlFile->loblksize);
249 4 : nulls[8] = false;
250 :
251 4 : values[9] = BoolGetDatum(ControlFile->float8ByVal);
252 4 : nulls[9] = false;
253 :
254 4 : values[10] = Int32GetDatum(ControlFile->data_checksum_version);
255 4 : nulls[10] = false;
256 :
257 4 : values[11] = BoolGetDatum(ControlFile->default_char_signedness);
258 4 : nulls[11] = false;
259 :
260 4 : htup = heap_form_tuple(tupdesc, values, nulls);
261 :
262 4 : PG_RETURN_DATUM(HeapTupleGetDatum(htup));
263 : }
|