]> granicus.if.org Git - postgresql/blob - src/backend/utils/misc/pg_controldata.c
Fix initialization of fake LSN for unlogged relations
[postgresql] / src / backend / utils / misc / pg_controldata.c
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-2019, 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_internal.h"
21 #include "access/xlog.h"
22 #include "catalog/pg_control.h"
23 #include "catalog/pg_type.h"
24 #include "common/controldata_utils.h"
25 #include "funcapi.h"
26 #include "miscadmin.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 {
34         Datum           values[4];
35         bool            nulls[4];
36         TupleDesc       tupdesc;
37         HeapTuple       htup;
38         ControlFileData *ControlFile;
39         bool            crc_ok;
40
41         /*
42          * Construct a tuple descriptor for the result row.  This must match this
43          * function's pg_proc entry!
44          */
45         tupdesc = CreateTemplateTupleDesc(4);
46         TupleDescInitEntry(tupdesc, (AttrNumber) 1, "pg_control_version",
47                                            INT4OID, -1, 0);
48         TupleDescInitEntry(tupdesc, (AttrNumber) 2, "catalog_version_no",
49                                            INT4OID, -1, 0);
50         TupleDescInitEntry(tupdesc, (AttrNumber) 3, "system_identifier",
51                                            INT8OID, -1, 0);
52         TupleDescInitEntry(tupdesc, (AttrNumber) 4, "pg_control_last_modified",
53                                            TIMESTAMPTZOID, -1, 0);
54         tupdesc = BlessTupleDesc(tupdesc);
55
56         /* read the control file */
57         ControlFile = get_controlfile(DataDir, &crc_ok);
58         if (!crc_ok)
59                 ereport(ERROR,
60                                 (errmsg("calculated CRC checksum does not match value stored in file")));
61
62         values[0] = Int32GetDatum(ControlFile->pg_control_version);
63         nulls[0] = false;
64
65         values[1] = Int32GetDatum(ControlFile->catalog_version_no);
66         nulls[1] = false;
67
68         values[2] = Int64GetDatum(ControlFile->system_identifier);
69         nulls[2] = false;
70
71         values[3] = TimestampTzGetDatum(time_t_to_timestamptz(ControlFile->time));
72         nulls[3] = false;
73
74         htup = heap_form_tuple(tupdesc, values, nulls);
75
76         PG_RETURN_DATUM(HeapTupleGetDatum(htup));
77 }
78
79 Datum
80 pg_control_checkpoint(PG_FUNCTION_ARGS)
81 {
82         Datum           values[19];
83         bool            nulls[19];
84         TupleDesc       tupdesc;
85         HeapTuple       htup;
86         ControlFileData *ControlFile;
87         XLogSegNo       segno;
88         char            xlogfilename[MAXFNAMELEN];
89         bool            crc_ok;
90
91         /*
92          * Construct a tuple descriptor for the result row.  This must match this
93          * function's pg_proc entry!
94          */
95         tupdesc = CreateTemplateTupleDesc(18);
96         TupleDescInitEntry(tupdesc, (AttrNumber) 1, "checkpoint_lsn",
97                                            LSNOID, -1, 0);
98         TupleDescInitEntry(tupdesc, (AttrNumber) 2, "redo_lsn",
99                                            LSNOID, -1, 0);
100         TupleDescInitEntry(tupdesc, (AttrNumber) 3, "redo_wal_file",
101                                            TEXTOID, -1, 0);
102         TupleDescInitEntry(tupdesc, (AttrNumber) 4, "timeline_id",
103                                            INT4OID, -1, 0);
104         TupleDescInitEntry(tupdesc, (AttrNumber) 5, "prev_timeline_id",
105                                            INT4OID, -1, 0);
106         TupleDescInitEntry(tupdesc, (AttrNumber) 6, "full_page_writes",
107                                            BOOLOID, -1, 0);
108         TupleDescInitEntry(tupdesc, (AttrNumber) 7, "next_xid",
109                                            TEXTOID, -1, 0);
110         TupleDescInitEntry(tupdesc, (AttrNumber) 8, "next_oid",
111                                            OIDOID, -1, 0);
112         TupleDescInitEntry(tupdesc, (AttrNumber) 9, "next_multixact_id",
113                                            XIDOID, -1, 0);
114         TupleDescInitEntry(tupdesc, (AttrNumber) 10, "next_multi_offset",
115                                            XIDOID, -1, 0);
116         TupleDescInitEntry(tupdesc, (AttrNumber) 11, "oldest_xid",
117                                            XIDOID, -1, 0);
118         TupleDescInitEntry(tupdesc, (AttrNumber) 12, "oldest_xid_dbid",
119                                            OIDOID, -1, 0);
120         TupleDescInitEntry(tupdesc, (AttrNumber) 13, "oldest_active_xid",
121                                            XIDOID, -1, 0);
122         TupleDescInitEntry(tupdesc, (AttrNumber) 14, "oldest_multi_xid",
123                                            XIDOID, -1, 0);
124         TupleDescInitEntry(tupdesc, (AttrNumber) 15, "oldest_multi_dbid",
125                                            OIDOID, -1, 0);
126         TupleDescInitEntry(tupdesc, (AttrNumber) 16, "oldest_commit_ts_xid",
127                                            XIDOID, -1, 0);
128         TupleDescInitEntry(tupdesc, (AttrNumber) 17, "newest_commit_ts_xid",
129                                            XIDOID, -1, 0);
130         TupleDescInitEntry(tupdesc, (AttrNumber) 18, "checkpoint_time",
131                                            TIMESTAMPTZOID, -1, 0);
132         tupdesc = BlessTupleDesc(tupdesc);
133
134         /* Read the control file. */
135         ControlFile = get_controlfile(DataDir, &crc_ok);
136         if (!crc_ok)
137                 ereport(ERROR,
138                                 (errmsg("calculated CRC checksum does not match value stored in file")));
139
140         /*
141          * Calculate name of the WAL file containing the latest checkpoint's REDO
142          * start point.
143          */
144         XLByteToSeg(ControlFile->checkPointCopy.redo, segno, wal_segment_size);
145         XLogFileName(xlogfilename, ControlFile->checkPointCopy.ThisTimeLineID,
146                                  segno, wal_segment_size);
147
148         /* Populate the values and null arrays */
149         values[0] = LSNGetDatum(ControlFile->checkPoint);
150         nulls[0] = false;
151
152         values[1] = LSNGetDatum(ControlFile->checkPointCopy.redo);
153         nulls[1] = false;
154
155         values[2] = CStringGetTextDatum(xlogfilename);
156         nulls[2] = false;
157
158         values[3] = Int32GetDatum(ControlFile->checkPointCopy.ThisTimeLineID);
159         nulls[3] = false;
160
161         values[4] = Int32GetDatum(ControlFile->checkPointCopy.PrevTimeLineID);
162         nulls[4] = false;
163
164         values[5] = BoolGetDatum(ControlFile->checkPointCopy.fullPageWrites);
165         nulls[5] = false;
166
167         values[6] = CStringGetTextDatum(psprintf("%u:%u",
168                                                                                          EpochFromFullTransactionId(ControlFile->checkPointCopy.nextFullXid),
169                                                                                          XidFromFullTransactionId(ControlFile->checkPointCopy.nextFullXid)));
170         nulls[6] = false;
171
172         values[7] = ObjectIdGetDatum(ControlFile->checkPointCopy.nextOid);
173         nulls[7] = false;
174
175         values[8] = TransactionIdGetDatum(ControlFile->checkPointCopy.nextMulti);
176         nulls[8] = false;
177
178         values[9] = TransactionIdGetDatum(ControlFile->checkPointCopy.nextMultiOffset);
179         nulls[9] = false;
180
181         values[10] = TransactionIdGetDatum(ControlFile->checkPointCopy.oldestXid);
182         nulls[10] = false;
183
184         values[11] = ObjectIdGetDatum(ControlFile->checkPointCopy.oldestXidDB);
185         nulls[11] = false;
186
187         values[12] = TransactionIdGetDatum(ControlFile->checkPointCopy.oldestActiveXid);
188         nulls[12] = false;
189
190         values[13] = TransactionIdGetDatum(ControlFile->checkPointCopy.oldestMulti);
191         nulls[13] = false;
192
193         values[14] = ObjectIdGetDatum(ControlFile->checkPointCopy.oldestMultiDB);
194         nulls[14] = false;
195
196         values[15] = TransactionIdGetDatum(ControlFile->checkPointCopy.oldestCommitTsXid);
197         nulls[15] = false;
198
199         values[16] = TransactionIdGetDatum(ControlFile->checkPointCopy.newestCommitTsXid);
200         nulls[16] = false;
201
202         values[17] = TimestampTzGetDatum(
203                                                                          time_t_to_timestamptz(ControlFile->checkPointCopy.time));
204         nulls[17] = false;
205
206         htup = heap_form_tuple(tupdesc, values, nulls);
207
208         PG_RETURN_DATUM(HeapTupleGetDatum(htup));
209 }
210
211 Datum
212 pg_control_recovery(PG_FUNCTION_ARGS)
213 {
214         Datum           values[5];
215         bool            nulls[5];
216         TupleDesc       tupdesc;
217         HeapTuple       htup;
218         ControlFileData *ControlFile;
219         bool            crc_ok;
220
221         /*
222          * Construct a tuple descriptor for the result row.  This must match this
223          * function's pg_proc entry!
224          */
225         tupdesc = CreateTemplateTupleDesc(5);
226         TupleDescInitEntry(tupdesc, (AttrNumber) 1, "min_recovery_end_lsn",
227                                            LSNOID, -1, 0);
228         TupleDescInitEntry(tupdesc, (AttrNumber) 2, "min_recovery_end_timeline",
229                                            INT4OID, -1, 0);
230         TupleDescInitEntry(tupdesc, (AttrNumber) 3, "backup_start_lsn",
231                                            LSNOID, -1, 0);
232         TupleDescInitEntry(tupdesc, (AttrNumber) 4, "backup_end_lsn",
233                                            LSNOID, -1, 0);
234         TupleDescInitEntry(tupdesc, (AttrNumber) 5, "end_of_backup_record_required",
235                                            BOOLOID, -1, 0);
236         tupdesc = BlessTupleDesc(tupdesc);
237
238         /* read the control file */
239         ControlFile = get_controlfile(DataDir, &crc_ok);
240         if (!crc_ok)
241                 ereport(ERROR,
242                                 (errmsg("calculated CRC checksum does not match value stored in file")));
243
244         values[0] = LSNGetDatum(ControlFile->minRecoveryPoint);
245         nulls[0] = false;
246
247         values[1] = Int32GetDatum(ControlFile->minRecoveryPointTLI);
248         nulls[1] = false;
249
250         values[2] = LSNGetDatum(ControlFile->backupStartPoint);
251         nulls[2] = false;
252
253         values[3] = LSNGetDatum(ControlFile->backupEndPoint);
254         nulls[3] = false;
255
256         values[4] = BoolGetDatum(ControlFile->backupEndRequired);
257         nulls[4] = false;
258
259         htup = heap_form_tuple(tupdesc, values, nulls);
260
261         PG_RETURN_DATUM(HeapTupleGetDatum(htup));
262 }
263
264 Datum
265 pg_control_init(PG_FUNCTION_ARGS)
266 {
267         Datum           values[12];
268         bool            nulls[12];
269         TupleDesc       tupdesc;
270         HeapTuple       htup;
271         ControlFileData *ControlFile;
272         bool            crc_ok;
273
274         /*
275          * Construct a tuple descriptor for the result row.  This must match this
276          * function's pg_proc entry!
277          */
278         tupdesc = CreateTemplateTupleDesc(12);
279         TupleDescInitEntry(tupdesc, (AttrNumber) 1, "max_data_alignment",
280                                            INT4OID, -1, 0);
281         TupleDescInitEntry(tupdesc, (AttrNumber) 2, "database_block_size",
282                                            INT4OID, -1, 0);
283         TupleDescInitEntry(tupdesc, (AttrNumber) 3, "blocks_per_segment",
284                                            INT4OID, -1, 0);
285         TupleDescInitEntry(tupdesc, (AttrNumber) 4, "wal_block_size",
286                                            INT4OID, -1, 0);
287         TupleDescInitEntry(tupdesc, (AttrNumber) 5, "bytes_per_wal_segment",
288                                            INT4OID, -1, 0);
289         TupleDescInitEntry(tupdesc, (AttrNumber) 6, "max_identifier_length",
290                                            INT4OID, -1, 0);
291         TupleDescInitEntry(tupdesc, (AttrNumber) 7, "max_index_columns",
292                                            INT4OID, -1, 0);
293         TupleDescInitEntry(tupdesc, (AttrNumber) 8, "max_toast_chunk_size",
294                                            INT4OID, -1, 0);
295         TupleDescInitEntry(tupdesc, (AttrNumber) 9, "large_object_chunk_size",
296                                            INT4OID, -1, 0);
297         TupleDescInitEntry(tupdesc, (AttrNumber) 10, "float4_pass_by_value",
298                                            BOOLOID, -1, 0);
299         TupleDescInitEntry(tupdesc, (AttrNumber) 11, "float8_pass_by_value",
300                                            BOOLOID, -1, 0);
301         TupleDescInitEntry(tupdesc, (AttrNumber) 12, "data_page_checksum_version",
302                                            INT4OID, -1, 0);
303         tupdesc = BlessTupleDesc(tupdesc);
304
305         /* read the control file */
306         ControlFile = get_controlfile(DataDir, &crc_ok);
307         if (!crc_ok)
308                 ereport(ERROR,
309                                 (errmsg("calculated CRC checksum does not match value stored in file")));
310
311         values[0] = Int32GetDatum(ControlFile->maxAlign);
312         nulls[0] = false;
313
314         values[1] = Int32GetDatum(ControlFile->blcksz);
315         nulls[1] = false;
316
317         values[2] = Int32GetDatum(ControlFile->relseg_size);
318         nulls[2] = false;
319
320         values[3] = Int32GetDatum(ControlFile->xlog_blcksz);
321         nulls[3] = false;
322
323         values[4] = Int32GetDatum(ControlFile->xlog_seg_size);
324         nulls[4] = false;
325
326         values[5] = Int32GetDatum(ControlFile->nameDataLen);
327         nulls[5] = false;
328
329         values[6] = Int32GetDatum(ControlFile->indexMaxKeys);
330         nulls[6] = false;
331
332         values[7] = Int32GetDatum(ControlFile->toast_max_chunk_size);
333         nulls[7] = false;
334
335         values[8] = Int32GetDatum(ControlFile->loblksize);
336         nulls[8] = false;
337
338         values[9] = BoolGetDatum(ControlFile->float4ByVal);
339         nulls[9] = false;
340
341         values[10] = BoolGetDatum(ControlFile->float8ByVal);
342         nulls[10] = false;
343
344         values[11] = Int32GetDatum(ControlFile->data_checksum_version);
345         nulls[11] = false;
346
347         htup = heap_form_tuple(tupdesc, values, nulls);
348
349         PG_RETURN_DATUM(HeapTupleGetDatum(htup));
350 }