Prohibit altering invalidated replication slots.
authorAmit Kapila <[email protected]>
Fri, 13 Sep 2024 03:59:13 +0000 (09:29 +0530)
committerAmit Kapila <[email protected]>
Fri, 13 Sep 2024 04:01:23 +0000 (09:31 +0530)
ALTER_REPLICATION_SLOT for invalid replication slots should not be allowed
because there is no way to get back the invalidated (logical) slot to
work.

Author: Bharath Rupireddy
Reviewed-by: Peter Smith, Shveta Malik
Discussion: https://www.postgresql.org/message-id/CALj2ACW4fSOMiKjQ3=2NVBMTZRTG8Ujg6jsK9z3EvOtvA4vzKQ@mail.gmail.com

src/backend/replication/slot.c
src/test/recovery/t/035_standby_logical_decoding.pl

index 0a037761569254451ba49788e2e0d6feba2362a5..6828100cf1ad720b0ee3a9a4474fa5cc108b3a24 100644 (file)
@@ -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 invalid replication slot \"%s\"", name),
+               errdetail("This replication slot has been invalidated due to \"%s\".",
+                         SlotInvalidationCauses[MyReplicationSlot->data.invalidated]));
+
    if (RecoveryInProgress())
    {
        /*
index 4185b803b2582793a45433b88af231c8a8f2d4ee..d658fdf417c0c63e0968c0e7af733f9bc2c9ba3e 100644 (file)
@@ -495,7 +495,8 @@ $node_subscriber->stop;
 # Scenario 1: hot_standby_feedback off and vacuum FULL
 #
 # In passing, ensure that replication slot stats are not removed when the
-# active slot is invalidated.
+# active slot is invalidated, and check that an error occurs when
+# attempting to alter the invalid slot.
 ##################################################
 
 # One way to produce recovery conflict is to create/drop a relation and
@@ -526,6 +527,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 invalid replication slot "vacuum_full_inactiveslot"/ &&
+   $stderr =~ /DETAIL:  This replication slot has been 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',