From 317df99449a9cabff2af53407abfe11be7895d82 Mon Sep 17 00:00:00 2001
From: Jehan-Guillaume de Rorthais <jgdr@dalibo.com>
Date: Thu, 25 Jul 2019 19:36:40 +0200
Subject: [PATCH] Add functions to get timeline

pg_current_wal_tl() returns the current timeline of a cluster in production.

pg_last_wal_received_tl() returns the timeline of the last xlog record
flushed to disk.
---
 doc/src/sgml/func.sgml                 | 22 ++++++++++++++++++++++
 src/backend/access/transam/xlogfuncs.c | 16 ++++++++++++++++
 src/backend/replication/walreceiver.c  | 16 ++++++++++++++++
 src/include/catalog/pg_proc.dat        | 12 ++++++++++++
 4 files changed, 66 insertions(+)

diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index c878a0ba4d..b0adc21883 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -19920,6 +19920,9 @@ SELECT set_config('log_statement_stats', 'off', false);
    <indexterm>
     <primary>pg_current_wal_lsn</primary>
    </indexterm>
+   <indexterm>
+    <primary>pg_current_wal_tl</primary>
+   </indexterm>
    <indexterm>
     <primary>pg_start_backup</primary>
    </indexterm>
@@ -19992,6 +19995,13 @@ SELECT set_config('log_statement_stats', 'off', false);
        <entry><type>pg_lsn</type></entry>
        <entry>Get current write-ahead log write location</entry>
       </row>
+      <row>
+       <entry>
+        <literal><function>pg_current_wal_tl()</function></literal>
+        </entry>
+       <entry><type>int</type></entry>
+       <entry>Get current write-ahead log timeline</entry>
+      </row>
       <row>
        <entry>
         <literal><function>pg_start_backup(<parameter>label</parameter> <type>text</type> <optional>, <parameter>fast</parameter> <type>boolean</type> <optional>, <parameter>exclusive</parameter> <type>boolean</type> </optional></optional>)</function></literal>
@@ -20196,6 +20206,9 @@ postgres=# SELECT * FROM pg_walfile_name_offset(pg_stop_backup());
    <indexterm>
     <primary>pg_last_wal_receive_lsn</primary>
    </indexterm>
+   <indexterm>
+    <primary>pg_last_wal_receive_tl</primary>
+   </indexterm>
    <indexterm>
     <primary>pg_last_wal_replay_lsn</primary>
    </indexterm>
@@ -20241,6 +20254,15 @@ postgres=# SELECT * FROM pg_walfile_name_offset(pg_stop_backup());
         started, the function returns NULL.
        </entry>
       </row>
+      <row>
+       <entry>
+        <literal><function>pg_last_wal_receive_tl()</function></literal>
+        </entry>
+       <entry><type>int</type></entry>
+       <entry>Get last write-ahead log timeline received and sync to disk by
+        streaming replication.
+       </entry>
+      </row>
       <row>
        <entry>
         <literal><function>pg_last_wal_replay_lsn()</function></literal>
diff --git a/src/backend/access/transam/xlogfuncs.c b/src/backend/access/transam/xlogfuncs.c
index 8a70503228..86adce2f20 100644
--- a/src/backend/access/transam/xlogfuncs.c
+++ b/src/backend/access/transam/xlogfuncs.c
@@ -785,3 +785,19 @@ pg_promote(PG_FUNCTION_ARGS)
 			(errmsg("server did not promote within %d seconds", wait_seconds)));
 	PG_RETURN_BOOL(false);
 }
+
+/*
+ * Returns the current timeline on a production cluster
+ */
+Datum
+pg_current_wal_tl(PG_FUNCTION_ARGS)
+{
+	if (RecoveryInProgress())
+		ereport(ERROR,
+				(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+				 errmsg("recovery is in progress"),
+				 errhint("%s cannot be executed during recovery.",
+						 "pg_current_wal_tl()")));
+
+	PG_RETURN_INT32(ThisTimeLineID);
+}
diff --git a/src/backend/replication/walreceiver.c b/src/backend/replication/walreceiver.c
index 6abc780778..3e8e64abba 100644
--- a/src/backend/replication/walreceiver.c
+++ b/src/backend/replication/walreceiver.c
@@ -1454,3 +1454,19 @@ pg_stat_get_wal_receiver(PG_FUNCTION_ARGS)
 	/* Returns the record as Datum */
 	PG_RETURN_DATUM(HeapTupleGetDatum(heap_form_tuple(tupdesc, values, nulls)));
 }
+
+/*
+ * Returns the timeline of the last xlog record flushed to WAL
+ */
+Datum
+pg_last_wal_receive_tl(PG_FUNCTION_ARGS)
+{
+	TimeLineID	lastReceivedTL;
+
+	GetWalRcvWriteRecPtr(NULL, &lastReceivedTL);
+
+	if (!lastReceivedTL)
+		PG_RETURN_NULL();
+
+	PG_RETURN_INT32(lastReceivedTL);
+}
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index cf1f409351..b0ad04bc08 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -6009,6 +6009,18 @@
 { oid => '2851', descr => 'wal filename, given a wal location',
   proname => 'pg_walfile_name', prorettype => 'text', proargtypes => 'pg_lsn',
   prosrc => 'pg_walfile_name' },
+{ oid => '3434',
+  descr => 'current timeline',
+  proname => 'pg_current_wal_tl', prorettype => 'int4',
+  proargtypes => '', proallargtypes => '{int4}',
+  proargmodes => '{o}', proargnames => '{timeline}',
+  prosrc => 'pg_current_wal_tl' },
+{ oid => '3435',
+  descr => 'current wal flush timeline',
+  proname => 'pg_last_wal_receive_tl', prorettype => 'int4',
+  proargtypes => '', proallargtypes => '{int4}',
+  proargmodes => '{o}', proargnames => '{timeline}',
+  prosrc => 'pg_last_wal_receive_tl' },
 
 { oid => '3165', descr => 'difference in bytes, given two wal locations',
   proname => 'pg_wal_lsn_diff', prorettype => 'numeric',
-- 
2.20.1

