]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
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).
  */