From ac304f75d5f6f9bb9712ef4113da035ad74b7344 Mon Sep 17 00:00:00 2001
From: Mikhail Litsarev <m.litsarev@postgrespro.ru>
Date: Thu, 13 Jun 2024 18:37:13 +0300
Subject: [PATCH] Wrapper function to extract whole text array from the
 SharedRecoveryDataFlags.

---
 src/backend/access/transam/xlogfuncs.c    | 31 +++++++++++++++++++++++
 src/backend/access/transam/xlogrecovery.c | 17 +++++++++++++
 src/include/access/xlogrecovery.h         |  1 +
 src/include/catalog/pg_proc.dat           |  4 +++
 4 files changed, 53 insertions(+)

diff --git a/src/backend/access/transam/xlogfuncs.c b/src/backend/access/transam/xlogfuncs.c
index 4e46baaebdf..9e752639aa4 100644
--- a/src/backend/access/transam/xlogfuncs.c
+++ b/src/backend/access/transam/xlogfuncs.c
@@ -29,6 +29,7 @@
 #include "replication/walreceiver.h"
 #include "storage/fd.h"
 #include "storage/standby.h"
+#include "utils/array.h"
 #include "utils/builtins.h"
 #include "utils/memutils.h"
 #include "utils/pg_lsn.h"
@@ -747,3 +748,33 @@ pg_promote(PG_FUNCTION_ARGS)
 						   wait_seconds)));
 	PG_RETURN_BOOL(false);
 }
+
+Datum
+pg_get_recovery_flags(PG_FUNCTION_ARGS)
+{
+/*
+ * Currently supported number of recovery flags is equal to 2:
+ * {XLR_PROMOTE_IS_TRIGGERED, XLR_STANDBY_MODE_REQUESTED}.
+ * It can be extended in future.
+ */
+#define MAX_RECOVERY_FLAGS 2
+
+	bits32		recovery_flags;
+	int			cnt = 0;
+	Datum		flags[MAX_RECOVERY_FLAGS];
+	ArrayType	*txt_arr;
+
+	recovery_flags = GetXLogRecoveryFlags();
+
+	if (recovery_flags & XLR_PROMOTE_IS_TRIGGERED)
+		flags[cnt++] = CStringGetTextDatum("PROMOTE_IS_TRIGGERED");
+
+	if (recovery_flags & XLR_STANDBY_MODE_REQUESTED)
+		flags[cnt++] = CStringGetTextDatum("STANDBY_MODE_REQUESTED");
+
+	Assert(cnt <= MAX_RECOVERY_FLAGS);
+
+	/* Returns bit array as Datum */
+	txt_arr = construct_array_builtin(flags, cnt, TEXTOID);
+	PG_RETURN_ARRAYTYPE_P(txt_arr);
+}
diff --git a/src/backend/access/transam/xlogrecovery.c b/src/backend/access/transam/xlogrecovery.c
index de92f48e4ae..bd919732a56 100644
--- a/src/backend/access/transam/xlogrecovery.c
+++ b/src/backend/access/transam/xlogrecovery.c
@@ -4399,6 +4399,22 @@ StartupRequestWalReceiverRestart(void)
 	}
 }
 
+/*
+ * Return flags for recovery states.
+ *
+ * Please, see description of
+ * XLR_PROMOTE_IS_TRIGGERED and XLR_STANDBY_MODE_REQUESTED.
+ */
+bits32 GetXLogRecoveryFlags(void)
+{
+	bits32		flags;
+
+	SpinLockAcquire(&XLogRecoveryCtl->info_lck);
+	flags = XLogRecoveryCtl->SharedRecoveryDataFlags;
+	SpinLockRelease(&XLogRecoveryCtl->info_lck);
+
+	return flags;
+}
 
 /*
  * Has a standby promotion already been triggered?
@@ -4551,6 +4567,7 @@ HotStandbyActiveInReplay(void)
 	return (LocalRecoveryDataFlags & XLR_HOT_STANDBY_ACTIVE);
 }
 
+
 /*
  * Get latest redo apply position.
  *
diff --git a/src/include/access/xlogrecovery.h b/src/include/access/xlogrecovery.h
index 2cb56fc365f..40487de1846 100644
--- a/src/include/access/xlogrecovery.h
+++ b/src/include/access/xlogrecovery.h
@@ -165,6 +165,7 @@ extern TimestampTz GetLatestXTime(void);
 extern TimestampTz GetCurrentChunkReplayStartTime(void);
 extern XLogRecPtr GetCurrentReplayRecPtr(TimeLineID *replayEndTLI);
 
+extern bits32 GetXLogRecoveryFlags(void);
 extern bool PromoteIsTriggered(void);
 extern bool CheckPromoteSignal(void);
 extern void WakeupRecovery(void);
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 6a5476d3c4c..7b199780c01 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -6520,6 +6520,10 @@
 { oid => '3810', descr => 'true if server is in recovery',
   proname => 'pg_is_in_recovery', provolatile => 'v', prorettype => 'bool',
   proargtypes => '', prosrc => 'pg_is_in_recovery' },
+{ oid => '8439',
+  descr => 'return flags for recovery states',
+  proname => 'pg_get_recovery_flags', provolatile => 'v', prorettype => '_text',
+  proargtypes => '', prosrc => 'pg_get_recovery_flags' },
 
 { oid => '3820', descr => 'current wal flush location',
   proname => 'pg_last_wal_receive_lsn', provolatile => 'v',
-- 
2.34.1

