From aa05c37e823a41056273e73f6b3d168009a67c3f Mon Sep 17 00:00:00 2001 From: Heikki Linnakangas <heikki.linnakangas@iki.fi> Date: Mon, 25 Feb 2013 14:48:27 +0200 Subject: [PATCH] Add -d option to pg_basebackup and pg_receivexlog, for connection string. Without this, there's no way to pass arbitrary libpq connection parameters to these applications. It's a bit strange that the option is called -d/--dbname, when in fact you can *not* pass a database name in it, but it's consistent with other client applications where a connection string is also passed using -d. Original patch by Amit Kapila, heavily modified by me. --- doc/src/sgml/ref/pg_basebackup.sgml | 17 +++++ doc/src/sgml/ref/pg_receivexlog.sgml | 17 +++++ src/bin/pg_basebackup/pg_basebackup.c | 7 ++- src/bin/pg_basebackup/pg_receivexlog.c | 7 ++- src/bin/pg_basebackup/streamutil.c | 87 +++++++++++++++++++------- src/bin/pg_basebackup/streamutil.h | 1 + 6 files changed, 111 insertions(+), 25 deletions(-) diff --git a/doc/src/sgml/ref/pg_basebackup.sgml b/doc/src/sgml/ref/pg_basebackup.sgml index 2f89f2c322e..9906b0c6d55 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 d06dd1f171c..ec9afad1974 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 fb5a1bd1c19..2de03acabd6 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 33dbc50389b..352ff353768 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 8a43c4bad1d..a878dd43451 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 4f5ff914e23..77d6b86ced3 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; -- GitLab