From 0e7f61589c282a2e9b82cdbf8eadc2159301c3e8 Mon Sep 17 00:00:00 2001
From: Mikhail Litsarev <m.litsarev@postgrespro.ru>
Date: Tue, 25 Mar 2025 23:02:23 +0300
Subject: [PATCH v7 2/2] Wrapper function to extract whole text array from
 recovery flags bitset.

It returns SX_PROMOTE_IS_TRIGGERED, SX_STANDBY_MODE_REQUESTED flags for recovery states.
---
 src/backend/access/transam/xlogfuncs.c    | 31 +++++++++++++++++++++++
 src/backend/access/transam/xlogrecovery.c | 16 ++++++++++++
 src/include/access/xlogrecovery.h         |  1 +
 src/include/catalog/pg_proc.dat           |  5 ++++
 4 files changed, 53 insertions(+)

diff --git a/src/backend/access/transam/xlogfuncs.c b/src/backend/access/transam/xlogfuncs.c
index 8c3090165f0..9b71ff7583c 100644
--- a/src/backend/access/transam/xlogfuncs.c
+++ b/src/backend/access/transam/xlogfuncs.c
@@ -30,6 +30,7 @@
 #include "storage/fd.h"
 #include "storage/latch.h"
 #include "storage/standby.h"
+#include "utils/array.h"
 #include "utils/builtins.h"
 #include "utils/memutils.h"
 #include "utils/pg_lsn.h"
@@ -748,3 +749,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 two:
+ * {SX_PROMOTE_IS_TRIGGERED, SX_STANDBY_MODE_REQUESTED}.
+ * The SX_STANDBY_MODE_REQUESTED is valid only in the startup process.
+ */
+#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 & SX_PROMOTE_IS_TRIGGERED)
+		flags[cnt++] = CStringGetTextDatum("PROMOTE_IS_TRIGGERED");
+
+	if (recovery_flags & SX_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 9d8c1cdde43..bd5bdeb5db8 100644
--- a/src/backend/access/transam/xlogrecovery.c
+++ b/src/backend/access/transam/xlogrecovery.c
@@ -4370,6 +4370,22 @@ StartupRequestWalReceiverRestart(void)
 	}
 }
 
+/*
+ * Return SX_PROMOTE_IS_TRIGGERED, SX_STANDBY_MODE_REQUESTED flags for
+ * recovery states.
+ */
+bits32 GetXLogRecoveryFlags(void)
+{
+	bits32		flags = 0;
+
+	SpinLockAcquire(&XLogRecoveryCtl->info_lck);
+	flags = XLogRecoveryCtl->sharedRecoveryFlags;
+	SpinLockRelease(&XLogRecoveryCtl->info_lck);
+
+	flags |= (localRecoveryFlags & SX_STANDBY_MODE_REQUESTED);
+
+	return flags;
+}
 
 /*
  * Has a standby promotion already been triggered?
diff --git a/src/include/access/xlogrecovery.h b/src/include/access/xlogrecovery.h
index 2d44905ea36..faa6c666ede 100644
--- a/src/include/access/xlogrecovery.h
+++ b/src/include/access/xlogrecovery.h
@@ -172,6 +172,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 3f7b82e02bb..8b775f0bbd9 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -6714,6 +6714,11 @@
   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',
   prorettype => 'pg_lsn', proargtypes => '',
-- 
2.34.1

