diff --git a/doc/src/sgml/ref/pg_basebackup.sgml b/doc/src/sgml/ref/pg_basebackup.sgml index 2f89f2c322efccbd5c04d3508800932544b09275..9906b0c6d5533a125b82ca72a9d1a81982937a7b 100644 --- a/doc/src/sgml/ref/pg_basebackup.sgml +++ b/doc/src/sgml/ref/pg_basebackup.sgml @@ -358,6 +358,23 @@ PostgreSQL documentation The following command-line options control the database connection parameters. <variablelist> + <varlistentry> + <term><option>-d <replaceable class="parameter">connstr</replaceable></option></term> + <term><option>--dbname=<replaceable class="parameter">connstr</replaceable></option></term> + <listitem> + <para> + Specifies parameters used to connect to the server, as a connection + string. See <xref linkend="libpq-connstring"> for more information. + </para> + <para> + The option is called <literal>--dbname</> for consistency with other + client applications, but because <application>pg_basebackup</application> + doesn't connect to any particular database in the cluster, database + name in the connection string will be ignored. + </para> + </listitem> + </varlistentry> + <varlistentry> <term><option>-h <replaceable class="parameter">host</replaceable></option></term> <term><option>--host=<replaceable class="parameter">host</replaceable></option></term> diff --git a/doc/src/sgml/ref/pg_receivexlog.sgml b/doc/src/sgml/ref/pg_receivexlog.sgml index d06dd1f171c6ec3c8f2b524166b3f08ee8b0b2e2..ec9afad1974d153a79fca1305393a1f24a269ea5 100644 --- a/doc/src/sgml/ref/pg_receivexlog.sgml +++ b/doc/src/sgml/ref/pg_receivexlog.sgml @@ -122,6 +122,23 @@ PostgreSQL documentation The following command-line options control the database connection parameters. <variablelist> + <varlistentry> + <term><option>-d <replaceable class="parameter">connstr</replaceable></option></term> + <term><option>--dbname=<replaceable class="parameter">connstr</replaceable></option></term> + <listitem> + <para> + Specifies parameters used to connect to the server, as a connection + string. See <xref linkend="libpq-connstring"> for more information. + </para> + <para> + The option is called <literal>--dbname</> for consistency with other + client applications, but because <application>pg_basebackup</application> + doesn't connect to any particular database in the cluster, database + name in the connection string will be ignored. + </para> + </listitem> + </varlistentry> + <varlistentry> <term><option>-h <replaceable class="parameter">host</replaceable></option></term> <term><option>--host=<replaceable class="parameter">host</replaceable></option></term> diff --git a/src/bin/pg_basebackup/pg_basebackup.c b/src/bin/pg_basebackup/pg_basebackup.c index fb5a1bd1c199035b4d75295aa63b8743960926f0..2de03acabd6fe997be1b51d4f81ce33f81998eab 100644 --- a/src/bin/pg_basebackup/pg_basebackup.c +++ b/src/bin/pg_basebackup/pg_basebackup.c @@ -126,6 +126,7 @@ usage(void) printf(_(" -V, --version output version information, then exit\n")); printf(_(" -?, --help show this help, then exit\n")); printf(_("\nConnection options:\n")); + printf(_(" -d, --dbname=CONNSTR connection string\n")); printf(_(" -h, --host=HOSTNAME database server host or socket directory\n")); printf(_(" -p, --port=PORT database server port number\n")); printf(_(" -s, --status-interval=INTERVAL\n" @@ -1540,6 +1541,7 @@ main(int argc, char **argv) {"gzip", no_argument, NULL, 'z'}, {"compress", required_argument, NULL, 'Z'}, {"label", required_argument, NULL, 'l'}, + {"dbname", required_argument, NULL, 'd'}, {"host", required_argument, NULL, 'h'}, {"port", required_argument, NULL, 'p'}, {"username", required_argument, NULL, 'U'}, @@ -1572,7 +1574,7 @@ main(int argc, char **argv) } } - while ((c = getopt_long(argc, argv, "D:F:RxX:l:zZ:c:h:p:U:s:wWvP", + while ((c = getopt_long(argc, argv, "D:F:RxX:l:zZ:d:c:h:p:U:s:wWvP", long_options, &option_index)) != -1) { switch (c) @@ -1663,6 +1665,9 @@ main(int argc, char **argv) exit(1); } break; + case 'd': + connection_string = pg_strdup(optarg); + break; case 'h': dbhost = pg_strdup(optarg); break; diff --git a/src/bin/pg_basebackup/pg_receivexlog.c b/src/bin/pg_basebackup/pg_receivexlog.c index 33dbc50389b86d3cb3e467bcda8cc458d7d06911..352ff3537688caddacfc5e68c8ec890cc83d78ca 100644 --- a/src/bin/pg_basebackup/pg_receivexlog.c +++ b/src/bin/pg_basebackup/pg_receivexlog.c @@ -58,6 +58,7 @@ usage(void) printf(_(" -V, --version output version information, then exit\n")); printf(_(" -?, --help show this help, then exit\n")); printf(_("\nConnection options:\n")); + printf(_(" -d, --dbname=CONNSTR connection string\n")); printf(_(" -h, --host=HOSTNAME database server host or socket directory\n")); printf(_(" -p, --port=PORT database server port number\n")); printf(_(" -s, --status-interval=INTERVAL\n" @@ -306,6 +307,7 @@ main(int argc, char **argv) {"help", no_argument, NULL, '?'}, {"version", no_argument, NULL, 'V'}, {"directory", required_argument, NULL, 'D'}, + {"dbname", required_argument, NULL, 'd'}, {"host", required_argument, NULL, 'h'}, {"port", required_argument, NULL, 'p'}, {"username", required_argument, NULL, 'U'}, @@ -338,7 +340,7 @@ main(int argc, char **argv) } } - while ((c = getopt_long(argc, argv, "D:h:p:U:s:nwWv", + while ((c = getopt_long(argc, argv, "D:d:h:p:U:s:nwWv", long_options, &option_index)) != -1) { switch (c) @@ -346,6 +348,9 @@ main(int argc, char **argv) case 'D': basedir = pg_strdup(optarg); break; + case 'd': + connection_string = pg_strdup(optarg); + break; case 'h': dbhost = pg_strdup(optarg); break; diff --git a/src/bin/pg_basebackup/streamutil.c b/src/bin/pg_basebackup/streamutil.c index 8a43c4bad1dd3a33230634132a8abec4e746afa2..a878dd4345168b67763f54d12916d6271b972dbb 100644 --- a/src/bin/pg_basebackup/streamutil.c +++ b/src/bin/pg_basebackup/streamutil.c @@ -18,6 +18,7 @@ #include <string.h> const char *progname; +char *connection_string = NULL; char *dbhost = NULL; char *dbuser = NULL; char *dbport = NULL; @@ -34,31 +35,67 @@ PGconn * GetConnection(void) { PGconn *tmpconn; - int argcount = 4; /* dbname, replication, fallback_app_name, - * password */ + int argcount = 7; /* dbname, replication, fallback_app_name, + * host, user, port, password */ int i; const char **keywords; const char **values; char *password = NULL; const char *tmpparam; + PQconninfoOption *conn_opts = NULL; + PQconninfoOption *conn_opt; + char *err_msg = NULL; + + /* + * Merge the connection info inputs given in form of connection string, + * options and default values (dbname=replication, replication=true, + * etc.) + */ + i = 0; + if (connection_string) + { + conn_opts = PQconninfoParse(connection_string, &err_msg); + if (conn_opts == NULL) + { + fprintf(stderr, "%s: %s\n", progname, err_msg); + return NULL; + } + + for (conn_opt = conn_opts; conn_opt->keyword != NULL; conn_opt++) + { + if (conn_opt->val != NULL && conn_opt->val[0] != '\0') + argcount++; + } + + keywords = pg_malloc0((argcount + 1) * sizeof(*keywords)); + values = pg_malloc0((argcount + 1) * sizeof(*values)); + + for (conn_opt = conn_opts; conn_opt->keyword != NULL; conn_opt++) + { + if (conn_opt->val != NULL && conn_opt->val[0] != '\0') + { + keywords[i] = conn_opt->keyword; + values[i] = conn_opt->val; + i++; + } + } + } + else + { + keywords = pg_malloc0((argcount + 1) * sizeof(*keywords)); + values = pg_malloc0((argcount + 1) * sizeof(*values)); + } + + keywords[i] = "dbname"; + values[i] = "replication"; + i++; + keywords[i] = "replication"; + values[i] = "true"; + i++; + keywords[i] = "fallback_application_name"; + values[i] = progname; + i++; - if (dbhost) - argcount++; - if (dbuser) - argcount++; - if (dbport) - argcount++; - - keywords = pg_malloc0((argcount + 1) * sizeof(*keywords)); - values = pg_malloc0((argcount + 1) * sizeof(*values)); - - keywords[0] = "dbname"; - values[0] = "replication"; - keywords[1] = "replication"; - values[1] = "true"; - keywords[2] = "fallback_application_name"; - values[2] = progname; - i = 3; if (dbhost) { keywords[i] = "host"; @@ -90,15 +127,15 @@ GetConnection(void) * meaning this is the call for a second session to the same * database, so just forcibly reuse that password. */ - keywords[argcount - 1] = "password"; - values[argcount - 1] = dbpassword; + keywords[i] = "password"; + values[i] = dbpassword; dbgetpassword = -1; /* Don't try again if this fails */ } else if (dbgetpassword == 1) { password = simple_prompt(_("Password: "), 100, false); - keywords[argcount - 1] = "password"; - values[argcount - 1] = password; + keywords[i] = "password"; + values[i] = password; } tmpconn = PQconnectdbParams(keywords, values, true); @@ -130,12 +167,16 @@ GetConnection(void) PQfinish(tmpconn); free(values); free(keywords); + if (conn_opts) + PQconninfoFree(conn_opts); return NULL; } /* Connection ok! */ free(values); free(keywords); + if (conn_opts) + PQconninfoFree(conn_opts); /* * Ensure we have the same value of integer timestamps as the server diff --git a/src/bin/pg_basebackup/streamutil.h b/src/bin/pg_basebackup/streamutil.h index 4f5ff914e23fd807cfaa461f0b5905a029429a5b..77d6b86ced3c4aed719f76d14654dfb12442e7d6 100644 --- a/src/bin/pg_basebackup/streamutil.h +++ b/src/bin/pg_basebackup/streamutil.h @@ -1,6 +1,7 @@ #include "libpq-fe.h" extern const char *progname; +extern char *connection_string; extern char *dbhost; extern char *dbuser; extern char *dbport;