On Tue, Dec 13, 2022 at 09:32:19PM +0530, Bharath Rupireddy wrote: > Okay, here's the v5 patch that I could come up with. It basically adds > functions for dissecting WAL file names and computing offset from lsn. > Thoughts?
I had a second look at that, and I still have mixed feelings about the addition of the SQL function, no real objection about pg_dissect_walfile_name(). I don't really think that we need a specific handling with a new macro from xlog_internal.h that does its own parsing of the segment number while XLogFromFileName() can do that based on the user input, so I have simplified that. A second thing is the TLI that had better be returned as int8 and not int4 so as we don't have a negative number for a TLI higher than 2B in a WAL segment name. -- Michael
From 25fb0848cf3220a5fc9638c2cfd116e5390be887 Mon Sep 17 00:00:00 2001 From: Michael Paquier <mich...@paquier.xyz> Date: Mon, 19 Dec 2022 17:02:16 +0900 Subject: [PATCH v6] Add utility functions to disset WAL file name and compute offset --- src/include/catalog/pg_proc.dat | 7 +++ src/backend/access/transam/xlogfuncs.c | 53 ++++++++++++++++++++ src/test/regress/expected/misc_functions.out | 18 +++++++ src/test/regress/sql/misc_functions.sql | 8 +++ doc/src/sgml/func.sgml | 16 ++++++ 5 files changed, 102 insertions(+) diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat index 719599649a..79cfd1378d 100644 --- a/src/include/catalog/pg_proc.dat +++ b/src/include/catalog/pg_proc.dat @@ -6365,6 +6365,13 @@ { oid => '2851', descr => 'wal filename, given a wal location', proname => 'pg_walfile_name', prorettype => 'text', proargtypes => 'pg_lsn', prosrc => 'pg_walfile_name' }, +{ oid => '8205', + descr => 'sequence number and timeline ID given a wal filename', + proname => 'pg_dissect_walfile_name', prorettype => 'record', + proargtypes => 'text', proallargtypes => '{text,numeric,int8}', + provolatile => 's', proargmodes => '{i,o,o}', + proargnames => '{file_name,segno,timeline_id}', + prosrc => 'pg_dissect_walfile_name' }, { oid => '3165', descr => 'difference in bytes, given two wal locations', proname => 'pg_wal_lsn_diff', prorettype => 'numeric', diff --git a/src/backend/access/transam/xlogfuncs.c b/src/backend/access/transam/xlogfuncs.c index 487d5d9cac..0a31837ef1 100644 --- a/src/backend/access/transam/xlogfuncs.c +++ b/src/backend/access/transam/xlogfuncs.c @@ -432,6 +432,59 @@ pg_walfile_name(PG_FUNCTION_ARGS) PG_RETURN_TEXT_P(cstring_to_text(xlogfilename)); } +/* + * Extract the sequence number and the timeline ID from given a WAL file + * name. + */ +Datum +pg_dissect_walfile_name(PG_FUNCTION_ARGS) +{ +#define PG_DISSECT_WALFILE_NAME_COLS 2 + char *fname = text_to_cstring(PG_GETARG_TEXT_PP(0)); + char *fname_upper; + char *p; + TimeLineID tli; + XLogSegNo segno; + Datum values[PG_DISSECT_WALFILE_NAME_COLS] = {0}; + bool isnull[PG_DISSECT_WALFILE_NAME_COLS] = {0}; + TupleDesc tupdesc; + HeapTuple tuple; + char buf[256]; + Datum result; + + fname_upper = pstrdup(fname); + + /* Capitalize WAL file name. */ + for (p = fname_upper; *p; p++) + *p = pg_toupper((unsigned char) *p); + + if (!IsXLogFileName(fname_upper)) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("invalid WAL file name \"%s\"", fname))); + + XLogFromFileName(fname_upper, &tli, &segno, wal_segment_size); + + if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) + elog(ERROR, "return type must be a row type"); + + /* Convert to numeric. */ + snprintf(buf, sizeof buf, UINT64_FORMAT, segno); + values[0] = DirectFunctionCall3(numeric_in, + CStringGetDatum(buf), + ObjectIdGetDatum(0), + Int32GetDatum(-1)); + + values[1] = Int64GetDatum(tli); + + tuple = heap_form_tuple(tupdesc, values, isnull); + result = HeapTupleGetDatum(tuple); + + PG_RETURN_DATUM(result); + +#undef PG_DISSECT_WALFILE_NAME_COLS +} + /* * pg_wal_replay_pause - Request to pause recovery * diff --git a/src/test/regress/expected/misc_functions.out b/src/test/regress/expected/misc_functions.out index 88bb696ded..fb676e9971 100644 --- a/src/test/regress/expected/misc_functions.out +++ b/src/test/regress/expected/misc_functions.out @@ -619,3 +619,21 @@ SELECT count(*) > 0 AS ok FROM pg_control_system(); t (1 row) +-- pg_dissect_walfile_name +SELECT segno > 0 AS ok_segno, timeline_id + FROM pg_dissect_walfile_name('invalid'); +ERROR: invalid WAL file name "invalid" +SELECT segno > 0 AS ok_segno, timeline_id + FROM pg_dissect_walfile_name('000000010000000100000000'); + ok_segno | timeline_id +----------+------------- + t | 1 +(1 row) + +SELECT segno > 0 AS ok_segno, timeline_id + FROM pg_dissect_walfile_name('FFFFFFFF00000001000000af'); + ok_segno | timeline_id +----------+------------- + t | 4294967295 +(1 row) + diff --git a/src/test/regress/sql/misc_functions.sql b/src/test/regress/sql/misc_functions.sql index b07e9e8dbb..74cfc31913 100644 --- a/src/test/regress/sql/misc_functions.sql +++ b/src/test/regress/sql/misc_functions.sql @@ -229,3 +229,11 @@ SELECT count(*) > 0 AS ok FROM pg_control_checkpoint(); SELECT count(*) > 0 AS ok FROM pg_control_init(); SELECT count(*) > 0 AS ok FROM pg_control_recovery(); SELECT count(*) > 0 AS ok FROM pg_control_system(); + +-- pg_dissect_walfile_name +SELECT segno > 0 AS ok_segno, timeline_id + FROM pg_dissect_walfile_name('invalid'); +SELECT segno > 0 AS ok_segno, timeline_id + FROM pg_dissect_walfile_name('000000010000000100000000'); +SELECT segno > 0 AS ok_segno, timeline_id + FROM pg_dissect_walfile_name('FFFFFFFF00000001000000af'); diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index 1cd8b11334..2f05b06f14 100644 --- a/doc/src/sgml/func.sgml +++ b/doc/src/sgml/func.sgml @@ -26098,6 +26098,22 @@ LOG: Grand total: 1651920 bytes in 201 blocks; 622360 free (88 chunks); 1029560 </para></entry> </row> + <row> + <entry role="func_table_entry"><para role="func_signature"> + <indexterm> + <primary>pg_dissect_walfile_name</primary> + </indexterm> + <function>pg_dissect_walfile_name</function> ( <parameter>file_name</parameter> <type>text</type> ) + <returnvalue>record</returnvalue> + ( <parameter>segno</parameter> <type>numeric</type>, + <parameter>timeline_id</parameter> <type>bigint</type> ) + </para> + <para> + Extract the file sequence number and timeline ID from a WAL file + name. + </para></entry> + </row> + <row> <entry role="func_table_entry"><para role="func_signature"> <indexterm> -- 2.39.0
signature.asc
Description: PGP signature