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; NAMESPACE_BEGIN(CryptoPP)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); ConvertToInteger(const Integer & x)66 nulls[1] = false; 67 68 values[2] = Int64GetDatum(ControlFile->system_identifier); 69 nulls[2] = false; 70 CheckMOVCondition(const Integer & q,const Integer & r)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); EcRecommendedParametersEcRecommendedParameters96 TupleDescInitEntry(tupdesc, (AttrNumber) 1, "checkpoint_lsn", 97 LSNOID, -1, 0); EcRecommendedParametersEcRecommendedParameters98 TupleDescInitEntry(tupdesc, (AttrNumber) 2, "redo_lsn", 99 LSNOID, -1, 0); NewECEcRecommendedParameters100 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); EcRecommendedParametersEcRecommendedParameters122 TupleDescInitEntry(tupdesc, (AttrNumber) 14, "oldest_multi_xid", 123 XIDOID, -1, 0); NewECEcRecommendedParameters124 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 operator ()OIDLessThan140 /* 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); GetRecommendedParameters(const EcRecommendedParameters<EC2N> * & begin,const EcRecommendedParameters<EC2N> * & end)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); GetRecommendedParameters(const EcRecommendedParameters<ECP> * & begin,const EcRecommendedParameters<ECP> * & end)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 } 351