Heikki Linnakangas <hlinnakan...@vmware.com> writes: >> >> It appears that replication connection doesn't support URI but only the >> traditional conninfo string. >> >> src/backend/replication/libpqwalreceiver/libpqwalreceiver.c:99: in >> libpqrcv_connect(): >> >> snprintf(conninfo_repl, sizeof(conninfo_repl), >> "%s dbname=replication replication=true >> fallback_application_name=walreceiver", >> conninfo); >> >> A patch to fix this welcome? > > Yeah, seems like an oversight. Hopefully you can fix that without > teaching libpqwalreceiver what connection URIs look like..
Please see attached. We're lucky that PQconnectdbParams has an option to parse and expand the first dbname parameter if it looks like a connection string (or a URI). The first patch is not on topic, I just spotted this missing check. The second one is a self-contained fix, but the third one which is the actual patch depends on the second one, because it specifies the dbname keyword two times: first to parse the conninfo/URI, then to override any dbname provided by the user with "replication" pseudo-database name. Have a nice day! -- Alex
>From 156e6faa96ad6a2ce58055ad72883ed78c576e5b Mon Sep 17 00:00:00 2001 From: Alex Shulgin <a...@commandprompt.com> Date: Mon, 24 Nov 2014 16:55:50 +0300 Subject: [PATCH 1/3] Add missing check on OOM in expand_dbname path of conninfo_array_parse(). --- src/interfaces/libpq/fe-connect.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c new file mode 100644 index 3fe8c21..d7f2ec2 *** a/src/interfaces/libpq/fe-connect.c --- b/src/interfaces/libpq/fe-connect.c *************** conninfo_array_parse(const char *const * *** 4402,4407 **** --- 4402,4415 ---- if (options[k].val) free(options[k].val); options[k].val = strdup(str_option->val); + if (!options[k].val) + { + printfPQExpBuffer(errorMessage, + libpq_gettext("out of memory\n")); + PQconninfoFree(options); + PQconninfoFree(dbname_options); + return NULL; + } break; } } -- 2.1.0
>From 44d9d6a2c9cf5af83988f9d3b6eeb39c36104ef9 Mon Sep 17 00:00:00 2001 From: Alex Shulgin <a...@commandprompt.com> Date: Mon, 24 Nov 2014 18:12:51 +0300 Subject: [PATCH 2/3] Allow further dbname=value to override conninfo parsed from an expanded dbname in conninfo_array_parse(). --- src/interfaces/libpq/fe-connect.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c new file mode 100644 index d7f2ec2..5b45128 *** a/src/interfaces/libpq/fe-connect.c --- b/src/interfaces/libpq/fe-connect.c *************** conninfo_parse(const char *conninfo, PQE *** 4302,4311 **** * Defaults are supplied (from a service file, environment variables, etc) * for unspecified options, but only if use_defaults is TRUE. * ! * If expand_dbname is non-zero, and the value passed for keyword "dbname" is a ! * connection string (as indicated by recognized_connection_string) then parse ! * and process it, overriding any previously processed conflicting ! * keywords. Subsequent keywords will take precedence, however. */ static PQconninfoOption * conninfo_array_parse(const char *const * keywords, const char *const * values, --- 4302,4313 ---- * Defaults are supplied (from a service file, environment variables, etc) * for unspecified options, but only if use_defaults is TRUE. * ! * If expand_dbname is non-zero, and the value passed for the first occurrence ! * of "dbname" keyword is a connection string (as indicated by ! * recognized_connection_string) then parse and process it, overriding any ! * previously processed conflicting keywords. Subsequent keywords will take ! * precedence, however. In particular, a further occurrence of "dbname" may ! * override the dbname provided in the connection string. */ static PQconninfoOption * conninfo_array_parse(const char *const * keywords, const char *const * values, *************** conninfo_array_parse(const char *const * *** 4381,4387 **** } /* ! * If we are on the dbname parameter, and we have a parsed * connection string, copy those parameters across, overriding any * existing previous settings. */ --- 4383,4389 ---- } /* ! * If we are on the *first* dbname parameter, and we have a parsed * connection string, copy those parameters across, overriding any * existing previous settings. */ *************** conninfo_array_parse(const char *const * *** 4415,4420 **** --- 4417,4428 ---- } } } + /* + * Clear out the parsed dbname, so that a possible further + * occurrence of dbname have the chance to override it. + */ + PQconninfoFree(dbname_options); + dbname_options = NULL; } else { -- 2.1.0
>From 69e7c676e3af6f25520990cfb4337fc129741a95 Mon Sep 17 00:00:00 2001 From: Alex Shulgin <a...@commandprompt.com> Date: Mon, 24 Nov 2014 18:54:01 +0300 Subject: [PATCH 3/3] Allow URI in primary_conninfo line of recovery.conf file. --- doc/src/sgml/high-availability.sgml | 6 +++--- doc/src/sgml/recovery-config.sgml | 4 ++-- src/backend/access/transam/recovery.conf.sample | 3 ++- .../replication/libpqwalreceiver/libpqwalreceiver.c | 16 +++++++--------- 4 files changed, 14 insertions(+), 15 deletions(-) diff --git a/doc/src/sgml/high-availability.sgml b/doc/src/sgml/high-availability.sgml new file mode 100644 index d249959..61cf585 *** a/doc/src/sgml/high-availability.sgml --- b/doc/src/sgml/high-availability.sgml *************** protocol to make nodes agree on a serial *** 681,689 **** <para> If you want to use streaming replication, fill in ! <varname>primary_conninfo</> with a libpq connection string, including ! the host name (or IP address) and any additional details needed to ! connect to the primary server. If the primary needs a password for authentication, the password needs to be specified in <varname>primary_conninfo</> as well. </para> --- 681,689 ---- <para> If you want to use streaming replication, fill in ! <varname>primary_conninfo</> with a libpq connection string or a URI, ! including the host name (or IP address) and any additional details needed ! to connect to the primary server. If the primary needs a password for authentication, the password needs to be specified in <varname>primary_conninfo</> as well. </para> diff --git a/doc/src/sgml/recovery-config.sgml b/doc/src/sgml/recovery-config.sgml new file mode 100644 index 0f1ff34..9e17e20 *** a/doc/src/sgml/recovery-config.sgml --- b/doc/src/sgml/recovery-config.sgml *************** restore_command = 'copy "C:\\server\\arc *** 342,349 **** </term> <listitem> <para> ! Specifies a connection string to be used for the standby server ! to connect with the primary. This string is in the format described in <xref linkend="libpq-connstring">. If any option is unspecified in this string, then the corresponding environment variable (see <xref linkend="libpq-envars">) is checked. If the --- 342,349 ---- </term> <listitem> <para> ! Specifies a connection string or a URI to be used for the standby ! server to connect with the primary. This string is in the format described in <xref linkend="libpq-connstring">. If any option is unspecified in this string, then the corresponding environment variable (see <xref linkend="libpq-envars">) is checked. If the diff --git a/src/backend/access/transam/recovery.conf.sample b/src/backend/access/transam/recovery.conf.sample new file mode 100644 index 7657df3..b1815be *** a/src/backend/access/transam/recovery.conf.sample --- b/src/backend/access/transam/recovery.conf.sample *************** *** 116,124 **** # primary_conninfo # # If set, the PostgreSQL server will try to connect to the primary using this ! # connection string and receive XLOG records continuously. # #primary_conninfo = '' # e.g. 'host=localhost port=5432' # # If set, the PostgreSQL server will use the specified replication slot when # connecting to the primary via streaming replication to control resource --- 116,125 ---- # primary_conninfo # # If set, the PostgreSQL server will try to connect to the primary using this ! # connection string or URI and receive XLOG records continuously. # #primary_conninfo = '' # e.g. 'host=localhost port=5432' + # or 'postgres://localhost:5432/' # # If set, the PostgreSQL server will use the specified replication slot when # connecting to the primary via streaming replication to control resource diff --git a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c new file mode 100644 index 65e95c5..eebb3bb *** a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c --- b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c *************** _PG_init(void) *** 89,106 **** static void libpqrcv_connect(char *conninfo) { ! char conninfo_repl[MAXCONNINFO + 75]; /* ! * Connect using deliberately undocumented parameter: replication. The ! * database name is ignored by the server in replication mode, but specify ! * "replication" for .pgpass lookup. */ ! snprintf(conninfo_repl, sizeof(conninfo_repl), ! "%s dbname=replication replication=true fallback_application_name=walreceiver", ! conninfo); ! ! streamConn = PQconnectdb(conninfo_repl); if (PQstatus(streamConn) != CONNECTION_OK) ereport(ERROR, (errmsg("could not connect to the primary server: %s", --- 89,104 ---- static void libpqrcv_connect(char *conninfo) { ! const char *keys[] = { "dbname", "dbname", "replication", "fallback_application_name", NULL }; ! const char *vals[] = { conninfo, "replication", "true", "walreceiver", NULL }; /* ! * We exploit the expand_dbname parameter to process the connection string ! * (or URI), then override the options that are necessary to establish the ! * replication type of connection. In particular, we override any ! * database name provided in conninfo with "replication". */ ! streamConn = PQconnectdbParams(keys, vals, /* expand_dbname = */ true); if (PQstatus(streamConn) != CONNECTION_OK) ereport(ERROR, (errmsg("could not connect to the primary server: %s", -- 2.1.0
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers