Add -d option to pg_basebackup and pg_receivexlog, for connection string.
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>
Mon, 25 Feb 2013 12:48:27 +0000 (14:48 +0200)
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>
Mon, 25 Feb 2013 12:59:33 +0000 (14:59 +0200)
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
doc/src/sgml/ref/pg_receivexlog.sgml
src/bin/pg_basebackup/pg_basebackup.c
src/bin/pg_basebackup/pg_receivexlog.c
src/bin/pg_basebackup/streamutil.c
src/bin/pg_basebackup/streamutil.h

index 2f89f2c322efccbd5c04d3508800932544b09275..9906b0c6d5533a125b82ca72a9d1a81982937a7b 100644 (file)
@@ -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>
index d06dd1f171c6ec3c8f2b524166b3f08ee8b0b2e2..ec9afad1974d153a79fca1305393a1f24a269ea5 100644 (file)
@@ -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>
index fb5a1bd1c199035b4d75295aa63b8743960926f0..2de03acabd6fe997be1b51d4f81ce33f81998eab 100644 (file)
@@ -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;
index 33dbc50389b86d3cb3e467bcda8cc458d7d06911..352ff3537688caddacfc5e68c8ec890cc83d78ca 100644 (file)
@@ -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;
index 8a43c4bad1dd3a33230634132a8abec4e746afa2..a878dd4345168b67763f54d12916d6271b972dbb 100644 (file)
@@ -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
index 4f5ff914e23fd807cfaa461f0b5905a029429a5b..77d6b86ced3c4aed719f76d14654dfb12442e7d6 100644 (file)
@@ -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;