v3-0002-Emit-WAL-record-info-via-pg_get_wal_block_info.patch
application/x-patch
Filename: v3-0002-Emit-WAL-record-info-via-pg_get_wal_block_info.patch
Type: application/x-patch
Part: 1
Patch
Format: format-patch
Series: patch v3-0002
Subject: Emit WAL record info via pg_get_wal_block_info()
| File | + | − |
|---|---|---|
| contrib/pg_walinspect/pg_walinspect--1.0--1.1.sql | 9 | 1 |
| contrib/pg_walinspect/pg_walinspect.c | 32 | 15 |
| doc/src/sgml/pgwalinspect.sgml | 24 | 14 |
From dabc3c0a5625a45e0c179f1a0b1ede5187702198 Mon Sep 17 00:00:00 2001
From: Bharath Rupireddy <bharath.rupireddyforpostgres@gmail.com>
Date: Sat, 18 Mar 2023 04:06:27 +0000
Subject: [PATCH v3] Emit WAL record info via pg_get_wal_block_info()
---
.../pg_walinspect/pg_walinspect--1.0--1.1.sql | 10 +++-
contrib/pg_walinspect/pg_walinspect.c | 47 +++++++++++++------
doc/src/sgml/pgwalinspect.sgml | 38 +++++++++------
3 files changed, 65 insertions(+), 30 deletions(-)
diff --git a/contrib/pg_walinspect/pg_walinspect--1.0--1.1.sql b/contrib/pg_walinspect/pg_walinspect--1.0--1.1.sql
index 586c3b4467..46fcaff3a1 100644
--- a/contrib/pg_walinspect/pg_walinspect--1.0--1.1.sql
+++ b/contrib/pg_walinspect/pg_walinspect--1.0--1.1.sql
@@ -12,7 +12,15 @@ DROP FUNCTION pg_get_wal_stats_till_end_of_wal(pg_lsn, boolean);
--
CREATE FUNCTION pg_get_wal_block_info(IN start_lsn pg_lsn,
IN end_lsn pg_lsn,
- OUT lsn pg_lsn,
+ OUT start_lsn pg_lsn,
+ OUT end_lsn pg_lsn,
+ OUT prev_lsn pg_lsn,
+ OUT xid xid,
+ OUT resource_manager text,
+ OUT record_type text,
+ OUT record_length int4,
+ OUT main_data_length int4,
+ OUT description text,
OUT blockid int2,
OUT reltablespace oid,
OUT reldatabase oid,
diff --git a/contrib/pg_walinspect/pg_walinspect.c b/contrib/pg_walinspect/pg_walinspect.c
index c3ed31db8f..520d39a27f 100644
--- a/contrib/pg_walinspect/pg_walinspect.c
+++ b/contrib/pg_walinspect/pg_walinspect.c
@@ -43,7 +43,8 @@ static XLogRecPtr GetCurrentLSN(void);
static XLogReaderState *InitXLogReaderState(XLogRecPtr lsn);
static XLogRecord *ReadNextXLogRecord(XLogReaderState *xlogreader);
static void GetWALRecordInfo(XLogReaderState *record, Datum *values,
- bool *nulls, uint32 ncols);
+ bool *nulls, uint32 ncols,
+ bool fetch_blk_ref);
static void GetWALRecordsInfo(FunctionCallInfo fcinfo,
XLogRecPtr start_lsn,
XLogRecPtr end_lsn);
@@ -180,7 +181,8 @@ ReadNextXLogRecord(XLogReaderState *xlogreader)
*/
static void
GetWALRecordInfo(XLogReaderState *record, Datum *values,
- bool *nulls, uint32 ncols)
+ bool *nulls, uint32 ncols,
+ bool fetch_blk_ref)
{
const char *id;
RmgrData desc;
@@ -199,8 +201,8 @@ GetWALRecordInfo(XLogReaderState *record, Datum *values,
initStringInfo(&rec_desc);
desc.rm_desc(&rec_desc, record);
- /* Get block references, if any. */
- if (XLogRecHasAnyBlockRefs(record))
+ /* Get block references, if any and if asked. */
+ if (XLogRecHasAnyBlockRefs(record) && fetch_blk_ref)
{
initStringInfo(&rec_blk_ref);
XLogRecGetBlockRefInfo(record, false, true, &rec_blk_ref, &fpi_len);
@@ -216,13 +218,16 @@ GetWALRecordInfo(XLogReaderState *record, Datum *values,
values[i++] = CStringGetTextDatum(id);
values[i++] = UInt32GetDatum(XLogRecGetTotalLen(record));
values[i++] = UInt32GetDatum(main_data_len);
- values[i++] = UInt32GetDatum(fpi_len);
+
+ if (fetch_blk_ref)
+ values[i++] = UInt32GetDatum(fpi_len);
+
values[i++] = CStringGetTextDatum(rec_desc.data);
- /* Output block references, if any. */
- if (XLogRecHasAnyBlockRefs(record))
+ /* Output block references, if any and if asked. */
+ if (XLogRecHasAnyBlockRefs(record) && fetch_blk_ref)
values[i++] = CStringGetTextDatum(rec_blk_ref.data);
- else
+ else if (fetch_blk_ref)
nulls[i++] = true;
Assert(i == ncols);
@@ -236,19 +241,30 @@ GetWALRecordInfo(XLogReaderState *record, Datum *values,
static void
GetWALBlockInfo(FunctionCallInfo fcinfo, XLogReaderState *record)
{
-#define PG_GET_WAL_BLOCK_INFO_COLS 11
+#define PG_GET_WAL_BLOCK_INFO_COLS 19
+#define PG_GET_WAL_BLOCK_INFO_PER_RECORD_COLS 9
+ Datum values[PG_GET_WAL_BLOCK_INFO_COLS] = {0};
+ bool nulls[PG_GET_WAL_BLOCK_INFO_COLS] = {0};
int block_id;
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
+ /* Get per-record info. */
+ GetWALRecordInfo(record, values, nulls,
+ PG_GET_WAL_BLOCK_INFO_PER_RECORD_COLS, false);
+
for (block_id = 0; block_id <= XLogRecMaxBlockId(record); block_id++)
{
DecodedBkpBlock *blk;
BlockNumber blkno;
RelFileLocator rnode;
ForkNumber fork;
- Datum values[PG_GET_WAL_BLOCK_INFO_COLS] = {0};
- bool nulls[PG_GET_WAL_BLOCK_INFO_COLS] = {0};
- int i = 0;
+ int i = PG_GET_WAL_BLOCK_INFO_PER_RECORD_COLS;
+
+ /* Reset only per-block output columns, keep per-record info as-is. */
+ memset(&nulls[PG_GET_WAL_BLOCK_INFO_PER_RECORD_COLS], 0,
+ PG_GET_WAL_BLOCK_INFO_PER_RECORD_COLS * sizeof(bool));
+ memset(&values[PG_GET_WAL_BLOCK_INFO_PER_RECORD_COLS], 0,
+ PG_GET_WAL_BLOCK_INFO_PER_RECORD_COLS * sizeof(bool));
if (!XLogRecHasBlockRef(record, block_id))
continue;
@@ -258,7 +274,6 @@ GetWALBlockInfo(FunctionCallInfo fcinfo, XLogReaderState *record)
(void) XLogRecGetBlockTagExtended(record, block_id,
&rnode, &fork, &blkno, NULL);
- values[i++] = LSNGetDatum(record->ReadRecPtr);
values[i++] = Int16GetDatum(block_id);
values[i++] = ObjectIdGetDatum(blk->rlocator.spcOid);
values[i++] = ObjectIdGetDatum(blk->rlocator.dbOid);
@@ -353,6 +368,7 @@ GetWALBlockInfo(FunctionCallInfo fcinfo, XLogReaderState *record)
values, nulls);
}
+#undef PG_GET_WAL_BLOCK_INFO_PER_RECORD_COLS
#undef PG_GET_WAL_FPI_BLOCK_COLS
}
@@ -446,7 +462,8 @@ pg_get_wal_record_info(PG_FUNCTION_ARGS)
errmsg("could not read WAL at %X/%X",
LSN_FORMAT_ARGS(xlogreader->EndRecPtr))));
- GetWALRecordInfo(xlogreader, values, nulls, PG_GET_WAL_RECORD_INFO_COLS);
+ GetWALRecordInfo(xlogreader, values, nulls, PG_GET_WAL_RECORD_INFO_COLS,
+ true);
pfree(xlogreader->private_data);
XLogReaderFree(xlogreader);
@@ -518,7 +535,7 @@ GetWALRecordsInfo(FunctionCallInfo fcinfo, XLogRecPtr start_lsn,
old_cxt = MemoryContextSwitchTo(tmp_cxt);
GetWALRecordInfo(xlogreader, values, nulls,
- PG_GET_WAL_RECORDS_INFO_COLS);
+ PG_GET_WAL_RECORDS_INFO_COLS, true);
tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
values, nulls);
diff --git a/doc/src/sgml/pgwalinspect.sgml b/doc/src/sgml/pgwalinspect.sgml
index 9a0241a8d6..864ea298f3 100644
--- a/doc/src/sgml/pgwalinspect.sgml
+++ b/doc/src/sgml/pgwalinspect.sgml
@@ -177,23 +177,33 @@ combined_size_percentage | 2.8634072910530795
<replaceable>start_lsn</replaceable> is not available. For example,
usage of the function is as follows:
<screen>
-postgres=# SELECT lsn, blockid, reltablespace, reldatabase, relfilenode,
+postgres=# SELECT start_lsn, end_lsn, prev_lsn, xid, resource_manager,
+ record_type, record_length, main_data_length, description,
+ blockid, reltablespace, reldatabase, relfilenode,
relblocknumber, forkname,
substring(blockdata for 24) as block_trimmed,
substring(fpi for 24) as fpi_trimmed, fpilen, fpiinfo
- FROM pg_get_wal_block_info('0/1871080', '0/1871440');
--[ RECORD 1 ]--+---------------------------------------------------
-lsn | 0/18712F8
-blockid | 0
-reltablespace | 1663
-reldatabase | 16384
-relfilenode | 16392
-relblocknumber | 0
-forkname | main
-block_trimmed | \x02800128180164000000
-fpi_trimmed | \x0000000050108701000000002c00601f00200420e0020000
-fpilen | 204
-fpiinfo | {HAS_HOLE,APPLY}
+ FROM pg_get_wal_block_info('0/15457B0', '0/1545A40');
+-[ RECORD 1 ]----+---------------------------------------------------
+start_lsn | 0/1545860
+end_lsn | 0/1545998
+prev_lsn | 0/15457E8
+xid | 750
+resource_manager | Heap
+record_type | HOT_UPDATE
+record_length | 305
+main_data_length | 14
+description | off 2 xmax 750 flags 0x00 ; new off 6 xmax 0
+blockid | 0
+reltablespace | 1663
+reldatabase | 5
+relfilenode | 24594
+relblocknumber | 0
+forkname | main
+block_trimmed | \x02800128180164000000
+fpi_trimmed | \x00000000203a5401000000003000401f00200420ed020000
+fpilen | 240
+fpiinfo | {HAS_HOLE,APPLY}
</screen>
</para>
</listitem>
--
2.34.1