Skip to content

Commit cca1863

Browse files
committed
Add pg_dissect_walfile_name()
This function takes in input a WAL segment name and returns a tuple made of the segment sequence number (dependent on the WAL segment size of the cluster) and its timeline, as of a thin SQL wrapper around the existing XLogFromFileName(). This function has multiple usages, like being able to compile a LSN from a file name and an offset, or finding the timeline of a segment without having to do to some maths based on the first eight characters of the segment. Bump catalog version. Author: Bharath Rupireddy Reviewed-by: Nathan Bossart, Kyotaro Horiguchi, Maxim Orlov, Michael Paquier Discussion: https://postgr.es/m/CALj2ACWV=FCddsxcGbVOA=cvPyMr75YCFbSQT6g4KDj=gcJK4g@mail.gmail.com
1 parent b3bb7d1 commit cca1863

File tree

6 files changed

+125
-1
lines changed

6 files changed

+125
-1
lines changed

doc/src/sgml/func.sgml

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26098,6 +26098,22 @@ LOG: Grand total: 1651920 bytes in 201 blocks; 622360 free (88 chunks); 1029560
2609826098
</para></entry>
2609926099
</row>
2610026100

26101+
<row>
26102+
<entry role="func_table_entry"><para role="func_signature">
26103+
<indexterm>
26104+
<primary>pg_dissect_walfile_name</primary>
26105+
</indexterm>
26106+
<function>pg_dissect_walfile_name</function> ( <parameter>file_name</parameter> <type>text</type> )
26107+
<returnvalue>record</returnvalue>
26108+
( <parameter>segno</parameter> <type>numeric</type>,
26109+
<parameter>timeline_id</parameter> <type>bigint</type> )
26110+
</para>
26111+
<para>
26112+
Extracts the file sequence number and timeline ID from a WAL file
26113+
name.
26114+
</para></entry>
26115+
</row>
26116+
2610126117
<row>
2610226118
<entry role="func_table_entry"><para role="func_signature">
2610326119
<indexterm>
@@ -26155,6 +26171,23 @@ postgres=# SELECT * FROM pg_walfile_name_offset((pg_backup_stop()).lsn);
2615526171
needs to be archived.
2615626172
</para>
2615726173

26174+
<para>
26175+
<function>pg_dissect_walfile_name</function> is useful to compute a
26176+
<acronym>LSN</acronym> from a file offset and WAL file name, for example:
26177+
<programlisting>
26178+
postgres=# \set file_name '000000010000000100C000AB'
26179+
postgres=# \set offset 256
26180+
postgres=# SELECT '0/0'::pg_lsn + pd.segno * ps.setting::int + :offset AS lsn
26181+
FROM pg_dissect_walfile_name(:'file_name') pd,
26182+
pg_show_all_settings() ps
26183+
WHERE ps.name = 'wal_segment_size';
26184+
lsn
26185+
---------------
26186+
C001/AB000100
26187+
(1 row)
26188+
</programlisting>
26189+
</para>
26190+
2615826191
</sect2>
2615926192

2616026193
<sect2 id="functions-recovery-control">

src/backend/access/transam/xlogfuncs.c

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,59 @@ pg_walfile_name(PG_FUNCTION_ARGS)
432432
PG_RETURN_TEXT_P(cstring_to_text(xlogfilename));
433433
}
434434

435+
/*
436+
* Extract the sequence number and the timeline ID from given a WAL file
437+
* name.
438+
*/
439+
Datum
440+
pg_dissect_walfile_name(PG_FUNCTION_ARGS)
441+
{
442+
#define PG_DISSECT_WALFILE_NAME_COLS 2
443+
char *fname = text_to_cstring(PG_GETARG_TEXT_PP(0));
444+
char *fname_upper;
445+
char *p;
446+
TimeLineID tli;
447+
XLogSegNo segno;
448+
Datum values[PG_DISSECT_WALFILE_NAME_COLS] = {0};
449+
bool isnull[PG_DISSECT_WALFILE_NAME_COLS] = {0};
450+
TupleDesc tupdesc;
451+
HeapTuple tuple;
452+
char buf[256];
453+
Datum result;
454+
455+
fname_upper = pstrdup(fname);
456+
457+
/* Capitalize WAL file name. */
458+
for (p = fname_upper; *p; p++)
459+
*p = pg_toupper((unsigned char) *p);
460+
461+
if (!IsXLogFileName(fname_upper))
462+
ereport(ERROR,
463+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
464+
errmsg("invalid WAL file name \"%s\"", fname)));
465+
466+
XLogFromFileName(fname_upper, &tli, &segno, wal_segment_size);
467+
468+
if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
469+
elog(ERROR, "return type must be a row type");
470+
471+
/* Convert to numeric. */
472+
snprintf(buf, sizeof buf, UINT64_FORMAT, segno);
473+
values[0] = DirectFunctionCall3(numeric_in,
474+
CStringGetDatum(buf),
475+
ObjectIdGetDatum(0),
476+
Int32GetDatum(-1));
477+
478+
values[1] = Int64GetDatum(tli);
479+
480+
tuple = heap_form_tuple(tupdesc, values, isnull);
481+
result = HeapTupleGetDatum(tuple);
482+
483+
PG_RETURN_DATUM(result);
484+
485+
#undef PG_DISSECT_WALFILE_NAME_COLS
486+
}
487+
435488
/*
436489
* pg_wal_replay_pause - Request to pause recovery
437490
*

src/include/catalog/catversion.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,6 @@
5757
*/
5858

5959
/* yyyymmddN */
60-
#define CATALOG_VERSION_NO 202212191
60+
#define CATALOG_VERSION_NO 202212201
6161

6262
#endif

src/include/catalog/pg_proc.dat

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6372,6 +6372,13 @@
63726372
{ oid => '2851', descr => 'wal filename, given a wal location',
63736373
proname => 'pg_walfile_name', prorettype => 'text', proargtypes => 'pg_lsn',
63746374
prosrc => 'pg_walfile_name' },
6375+
{ oid => '8205',
6376+
descr => 'sequence number and timeline ID given a wal filename',
6377+
proname => 'pg_dissect_walfile_name', provolatile => 's',
6378+
prorettype => 'record', proargtypes => 'text',
6379+
proallargtypes => '{text,numeric,int8}', proargmodes => '{i,o,o}',
6380+
proargnames => '{file_name,segno,timeline_id}',
6381+
prosrc => 'pg_dissect_walfile_name' },
63756382

63766383
{ oid => '3165', descr => 'difference in bytes, given two wal locations',
63776384
proname => 'pg_wal_lsn_diff', prorettype => 'numeric',

src/test/regress/expected/misc_functions.out

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -619,3 +619,26 @@ SELECT count(*) > 0 AS ok FROM pg_control_system();
619619
t
620620
(1 row)
621621

622+
-- pg_dissect_walfile_name
623+
SELECT * FROM pg_dissect_walfile_name(NULL);
624+
segno | timeline_id
625+
-------+-------------
626+
|
627+
(1 row)
628+
629+
SELECT * FROM pg_dissect_walfile_name('invalid');
630+
ERROR: invalid WAL file name "invalid"
631+
SELECT segno > 0 AS ok_segno, timeline_id
632+
FROM pg_dissect_walfile_name('000000010000000100000000');
633+
ok_segno | timeline_id
634+
----------+-------------
635+
t | 1
636+
(1 row)
637+
638+
SELECT segno > 0 AS ok_segno, timeline_id
639+
FROM pg_dissect_walfile_name('ffffffFF00000001000000af');
640+
ok_segno | timeline_id
641+
----------+-------------
642+
t | 4294967295
643+
(1 row)
644+

src/test/regress/sql/misc_functions.sql

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,3 +229,11 @@ SELECT count(*) > 0 AS ok FROM pg_control_checkpoint();
229229
SELECT count(*) > 0 AS ok FROM pg_control_init();
230230
SELECT count(*) > 0 AS ok FROM pg_control_recovery();
231231
SELECT count(*) > 0 AS ok FROM pg_control_system();
232+
233+
-- pg_dissect_walfile_name
234+
SELECT * FROM pg_dissect_walfile_name(NULL);
235+
SELECT * FROM pg_dissect_walfile_name('invalid');
236+
SELECT segno > 0 AS ok_segno, timeline_id
237+
FROM pg_dissect_walfile_name('000000010000000100000000');
238+
SELECT segno > 0 AS ok_segno, timeline_id
239+
FROM pg_dissect_walfile_name('ffffffFF00000001000000af');

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy