aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMichael Paquier <michael@paquier.xyz>2022-12-20 13:36:27 +0900
committerMichael Paquier <michael@paquier.xyz>2022-12-20 13:36:27 +0900
commitcca186348929cd75f23ef1b25922386bf38cf99c (patch)
treef4b4a6ae944991ef0275fed8eebcd867e40cc0e6 /src
parentb3bb7d12af97f035c3aa3ad8dd41b44d01e2defa (diff)
downloadpostgresql-cca186348929cd75f23ef1b25922386bf38cf99c.tar.gz
postgresql-cca186348929cd75f23ef1b25922386bf38cf99c.zip
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
Diffstat (limited to 'src')
-rw-r--r--src/backend/access/transam/xlogfuncs.c53
-rw-r--r--src/include/catalog/catversion.h2
-rw-r--r--src/include/catalog/pg_proc.dat7
-rw-r--r--src/test/regress/expected/misc_functions.out23
-rw-r--r--src/test/regress/sql/misc_functions.sql8
5 files changed, 92 insertions, 1 deletions
diff --git a/src/backend/access/transam/xlogfuncs.c b/src/backend/access/transam/xlogfuncs.c
index 487d5d9cac7..0a31837ef18 100644
--- a/src/backend/access/transam/xlogfuncs.c
+++ b/src/backend/access/transam/xlogfuncs.c
@@ -433,6 +433,59 @@ pg_walfile_name(PG_FUNCTION_ARGS)
}
/*
+ * 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
*
* Permission checking for this function is managed through the normal
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index 094f59f82db..091ad94c5eb 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -57,6 +57,6 @@
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 202212191
+#define CATALOG_VERSION_NO 202212201
#endif
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index d763419c0de..98d90d93389 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -6372,6 +6372,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', provolatile => 's',
+ prorettype => 'record', proargtypes => 'text',
+ proallargtypes => '{text,numeric,int8}', 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/test/regress/expected/misc_functions.out b/src/test/regress/expected/misc_functions.out
index 88bb696ded8..2907f779a75 100644
--- a/src/test/regress/expected/misc_functions.out
+++ b/src/test/regress/expected/misc_functions.out
@@ -619,3 +619,26 @@ SELECT count(*) > 0 AS ok FROM pg_control_system();
t
(1 row)
+-- pg_dissect_walfile_name
+SELECT * FROM pg_dissect_walfile_name(NULL);
+ segno | timeline_id
+-------+-------------
+ |
+(1 row)
+
+SELECT * 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 b07e9e8dbb3..0c3d75fd1ac 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 * FROM pg_dissect_walfile_name(NULL);
+SELECT * 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');