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;