mirror of
https://github.com/postgres/postgres.git
synced 2026-01-26 09:41:40 +03:00
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 f3d4019da5 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 <masao.fujii@gmail.com>
Reviewed-by: Chao Li <lic@highgo.com>
Reviewed-by: Kirill Reshke <reshkekirill@gmail.com>
Reviewed-by: Amit Kapila <amit.kapila16@gmail.com>
Reviewed-by: Japin Li <japinli@hotmail.com>
Discussion: https://postgr.es/m/CAHGQGwGYV+-abbKwdrM2UHUe-JYOFWmsrs6=QicyJO-j+-Widw@mail.gmail.com
Backpatch-through: 15
This commit is contained in:
@@ -65,6 +65,8 @@ static void libpqrcv_get_senderinfo(WalReceiverConn *conn,
|
|||||||
static char *libpqrcv_identify_system(WalReceiverConn *conn,
|
static char *libpqrcv_identify_system(WalReceiverConn *conn,
|
||||||
TimeLineID *primary_tli);
|
TimeLineID *primary_tli);
|
||||||
static char *libpqrcv_get_dbname_from_conninfo(const char *connInfo);
|
static char *libpqrcv_get_dbname_from_conninfo(const char *connInfo);
|
||||||
|
static char *libpqrcv_get_option_from_conninfo(const char *connInfo,
|
||||||
|
const char *keyword);
|
||||||
static int libpqrcv_server_version(WalReceiverConn *conn);
|
static int libpqrcv_server_version(WalReceiverConn *conn);
|
||||||
static void libpqrcv_readtimelinehistoryfile(WalReceiverConn *conn,
|
static void libpqrcv_readtimelinehistoryfile(WalReceiverConn *conn,
|
||||||
TimeLineID tli, char **filename,
|
TimeLineID tli, char **filename,
|
||||||
@@ -150,6 +152,7 @@ libpqrcv_connect(const char *conninfo, bool replication, bool logical,
|
|||||||
const char *keys[6];
|
const char *keys[6];
|
||||||
const char *vals[6];
|
const char *vals[6];
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
char *options_val = NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Re-validate connection string. The validation already happened at DDL
|
* Re-validate connection string. The validation already happened at DDL
|
||||||
@@ -177,6 +180,8 @@ libpqrcv_connect(const char *conninfo, bool replication, bool logical,
|
|||||||
|
|
||||||
if (logical)
|
if (logical)
|
||||||
{
|
{
|
||||||
|
char *opt = NULL;
|
||||||
|
|
||||||
/* Tell the publisher to translate to our encoding */
|
/* Tell the publisher to translate to our encoding */
|
||||||
keys[++i] = "client_encoding";
|
keys[++i] = "client_encoding";
|
||||||
vals[i] = GetDatabaseEncodingName();
|
vals[i] = GetDatabaseEncodingName();
|
||||||
@@ -189,8 +194,13 @@ libpqrcv_connect(const char *conninfo, bool replication, bool logical,
|
|||||||
* running in the subscriber, such as triggers.) This should
|
* running in the subscriber, such as triggers.) This should
|
||||||
* match what pg_dump does.
|
* match what pg_dump does.
|
||||||
*/
|
*/
|
||||||
|
opt = libpqrcv_get_option_from_conninfo(conninfo, "options");
|
||||||
|
options_val = psprintf("%s -c datestyle=ISO -c intervalstyle=postgres -c extra_float_digits=3",
|
||||||
|
(opt == NULL) ? "" : opt);
|
||||||
keys[++i] = "options";
|
keys[++i] = "options";
|
||||||
vals[i] = "-c datestyle=ISO -c intervalstyle=postgres -c extra_float_digits=3";
|
vals[i] = options_val;
|
||||||
|
if (opt != NULL)
|
||||||
|
pfree(opt);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -217,6 +227,9 @@ libpqrcv_connect(const char *conninfo, bool replication, bool logical,
|
|||||||
/* expand_dbname = */ true,
|
/* expand_dbname = */ true,
|
||||||
WAIT_EVENT_LIBPQWALRECEIVER_CONNECT);
|
WAIT_EVENT_LIBPQWALRECEIVER_CONNECT);
|
||||||
|
|
||||||
|
if (options_val != NULL)
|
||||||
|
pfree(options_val);
|
||||||
|
|
||||||
if (PQstatus(conn->streamConn) != CONNECTION_OK)
|
if (PQstatus(conn->streamConn) != CONNECTION_OK)
|
||||||
goto bad_connection_errmsg;
|
goto bad_connection_errmsg;
|
||||||
|
|
||||||
@@ -460,9 +473,21 @@ libpqrcv_server_version(WalReceiverConn *conn)
|
|||||||
*/
|
*/
|
||||||
static char *
|
static char *
|
||||||
libpqrcv_get_dbname_from_conninfo(const char *connInfo)
|
libpqrcv_get_dbname_from_conninfo(const char *connInfo)
|
||||||
|
{
|
||||||
|
return libpqrcv_get_option_from_conninfo(connInfo, "dbname");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the value of the option with the given keyword from the primary
|
||||||
|
* server's conninfo.
|
||||||
|
*
|
||||||
|
* If the option is not found in connInfo, return NULL value.
|
||||||
|
*/
|
||||||
|
static char *
|
||||||
|
libpqrcv_get_option_from_conninfo(const char *connInfo, const char *keyword)
|
||||||
{
|
{
|
||||||
PQconninfoOption *opts;
|
PQconninfoOption *opts;
|
||||||
char *dbname = NULL;
|
char *option = NULL;
|
||||||
char *err = NULL;
|
char *err = NULL;
|
||||||
|
|
||||||
opts = PQconninfoParse(connInfo, &err);
|
opts = PQconninfoParse(connInfo, &err);
|
||||||
@@ -480,21 +505,21 @@ libpqrcv_get_dbname_from_conninfo(const char *connInfo)
|
|||||||
for (PQconninfoOption *opt = opts; opt->keyword != NULL; ++opt)
|
for (PQconninfoOption *opt = opts; opt->keyword != NULL; ++opt)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* If multiple dbnames are specified, then the last one will be
|
* If the same option appears multiple times, then the last one will
|
||||||
* returned
|
* be returned
|
||||||
*/
|
*/
|
||||||
if (strcmp(opt->keyword, "dbname") == 0 && opt->val &&
|
if (strcmp(opt->keyword, keyword) == 0 && opt->val &&
|
||||||
*opt->val)
|
*opt->val)
|
||||||
{
|
{
|
||||||
if (dbname)
|
if (option)
|
||||||
pfree(dbname);
|
pfree(option);
|
||||||
|
|
||||||
dbname = pstrdup(opt->val);
|
option = pstrdup(opt->val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PQconninfoFree(opts);
|
PQconninfoFree(opts);
|
||||||
return dbname;
|
return option;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
Reference in New Issue
Block a user