From e7d7de8fc99258ea826fc6269497313fefb417c1 Mon Sep 17 00:00:00 2001
From: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Date: Mon, 18 Aug 2025 11:47:43 +0900
Subject: [PATCH v6 1/2] Set ReplicationSlot::active_pid even in single-user
 mode

Slot manipulation functions except drop could be failed in single-user mode, because
active_pid was not set. Actually the attribute is no-op in the mode but fix the
inconsisntency anyway.
---
 src/backend/replication/slot.c                |  2 +-
 src/test/recovery/meson.build                 |  3 +-
 .../t/049_slots_in_single_user_mode.pl        | 67 +++++++++++++++++++
 3 files changed, 70 insertions(+), 2 deletions(-)
 create mode 100644 src/test/recovery/t/049_slots_in_single_user_mode.pl

diff --git a/src/backend/replication/slot.c b/src/backend/replication/slot.c
index 8605776ad86..fd0fdb96d42 100644
--- a/src/backend/replication/slot.c
+++ b/src/backend/replication/slot.c
@@ -653,7 +653,7 @@ retry:
 	}
 	else
 	{
-		active_pid = MyProcPid;
+		s->active_pid = active_pid = MyProcPid;
 		ReplicationSlotSetInactiveSince(s, 0, true);
 	}
 	LWLockRelease(ReplicationSlotControlLock);
diff --git a/src/test/recovery/meson.build b/src/test/recovery/meson.build
index 52993c32dbb..7b1fe30f112 100644
--- a/src/test/recovery/meson.build
+++ b/src/test/recovery/meson.build
@@ -56,7 +56,8 @@ tests += {
       't/045_archive_restartpoint.pl',
       't/046_checkpoint_logical_slot.pl',
       't/047_checkpoint_physical_slot.pl',
-      't/048_vacuum_horizon_floor.pl'
+      't/048_vacuum_horizon_floor.pl',
+      't/049_slots_in_single_user_mode.pl',
     ],
   },
 }
diff --git a/src/test/recovery/t/049_slots_in_single_user_mode.pl b/src/test/recovery/t/049_slots_in_single_user_mode.pl
new file mode 100644
index 00000000000..de32160be07
--- /dev/null
+++ b/src/test/recovery/t/049_slots_in_single_user_mode.pl
@@ -0,0 +1,67 @@
+use strict;
+use warnings;
+use PostgreSQL::Test::Cluster;
+use PostgreSQL::Test::Utils;
+use Test::More;
+
+# Tests the slot manipulation in the single-user mode
+
+# Run passed commands in single-user mode. The return value from the command is
+# passed through.
+sub run_test_in_single_user_mode
+{
+	my ($node, $commands, $testname) = @_;
+
+	my $result = run_log(
+		[
+			'postgres', '--single', '-F',
+			'-c' => 'exit_on_error=true',
+			'-D' => $node->data_dir,
+			'postgres'
+		],
+		\$commands);
+
+	ok($result, $testname);
+}
+
+my $slotname = 'test_slot';
+
+# Initialize a node
+my $node = PostgreSQL::Test::Cluster->new('node');
+$node->init(allows_streaming => "logical");
+$node->start;
+
+# Define initial table
+$node->safe_psql('postgres', "CREATE TABLE foo (id int)");
+
+# Stop the node to run and test in single-user mode
+$node->stop;
+
+run_test_in_single_user_mode(
+	$node,
+	"SELECT pg_create_logical_replication_slot('$slotname', 'test_decoding')",
+	"replication slot can be created in single-user mode");
+
+run_test_in_single_user_mode(
+	$node, qq(
+INSERT INTO foo VALUES (1);
+SELECT count(1) FROM pg_logical_slot_get_changes('$slotname', NULL, NULL);
+),
+	"logical decoding be done in single-user mode");
+
+run_test_in_single_user_mode(
+	$node,
+	"SELECT pg_replication_slot_advance('$slotname', pg_current_wal_lsn())",
+	"replication slot can be advanced in single-user mode");
+
+run_test_in_single_user_mode(
+	$node,
+	"SELECT pg_copy_logical_replication_slot('$slotname', 'dest_slot')",
+	"replication slot can be copied in single-user mode");
+
+run_test_in_single_user_mode(
+	$node,
+	"SELECT pg_drop_replication_slot('$slotname')",
+	"replication slot can be dropped in single-user mode");
+
+done_testing();
-- 
2.47.1

