Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Fix handling of -d "connection string" in pg_dump/pg_restore.
authorTom Lane <tgl@sss.pgh.pa.us>
Thu, 24 Sep 2020 22:19:39 +0000 (18:19 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Thu, 24 Sep 2020 22:19:39 +0000 (18:19 -0400)
Parallel pg_dump failed if its -d parameter was a connection string
containing any essential information other than host, port, or username.
The same was true for pg_restore with --create.

The reason is that these scenarios failed to preserve the connection
string from the command line; the code felt free to replace that with
just the database name when reconnecting from a pg_dump parallel worker
or after creating the target database.  By chance, parallel pg_restore
did not suffer this defect, as long as you didn't say --create.

In practice it seems that the error would be obvious only if the
connstring included essential, non-default SSL or GSS parameters.
This may explain why it took us so long to notice.  (It also makes
it very difficult to craft a regression test case illustrating the
problem, since the test would fail in builds without those options.)

Fix by refactoring so that ConnectDatabase always receives all the
relevant options directly from the command line, rather than
reconstructed values.  Inject a different database name, when necessary,
by relying on libpq's rules for handling multiple "dbname" parameters.

While here, let's get rid of the essentially duplicate _connectDB
function, as well as some obsolete nearby cruft.

Per bug #16604 from Zsolt Ero.  Back-patch to all supported branches.

Discussion: https://postgr.es/m/16604-933f4b8791227b15@postgresql.org

src/bin/pg_dump/pg_backup.h
src/bin/pg_dump/pg_backup_archiver.c
src/bin/pg_dump/pg_backup_archiver.h
src/bin/pg_dump/pg_backup_db.c
src/bin/pg_dump/pg_dump.c
src/bin/pg_dump/pg_restore.c

index 625557096dff61e131271bcb56f660e401156c4b..cbd7541577d215182412ccf5cee495bdd5fae792 100644 (file)
@@ -58,6 +58,20 @@ typedef enum _teSection
    SECTION_POST_DATA           /* stuff to be processed after data */
 } teSection;
 
+/* Parameters needed by ConnectDatabase; same for dump and restore */
+typedef struct _connParams
+{
+   /* These fields record the actual command line parameters */
+   char       *dbname;         /* this may be a connstring! */
+   char       *pgport;
+   char       *pghost;
+   char       *username;
+   trivalue    promptPassword;
+   /* If not NULL, this overrides the dbname obtained from command line */
+   /* (but *only* the DB name, not anything else in the connstring) */
+   char       *override_dbname;
+} ConnParams;
+
 typedef struct _restoreOptions
 {
    int         createDB;       /* Issue commands to create the database */
@@ -103,12 +117,9 @@ typedef struct _restoreOptions
    SimpleStringList tableNames;
 
    int         useDB;
-   char       *dbname;         /* subject to expand_dbname */
-   char       *pgport;
-   char       *pghost;
-   char       *username;
+   ConnParams  cparams;        /* parameters to use if useDB */
+
    int         noDataForFailedTables;
-   trivalue    promptPassword;
    int         exit_on_error;
    int         compression;
    int         suppressDumpWarnings;   /* Suppress output of WARNING entries
@@ -122,10 +133,8 @@ typedef struct _restoreOptions
 
 typedef struct _dumpOptions
 {
-   const char *dbname;         /* subject to expand_dbname */
-   const char *pghost;
-   const char *pgport;
-   const char *username;
+   ConnParams  cparams;
+
    bool        oids;
 
    int         binary_upgrade;
@@ -237,12 +246,9 @@ typedef void (*SetupWorkerPtr) (Archive *AH);
  * Main archiver interface.
  */
 
-extern void ConnectDatabase(Archive *AH,
-               const char *dbname,
-               const char *pghost,
-               const char *pgport,
-               const char *username,
-               trivalue prompt_password);
+extern void ConnectDatabase(Archive *AHX,
+                           const ConnParams *cparams,
+                           bool isReconnect);
 extern void DisconnectDatabase(Archive *AHX);
 extern PGconn *GetConnection(Archive *AHX);
 
index 48a1ac1a26155b39e175a9a097f96b172a1b3d34..04cf40b43691baa71a469111738b119d1d8ffc69 100644 (file)
@@ -140,6 +140,7 @@ InitDumpOptions(DumpOptions *opts)
    memset(opts, 0, sizeof(DumpOptions));
    /* set any fields that shouldn't default to zeroes */
    opts->include_everything = true;
+   opts->cparams.promptPassword = TRI_DEFAULT;
    opts->dumpSections = DUMP_UNSECTIONED;
 }
 
@@ -153,6 +154,11 @@ dumpOptionsFromRestoreOptions(RestoreOptions *ropt)
    DumpOptions *dopt = NewDumpOptions();
 
    /* this is the inverse of what's at the end of pg_dump.c's main() */
+   dopt->cparams.dbname = ropt->cparams.dbname ? pg_strdup(ropt->cparams.dbname) : NULL;
+   dopt->cparams.pgport = ropt->cparams.pgport ? pg_strdup(ropt->cparams.pgport) : NULL;
+   dopt->cparams.pghost = ropt->cparams.pghost ? pg_strdup(ropt->cparams.pghost) : NULL;
+   dopt->cparams.username = ropt->cparams.username ? pg_strdup(ropt->cparams.username) : NULL;
+   dopt->cparams.promptPassword = ropt->cparams.promptPassword;
    dopt->outputClean = ropt->dropSchema;
    dopt->dataOnly = ropt->dataOnly;
    dopt->schemaOnly = ropt->schemaOnly;
@@ -392,9 +398,7 @@ RestoreArchive(Archive *AHX)
        AHX->minRemoteVersion = 0;
        AHX->maxRemoteVersion = 999999;
 
-       ConnectDatabase(AHX, ropt->dbname,
-                       ropt->pghost, ropt->pgport, ropt->username,
-                       ropt->promptPassword);
+       ConnectDatabase(AHX, &ropt->cparams, false);
 
        /*
         * If we're talking to the DB directly, don't send comments since they
@@ -814,16 +818,8 @@ restore_toc_entry(ArchiveHandle *AH, TocEntry *te, bool is_parallel)
        /* If we created a DB, connect to it... */
        if (strcmp(te->desc, "DATABASE") == 0)
        {
-           PQExpBufferData connstr;
-
-           initPQExpBuffer(&connstr);
-           appendPQExpBufferStr(&connstr, "dbname=");
-           appendConnStrVal(&connstr, te->tag);
-           /* Abandon struct, but keep its buffer until process exit. */
-
            ahlog(AH, 1, "connecting to new database \"%s\"\n", te->tag);
            _reconnectToDB(AH, te->tag);
-           ropt->dbname = connstr.data;
        }
    }
 
@@ -957,7 +953,7 @@ NewRestoreOptions(void)
 
    /* set any fields that shouldn't default to zeroes */
    opts->format = archUnknown;
-   opts->promptPassword = TRI_DEFAULT;
+   opts->cparams.promptPassword = TRI_DEFAULT;
    opts->dumpSections = DUMP_UNSECTIONED;
 
    return opts;
@@ -2389,8 +2385,6 @@ _allocAH(const char *FileSpec, const ArchiveFormat fmt,
    else
        AH->format = fmt;
 
-   AH->promptPassword = TRI_DEFAULT;
-
    switch (AH->format)
    {
        case archCustom:
@@ -3135,27 +3129,20 @@ _doSetWithOids(ArchiveHandle *AH, const bool withOids)
  * If we're currently restoring right into a database, this will
  * actually establish a connection. Otherwise it puts a \connect into
  * the script output.
- *
- * NULL dbname implies reconnecting to the current DB (pretty useless).
  */
 static void
 _reconnectToDB(ArchiveHandle *AH, const char *dbname)
 {
    if (RestoringToDB(AH))
-       ReconnectToServer(AH, dbname, NULL);
+       ReconnectToServer(AH, dbname);
    else
    {
-       if (dbname)
-       {
-           PQExpBufferData connectbuf;
+       PQExpBufferData connectbuf;
 
-           initPQExpBuffer(&connectbuf);
-           appendPsqlMetaConnect(&connectbuf, dbname);
-           ahprintf(AH, "%s\n", connectbuf.data);
-           termPQExpBuffer(&connectbuf);
-       }
-       else
-           ahprintf(AH, "%s\n", "\\connect -\n");
+       initPQExpBuffer(&connectbuf);
+       appendPsqlMetaConnect(&connectbuf, dbname);
+       ahprintf(AH, "%s\n", connectbuf.data);
+       termPQExpBuffer(&connectbuf);
    }
 
    /*
@@ -4102,9 +4089,7 @@ restore_toc_entries_postfork(ArchiveHandle *AH, TocEntry *pending_list)
    /*
     * Now reconnect the single parent connection.
     */
-   ConnectDatabase((Archive *) AH, ropt->dbname,
-                   ropt->pghost, ropt->pgport, ropt->username,
-                   ropt->promptPassword);
+   ConnectDatabase((Archive *) AH, &ropt->cparams, true);
 
    /* re-establish fixed state */
    _doSetFixedOutputState(AH);
@@ -4697,54 +4682,15 @@ CloneArchive(ArchiveHandle *AH)
    clone->public.n_errors = 0;
 
    /*
-    * Connect our new clone object to the database: In parallel restore the
-    * parent is already disconnected, because we can connect the worker
-    * processes independently to the database (no snapshot sync required). In
-    * parallel backup we clone the parent's existing connection.
+    * Connect our new clone object to the database, using the same connection
+    * parameters used for the original connection.
     */
-   if (AH->mode == archModeRead)
-   {
-       RestoreOptions *ropt = AH->public.ropt;
-
-       Assert(AH->connection == NULL);
-
-       /* this also sets clone->connection */
-       ConnectDatabase((Archive *) clone, ropt->dbname,
-                       ropt->pghost, ropt->pgport, ropt->username,
-                       ropt->promptPassword);
+   ConnectDatabase((Archive *) clone, &clone->public.ropt->cparams, true);
 
-       /* re-establish fixed state */
+   /* re-establish fixed state */
+   if (AH->mode == archModeRead)
        _doSetFixedOutputState(clone);
-   }
-   else
-   {
-       PQExpBufferData connstr;
-       char       *pghost;
-       char       *pgport;
-       char       *username;
-
-       Assert(AH->connection != NULL);
-
-       /*
-        * Even though we are technically accessing the parent's database
-        * object here, these functions are fine to be called like that
-        * because all just return a pointer and do not actually send/receive
-        * any data to/from the database.
-        */
-       initPQExpBuffer(&connstr);
-       appendPQExpBuffer(&connstr, "dbname=");
-       appendConnStrVal(&connstr, PQdb(AH->connection));
-       pghost = PQhost(AH->connection);
-       pgport = PQport(AH->connection);
-       username = PQuser(AH->connection);
-
-       /* this also sets clone->connection */
-       ConnectDatabase((Archive *) clone, connstr.data,
-                       pghost, pgport, username, TRI_NO);
-
-       termPQExpBuffer(&connstr);
-       /* setupDumpWorker will fix up connection state */
-   }
+   /* in write case, setupDumpWorker will fix up connection state */
 
    /* Let the format-specific code have a chance too */
    (clone->ClonePtr) (clone);
index 79942abb310156319a1ee8b0ba3e662e06e9f2e4..ef98744d1def96f248d73e875efba8aa52900c54 100644 (file)
@@ -311,7 +311,6 @@ struct _archiveHandle
 
    /* Stuff for direct DB connection */
    char       *archdbname;     /* DB name *read* from archive */
-   trivalue    promptPassword;
    char       *savedPassword;  /* password for ropt->username, if known */
    char       *use_role;
    PGconn     *connection;
@@ -456,7 +455,7 @@ extern void InitArchiveFmt_Tar(ArchiveHandle *AH);
 
 extern bool isValidTarHeader(char *header);
 
-extern int ReconnectToServer(ArchiveHandle *AH, const char *dbname, const char *newUser);
+extern void ReconnectToServer(ArchiveHandle *AH, const char *dbname);
 extern void DropBlobIfExists(ArchiveHandle *AH, Oid oid);
 
 void       ahwrite(const void *ptr, size_t size, size_t nmemb, ArchiveHandle *AH);
index ed0ace814443b0a8b63970aa9a3e8c6d7087cc1c..944d68a53c8d8f581e0eddf4c1332005df564ebb 100644 (file)
@@ -32,7 +32,6 @@
 static const char *modulename = gettext_noop("archiver (db)");
 
 static void _check_database_version(ArchiveHandle *AH);
-static PGconn *_connectDB(ArchiveHandle *AH, const char *newdbname, const char *newUser);
 static void notice_processor(void *arg, const char *message);
 
 static void
@@ -78,197 +77,60 @@ _check_database_version(ArchiveHandle *AH)
 
 /*
  * Reconnect to the server.  If dbname is not NULL, use that database,
- * else the one associated with the archive handle.  If username is
- * not NULL, use that user name, else the one from the handle.  If
- * both the database and the user match the existing connection already,
- * nothing will be done.
- *
- * Returns 1 in any case.
- */
-int
-ReconnectToServer(ArchiveHandle *AH, const char *dbname, const char *username)
-{
-   PGconn     *newConn;
-   const char *newdbname;
-   const char *newusername;
-
-   if (!dbname)
-       newdbname = PQdb(AH->connection);
-   else
-       newdbname = dbname;
-
-   if (!username)
-       newusername = PQuser(AH->connection);
-   else
-       newusername = username;
-
-   /* Let's see if the request is already satisfied */
-   if (strcmp(newdbname, PQdb(AH->connection)) == 0 &&
-       strcmp(newusername, PQuser(AH->connection)) == 0)
-       return 1;
-
-   newConn = _connectDB(AH, newdbname, newusername);
-
-   /* Update ArchiveHandle's connCancel before closing old connection */
-   set_archive_cancel_info(AH, newConn);
-
-   PQfinish(AH->connection);
-   AH->connection = newConn;
-
-   /* Start strict; later phases may override this. */
-   if (PQserverVersion(AH->connection) >= 70300)
-       PQclear(ExecuteSqlQueryForSingleRow((Archive *) AH,
-                                           ALWAYS_SECURE_SEARCH_PATH_SQL));
-
-   return 1;
-}
-
-/*
- * Connect to the db again.
- *
- * Note: it's not really all that sensible to use a single-entry password
- * cache if the username keeps changing.  In current usage, however, the
- * username never does change, so one savedPassword is sufficient.  We do
- * update the cache on the off chance that the password has changed since the
- * start of the run.
+ * else the one associated with the archive handle.
  */
-static PGconn *
-_connectDB(ArchiveHandle *AH, const char *reqdb, const char *requser)
+void
+ReconnectToServer(ArchiveHandle *AH, const char *dbname)
 {
-   PQExpBufferData connstr;
-   PGconn     *newConn;
-   const char *newdb;
-   const char *newuser;
-   char       *password;
-   bool        new_pass;
-
-   if (!reqdb)
-       newdb = PQdb(AH->connection);
-   else
-       newdb = reqdb;
-
-   if (!requser || strlen(requser) == 0)
-       newuser = PQuser(AH->connection);
-   else
-       newuser = requser;
-
-   ahlog(AH, 1, "connecting to database \"%s\" as user \"%s\"\n",
-         newdb, newuser);
-
-   password = AH->savedPassword ? pg_strdup(AH->savedPassword) : NULL;
-
-   if (AH->promptPassword == TRI_YES && password == NULL)
-   {
-       password = simple_prompt("Password: ", 100, false);
-       if (password == NULL)
-           exit_horribly(modulename, "out of memory\n");
-   }
-
-   initPQExpBuffer(&connstr);
-   appendPQExpBuffer(&connstr, "dbname=");
-   appendConnStrVal(&connstr, newdb);
-
-   do
-   {
-       const char *keywords[7];
-       const char *values[7];
-
-       keywords[0] = "host";
-       values[0] = PQhost(AH->connection);
-       keywords[1] = "port";
-       values[1] = PQport(AH->connection);
-       keywords[2] = "user";
-       values[2] = newuser;
-       keywords[3] = "password";
-       values[3] = password;
-       keywords[4] = "dbname";
-       values[4] = connstr.data;
-       keywords[5] = "fallback_application_name";
-       values[5] = progname;
-       keywords[6] = NULL;
-       values[6] = NULL;
-
-       new_pass = false;
-       newConn = PQconnectdbParams(keywords, values, true);
-
-       if (!newConn)
-           exit_horribly(modulename, "failed to reconnect to database\n");
-
-       if (PQstatus(newConn) == CONNECTION_BAD)
-       {
-           if (!PQconnectionNeedsPassword(newConn))
-               exit_horribly(modulename, "could not reconnect to database: %s",
-                             PQerrorMessage(newConn));
-           PQfinish(newConn);
-
-           if (password)
-               fprintf(stderr, "Password incorrect\n");
-
-           fprintf(stderr, "Connecting to %s as %s\n",
-                   newdb, newuser);
-
-           if (password)
-               free(password);
-
-           if (AH->promptPassword != TRI_NO)
-               password = simple_prompt("Password: ", 100, false);
-           else
-               exit_horribly(modulename, "connection needs password\n");
-
-           if (password == NULL)
-               exit_horribly(modulename, "out of memory\n");
-           new_pass = true;
-       }
-   } while (new_pass);
+   PGconn     *oldConn = AH->connection;
+   RestoreOptions *ropt = AH->public.ropt;
 
    /*
-    * We want to remember connection's actual password, whether or not we got
-    * it by prompting.  So we don't just store the password variable.
+    * Save the dbname, if given, in override_dbname so that it will also
+    * affect any later reconnection attempt.
     */
-   if (PQconnectionUsedPassword(newConn))
-   {
-       if (AH->savedPassword)
-           free(AH->savedPassword);
-       AH->savedPassword = pg_strdup(PQpass(newConn));
-   }
-   if (password)
-       free(password);
-
-   termPQExpBuffer(&connstr);
+   if (dbname)
+       ropt->cparams.override_dbname = pg_strdup(dbname);
 
-   /* check for version mismatch */
-   _check_database_version(AH);
+   /*
+    * Note: we want to establish the new connection, and in particular update
+    * ArchiveHandle's connCancel, before closing old connection.  Otherwise
+    * an ill-timed SIGINT could try to access a dead connection.
+    */
+   AH->connection = NULL;      /* dodge error check in ConnectDatabase */
 
-   PQsetNoticeProcessor(newConn, notice_processor, NULL);
+   ConnectDatabase((Archive *) AH, &ropt->cparams, true);
 
-   return newConn;
+   PQfinish(oldConn);
 }
 
-
 /*
- * Make a database connection with the given parameters.  The
- * connection handle is returned, the parameters are stored in AHX.
- * An interactive password prompt is automatically issued if required.
+ * Make, or remake, a database connection with the given parameters.
  *
+ * The resulting connection handle is stored in AHX->connection.
+ *
+ * An interactive password prompt is automatically issued if required.
+ * We store the results of that in AHX->savedPassword.
  * Note: it's not really all that sensible to use a single-entry password
  * cache if the username keeps changing.  In current usage, however, the
  * username never does change, so one savedPassword is sufficient.
  */
 void
 ConnectDatabase(Archive *AHX,
-               const char *dbname,
-               const char *pghost,
-               const char *pgport,
-               const char *username,
-               trivalue prompt_password)
+               const ConnParams *cparams,
+               bool isReconnect)
 {
    ArchiveHandle *AH = (ArchiveHandle *) AHX;
+   trivalue    prompt_password;
    char       *password;
    bool        new_pass;
 
    if (AH->connection)
        exit_horribly(modulename, "already connected to a database\n");
 
+   /* Never prompt for a password during a reconnection */
+   prompt_password = isReconnect ? TRI_NO : cparams->promptPassword;
+
    password = AH->savedPassword ? pg_strdup(AH->savedPassword) : NULL;
 
    if (prompt_password == TRI_YES && password == NULL)
@@ -277,7 +139,6 @@ ConnectDatabase(Archive *AHX,
        if (password == NULL)
            exit_horribly(modulename, "out of memory\n");
    }
-   AH->promptPassword = prompt_password;
 
    /*
     * Start the connection.  Loop until we have a password if requested by
@@ -285,23 +146,35 @@ ConnectDatabase(Archive *AHX,
     */
    do
    {
-       const char *keywords[7];
-       const char *values[7];
-
-       keywords[0] = "host";
-       values[0] = pghost;
-       keywords[1] = "port";
-       values[1] = pgport;
-       keywords[2] = "user";
-       values[2] = username;
-       keywords[3] = "password";
-       values[3] = password;
-       keywords[4] = "dbname";
-       values[4] = dbname;
-       keywords[5] = "fallback_application_name";
-       values[5] = progname;
-       keywords[6] = NULL;
-       values[6] = NULL;
+       const char *keywords[8];
+       const char *values[8];
+       int         i = 0;
+
+       /*
+        * If dbname is a connstring, its entries can override the other
+        * values obtained from cparams; but in turn, override_dbname can
+        * override the dbname component of it.
+        */
+       keywords[i] = "host";
+       values[i++] = cparams->pghost;
+       keywords[i] = "port";
+       values[i++] = cparams->pgport;
+       keywords[i] = "user";
+       values[i++] = cparams->username;
+       keywords[i] = "password";
+       values[i++] = password;
+       keywords[i] = "dbname";
+       values[i++] = cparams->dbname;
+       if (cparams->override_dbname)
+       {
+           keywords[i] = "dbname";
+           values[i++] = cparams->override_dbname;
+       }
+       keywords[i] = "fallback_application_name";
+       values[i++] = progname;
+       keywords[i] = NULL;
+       values[i++] = NULL;
+       Assert(i <= lengthof(keywords));
 
        new_pass = false;
        AH->connection = PQconnectdbParams(keywords, values, true);
@@ -324,9 +197,16 @@ ConnectDatabase(Archive *AHX,
 
    /* check to see that the backend connection was successfully made */
    if (PQstatus(AH->connection) == CONNECTION_BAD)
-       exit_horribly(modulename, "connection to database \"%s\" failed: %s",
-                     PQdb(AH->connection) ? PQdb(AH->connection) : "",
-                     PQerrorMessage(AH->connection));
+   {
+       if (isReconnect)
+           exit_horribly(modulename, "reconnection to database \"%s\" failed: %s",
+                         PQdb(AH->connection) ? PQdb(AH->connection) : "",
+                         PQerrorMessage(AH->connection));
+       else
+           exit_horribly(modulename, "connection to database \"%s\" failed: %s",
+                         PQdb(AH->connection) ? PQdb(AH->connection) : "",
+                         PQerrorMessage(AH->connection));
+   }
 
    /* Start strict; later phases may override this. */
    if (PQserverVersion(AH->connection) >= 70300)
index 42b99abba63bff091dd375e724beef7ec5eb2528..26184f10bf8a197354214973e4848f2b914064c9 100644 (file)
@@ -301,7 +301,6 @@ main(int argc, char **argv)
    const char *dumpsnapshot = NULL;
    char       *use_role = NULL;
    int         numWorkers = 1;
-   trivalue    prompt_password = TRI_DEFAULT;
    int         compressLevel = -1;
    int         plainText = 0;
    ArchiveFormat archiveFormat = archUnknown;
@@ -426,7 +425,7 @@ main(int argc, char **argv)
                break;
 
            case 'd':           /* database name */
-               dopt.dbname = pg_strdup(optarg);
+               dopt.cparams.dbname = pg_strdup(optarg);
                break;
 
            case 'E':           /* Dump encoding */
@@ -442,7 +441,7 @@ main(int argc, char **argv)
                break;
 
            case 'h':           /* server host */
-               dopt.pghost = pg_strdup(optarg);
+               dopt.cparams.pghost = pg_strdup(optarg);
                break;
 
            case 'j':           /* number of dump jobs */
@@ -467,7 +466,7 @@ main(int argc, char **argv)
                break;
 
            case 'p':           /* server port */
-               dopt.pgport = pg_strdup(optarg);
+               dopt.cparams.pgport = pg_strdup(optarg);
                break;
 
            case 'R':
@@ -492,7 +491,7 @@ main(int argc, char **argv)
                break;
 
            case 'U':
-               dopt.username = pg_strdup(optarg);
+               dopt.cparams.username = pg_strdup(optarg);
                break;
 
            case 'v':           /* verbose */
@@ -500,11 +499,11 @@ main(int argc, char **argv)
                break;
 
            case 'w':
-               prompt_password = TRI_NO;
+               dopt.cparams.promptPassword = TRI_NO;
                break;
 
            case 'W':
-               prompt_password = TRI_YES;
+               dopt.cparams.promptPassword = TRI_YES;
                break;
 
            case 'x':           /* skip ACL dump */
@@ -554,8 +553,8 @@ main(int argc, char **argv)
     * Non-option argument specifies database name as long as it wasn't
     * already specified with -d / --dbname
     */
-   if (optind < argc && dopt.dbname == NULL)
-       dopt.dbname = argv[optind++];
+   if (optind < argc && dopt.cparams.dbname == NULL)
+       dopt.cparams.dbname = argv[optind++];
 
    /* Complain if any arguments remain */
    if (optind < argc)
@@ -660,7 +659,7 @@ main(int argc, char **argv)
     * Open the database using the Archiver, so it knows about it. Errors mean
     * death.
     */
-   ConnectDatabase(fout, dopt.dbname, dopt.pghost, dopt.pgport, dopt.username, prompt_password);
+   ConnectDatabase(fout, &dopt.cparams, false);
    setup_connection(fout, dumpencoding, dumpsnapshot, use_role);
 
    /*
@@ -847,6 +846,11 @@ main(int argc, char **argv)
    ropt->filename = filename;
 
    /* if you change this list, see dumpOptionsFromRestoreOptions */
+   ropt->cparams.dbname = dopt.cparams.dbname ? pg_strdup(dopt.cparams.dbname) : NULL;
+   ropt->cparams.pgport = dopt.cparams.pgport ? pg_strdup(dopt.cparams.pgport) : NULL;
+   ropt->cparams.pghost = dopt.cparams.pghost ? pg_strdup(dopt.cparams.pghost) : NULL;
+   ropt->cparams.username = dopt.cparams.username ? pg_strdup(dopt.cparams.username) : NULL;
+   ropt->cparams.promptPassword = dopt.cparams.promptPassword;
    ropt->dropSchema = dopt.outputClean;
    ropt->dataOnly = dopt.dataOnly;
    ropt->schemaOnly = dopt.schemaOnly;
index cf06c484e741c2c0a67f4bfaeeaf4d12d3524f0c..4d3d702334f2eefb19b33bf60b99a58db7fc921e 100644 (file)
@@ -163,7 +163,7 @@ main(int argc, char **argv)
                opts->createDB = 1;
                break;
            case 'd':
-               opts->dbname = pg_strdup(optarg);
+               opts->cparams.dbname = pg_strdup(optarg);
                break;
            case 'e':
                opts->exit_on_error = true;
@@ -177,7 +177,7 @@ main(int argc, char **argv)
                break;
            case 'h':
                if (strlen(optarg) != 0)
-                   opts->pghost = pg_strdup(optarg);
+                   opts->cparams.pghost = pg_strdup(optarg);
                break;
 
            case 'j':           /* number of restore jobs */
@@ -202,7 +202,7 @@ main(int argc, char **argv)
 
            case 'p':
                if (strlen(optarg) != 0)
-                   opts->pgport = pg_strdup(optarg);
+                   opts->cparams.pgport = pg_strdup(optarg);
                break;
            case 'R':
                /* no-op, still accepted for backwards compatibility */
@@ -236,7 +236,7 @@ main(int argc, char **argv)
                break;
 
            case 'U':
-               opts->username = pg_strdup(optarg);
+               opts->cparams.username = pg_strdup(optarg);
                break;
 
            case 'v':           /* verbose */
@@ -244,11 +244,11 @@ main(int argc, char **argv)
                break;
 
            case 'w':
-               opts->promptPassword = TRI_NO;
+               opts->cparams.promptPassword = TRI_NO;
                break;
 
            case 'W':
-               opts->promptPassword = TRI_YES;
+               opts->cparams.promptPassword = TRI_YES;
                break;
 
            case 'x':           /* skip ACL dump */
@@ -298,7 +298,7 @@ main(int argc, char **argv)
    }
 
    /* Should get at most one of -d and -f, else user is confused */
-   if (opts->dbname)
+   if (opts->cparams.dbname)
    {
        if (opts->filename)
        {