From 5453fcfee43cea3e1b499573e4d144eb9f68a24d Mon Sep 17 00:00:00 2001 From: Fujii Masao Date: Wed, 26 Nov 2025 23:35:44 +0900 Subject: [PATCH 1/2] Honor GUC settings specified in CREATE SUBSCRIPTION CONNECTION. Prior to v15, GUC settings supplied in the CONNECTION clause of CREATE SUBSCRIPTION were correctly passed through to the publisher's walsender. For example: CREATE SUBSCRIPTION mysub CONNECTION 'options=''-c wal_sender_timeout=1000''' PUBLICATION ... would cause wal_sender_timeout to take effect on the publisher's walsender. However, commit f3d4019da5d changed the way logical replication connections are established, forcing the publisher's relevant GUC settings (datestyle, intervalstyle, extra_float_digits) to override those provided in the CONNECTION string. As a result, from v15 through v18, GUC settings in the CONNECTION string were always ignored. This regression prevented per-connection tuning of logical replication. For example, using a shorter timeout for walsender connecting to a nearby subscriber and a longer one for walsender connecting to a remote subscriber. This commit restores the intended behavior by ensuring that GUC settings in the CONNECTION string are again passed through and applied by the walsender, allowing per-connection configuration. Backpatch to v15, where the regression was introduced. Author: Fujii Masao Reviewed-by: Chao Li Discussion: https://postgr.es/m/CAHGQGwGYV+-abbKwdrM2UHUe-JYOFWmsrs6=QicyJO-j+-Widw@mail.gmail.com Backpatch-through: 15 --- .../libpqwalreceiver/libpqwalreceiver.c | 43 ++++++++++++++----- 1 file changed, 32 insertions(+), 11 deletions(-) diff --git a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c index 5ddc9e812e70..51a240ea6d8b 100644 --- a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c +++ b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c @@ -180,17 +180,6 @@ libpqrcv_connect(const char *conninfo, bool replication, bool logical, /* Tell the publisher to translate to our encoding */ keys[++i] = "client_encoding"; vals[i] = GetDatabaseEncodingName(); - - /* - * Force assorted GUC parameters to settings that ensure that the - * publisher will output data values in a form that is unambiguous - * to the subscriber. (We don't want to modify the subscriber's - * GUC settings, since that might surprise user-defined code - * running in the subscriber, such as triggers.) This should - * match what pg_dump does. - */ - keys[++i] = "options"; - vals[i] = "-c datestyle=ISO -c intervalstyle=postgres -c extra_float_digits=3"; } else { @@ -256,6 +245,38 @@ libpqrcv_connect(const char *conninfo, bool replication, bool logical, PQclear(res); } + /* + * Force assorted GUC parameters to settings that ensure that the + * publisher will output data values in a form that is unambiguous to the + * subscriber. (We don't want to modify the subscriber's GUC settings, + * since that might surprise user-defined code running in the subscriber, + * such as triggers.) This should match what pg_dump does. + */ + if (replication && logical) + { + const char *params[] = + {"datestyle", "intervalstyle", "extra_float_digits"}; + const char *values[] = {"ISO", "postgres", "3"}; + + for (int j = 0; j < lengthof(params); j++) + { + char sql[100]; + PGresult *res; + + sprintf(sql, "SET %s = %s", params[j], values[j]); + res = libpqsrv_exec(conn->streamConn, sql, + WAIT_EVENT_LIBPQWALRECEIVER_RECEIVE); + if (PQresultStatus(res) != PGRES_COMMAND_OK) + { + PQclear(res); + *err = psprintf(_("could not set %s: %s"), + params[j], pchomp(PQerrorMessage(conn->streamConn))); + goto bad_connection; + } + PQclear(res); + } + } + conn->logical = logical; return conn; From 0d2149e26286411d3dd1560bb075904e0d639ec7 Mon Sep 17 00:00:00 2001 From: Fujii Masao Date: Thu, 27 Nov 2025 12:36:59 +0900 Subject: [PATCH 2/2] Add TAP test for GUC settings passed via CONNECTION in logical replication. This commit adds a TAP test to verify that GUC settings provided in the CONNECTION string of CREATE/ALTER SUBSCRIPTION are correctly passed through to and applied by the publisher's walsender. --- src/test/subscription/t/001_rep_changes.pl | 28 +++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/src/test/subscription/t/001_rep_changes.pl b/src/test/subscription/t/001_rep_changes.pl index 430c1246d14c..9d08ae8b6413 100644 --- a/src/test/subscription/t/001_rep_changes.pl +++ b/src/test/subscription/t/001_rep_changes.pl @@ -438,17 +438,34 @@ 22.22|bar|2), 'update works with dropped subscriber column'); +# Verify that GUC settings supplied in the CONNECTION string take effect on +# the publisher's walsender. We do this by enabling log_disconnections in +# the CONNECTION string later and checking that the publisher's log contains a +# disconnection message. +# +# First, confirm that no such disconnection message appears before enabling +# log_disconnections. +$logfile = slurp_file($node_publisher->logfile, $log_location); +unlike( + $logfile, + qr/disconnection: session time:/, + 'log_disconnections has not been enabled yet'); + # check that change of connection string and/or publication list causes # restart of subscription workers. We check the state along with # application_name to ensure that the walsender is (re)started. # # Not all of these are registered as tests as we need to poll for a change # but the test suite will fail nonetheless when something goes wrong. +# +# Enable log_disconnections as the change of connection string, +# which is also for the above mentioned test of GUC settings passed through +# CONNECTION. my $oldpid = $node_publisher->safe_psql('postgres', "SELECT pid FROM pg_stat_replication WHERE application_name = 'tap_sub' AND state = 'streaming';" ); $node_subscriber->safe_psql('postgres', - "ALTER SUBSCRIPTION tap_sub CONNECTION '$publisher_connstr sslmode=disable'" + "ALTER SUBSCRIPTION tap_sub CONNECTION '$publisher_connstr options=''-c log_disconnections=on'''" ); $node_publisher->poll_query_until('postgres', "SELECT pid != $oldpid FROM pg_stat_replication WHERE application_name = 'tap_sub' AND state = 'streaming';" @@ -552,6 +569,15 @@ or die "Timed out while waiting for apply to restart after renaming SUBSCRIPTION"; +# Check that the expected disconnection message appears, +# which shows that log_disconnections=on from the CONNECTION string +# was correctly passed through to and honored by the walsender. +$logfile = slurp_file($node_publisher->logfile, $log_location); +like( + $logfile, + qr/disconnection: session time:/, + 'log_disconnections in CONNECTION string had effect on publisher\'s walsender'); + # check all the cleanup $node_subscriber->safe_psql('postgres', "DROP SUBSCRIPTION tap_sub_renamed");