Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1kLXch-000701-1U for pgsql-bugs@arkaria.postgresql.org; Thu, 24 Sep 2020 20:13:47 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.92) (envelope-from ) id 1kLXcA-0004EC-I1 for pgsql-bugs@arkaria.postgresql.org; Thu, 24 Sep 2020 20:13:14 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1kLXcA-0004BF-3H for pgsql-bugs@lists.postgresql.org; Thu, 24 Sep 2020 20:13:14 +0000 Received: from sss.pgh.pa.us ([66.207.139.130]) by makus.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1kLXc7-000164-8D for pgsql-bugs@lists.postgresql.org; Thu, 24 Sep 2020 20:13:13 +0000 Received: from sss1.sss.pgh.pa.us (localhost [127.0.0.1]) by sss.pgh.pa.us (8.15.2/8.15.2) with ESMTP id 08OKD8U71732345; Thu, 24 Sep 2020 16:13:08 -0400 From: Tom Lane To: Zsolt Ero cc: Magnus Hagander , PostgreSQL mailing lists , Daniel Gustafsson Subject: Re: BUG #16604: pg_dump with --jobs breaks SSL connections In-reply-to: <1664516.1600969345@sss.pgh.pa.us> References: <16604-933f4b8791227b15@postgresql.org> <61B1FFD2-EA7B-4C62-92A1-44C5459189C0@yesql.se> <1638874.1600963896@sss.pgh.pa.us> <1663666.1600968283@sss.pgh.pa.us> <1664516.1600969345@sss.pgh.pa.us> Comments: In-reply-to Tom Lane message dated "Thu, 24 Sep 2020 13:42:25 -0400" MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="----- =_aaaaaaaaaa0" Content-ID: <1732321.1600978351.0@sss.pgh.pa.us> Date: Thu, 24 Sep 2020 16:13:08 -0400 Message-ID: <1732344.1600978388@sss.pgh.pa.us> List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Precedence: bulk ------- =_aaaaaaaaaa0 Content-Type: text/plain; charset="us-ascii" Content-ID: <1732321.1600978351.1@sss.pgh.pa.us> I wrote: > I'm inclined to think that > we should get rid of _connectDB, because it seems unnecessarily > duplicative with ConnectDatabase. But we'll need a bit more > API refactoring than what I had. New patch coming ... A bit of refactoring later, I have the attached, which seems to clean up all cases. I got rid of some bits of dead code along the way. regards, tom lane ------- =_aaaaaaaaaa0 Content-Type: text/x-diff; name="fix-parallel-pg-dump-with-dbname-connstring-2.patch"; charset="us-ascii" Content-ID: <1732321.1600978351.2@sss.pgh.pa.us> Content-Description: fix-parallel-pg-dump-with-dbname-connstring-2.patch Content-Transfer-Encoding: quoted-printable diff --git a/src/bin/pg_dump/pg_backup.h b/src/bin/pg_dump/pg_backup.h index 1017abbbe5..a6a8e6f2fd 100644 --- a/src/bin/pg_dump/pg_backup.h +++ b/src/bin/pg_dump/pg_backup.h @@ -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 */ @@ -107,12 +121,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 @@ -127,10 +138,7 @@ typedef struct _restoreOptions = typedef struct _dumpOptions { - const char *dbname; /* subject to expand_dbname */ - const char *pghost; - const char *pgport; - const char *username; + ConnParams cparams; = int binary_upgrade; = @@ -247,12 +255,9 @@ typedef void (*SetupWorkerPtrType) (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); = diff --git a/src/bin/pg_dump/pg_backup_archiver.c b/src/bin/pg_dump/pg_bac= kup_archiver.c index 3567e9f365..d61b290d2a 100644 --- a/src/bin/pg_dump/pg_backup_archiver.c +++ b/src/bin/pg_dump/pg_backup_archiver.c @@ -165,6 +165,7 @@ InitDumpOptions(DumpOptions *opts) memset(opts, 0, sizeof(DumpOptions)); /* set any fields that shouldn't default to zeroes */ opts->include_everything =3D true; + opts->cparams.promptPassword =3D TRI_DEFAULT; opts->dumpSections =3D DUMP_UNSECTIONED; } = @@ -178,6 +179,11 @@ dumpOptionsFromRestoreOptions(RestoreOptions *ropt) DumpOptions *dopt =3D NewDumpOptions(); = /* this is the inverse of what's at the end of pg_dump.c's main() */ + dopt->cparams.dbname =3D ropt->cparams.dbname ? pg_strdup(ropt->cparams.= dbname) : NULL; + dopt->cparams.pgport =3D ropt->cparams.pgport ? pg_strdup(ropt->cparams.= pgport) : NULL; + dopt->cparams.pghost =3D ropt->cparams.pghost ? pg_strdup(ropt->cparams.= pghost) : NULL; + dopt->cparams.username =3D ropt->cparams.username ? pg_strdup(ropt->cpar= ams.username) : NULL; + dopt->cparams.promptPassword =3D ropt->cparams.promptPassword; dopt->outputClean =3D ropt->dropSchema; dopt->dataOnly =3D ropt->dataOnly; dopt->schemaOnly =3D ropt->schemaOnly; @@ -410,9 +416,7 @@ RestoreArchive(Archive *AHX) AHX->minRemoteVersion =3D 0; AHX->maxRemoteVersion =3D 9999999; = - 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 @@ -832,16 +836,8 @@ restore_toc_entry(ArchiveHandle *AH, TocEntry *te, bo= ol is_parallel) if (strcmp(te->desc, "DATABASE") =3D=3D 0 || strcmp(te->desc, "DATABASE PROPERTIES") =3D=3D 0) { - PQExpBufferData connstr; - - initPQExpBuffer(&connstr); - appendPQExpBufferStr(&connstr, "dbname=3D"); - appendConnStrVal(&connstr, te->tag); - /* Abandon struct, but keep its buffer until process exit. */ - pg_log_info("connecting to new database \"%s\"", te->tag); _reconnectToDB(AH, te->tag); - ropt->dbname =3D connstr.data; } } = @@ -973,7 +969,7 @@ NewRestoreOptions(void) = /* set any fields that shouldn't default to zeroes */ opts->format =3D archUnknown; - opts->promptPassword =3D TRI_DEFAULT; + opts->cparams.promptPassword =3D TRI_DEFAULT; opts->dumpSections =3D DUMP_UNSECTIONED; = return opts; @@ -2345,8 +2341,6 @@ _allocAH(const char *FileSpec, const ArchiveFormat f= mt, else AH->format =3D fmt; = - AH->promptPassword =3D TRI_DEFAULT; - switch (AH->format) { case archCustom: @@ -3207,27 +3201,20 @@ _doSetSessionAuth(ArchiveHandle *AH, const char *u= ser) * 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); } = /* @@ -4159,9 +4146,7 @@ restore_toc_entries_postfork(ArchiveHandle *AH, TocE= ntry *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); @@ -4823,54 +4808,15 @@ CloneArchive(ArchiveHandle *AH) clone->public.n_errors =3D 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 connecti= on + * parameters used for the original connection. */ - if (AH->mode =3D=3D archModeRead) - { - RestoreOptions *ropt =3D AH->public.ropt; - - Assert(AH->connection =3D=3D 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 =3D=3D archModeRead) _doSetFixedOutputState(clone); - } - else - { - PQExpBufferData connstr; - char *pghost; - char *pgport; - char *username; - - Assert(AH->connection !=3D 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); - appendPQExpBufferStr(&connstr, "dbname=3D"); - appendConnStrVal(&connstr, PQdb(AH->connection)); - pghost =3D PQhost(AH->connection); - pgport =3D PQport(AH->connection); - username =3D 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); diff --git a/src/bin/pg_dump/pg_backup_archiver.h b/src/bin/pg_dump/pg_bac= kup_archiver.h index f9e6b42752..fb8d226d48 100644 --- a/src/bin/pg_dump/pg_backup_archiver.h +++ b/src/bin/pg_dump/pg_backup_archiver.h @@ -303,7 +303,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; @@ -471,7 +470,7 @@ extern void InitArchiveFmt_Tar(ArchiveHandle *AH); = extern bool isValidTarHeader(char *header); = -extern void ReconnectToServer(ArchiveHandle *AH, const char *dbname, cons= t 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); diff --git a/src/bin/pg_dump/pg_backup_db.c b/src/bin/pg_dump/pg_backup_db= .c index 12899e26e2..5ba43441f5 100644 --- a/src/bin/pg_dump/pg_backup_db.c +++ b/src/bin/pg_dump/pg_backup_db.c @@ -27,7 +27,6 @@ #include "pg_backup_utils.h" = 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 @@ -73,211 +72,100 @@ _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. + * else the one associated with the archive handle. */ void -ReconnectToServer(ArchiveHandle *AH, const char *dbname, const char *user= name) +ReconnectToServer(ArchiveHandle *AH, const char *dbname) { - PGconn *newConn; - const char *newdbname; - const char *newusername; - - if (!dbname) - newdbname =3D PQdb(AH->connection); - else - newdbname =3D dbname; - - if (!username) - newusername =3D PQuser(AH->connection); - else - newusername =3D username; - - newConn =3D _connectDB(AH, newdbname, newusername); - - /* Update ArchiveHandle's connCancel before closing old connection */ - set_archive_cancel_info(AH, newConn); - - PQfinish(AH->connection); - AH->connection =3D newConn; - - /* Start strict; later phases may override this. */ - PQclear(ExecuteSqlQueryForSingleRow((Archive *) AH, - ALWAYS_SECURE_SEARCH_PATH_SQL)); -} - -/* - * 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. - */ -static PGconn * -_connectDB(ArchiveHandle *AH, const char *reqdb, const char *requser) -{ - PQExpBufferData connstr; - PGconn *newConn; - const char *newdb; - const char *newuser; - char *password; - bool new_pass; - - if (!reqdb) - newdb =3D PQdb(AH->connection); - else - newdb =3D reqdb; - - if (!requser || strlen(requser) =3D=3D 0) - newuser =3D PQuser(AH->connection); - else - newuser =3D requser; - - pg_log_info("connecting to database \"%s\" as user \"%s\"", - newdb, newuser); - - password =3D AH->savedPassword; - - if (AH->promptPassword =3D=3D TRI_YES && password =3D=3D NULL) - password =3D simple_prompt("Password: ", false); - - initPQExpBuffer(&connstr); - appendPQExpBufferStr(&connstr, "dbname=3D"); - appendConnStrVal(&connstr, newdb); - - do - { - const char *keywords[7]; - const char *values[7]; - - keywords[0] =3D "host"; - values[0] =3D PQhost(AH->connection); - keywords[1] =3D "port"; - values[1] =3D PQport(AH->connection); - keywords[2] =3D "user"; - values[2] =3D newuser; - keywords[3] =3D "password"; - values[3] =3D password; - keywords[4] =3D "dbname"; - values[4] =3D connstr.data; - keywords[5] =3D "fallback_application_name"; - values[5] =3D progname; - keywords[6] =3D NULL; - values[6] =3D NULL; - - new_pass =3D false; - newConn =3D PQconnectdbParams(keywords, values, true); - - if (!newConn) - fatal("could not reconnect to database"); - - if (PQstatus(newConn) =3D=3D CONNECTION_BAD) - { - if (!PQconnectionNeedsPassword(newConn)) - fatal("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 (AH->promptPassword !=3D TRI_NO) - { - if (password && password !=3D AH->savedPassword) - free(password); - password =3D simple_prompt("Password: ", false); - } - else - fatal("connection needs password"); - - new_pass =3D true; - } - } while (new_pass); - - if (password && password !=3D AH->savedPassword) - free(password); + PGconn *oldConn =3D AH->connection; + RestoreOptions *ropt =3D AH->public.ropt; = /* - * We want to remember connection's actual password, whether or not we g= ot - * 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 =3D pg_strdup(PQpass(newConn)); - } - - termPQExpBuffer(&connstr); + if (dbname) + ropt->cparams.override_dbname =3D pg_strdup(dbname); = - /* check for version mismatch */ - _check_database_version(AH); + /* + * Note: we want to establish the new connection, and in particular upda= te + * ArchiveHandle's connCancel, before closing old connection. Otherwise + * an ill-timed SIGINT could try to access a dead connection. + */ + AH->connection =3D 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 =3D (ArchiveHandle *) AHX; + trivalue prompt_password; char *password; bool new_pass; = if (AH->connection) fatal("already connected to a database"); = + /* Never prompt for a password during a reconnection */ + prompt_password =3D isReconnect ? TRI_NO : cparams->promptPassword; + password =3D AH->savedPassword; = if (prompt_password =3D=3D TRI_YES && password =3D=3D NULL) password =3D simple_prompt("Password: ", false); = - AH->promptPassword =3D prompt_password; - /* * Start the connection. Loop until we have a password if requested by * backend. */ do { - const char *keywords[7]; - const char *values[7]; - - keywords[0] =3D "host"; - values[0] =3D pghost; - keywords[1] =3D "port"; - values[1] =3D pgport; - keywords[2] =3D "user"; - values[2] =3D username; - keywords[3] =3D "password"; - values[3] =3D password; - keywords[4] =3D "dbname"; - values[4] =3D dbname; - keywords[5] =3D "fallback_application_name"; - values[5] =3D progname; - keywords[6] =3D NULL; - values[6] =3D NULL; + const char *keywords[8]; + const char *values[8]; + int i =3D 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] =3D "host"; + values[i++] =3D cparams->pghost; + keywords[i] =3D "port"; + values[i++] =3D cparams->pgport; + keywords[i] =3D "user"; + values[i++] =3D cparams->username; + keywords[i] =3D "password"; + values[i++] =3D password; + keywords[i] =3D "dbname"; + values[i++] =3D cparams->dbname; + if (cparams->override_dbname) + { + keywords[i] =3D "dbname"; + values[i++] =3D cparams->override_dbname; + } + keywords[i] =3D "fallback_application_name"; + values[i++] =3D progname; + keywords[i] =3D NULL; + values[i++] =3D NULL; + Assert(i <=3D lengthof(keywords)); = new_pass =3D false; AH->connection =3D PQconnectdbParams(keywords, values, true); @@ -298,9 +186,16 @@ ConnectDatabase(Archive *AHX, = /* check to see that the backend connection was successfully made */ if (PQstatus(AH->connection) =3D=3D CONNECTION_BAD) - fatal("connection to database \"%s\" failed: %s", - PQdb(AH->connection) ? PQdb(AH->connection) : "", - PQerrorMessage(AH->connection)); + { + if (isReconnect) + fatal("reconnection to database \"%s\" failed: %s", + PQdb(AH->connection) ? PQdb(AH->connection) : "", + PQerrorMessage(AH->connection)); + else + fatal("connection to database \"%s\" failed: %s", + PQdb(AH->connection) ? PQdb(AH->connection) : "", + PQerrorMessage(AH->connection)); + } = /* Start strict; later phases may override this. */ PQclear(ExecuteSqlQueryForSingleRow((Archive *) AH, diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index f021bb72f4..76320468ba 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -314,7 +314,6 @@ main(int argc, char **argv) char *use_role =3D NULL; long rowsPerInsert; int numWorkers =3D 1; - trivalue prompt_password =3D TRI_DEFAULT; int compressLevel =3D -1; int plainText =3D 0; ArchiveFormat archiveFormat =3D archUnknown; @@ -444,7 +443,7 @@ main(int argc, char **argv) break; = case 'd': /* database name */ - dopt.dbname =3D pg_strdup(optarg); + dopt.cparams.dbname =3D pg_strdup(optarg); break; = case 'E': /* Dump encoding */ @@ -460,7 +459,7 @@ main(int argc, char **argv) break; = case 'h': /* server host */ - dopt.pghost =3D pg_strdup(optarg); + dopt.cparams.pghost =3D pg_strdup(optarg); break; = case 'j': /* number of dump jobs */ @@ -481,7 +480,7 @@ main(int argc, char **argv) break; = case 'p': /* server port */ - dopt.pgport =3D pg_strdup(optarg); + dopt.cparams.pgport =3D pg_strdup(optarg); break; = case 'R': @@ -506,7 +505,7 @@ main(int argc, char **argv) break; = case 'U': - dopt.username =3D pg_strdup(optarg); + dopt.cparams.username =3D pg_strdup(optarg); break; = case 'v': /* verbose */ @@ -515,11 +514,11 @@ main(int argc, char **argv) break; = case 'w': - prompt_password =3D TRI_NO; + dopt.cparams.promptPassword =3D TRI_NO; break; = case 'W': - prompt_password =3D TRI_YES; + dopt.cparams.promptPassword =3D TRI_YES; break; = case 'x': /* skip ACL dump */ @@ -613,8 +612,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 =3D=3D NULL) - dopt.dbname =3D argv[optind++]; + if (optind < argc && dopt.cparams.dbname =3D=3D NULL) + dopt.cparams.dbname =3D argv[optind++]; = /* Complain if any arguments remain */ if (optind < argc) @@ -740,7 +739,7 @@ main(int argc, char **argv) * Open the database using the Archiver, so it knows about it. Errors me= an * death. */ - ConnectDatabase(fout, dopt.dbname, dopt.pghost, dopt.pgport, dopt.userna= me, prompt_password); + ConnectDatabase(fout, &dopt.cparams, false); setup_connection(fout, dumpencoding, dumpsnapshot, use_role); = /* @@ -918,6 +917,11 @@ main(int argc, char **argv) ropt->filename =3D filename; = /* if you change this list, see dumpOptionsFromRestoreOptions */ + ropt->cparams.dbname =3D dopt.cparams.dbname ? pg_strdup(dopt.cparams.db= name) : NULL; + ropt->cparams.pgport =3D dopt.cparams.pgport ? pg_strdup(dopt.cparams.pg= port) : NULL; + ropt->cparams.pghost =3D dopt.cparams.pghost ? pg_strdup(dopt.cparams.pg= host) : NULL; + ropt->cparams.username =3D dopt.cparams.username ? pg_strdup(dopt.cparam= s.username) : NULL; + ropt->cparams.promptPassword =3D dopt.cparams.promptPassword; ropt->dropSchema =3D dopt.outputClean; ropt->dataOnly =3D dopt.dataOnly; ropt->schemaOnly =3D dopt.schemaOnly; diff --git a/src/bin/pg_dump/pg_restore.c b/src/bin/pg_dump/pg_restore.c index eebf0d300b..589b4aed53 100644 --- a/src/bin/pg_dump/pg_restore.c +++ b/src/bin/pg_dump/pg_restore.c @@ -163,7 +163,7 @@ main(int argc, char **argv) opts->createDB =3D 1; break; case 'd': - opts->dbname =3D pg_strdup(optarg); + opts->cparams.dbname =3D pg_strdup(optarg); break; case 'e': opts->exit_on_error =3D true; @@ -177,7 +177,7 @@ main(int argc, char **argv) break; case 'h': if (strlen(optarg) !=3D 0) - opts->pghost =3D pg_strdup(optarg); + opts->cparams.pghost =3D pg_strdup(optarg); break; = case 'j': /* number of restore jobs */ @@ -206,7 +206,7 @@ main(int argc, char **argv) = case 'p': if (strlen(optarg) !=3D 0) - opts->pgport =3D pg_strdup(optarg); + opts->cparams.pgport =3D pg_strdup(optarg); break; case 'R': /* no-op, still accepted for backwards compatibility */ @@ -240,7 +240,7 @@ main(int argc, char **argv) break; = case 'U': - opts->username =3D pg_strdup(optarg); + opts->cparams.username =3D pg_strdup(optarg); break; = case 'v': /* verbose */ @@ -249,11 +249,11 @@ main(int argc, char **argv) break; = case 'w': - opts->promptPassword =3D TRI_NO; + opts->cparams.promptPassword =3D TRI_NO; break; = case 'W': - opts->promptPassword =3D TRI_YES; + opts->cparams.promptPassword =3D TRI_YES; break; = case 'x': /* skip ACL dump */ @@ -303,14 +303,14 @@ main(int argc, char **argv) } = /* Complain if neither -f nor -d was specified (except if dumping TOC) *= / - if (!opts->dbname && !opts->filename && !opts->tocSummary) + if (!opts->cparams.dbname && !opts->filename && !opts->tocSummary) { pg_log_error("one of -d/--dbname and -f/--file must be specified"); exit_nicely(1); } = /* Should get at most one of -d and -f, else user is confused */ - if (opts->dbname) + if (opts->cparams.dbname) { if (opts->filename) { ------- =_aaaaaaaaaa0--