From cf6c42de2558b86bcee54c0b629385b8141f3054 Mon Sep 17 00:00:00 2001 From: "Chao Li (Evan)" Date: Wed, 5 Aug 2026 15:11:13 +0800 Subject: [PATCH v1] pg_createsubscriber: Allow duplicate subscription names Subscription names are database-local, so the same name can be used in different databases. However, pg_createsubscriber rejected duplicate --subscription values unconditionally. Allow duplicate subscription names when distinct replication slot names are specified explicitly. Continue to reject them when --replication-slot is omitted, because subscription names are then reused as replication slot names, which must be unique within a cluster. Add tests and update the documentation. Suggested-by: Amit Kapila Author: Chao Li Reviewed-by: Discussion: https://postgr.es/m/ --- doc/src/sgml/ref/pg_createsubscriber.sgml | 4 +++- src/bin/pg_basebackup/pg_createsubscriber.c | 19 +++++++++------ .../t/040_pg_createsubscriber.pl | 24 +++++++++++++++---- 3 files changed, 35 insertions(+), 12 deletions(-) diff --git a/doc/src/sgml/ref/pg_createsubscriber.sgml b/doc/src/sgml/ref/pg_createsubscriber.sgml index 193f60628bc..60d7c8e2a2d 100644 --- a/doc/src/sgml/ref/pg_createsubscriber.sgml +++ b/doc/src/sgml/ref/pg_createsubscriber.sgml @@ -362,7 +362,9 @@ PostgreSQL documentation is reported. The order of the multiple subscription name switches must match the order of database switches. If this option is not specified, a generated name is assigned to the subscription name. This option cannot - be used together with . + be used together with . The same subscription name + can be used in different databases only when distinct replication slot + names are specified with . diff --git a/src/bin/pg_basebackup/pg_createsubscriber.c b/src/bin/pg_basebackup/pg_createsubscriber.c index 20b354aed56..dcf8422dd92 100644 --- a/src/bin/pg_basebackup/pg_createsubscriber.c +++ b/src/bin/pg_basebackup/pg_createsubscriber.c @@ -2262,6 +2262,7 @@ main(int argc, char **argv) int c; int option_index; + bool duplicate_sub_name = false; char *pub_base_conninfo; char *sub_base_conninfo; @@ -2394,13 +2395,10 @@ main(int argc, char **argv) pg_fatal("replication slot \"%s\" specified more than once for --replication-slot", optarg); break; case 4: - if (!simple_string_list_member(&opt.sub_names, optarg)) - { - simple_string_list_append(&opt.sub_names, optarg); - num_subs++; - } - else - pg_fatal("subscription \"%s\" specified more than once for --subscription", optarg); + if (simple_string_list_member(&opt.sub_names, optarg)) + duplicate_sub_name = true; + simple_string_list_append(&opt.sub_names, optarg); + num_subs++; break; case 5: if (!simple_string_list_member(&opt.objecttypes_to_clean, optarg)) @@ -2587,6 +2585,13 @@ main(int argc, char **argv) num_replslots, num_dbs); exit(1); } + if (duplicate_sub_name && num_replslots == 0) + { + pg_log_error("duplicate subscription names require distinct replication slot names"); + pg_log_error_detail("When replication slot names are not specified, subscription names are used, but replication slot names must be unique within a cluster."); + pg_log_error_hint("Specify a unique --replication-slot name for each database."); + exit(1); + } /* Verify the object types specified for removal from the subscriber */ for (SimpleStringListCell *cell = opt.objecttypes_to_clean.head; cell; cell = cell->next) diff --git a/src/bin/pg_basebackup/t/040_pg_createsubscriber.pl b/src/bin/pg_basebackup/t/040_pg_createsubscriber.pl index 9252d1c3c5c..82fb4394bea 100644 --- a/src/bin/pg_basebackup/t/040_pg_createsubscriber.pl +++ b/src/bin/pg_basebackup/t/040_pg_createsubscriber.pl @@ -91,6 +91,19 @@ command_fails( '--database' => 'pg2', ], 'wrong number of subscription names'); +command_fails_like( + [ + 'pg_createsubscriber', + '--verbose', + '--pgdata' => $datadir, + '--publisher-server' => 'port=5432', + '--subscription' => 'bar1', + '--subscription' => 'bar1', + '--database' => 'pg1', + '--database' => 'pg2', + ], + qr/duplicate subscription names require distinct replication slot names/, + 'duplicate subscription names without replication slot names'); command_fails( [ 'pg_createsubscriber', @@ -334,8 +347,9 @@ is($node_s->safe_psql($db1, "SELECT COUNT(*) FROM pg_publication"), $node_s->stop; -# dry run mode on node S. Use the same publication name for different -# databases, since publication names are database-local. +# dry run mode on node S. Use the same publication and subscription names for +# different databases, since both names are database-local. Distinct replication +# slot names are required because replication slots are cluster-global. command_ok( [ 'pg_createsubscriber', @@ -348,8 +362,10 @@ command_ok( '--subscriber-port' => $node_s->port, '--publication' => 'same_pub', '--publication' => 'same_pub', - '--subscription' => 'sub1', - '--subscription' => 'sub2', + '--subscription' => 'same_sub', + '--subscription' => 'same_sub', + '--replication-slot' => 'slot1', + '--replication-slot' => 'slot2', '--database' => $db1, '--database' => $db2, '--logdir' => $logdir, -- 2.50.1 (Apple Git-155)