PostgreSQL Source Code git master
Loading...
Searching...
No Matches
rawpage.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * rawpage.c
4 * Functions to extract a raw page as bytea and inspect it
5 *
6 * Access-method specific inspection functions are in separate files.
7 *
8 * Copyright (c) 2007-2026, PostgreSQL Global Development Group
9 *
10 * IDENTIFICATION
11 * contrib/pageinspect/rawpage.c
12 *
13 *-------------------------------------------------------------------------
14 */
15
16#include "postgres.h"
17
18#include "access/htup_details.h"
19#include "access/relation.h"
20#include "catalog/namespace.h"
21#include "catalog/pg_type.h"
22#include "funcapi.h"
23#include "miscadmin.h"
24#include "pageinspect.h"
25#include "storage/bufmgr.h"
26#include "storage/checksum.h"
27#include "utils/builtins.h"
28#include "utils/pg_lsn.h"
29#include "utils/rel.h"
30#include "utils/varlena.h"
31
33 .name = "pageinspect",
34 .version = PG_VERSION
35);
36
38 BlockNumber blkno);
39
40
41/*
42 * get_raw_page
43 *
44 * Returns a copy of a page from shared buffers as a bytea
45 */
47
64
65/*
66 * entry point for old extension version
67 */
69
72{
74 uint32 blkno = PG_GETARG_UINT32(1);
76
77 /*
78 * We don't normally bother to check the number of arguments to a C
79 * function, but here it's needed for safety because early 8.4 beta
80 * releases mistakenly redefined get_raw_page() as taking three arguments.
81 */
82 if (PG_NARGS() != 2)
84 (errmsg("wrong number of arguments to get_raw_page()"),
85 errhint("Run the updated pageinspect.sql script.")));
86
88
90}
91
92/*
93 * get_raw_page_fork
94 *
95 * Same, for any fork
96 */
98
119
120/*
121 * Entry point for old extension version
122 */
124
125Datum
140
141/*
142 * workhorse
143 */
144static bytea *
146{
149 Relation rel;
150 char *raw_page_data;
151 Buffer buf;
152
153 if (!superuser())
156 errmsg("must be superuser to use raw page functions")));
157
160
161 if (!RELKIND_HAS_STORAGE(rel->rd_rel->relkind))
164 errmsg("cannot get raw page from relation \"%s\"",
167
168 /*
169 * Reject attempts to read non-local temporary relations; we would be
170 * likely to get wrong data since we have no visibility into the owning
171 * session's local buffers.
172 */
173 if (RELATION_IS_OTHER_TEMP(rel))
176 errmsg("cannot access temporary tables of other sessions")));
177
178 if (blkno >= RelationGetNumberOfBlocksInFork(rel, forknum))
181 errmsg("block number %u is out of range for relation \"%s\"",
182 blkno, RelationGetRelationName(rel))));
183
184 /* Initialize buffer to copy to */
188
189 /* Take a verbatim copy of the page */
190
191 buf = ReadBufferExtended(rel, forknum, blkno, RBM_NORMAL, NULL);
193
195
198
200
201 return raw_page;
202}
203
204
205/*
206 * get_page_from_raw
207 *
208 * Get a palloc'd, maxalign'ed page image from the result of get_raw_page()
209 *
210 * On machines with MAXALIGN = 8, the payload of a bytea is not maxaligned,
211 * since it will start 4 bytes into a palloc'd value. On alignment-picky
212 * machines, this will cause failures in accesses to 8-byte-wide values
213 * within the page. We don't need to worry if accessing only 4-byte or
214 * smaller fields, but when examining a struct that contains 8-byte fields,
215 * use this function for safety.
216 */
217Page
219{
220 Page page;
221 int raw_page_size;
222
224
225 if (raw_page_size != BLCKSZ)
228 errmsg("invalid page size"),
229 errdetail("Expected %d bytes, got %d.",
231
232 page = palloc(raw_page_size);
233
235
236 return page;
237}
238
239
240/*
241 * page_header
242 *
243 * Allows inspection of page header fields of a raw page
244 */
245
247
248Datum
250{
252
253 TupleDesc tupdesc;
254
255 Datum result;
256 HeapTuple tuple;
257 Datum values[9];
258 bool nulls[9];
259
260 Page page;
262 XLogRecPtr lsn;
263
264 if (!superuser())
267 errmsg("must be superuser to use raw page functions")));
268
270 pageheader = (PageHeader) page;
271
272 /* Build a tuple descriptor for our result type */
273 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
274 elog(ERROR, "return type must be a row type");
275
276 /* Extract information from the page header */
277
278 lsn = PageGetLSN(page);
279
280 /* pageinspect >= 1.2 uses pg_lsn instead of text for the LSN field. */
281 if (TupleDescAttr(tupdesc, 0)->atttypid == TEXTOID)
282 {
283 char lsnchar[64];
284
285 snprintf(lsnchar, sizeof(lsnchar), "%X/%08X", LSN_FORMAT_ARGS(lsn));
287 }
288 else
289 values[0] = LSNGetDatum(lsn);
290 values[1] = UInt16GetDatum(pageheader->pd_checksum);
291 values[2] = UInt16GetDatum(pageheader->pd_flags);
292
293 /* pageinspect >= 1.10 uses int4 instead of int2 for those fields */
294 switch (TupleDescAttr(tupdesc, 3)->atttypid)
295 {
296 case INT2OID:
297 Assert(TupleDescAttr(tupdesc, 4)->atttypid == INT2OID &&
298 TupleDescAttr(tupdesc, 5)->atttypid == INT2OID &&
299 TupleDescAttr(tupdesc, 6)->atttypid == INT2OID);
300 values[3] = UInt16GetDatum(pageheader->pd_lower);
301 values[4] = UInt16GetDatum(pageheader->pd_upper);
302 values[5] = UInt16GetDatum(pageheader->pd_special);
304 break;
305 case INT4OID:
306 Assert(TupleDescAttr(tupdesc, 4)->atttypid == INT4OID &&
307 TupleDescAttr(tupdesc, 5)->atttypid == INT4OID &&
308 TupleDescAttr(tupdesc, 6)->atttypid == INT4OID);
309 values[3] = Int32GetDatum(pageheader->pd_lower);
310 values[4] = Int32GetDatum(pageheader->pd_upper);
311 values[5] = Int32GetDatum(pageheader->pd_special);
313 break;
314 default:
315 elog(ERROR, "incorrect output types");
316 break;
317 }
318
320 values[8] = TransactionIdGetDatum(pageheader->pd_prune_xid);
321
322 /* Build and return the tuple. */
323
324 memset(nulls, 0, sizeof(nulls));
325
326 tuple = heap_form_tuple(tupdesc, values, nulls);
327 result = HeapTupleGetDatum(tuple);
328
329 PG_RETURN_DATUM(result);
330}
331
332/*
333 * page_checksum
334 *
335 * Compute checksum of a raw page
336 */
337
340
341static Datum
343{
346 Page page;
347
348 if (!superuser())
351 errmsg("must be superuser to use raw page functions")));
352
356 errmsg("invalid block number")));
357
359
360 if (PageIsNew(page))
362
363 PG_RETURN_INT16(pg_checksum_page(page, blkno));
364}
365
366Datum
371
372/*
373 * Entry point for old extension version
374 */
375Datum
uint32 BlockNumber
Definition block.h:31
#define MaxBlockNumber
Definition block.h:35
static Datum values[MAXATTR]
Definition bootstrap.c:155
int Buffer
Definition buf.h:23
BlockNumber RelationGetNumberOfBlocksInFork(Relation relation, ForkNumber forkNum)
Definition bufmgr.c:4572
void ReleaseBuffer(Buffer buffer)
Definition bufmgr.c:5501
Buffer ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode, BufferAccessStrategy strategy)
Definition bufmgr.c:911
static Page BufferGetPage(Buffer buffer)
Definition bufmgr.h:466
@ BUFFER_LOCK_SHARE
Definition bufmgr.h:210
@ BUFFER_LOCK_UNLOCK
Definition bufmgr.h:205
static void LockBuffer(Buffer buffer, BufferLockMode mode)
Definition bufmgr.h:328
@ RBM_NORMAL
Definition bufmgr.h:46
PageHeaderData * PageHeader
Definition bufpage.h:173
static Size PageGetPageSize(const PageData *page)
Definition bufpage.h:276
static bool PageIsNew(const PageData *page)
Definition bufpage.h:233
static uint8 PageGetPageLayoutVersion(const PageData *page)
Definition bufpage.h:286
PageData * Page
Definition bufpage.h:81
static XLogRecPtr PageGetLSN(const PageData *page)
Definition bufpage.h:385
#define CStringGetTextDatum(s)
Definition builtins.h:97
#define VARHDRSZ
Definition c.h:711
#define Assert(condition)
Definition c.h:873
int64_t int64
Definition c.h:543
uint32_t uint32
Definition c.h:546
uint16 pg_checksum_page(char *page, BlockNumber blkno)
int errdetail(const char *fmt,...)
Definition elog.c:1216
int errhint(const char *fmt,...)
Definition elog.c:1330
int errcode(int sqlerrcode)
Definition elog.c:863
int errmsg(const char *fmt,...)
Definition elog.c:1080
#define ERROR
Definition elog.h:39
#define elog(elevel,...)
Definition elog.h:226
#define ereport(elevel,...)
Definition elog.h:150
#define PG_GETARG_TEXT_PP(n)
Definition fmgr.h:310
#define PG_RETURN_BYTEA_P(x)
Definition fmgr.h:373
#define PG_GETARG_UINT32(n)
Definition fmgr.h:270
#define PG_MODULE_MAGIC_EXT(...)
Definition fmgr.h:540
#define PG_NARGS()
Definition fmgr.h:203
#define PG_RETURN_NULL()
Definition fmgr.h:346
#define PG_GETARG_INT64(n)
Definition fmgr.h:284
#define PG_FUNCTION_INFO_V1(funcname)
Definition fmgr.h:417
#define PG_RETURN_INT16(x)
Definition fmgr.h:357
#define PG_RETURN_DATUM(x)
Definition fmgr.h:354
#define PG_GETARG_BYTEA_P(n)
Definition fmgr.h:336
#define PG_FUNCTION_ARGS
Definition fmgr.h:193
TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo, Oid *resultTypeId, TupleDesc *resultTupleDesc)
Definition funcapi.c:276
@ TYPEFUNC_COMPOSITE
Definition funcapi.h:149
static Datum HeapTupleGetDatum(const HeapTupleData *tuple)
Definition funcapi.h:230
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
Definition heaptuple.c:1117
#define AccessShareLock
Definition lockdefs.h:36
void * palloc(Size size)
Definition mcxt.c:1387
RangeVar * makeRangeVarFromNameList(const List *names)
Definition namespace.c:3624
pageinspect_version
Definition pageinspect.h:22
@ PAGEINSPECT_V1_9
Definition pageinspect.h:24
@ PAGEINSPECT_V1_8
Definition pageinspect.h:23
int errdetail_relkind_not_supported(char relkind)
Definition pg_class.c:24
NameData relname
Definition pg_class.h:38
static Datum LSNGetDatum(XLogRecPtr X)
Definition pg_lsn.h:31
static char buf[DEFAULT_XLOG_SEG_SIZE]
#define snprintf
Definition port.h:260
static Datum TransactionIdGetDatum(TransactionId X)
Definition postgres.h:302
static Datum UInt16GetDatum(uint16 X)
Definition postgres.h:202
uint64_t Datum
Definition postgres.h:70
static Datum Int32GetDatum(int32 X)
Definition postgres.h:222
static int fb(int x)
Datum get_raw_page(PG_FUNCTION_ARGS)
Definition rawpage.c:71
Datum page_checksum(PG_FUNCTION_ARGS)
Definition rawpage.c:376
Datum page_checksum_1_9(PG_FUNCTION_ARGS)
Definition rawpage.c:367
Datum get_raw_page_fork_1_9(PG_FUNCTION_ARGS)
Definition rawpage.c:100
static Datum page_checksum_internal(PG_FUNCTION_ARGS, enum pageinspect_version ext_version)
Definition rawpage.c:342
static bytea * get_raw_page_internal(text *relname, ForkNumber forknum, BlockNumber blkno)
Definition rawpage.c:145
Datum page_header(PG_FUNCTION_ARGS)
Definition rawpage.c:249
Datum get_raw_page_1_9(PG_FUNCTION_ARGS)
Definition rawpage.c:49
Page get_page_from_raw(bytea *raw_page)
Definition rawpage.c:218
Datum get_raw_page_fork(PG_FUNCTION_ARGS)
Definition rawpage.c:126
#define RelationGetRelationName(relation)
Definition rel.h:548
#define RELATION_IS_OTHER_TEMP(relation)
Definition rel.h:667
ForkNumber forkname_to_number(const char *forkName)
Definition relpath.c:50
ForkNumber
Definition relpath.h:56
@ MAIN_FORKNUM
Definition relpath.h:58
void relation_close(Relation relation, LOCKMODE lockmode)
Definition relation.c:205
Relation relation_openrv(const RangeVar *relation, LOCKMODE lockmode)
Definition relation.c:137
Form_pg_class rd_rel
Definition rel.h:111
Definition c.h:706
bool superuser(void)
Definition superuser.c:46
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)
Definition tupdesc.h:160
static Size VARSIZE_ANY_EXHDR(const void *PTR)
Definition varatt.h:472
static char * VARDATA(const void *PTR)
Definition varatt.h:305
static char * VARDATA_ANY(const void *PTR)
Definition varatt.h:486
static void SET_VARSIZE(void *PTR, Size len)
Definition varatt.h:432
char * text_to_cstring(const text *t)
Definition varlena.c:214
List * textToQualifiedNameList(text *textval)
Definition varlena.c:2672
const char * name
#define LSN_FORMAT_ARGS(lsn)
Definition xlogdefs.h:47
uint64 XLogRecPtr
Definition xlogdefs.h:21