v1-0001-Disallow-altering-invalidated-replication-slots.patch

application/octet-stream

Filename: v1-0001-Disallow-altering-invalidated-replication-slots.patch
Type: application/octet-stream
Part: 0
Message: Disallow altering invalidated replication slots

Patch

Same data as JSON: GET /api/v1/attachments/:id/patch the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes. API reference →
Format: format-patch
Series: patch v1-0001
Subject: Disallow altering invalidated replication slots
File+
src/backend/replication/slot.c 7 0
src/test/recovery/t/035_standby_logical_decoding.pl 9 0
From 8b2a7e7c629c5d21fdb801739d9661722904dd7e Mon Sep 17 00:00:00 2001
From: Bharath Rupireddy <bharath.rupireddyforpostgres@gmail.com>
Date: Mon, 9 Sep 2024 18:25:16 +0000
Subject: [PATCH v1] Disallow altering invalidated replication slots

ALTER_REPLICATION_SLOT on invalidated replication slots is
unnecessary as there is no way to get the invalidated
(logical) slot to work. This commit adds an error.

Discussion: https://www.postgresql.org/message-id/CAA4eK1%2Bszcosq0nS109mMSxPWyNT1Q%3DUNYCJgXKYuCceaPS%2BhA%40mail.gmail.com
---
 src/backend/replication/slot.c                      | 7 +++++++
 src/test/recovery/t/035_standby_logical_decoding.pl | 9 +++++++++
 2 files changed, 16 insertions(+)

diff --git a/src/backend/replication/slot.c b/src/backend/replication/slot.c
index 0a03776156..35652d9ad8 100644
--- a/src/backend/replication/slot.c
+++ b/src/backend/replication/slot.c
@@ -820,6 +820,13 @@ ReplicationSlotAlter(const char *name, const bool *failover,
 				errmsg("cannot use %s with a physical replication slot",
 					   "ALTER_REPLICATION_SLOT"));
 
+	if (MyReplicationSlot->data.invalidated != RS_INVAL_NONE)
+		ereport(ERROR,
+				errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+				errmsg("cannot alter replication slot \"%s\"", name),
+				errdetail("This replication slot was invalidated due to \"%s\".",
+						  SlotInvalidationCauses[MyReplicationSlot->data.invalidated]));
+
 	if (RecoveryInProgress())
 	{
 		/*
diff --git a/src/test/recovery/t/035_standby_logical_decoding.pl b/src/test/recovery/t/035_standby_logical_decoding.pl
index 4185b803b2..75ccfca409 100644
--- a/src/test/recovery/t/035_standby_logical_decoding.pl
+++ b/src/test/recovery/t/035_standby_logical_decoding.pl
@@ -526,6 +526,15 @@ check_for_invalidation('vacuum_full_', 1, 'with vacuum FULL on pg_class');
 # Verify reason for conflict is 'rows_removed' in pg_replication_slots
 check_slots_conflict_reason('vacuum_full_', 'rows_removed');
 
+# Attempting to alter an invalidated slot should result in an error
+($result, $stdout, $stderr) = $node_standby->psql(
+    'postgres',
+    qq[ALTER_REPLICATION_SLOT vacuum_full_inactiveslot (failover);],
+    replication => 'database');
+ok($stderr =~ /ERROR:  cannot alter replication slot "vacuum_full_inactiveslot"/ &&
+   $stderr =~ /DETAIL:  This replication slot was invalidated due to "rows_removed"./,
+    "invalidated slot cannot be altered");
+
 # Ensure that replication slot stats are not removed after invalidation.
 is( $node_standby->safe_psql(
 		'testdb',
-- 
2.43.0