Move common pg_dump code related to connections to a new file
authorAndrew Dunstan <andrew@dunslane.net>
Fri, 4 Apr 2025 14:04:35 +0000 (10:04 -0400)
committerAndrew Dunstan <andrew@dunslane.net>
Fri, 4 Apr 2025 20:01:22 +0000 (16:01 -0400)
ConnectDatabase is used by pg_dumpall, pg_restore and pg_dump so move
common code to new file.

new file name: connectdb.c

Author:    Mahendra Singh Thalor <mahi6run@gmail.com>

src/bin/pg_dump/Makefile
src/bin/pg_dump/connectdb.c [new file with mode: 0644]
src/bin/pg_dump/connectdb.h [new file with mode: 0644]
src/bin/pg_dump/meson.build
src/bin/pg_dump/pg_backup.h
src/bin/pg_dump/pg_backup_archiver.c
src/bin/pg_dump/pg_backup_db.c
src/bin/pg_dump/pg_dump.c
src/bin/pg_dump/pg_dumpall.c

index 233ad15ca75dc09f0a95852f55554294dfef505a..fa795883e9f30a74f2f308cf4ff483995929c026 100644 (file)
@@ -31,6 +31,7 @@ OBJS = \
    compress_lz4.o \
    compress_none.o \
    compress_zstd.o \
+   connectdb.o \
    dumputils.o \
    filter.o \
    parallel.o \
@@ -50,8 +51,8 @@ pg_dump: pg_dump.o common.o pg_dump_sort.o $(OBJS) | submake-libpq submake-libpg
 pg_restore: pg_restore.o $(OBJS) | submake-libpq submake-libpgport submake-libpgfeutils
    $(CC) $(CFLAGS) pg_restore.o $(OBJS) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X)
 
-pg_dumpall: pg_dumpall.o dumputils.o filter.o $(WIN32RES) | submake-libpq submake-libpgport submake-libpgfeutils
-   $(CC) $(CFLAGS) pg_dumpall.o dumputils.o filter.o $(WIN32RES) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X)
+pg_dumpall: pg_dumpall.o $(OBJS) | submake-libpq submake-libpgport submake-libpgfeutils
+   $(CC) $(CFLAGS) pg_dumpall.o $(OBJS) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X)
 
 install: all installdirs
    $(INSTALL_PROGRAM) pg_dump$(X) '$(DESTDIR)$(bindir)'/pg_dump$(X)
diff --git a/src/bin/pg_dump/connectdb.c b/src/bin/pg_dump/connectdb.c
new file mode 100644 (file)
index 0000000..9e593b7
--- /dev/null
@@ -0,0 +1,294 @@
+/*-------------------------------------------------------------------------
+ *
+ * connectdb.c
+ *    This is a common file connection to the database.
+ *
+ * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ *    src/bin/pg_dump/connectdb.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres_fe.h"
+
+#include "common/connect.h"
+#include "common/logging.h"
+#include "common/string.h"
+#include "connectdb.h"
+#include "dumputils.h"
+#include "fe_utils/string_utils.h"
+
+static char *constructConnStr(const char **keywords, const char **values);
+
+/*
+ * ConnectDatabase
+ *
+ * Make a database connection with the given parameters.  An
+ * interactive password prompt is automatically issued if required.
+ *
+ * If fail_on_error is false, we return NULL without printing any message
+ * on failure, but preserve any prompted password for the next try.
+ *
+ * On success, the 'connstr' is set to a connection string containing
+ * the options used and 'server_version' is set to version so that caller
+ * can use them.
+ */
+PGconn *
+ConnectDatabase(const char *dbname, const char *connection_string,
+               const char *pghost, const char *pgport, const char *pguser,
+               trivalue prompt_password, bool fail_on_error, const char *progname,
+               const char **connstr, int *server_version, char *password,
+               char *override_dbname)
+{
+   PGconn     *conn;
+   bool        new_pass;
+   const char *remoteversion_str;
+   int         my_version;
+   const char **keywords = NULL;
+   const char **values = NULL;
+   PQconninfoOption *conn_opts = NULL;
+   int         server_version_temp;
+
+   if (prompt_password == TRI_YES && !password)
+       password = simple_prompt("Password: ", false);
+
+   /*
+    * Start the connection.  Loop until we have a password if requested by
+    * backend.
+    */
+   do
+   {
+       int         argcount = 8;
+       PQconninfoOption *conn_opt;
+       char       *err_msg = NULL;
+       int         i = 0;
+
+       free(keywords);
+       free(values);
+       PQconninfoFree(conn_opts);
+
+       /*
+        * Merge the connection info inputs given in form of connection string
+        * and other options.  Explicitly discard any dbname value in the
+        * connection string; otherwise, PQconnectdbParams() would interpret
+        * that value as being itself a connection string.
+        */
+       if (connection_string)
+       {
+           conn_opts = PQconninfoParse(connection_string, &err_msg);
+           if (conn_opts == NULL)
+               pg_fatal("%s", err_msg);
+
+           for (conn_opt = conn_opts; conn_opt->keyword != NULL; conn_opt++)
+           {
+               if (conn_opt->val != NULL && conn_opt->val[0] != '\0' &&
+                   strcmp(conn_opt->keyword, "dbname") != 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' &&
+                   strcmp(conn_opt->keyword, "dbname") != 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));
+       }
+
+       if (pghost)
+       {
+           keywords[i] = "host";
+           values[i] = pghost;
+           i++;
+       }
+       if (pgport)
+       {
+           keywords[i] = "port";
+           values[i] = pgport;
+           i++;
+       }
+       if (pguser)
+       {
+           keywords[i] = "user";
+           values[i] = pguser;
+           i++;
+       }
+       if (password)
+       {
+           keywords[i] = "password";
+           values[i] = password;
+           i++;
+       }
+       if (dbname)
+       {
+           keywords[i] = "dbname";
+           values[i] = dbname;
+           i++;
+       }
+       if (override_dbname)
+       {
+           keywords[i] = "dbname";
+           values[i++] = override_dbname;
+       }
+
+       keywords[i] = "fallback_application_name";
+       values[i] = progname;
+       i++;
+
+       new_pass = false;
+       conn = PQconnectdbParams(keywords, values, true);
+
+       if (!conn)
+           pg_fatal("could not connect to database \"%s\"", dbname);
+
+       if (PQstatus(conn) == CONNECTION_BAD &&
+           PQconnectionNeedsPassword(conn) &&
+           !password &&
+           prompt_password != TRI_NO)
+       {
+           PQfinish(conn);
+           password = simple_prompt("Password: ", false);
+           new_pass = true;
+       }
+   } while (new_pass);
+
+   /* check to see that the backend connection was successfully made */
+   if (PQstatus(conn) == CONNECTION_BAD)
+   {
+       if (fail_on_error)
+           pg_fatal("%s", PQerrorMessage(conn));
+       else
+       {
+           PQfinish(conn);
+
+           free(keywords);
+           free(values);
+           PQconninfoFree(conn_opts);
+
+           return NULL;
+       }
+   }
+
+   /*
+    * Ok, connected successfully. If requested, remember the options used, in
+    * the form of a connection string.
+    */
+   if (connstr)
+       *connstr = constructConnStr(keywords, values);
+
+   free(keywords);
+   free(values);
+   PQconninfoFree(conn_opts);
+
+   /* Check version */
+   remoteversion_str = PQparameterStatus(conn, "server_version");
+   if (!remoteversion_str)
+       pg_fatal("could not get server version");
+
+   server_version_temp = PQserverVersion(conn);
+   if (server_version_temp == 0)
+       pg_fatal("could not parse server version \"%s\"",
+                remoteversion_str);
+
+   /* If requested, then copy server version to out variable. */
+   if (server_version)
+       *server_version = server_version_temp;
+
+   my_version = PG_VERSION_NUM;
+
+   /*
+    * We allow the server to be back to 9.2, and up to any minor release of
+    * our own major version.  (See also version check in pg_dump.c.)
+    */
+   if (my_version != server_version_temp
+       && (server_version_temp < 90200 ||
+           (server_version_temp / 100) > (my_version / 100)))
+   {
+       pg_log_error("aborting because of server version mismatch");
+       pg_log_error_detail("server version: %s; %s version: %s",
+                           remoteversion_str, progname, PG_VERSION);
+       exit_nicely(1);
+   }
+
+   PQclear(executeQuery(conn, ALWAYS_SECURE_SEARCH_PATH_SQL));
+
+   return conn;
+}
+
+/*
+ * constructConnStr
+ *
+ * Construct a connection string from the given keyword/value pairs. It is
+ * used to pass the connection options to the pg_dump subprocess.
+ *
+ * The following parameters are excluded:
+ * dbname      - varies in each pg_dump invocation
+ * password    - it's not secure to pass a password on the command line
+ * fallback_application_name - we'll let pg_dump set it
+ */
+static char *
+constructConnStr(const char **keywords, const char **values)
+{
+   PQExpBuffer buf = createPQExpBuffer();
+   char       *connstr;
+   int         i;
+   bool        firstkeyword = true;
+
+   /* Construct a new connection string in key='value' format. */
+   for (i = 0; keywords[i] != NULL; i++)
+   {
+       if (strcmp(keywords[i], "dbname") == 0 ||
+           strcmp(keywords[i], "password") == 0 ||
+           strcmp(keywords[i], "fallback_application_name") == 0)
+           continue;
+
+       if (!firstkeyword)
+           appendPQExpBufferChar(buf, ' ');
+       firstkeyword = false;
+       appendPQExpBuffer(buf, "%s=", keywords[i]);
+       appendConnStrVal(buf, values[i]);
+   }
+
+   connstr = pg_strdup(buf->data);
+   destroyPQExpBuffer(buf);
+   return connstr;
+}
+
+/*
+ * executeQuery
+ *
+ * Run a query, return the results, exit program on failure.
+ */
+PGresult *
+executeQuery(PGconn *conn, const char *query)
+{
+   PGresult   *res;
+
+   pg_log_info("executing %s", query);
+
+   res = PQexec(conn, query);
+   if (!res ||
+       PQresultStatus(res) != PGRES_TUPLES_OK)
+   {
+       pg_log_error("query failed: %s", PQerrorMessage(conn));
+       pg_log_error_detail("Query was: %s", query);
+       PQfinish(conn);
+       exit_nicely(1);
+   }
+
+   return res;
+}
diff --git a/src/bin/pg_dump/connectdb.h b/src/bin/pg_dump/connectdb.h
new file mode 100644 (file)
index 0000000..6c1e195
--- /dev/null
@@ -0,0 +1,26 @@
+/*-------------------------------------------------------------------------
+ *
+ * connectdb.h
+ *      Common header file for connection to the database.
+ *
+ * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ *    src/bin/pg_dump/connectdb.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef CONNECTDB_H
+#define CONNECTDB_H
+
+#include "pg_backup.h"
+#include "pg_backup_utils.h"
+
+extern PGconn *ConnectDatabase(const char *dbname, const char *connection_string, const char *pghost,
+                              const char *pgport, const char *pguser,
+                              trivalue prompt_password, bool fail_on_error,
+                              const char *progname, const char **connstr, int *server_version,
+                              char *password, char *override_dbname);
+extern PGresult *executeQuery(PGconn *conn, const char *query);
+#endif                         /* CONNECTDB_H */
index 603ba6cfbf0f63ddb9a02cb51b6ad37b02b66adf..25989e8f16b499e5bf647a4b4b65da7cdd5c751e 100644 (file)
@@ -6,6 +6,7 @@ pg_dump_common_sources = files(
   'compress_lz4.c',
   'compress_none.c',
   'compress_zstd.c',
+  'connectdb.c',
   'dumputils.c',
   'filter.c',
   'parallel.c',
index 9005b4253b402076fdb3fbff50fb34f5b9d5b3a3..453ff83b321a3ce062093a3d90a73ac442825d0c 100644 (file)
@@ -297,9 +297,9 @@ typedef void (*SetupWorkerPtrType) (Archive *AH);
  * Main archiver interface.
  */
 
-extern void ConnectDatabase(Archive *AHX,
-                           const ConnParams *cparams,
-                           bool isReconnect);
+extern void ConnectDatabaseAhx(Archive *AHX,
+                              const ConnParams *cparams,
+                              bool isReconnect);
 extern void DisconnectDatabase(Archive *AHX);
 extern PGconn *GetConnection(Archive *AHX);
 
index 541d26ecc8e680b63d7b90d871bc7c15690ad55c..7f6d4ed94e10069763ea5fc63216b62f0972e177 100644 (file)
@@ -414,7 +414,7 @@ RestoreArchive(Archive *AHX)
        AHX->minRemoteVersion = 0;
        AHX->maxRemoteVersion = 9999999;
 
-       ConnectDatabase(AHX, &ropt->cparams, false);
+       ConnectDatabaseAhx(AHX, &ropt->cparams, false);
 
        /*
         * If we're talking to the DB directly, don't send comments since they
@@ -4529,7 +4529,7 @@ restore_toc_entries_postfork(ArchiveHandle *AH, TocEntry *pending_list)
    /*
     * Now reconnect the single parent connection.
     */
-   ConnectDatabase((Archive *) AH, &ropt->cparams, true);
+   ConnectDatabaseAhx((Archive *) AH, &ropt->cparams, true);
 
    /* re-establish fixed state */
    _doSetFixedOutputState(AH);
@@ -5146,7 +5146,7 @@ CloneArchive(ArchiveHandle *AH)
     * Connect our new clone object to the database, using the same connection
     * parameters used for the original connection.
     */
-   ConnectDatabase((Archive *) clone, &clone->public.ropt->cparams, true);
+   ConnectDatabaseAhx((Archive *) clone, &clone->public.ropt->cparams, true);
 
    /* re-establish fixed state */
    if (AH->mode == archModeRead)
index 71c55d2466a59bd9f6242b46c05a28c00416e85d..5c349279beb56e5f6f352aceb598eb819b34f247 100644 (file)
@@ -19,6 +19,7 @@
 
 #include "common/connect.h"
 #include "common/string.h"
+#include "connectdb.h"
 #include "parallel.h"
 #include "pg_backup_archiver.h"
 #include "pg_backup_db.h"
@@ -86,9 +87,9 @@ ReconnectToServer(ArchiveHandle *AH, const char *dbname)
     * 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 */
+   AH->connection = NULL;      /* dodge error check in ConnectDatabaseAhx */
 
-   ConnectDatabase((Archive *) AH, &ropt->cparams, true);
+   ConnectDatabaseAhx((Archive *) AH, &ropt->cparams, true);
 
    PQfinish(oldConn);
 }
@@ -105,14 +106,13 @@ ReconnectToServer(ArchiveHandle *AH, const char *dbname)
  * username never does change, so one savedPassword is sufficient.
  */
 void
-ConnectDatabase(Archive *AHX,
-               const ConnParams *cparams,
-               bool isReconnect)
+ConnectDatabaseAhx(Archive *AHX,
+                  const ConnParams *cparams,
+                  bool isReconnect)
 {
    ArchiveHandle *AH = (ArchiveHandle *) AHX;
    trivalue    prompt_password;
    char       *password;
-   bool        new_pass;
 
    if (AH->connection)
        pg_fatal("already connected to a database");
@@ -125,69 +125,10 @@ ConnectDatabase(Archive *AHX,
    if (prompt_password == TRI_YES && password == NULL)
        password = simple_prompt("Password: ", false);
 
-   /*
-    * Start the connection.  Loop until we have a password if requested by
-    * backend.
-    */
-   do
-   {
-       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);
-
-       if (!AH->connection)
-           pg_fatal("could not connect to database");
-
-       if (PQstatus(AH->connection) == CONNECTION_BAD &&
-           PQconnectionNeedsPassword(AH->connection) &&
-           password == NULL &&
-           prompt_password != TRI_NO)
-       {
-           PQfinish(AH->connection);
-           password = simple_prompt("Password: ", false);
-           new_pass = true;
-       }
-   } while (new_pass);
-
-   /* check to see that the backend connection was successfully made */
-   if (PQstatus(AH->connection) == CONNECTION_BAD)
-   {
-       if (isReconnect)
-           pg_fatal("reconnection failed: %s",
-                    PQerrorMessage(AH->connection));
-       else
-           pg_fatal("%s",
-                    PQerrorMessage(AH->connection));
-   }
+   AH->connection = ConnectDatabase(cparams->dbname, NULL, cparams->pghost,
+                                    cparams->pgport, cparams->username,
+                                    prompt_password, true,
+                                    progname, NULL, NULL, password, cparams->override_dbname);
 
    /* Start strict; later phases may override this. */
    PQclear(ExecuteSqlQueryForSingleRow((Archive *) AH,
index 7977d0519f11b4bec0e51828e70ca8a298b8d8ce..784c067e8c623f666849b662720b6e207b0d9317 100644 (file)
@@ -969,7 +969,7 @@ main(int argc, char **argv)
     * Open the database using the Archiver, so it knows about it. Errors mean
     * death.
     */
-   ConnectDatabase(fout, &dopt.cparams, false);
+   ConnectDatabaseAhx(fout, &dopt.cparams, false);
    setup_connection(fout, dumpencoding, dumpsnapshot, use_role);
 
    /*
index 2ea574b0f065d4302c5293bee44a6aa2128bd7f3..573a8b61a45c30b1f3945ce53bccf01015f96fbf 100644 (file)
 #include "common/hashfn_unstable.h"
 #include "common/logging.h"
 #include "common/string.h"
+#include "connectdb.h"
 #include "dumputils.h"
 #include "fe_utils/string_utils.h"
 #include "filter.h"
 #include "getopt_long.h"
-#include "pg_backup.h"
 
 /* version string we expect back from pg_dump */
 #define PGDUMP_VERSIONSTR "pg_dump (PostgreSQL) " PG_VERSION "\n"
@@ -71,21 +71,14 @@ static void buildShSecLabels(PGconn *conn,
                             const char *catalog_name, Oid objectId,
                             const char *objtype, const char *objname,
                             PQExpBuffer buffer);
-static PGconn *connectDatabase(const char *dbname,
-                              const char *connection_string, const char *pghost,
-                              const char *pgport, const char *pguser,
-                              trivalue prompt_password, bool fail_on_error);
-static char *constructConnStr(const char **keywords, const char **values);
-static PGresult *executeQuery(PGconn *conn, const char *query);
 static void executeCommand(PGconn *conn, const char *query);
 static void expand_dbname_patterns(PGconn *conn, SimpleStringList *patterns,
                                   SimpleStringList *names);
 static void read_dumpall_filters(const char *filename, SimpleStringList *pattern);
 
 static char pg_dump_bin[MAXPGPATH];
-static const char *progname;
 static PQExpBuffer pgdumpopts;
-static char *connstr = "";
+static const char *connstr = "";
 static bool output_clean = false;
 static bool skip_acls = false;
 static bool verbose = false;
@@ -129,8 +122,6 @@ static char *filename = NULL;
 static SimpleStringList database_exclude_patterns = {NULL, NULL};
 static SimpleStringList database_exclude_names = {NULL, NULL};
 
-#define exit_nicely(code) exit(code)
-
 int
 main(int argc, char *argv[])
 {
@@ -499,19 +490,22 @@ main(int argc, char *argv[])
     */
    if (pgdb)
    {
-       conn = connectDatabase(pgdb, connstr, pghost, pgport, pguser,
-                              prompt_password, false);
+       conn = ConnectDatabase(pgdb, connstr, pghost, pgport, pguser,
+                              prompt_password, false,
+                              progname, &connstr, &server_version, NULL, NULL);
 
        if (!conn)
            pg_fatal("could not connect to database \"%s\"", pgdb);
    }
    else
    {
-       conn = connectDatabase("postgres", connstr, pghost, pgport, pguser,
-                              prompt_password, false);
+       conn = ConnectDatabase("postgres", connstr, pghost, pgport, pguser,
+                              prompt_password, false,
+                              progname, &connstr, &server_version, NULL, NULL);
        if (!conn)
-           conn = connectDatabase("template1", connstr, pghost, pgport, pguser,
-                                  prompt_password, true);
+           conn = ConnectDatabase("template1", connstr, pghost, pgport, pguser,
+                                  prompt_password, true,
+                                  progname, &connstr, &server_version, NULL, NULL);
 
        if (!conn)
        {
@@ -1738,256 +1732,6 @@ buildShSecLabels(PGconn *conn, const char *catalog_name, Oid objectId,
    destroyPQExpBuffer(sql);
 }
 
-/*
- * Make a database connection with the given parameters.  An
- * interactive password prompt is automatically issued if required.
- *
- * If fail_on_error is false, we return NULL without printing any message
- * on failure, but preserve any prompted password for the next try.
- *
- * On success, the global variable 'connstr' is set to a connection string
- * containing the options used.
- */
-static PGconn *
-connectDatabase(const char *dbname, const char *connection_string,
-               const char *pghost, const char *pgport, const char *pguser,
-               trivalue prompt_password, bool fail_on_error)
-{
-   PGconn     *conn;
-   bool        new_pass;
-   const char *remoteversion_str;
-   int         my_version;
-   const char **keywords = NULL;
-   const char **values = NULL;
-   PQconninfoOption *conn_opts = NULL;
-   static char *password = NULL;
-
-   if (prompt_password == TRI_YES && !password)
-       password = simple_prompt("Password: ", false);
-
-   /*
-    * Start the connection.  Loop until we have a password if requested by
-    * backend.
-    */
-   do
-   {
-       int         argcount = 6;
-       PQconninfoOption *conn_opt;
-       char       *err_msg = NULL;
-       int         i = 0;
-
-       free(keywords);
-       free(values);
-       PQconninfoFree(conn_opts);
-
-       /*
-        * Merge the connection info inputs given in form of connection string
-        * and other options.  Explicitly discard any dbname value in the
-        * connection string; otherwise, PQconnectdbParams() would interpret
-        * that value as being itself a connection string.
-        */
-       if (connection_string)
-       {
-           conn_opts = PQconninfoParse(connection_string, &err_msg);
-           if (conn_opts == NULL)
-               pg_fatal("%s", err_msg);
-
-           for (conn_opt = conn_opts; conn_opt->keyword != NULL; conn_opt++)
-           {
-               if (conn_opt->val != NULL && conn_opt->val[0] != '\0' &&
-                   strcmp(conn_opt->keyword, "dbname") != 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' &&
-                   strcmp(conn_opt->keyword, "dbname") != 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));
-       }
-
-       if (pghost)
-       {
-           keywords[i] = "host";
-           values[i] = pghost;
-           i++;
-       }
-       if (pgport)
-       {
-           keywords[i] = "port";
-           values[i] = pgport;
-           i++;
-       }
-       if (pguser)
-       {
-           keywords[i] = "user";
-           values[i] = pguser;
-           i++;
-       }
-       if (password)
-       {
-           keywords[i] = "password";
-           values[i] = password;
-           i++;
-       }
-       if (dbname)
-       {
-           keywords[i] = "dbname";
-           values[i] = dbname;
-           i++;
-       }
-       keywords[i] = "fallback_application_name";
-       values[i] = progname;
-       i++;
-
-       new_pass = false;
-       conn = PQconnectdbParams(keywords, values, true);
-
-       if (!conn)
-           pg_fatal("could not connect to database \"%s\"", dbname);
-
-       if (PQstatus(conn) == CONNECTION_BAD &&
-           PQconnectionNeedsPassword(conn) &&
-           !password &&
-           prompt_password != TRI_NO)
-       {
-           PQfinish(conn);
-           password = simple_prompt("Password: ", false);
-           new_pass = true;
-       }
-   } while (new_pass);
-
-   /* check to see that the backend connection was successfully made */
-   if (PQstatus(conn) == CONNECTION_BAD)
-   {
-       if (fail_on_error)
-           pg_fatal("%s", PQerrorMessage(conn));
-       else
-       {
-           PQfinish(conn);
-
-           free(keywords);
-           free(values);
-           PQconninfoFree(conn_opts);
-
-           return NULL;
-       }
-   }
-
-   /*
-    * Ok, connected successfully. Remember the options used, in the form of a
-    * connection string.
-    */
-   connstr = constructConnStr(keywords, values);
-
-   free(keywords);
-   free(values);
-   PQconninfoFree(conn_opts);
-
-   /* Check version */
-   remoteversion_str = PQparameterStatus(conn, "server_version");
-   if (!remoteversion_str)
-       pg_fatal("could not get server version");
-   server_version = PQserverVersion(conn);
-   if (server_version == 0)
-       pg_fatal("could not parse server version \"%s\"",
-                remoteversion_str);
-
-   my_version = PG_VERSION_NUM;
-
-   /*
-    * We allow the server to be back to 9.2, and up to any minor release of
-    * our own major version.  (See also version check in pg_dump.c.)
-    */
-   if (my_version != server_version
-       && (server_version < 90200 ||
-           (server_version / 100) > (my_version / 100)))
-   {
-       pg_log_error("aborting because of server version mismatch");
-       pg_log_error_detail("server version: %s; %s version: %s",
-                           remoteversion_str, progname, PG_VERSION);
-       exit_nicely(1);
-   }
-
-   PQclear(executeQuery(conn, ALWAYS_SECURE_SEARCH_PATH_SQL));
-
-   return conn;
-}
-
-/* ----------
- * Construct a connection string from the given keyword/value pairs. It is
- * used to pass the connection options to the pg_dump subprocess.
- *
- * The following parameters are excluded:
- * dbname      - varies in each pg_dump invocation
- * password    - it's not secure to pass a password on the command line
- * fallback_application_name - we'll let pg_dump set it
- * ----------
- */
-static char *
-constructConnStr(const char **keywords, const char **values)
-{
-   PQExpBuffer buf = createPQExpBuffer();
-   char       *connstr;
-   int         i;
-   bool        firstkeyword = true;
-
-   /* Construct a new connection string in key='value' format. */
-   for (i = 0; keywords[i] != NULL; i++)
-   {
-       if (strcmp(keywords[i], "dbname") == 0 ||
-           strcmp(keywords[i], "password") == 0 ||
-           strcmp(keywords[i], "fallback_application_name") == 0)
-           continue;
-
-       if (!firstkeyword)
-           appendPQExpBufferChar(buf, ' ');
-       firstkeyword = false;
-       appendPQExpBuffer(buf, "%s=", keywords[i]);
-       appendConnStrVal(buf, values[i]);
-   }
-
-   connstr = pg_strdup(buf->data);
-   destroyPQExpBuffer(buf);
-   return connstr;
-}
-
-/*
- * Run a query, return the results, exit program on failure.
- */
-static PGresult *
-executeQuery(PGconn *conn, const char *query)
-{
-   PGresult   *res;
-
-   pg_log_info("executing %s", query);
-
-   res = PQexec(conn, query);
-   if (!res ||
-       PQresultStatus(res) != PGRES_TUPLES_OK)
-   {
-       pg_log_error("query failed: %s", PQerrorMessage(conn));
-       pg_log_error_detail("Query was: %s", query);
-       PQfinish(conn);
-       exit_nicely(1);
-   }
-
-   return res;
-}
-
 /*
  * As above for a SQL command (which returns nothing).
  */