LCOV - differential code coverage report
Current view: top level - src/bin/pg_dump - connectdb.c (source / functions) Coverage Total Hit UBC CBC
Current: c70b6db34ffeab48beef1fb4ce61bcad3772b8dd vs 06473f5a344df8c9594ead90a609b86f6724cff8 Lines: 79.0 % 124 98 26 98
Current Date: 2025-09-06 07:49:51 +0900 Functions: 100.0 % 3 3 3
Baseline: lcov-20250906-005545-baseline Branches: 68.8 % 80 55 25 55
Baseline Date: 2025-09-05 08:21:35 +0100 Line coverage date bins:
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
(30,360] days: 79.0 % 124 98 26 98
Function coverage date bins:
(30,360] days: 100.0 % 3 3 3
Branch coverage date bins:
(30,360] days: 68.8 % 80 55 25 55

 Age         Owner                    Branch data    TLA  Line data    Source code
                                  1                 :                : /*-------------------------------------------------------------------------
                                  2                 :                :  *
                                  3                 :                :  * connectdb.c
                                  4                 :                :  *    This is a common file connection to the database.
                                  5                 :                :  *
                                  6                 :                :  * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
                                  7                 :                :  * Portions Copyright (c) 1994, Regents of the University of California
                                  8                 :                :  *
                                  9                 :                :  * IDENTIFICATION
                                 10                 :                :  *    src/bin/pg_dump/connectdb.c
                                 11                 :                :  *
                                 12                 :                :  *-------------------------------------------------------------------------
                                 13                 :                :  */
                                 14                 :                : 
                                 15                 :                : #include "postgres_fe.h"
                                 16                 :                : 
                                 17                 :                : #include "common/connect.h"
                                 18                 :                : #include "common/logging.h"
                                 19                 :                : #include "common/string.h"
                                 20                 :                : #include "connectdb.h"
                                 21                 :                : #include "dumputils.h"
                                 22                 :                : #include "fe_utils/string_utils.h"
                                 23                 :                : 
                                 24                 :                : static char *constructConnStr(const char **keywords, const char **values);
                                 25                 :                : 
                                 26                 :                : /*
                                 27                 :                :  * ConnectDatabase
                                 28                 :                :  *
                                 29                 :                :  * Make a database connection with the given parameters.  An
                                 30                 :                :  * interactive password prompt is automatically issued if required.
                                 31                 :                :  *
                                 32                 :                :  * If fail_on_error is false, we return NULL without printing any message
                                 33                 :                :  * on failure, but preserve any prompted password for the next try.
                                 34                 :                :  *
                                 35                 :                :  * On success, the 'connstr' is set to a connection string containing
                                 36                 :                :  * the options used and 'server_version' is set to version so that caller
                                 37                 :                :  * can use them.
                                 38                 :                :  */
                                 39                 :                : PGconn *
  155 andrew@dunslane.net        40                 :CBC         358 : ConnectDatabase(const char *dbname, const char *connection_string,
                                 41                 :                :                 const char *pghost, const char *pgport, const char *pguser,
                                 42                 :                :                 trivalue prompt_password, bool fail_on_error, const char *progname,
                                 43                 :                :                 const char **connstr, int *server_version, char *password,
                                 44                 :                :                 char *override_dbname)
                                 45                 :                : {
                                 46                 :                :     PGconn     *conn;
                                 47                 :                :     bool        new_pass;
                                 48                 :                :     const char *remoteversion_str;
                                 49                 :                :     int         my_version;
                                 50                 :            358 :     const char **keywords = NULL;
                                 51                 :            358 :     const char **values = NULL;
                                 52                 :            358 :     PQconninfoOption *conn_opts = NULL;
                                 53                 :                :     int         server_version_temp;
                                 54                 :                : 
                                 55   [ -  +  -  - ]:            358 :     if (prompt_password == TRI_YES && !password)
  155 andrew@dunslane.net        56                 :UBC           0 :         password = simple_prompt("Password: ", false);
                                 57                 :                : 
                                 58                 :                :     /*
                                 59                 :                :      * Start the connection.  Loop until we have a password if requested by
                                 60                 :                :      * backend.
                                 61                 :                :      */
                                 62                 :                :     do
                                 63                 :                :     {
  155 andrew@dunslane.net        64                 :CBC         358 :         int         argcount = 8;
                                 65                 :                :         PQconninfoOption *conn_opt;
                                 66                 :            358 :         char       *err_msg = NULL;
                                 67                 :            358 :         int         i = 0;
                                 68                 :                : 
                                 69                 :            358 :         free(keywords);
                                 70                 :            358 :         free(values);
                                 71                 :            358 :         PQconninfoFree(conn_opts);
                                 72                 :                : 
                                 73                 :                :         /*
                                 74                 :                :          * Merge the connection info inputs given in form of connection string
                                 75                 :                :          * and other options.  Explicitly discard any dbname value in the
                                 76                 :                :          * connection string; otherwise, PQconnectdbParams() would interpret
                                 77                 :                :          * that value as being itself a connection string.
                                 78                 :                :          */
                                 79         [ +  + ]:            358 :         if (connection_string)
                                 80                 :                :         {
                                 81                 :             33 :             conn_opts = PQconninfoParse(connection_string, &err_msg);
                                 82         [ -  + ]:             33 :             if (conn_opts == NULL)
  155 andrew@dunslane.net        83                 :UBC           0 :                 pg_fatal("%s", err_msg);
                                 84                 :                : 
  155 andrew@dunslane.net        85         [ +  + ]:CBC        1716 :             for (conn_opt = conn_opts; conn_opt->keyword != NULL; conn_opt++)
                                 86                 :                :             {
                                 87   [ +  +  +  - ]:           1683 :                 if (conn_opt->val != NULL && conn_opt->val[0] != '\0' &&
                                 88         [ +  + ]:             25 :                     strcmp(conn_opt->keyword, "dbname") != 0)
                                 89                 :             16 :                     argcount++;
                                 90                 :                :             }
                                 91                 :                : 
                                 92                 :             33 :             keywords = pg_malloc0((argcount + 1) * sizeof(*keywords));
                                 93                 :             33 :             values = pg_malloc0((argcount + 1) * sizeof(*values));
                                 94                 :                : 
                                 95         [ +  + ]:           1716 :             for (conn_opt = conn_opts; conn_opt->keyword != NULL; conn_opt++)
                                 96                 :                :             {
                                 97   [ +  +  +  - ]:           1683 :                 if (conn_opt->val != NULL && conn_opt->val[0] != '\0' &&
                                 98         [ +  + ]:             25 :                     strcmp(conn_opt->keyword, "dbname") != 0)
                                 99                 :                :                 {
                                100                 :             16 :                     keywords[i] = conn_opt->keyword;
                                101                 :             16 :                     values[i] = conn_opt->val;
                                102                 :             16 :                     i++;
                                103                 :                :                 }
                                104                 :                :             }
                                105                 :                :         }
                                106                 :                :         else
                                107                 :                :         {
                                108                 :            325 :             keywords = pg_malloc0((argcount + 1) * sizeof(*keywords));
                                109                 :            325 :             values = pg_malloc0((argcount + 1) * sizeof(*values));
                                110                 :                :         }
                                111                 :                : 
                                112         [ +  + ]:            358 :         if (pghost)
                                113                 :                :         {
                                114                 :            128 :             keywords[i] = "host";
                                115                 :            128 :             values[i] = pghost;
                                116                 :            128 :             i++;
                                117                 :                :         }
                                118         [ +  + ]:            358 :         if (pgport)
                                119                 :                :         {
                                120                 :            167 :             keywords[i] = "port";
                                121                 :            167 :             values[i] = pgport;
                                122                 :            167 :             i++;
                                123                 :                :         }
                                124         [ +  + ]:            358 :         if (pguser)
                                125                 :                :         {
                                126                 :            148 :             keywords[i] = "user";
                                127                 :            148 :             values[i] = pguser;
                                128                 :            148 :             i++;
                                129                 :                :         }
                                130         [ -  + ]:            358 :         if (password)
                                131                 :                :         {
  155 andrew@dunslane.net       132                 :UBC           0 :             keywords[i] = "password";
                                133                 :              0 :             values[i] = password;
                                134                 :              0 :             i++;
                                135                 :                :         }
  155 andrew@dunslane.net       136         [ +  + ]:CBC         358 :         if (dbname)
                                137                 :                :         {
                                138                 :            344 :             keywords[i] = "dbname";
                                139                 :            344 :             values[i] = dbname;
                                140                 :            344 :             i++;
                                141                 :                :         }
                                142         [ +  + ]:            358 :         if (override_dbname)
                                143                 :                :         {
                                144                 :             60 :             keywords[i] = "dbname";
  134 peter@eisentraut.org      145                 :             60 :             values[i] = override_dbname;
                                146                 :             60 :             i++;
                                147                 :                :         }
                                148                 :                : 
  155 andrew@dunslane.net       149                 :            358 :         keywords[i] = "fallback_application_name";
                                150                 :            358 :         values[i] = progname;
                                151                 :            358 :         i++;
                                152                 :                : 
                                153                 :            358 :         new_pass = false;
                                154                 :            358 :         conn = PQconnectdbParams(keywords, values, true);
                                155                 :                : 
                                156         [ -  + ]:            358 :         if (!conn)
  155 andrew@dunslane.net       157                 :UBC           0 :             pg_fatal("could not connect to database \"%s\"", dbname);
                                158                 :                : 
  155 andrew@dunslane.net       159   [ +  +  -  + ]:CBC         360 :         if (PQstatus(conn) == CONNECTION_BAD &&
                                160         [ -  - ]:              2 :             PQconnectionNeedsPassword(conn) &&
  155 andrew@dunslane.net       161         [ #  # ]:UBC           0 :             !password &&
                                162                 :                :             prompt_password != TRI_NO)
                                163                 :                :         {
                                164                 :              0 :             PQfinish(conn);
                                165                 :              0 :             password = simple_prompt("Password: ", false);
                                166                 :              0 :             new_pass = true;
                                167                 :                :         }
  155 andrew@dunslane.net       168         [ -  + ]:CBC         358 :     } while (new_pass);
                                169                 :                : 
                                170                 :                :     /* check to see that the backend connection was successfully made */
                                171         [ +  + ]:            358 :     if (PQstatus(conn) == CONNECTION_BAD)
                                172                 :                :     {
                                173         [ +  - ]:              2 :         if (fail_on_error)
                                174                 :              2 :             pg_fatal("%s", PQerrorMessage(conn));
                                175                 :                :         else
                                176                 :                :         {
  155 andrew@dunslane.net       177                 :UBC           0 :             PQfinish(conn);
                                178                 :                : 
                                179                 :              0 :             free(keywords);
                                180                 :              0 :             free(values);
                                181                 :              0 :             PQconninfoFree(conn_opts);
                                182                 :                : 
                                183                 :              0 :             return NULL;
                                184                 :                :         }
                                185                 :                :     }
                                186                 :                : 
                                187                 :                :     /*
                                188                 :                :      * Ok, connected successfully. If requested, remember the options used, in
                                189                 :                :      * the form of a connection string.
                                190                 :                :      */
  155 andrew@dunslane.net       191         [ +  + ]:CBC         356 :     if (connstr)
                                192                 :             33 :         *connstr = constructConnStr(keywords, values);
                                193                 :                : 
                                194                 :            356 :     free(keywords);
                                195                 :            356 :     free(values);
                                196                 :            356 :     PQconninfoFree(conn_opts);
                                197                 :                : 
                                198                 :                :     /* Check version */
                                199                 :            356 :     remoteversion_str = PQparameterStatus(conn, "server_version");
                                200         [ -  + ]:            356 :     if (!remoteversion_str)
  155 andrew@dunslane.net       201                 :UBC           0 :         pg_fatal("could not get server version");
                                202                 :                : 
  155 andrew@dunslane.net       203                 :CBC         356 :     server_version_temp = PQserverVersion(conn);
                                204         [ -  + ]:            356 :     if (server_version_temp == 0)
  155 andrew@dunslane.net       205                 :UBC           0 :         pg_fatal("could not parse server version \"%s\"",
                                206                 :                :                  remoteversion_str);
                                207                 :                : 
                                208                 :                :     /* If requested, then copy server version to out variable. */
  155 andrew@dunslane.net       209         [ +  + ]:CBC         356 :     if (server_version)
                                210                 :             33 :         *server_version = server_version_temp;
                                211                 :                : 
                                212                 :            356 :     my_version = PG_VERSION_NUM;
                                213                 :                : 
                                214                 :                :     /*
                                215                 :                :      * We allow the server to be back to 9.2, and up to any minor release of
                                216                 :                :      * our own major version.  (See also version check in pg_dump.c.)
                                217                 :                :      */
                                218         [ -  + ]:            356 :     if (my_version != server_version_temp
  155 andrew@dunslane.net       219         [ #  # ]:UBC           0 :         && (server_version_temp < 90200 ||
                                220         [ #  # ]:              0 :             (server_version_temp / 100) > (my_version / 100)))
                                221                 :                :     {
                                222                 :              0 :         pg_log_error("aborting because of server version mismatch");
                                223                 :              0 :         pg_log_error_detail("server version: %s; %s version: %s",
                                224                 :                :                             remoteversion_str, progname, PG_VERSION);
                                225                 :              0 :         exit_nicely(1);
                                226                 :                :     }
                                227                 :                : 
  155 andrew@dunslane.net       228                 :CBC         356 :     PQclear(executeQuery(conn, ALWAYS_SECURE_SEARCH_PATH_SQL));
                                229                 :                : 
                                230                 :            356 :     return conn;
                                231                 :                : }
                                232                 :                : 
                                233                 :                : /*
                                234                 :                :  * constructConnStr
                                235                 :                :  *
                                236                 :                :  * Construct a connection string from the given keyword/value pairs. It is
                                237                 :                :  * used to pass the connection options to the pg_dump subprocess.
                                238                 :                :  *
                                239                 :                :  * The following parameters are excluded:
                                240                 :                :  *  dbname      - varies in each pg_dump invocation
                                241                 :                :  *  password    - it's not secure to pass a password on the command line
                                242                 :                :  *  fallback_application_name - we'll let pg_dump set it
                                243                 :                :  */
                                244                 :                : static char *
                                245                 :             33 : constructConnStr(const char **keywords, const char **values)
                                246                 :                : {
                                247                 :             33 :     PQExpBuffer buf = createPQExpBuffer();
                                248                 :                :     char       *connstr;
                                249                 :                :     int         i;
                                250                 :             33 :     bool        firstkeyword = true;
                                251                 :                : 
                                252                 :                :     /* Construct a new connection string in key='value' format. */
                                253         [ +  + ]:            157 :     for (i = 0; keywords[i] != NULL; i++)
                                254                 :                :     {
                                255         [ +  + ]:            124 :         if (strcmp(keywords[i], "dbname") == 0 ||
                                256         [ +  - ]:             91 :             strcmp(keywords[i], "password") == 0 ||
                                257         [ +  + ]:             91 :             strcmp(keywords[i], "fallback_application_name") == 0)
                                258                 :             66 :             continue;
                                259                 :                : 
                                260         [ +  + ]:             58 :         if (!firstkeyword)
                                261                 :             32 :             appendPQExpBufferChar(buf, ' ');
                                262                 :             58 :         firstkeyword = false;
                                263                 :             58 :         appendPQExpBuffer(buf, "%s=", keywords[i]);
                                264                 :             58 :         appendConnStrVal(buf, values[i]);
                                265                 :                :     }
                                266                 :                : 
                                267                 :             33 :     connstr = pg_strdup(buf->data);
                                268                 :             33 :     destroyPQExpBuffer(buf);
                                269                 :             33 :     return connstr;
                                270                 :                : }
                                271                 :                : 
                                272                 :                : /*
                                273                 :                :  * executeQuery
                                274                 :                :  *
                                275                 :                :  * Run a query, return the results, exit program on failure.
                                276                 :                :  */
                                277                 :                : PGresult *
                                278                 :            658 : executeQuery(PGconn *conn, const char *query)
                                279                 :                : {
                                280                 :                :     PGresult   *res;
                                281                 :                : 
                                282                 :            658 :     pg_log_info("executing %s", query);
                                283                 :                : 
                                284                 :            658 :     res = PQexec(conn, query);
                                285   [ +  -  -  + ]:           1316 :     if (!res ||
                                286                 :            658 :         PQresultStatus(res) != PGRES_TUPLES_OK)
                                287                 :                :     {
  155 andrew@dunslane.net       288                 :UBC           0 :         pg_log_error("query failed: %s", PQerrorMessage(conn));
                                289                 :              0 :         pg_log_error_detail("Query was: %s", query);
                                290                 :              0 :         PQfinish(conn);
                                291                 :              0 :         exit_nicely(1);
                                292                 :                :     }
                                293                 :                : 
  155 andrew@dunslane.net       294                 :CBC         658 :     return res;
                                295                 :                : }
        

Generated by: LCOV version 2.4-beta