LCOV - code coverage report
Current view: top level - src/fe_utils - connect_utils.c (source / functions) Coverage Total Hit
Test: PostgreSQL 20devel Lines: 71.2 % 59 42
Test Date: 2026-07-16 06:15:47 Functions: 100.0 % 3 3
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 56.7 % 30 17

             Branch data     Line data    Source code
       1                 :             : /*-------------------------------------------------------------------------
       2                 :             :  *
       3                 :             :  * Facilities for frontend code to connect to and disconnect from databases.
       4                 :             :  *
       5                 :             :  * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
       6                 :             :  * Portions Copyright (c) 1994, Regents of the University of California
       7                 :             :  *
       8                 :             :  * src/fe_utils/connect_utils.c
       9                 :             :  *
      10                 :             :  *-------------------------------------------------------------------------
      11                 :             :  */
      12                 :             : #include "postgres_fe.h"
      13                 :             : 
      14                 :             : #include "common/connect.h"
      15                 :             : #include "common/logging.h"
      16                 :             : #include "common/string.h"
      17                 :             : #include "fe_utils/connect_utils.h"
      18                 :             : #include "fe_utils/query_utils.h"
      19                 :             : 
      20                 :             : /*
      21                 :             :  * Make a database connection with the given parameters.
      22                 :             :  *
      23                 :             :  * An interactive password prompt is automatically issued if needed and
      24                 :             :  * allowed by cparams->prompt_password.
      25                 :             :  *
      26                 :             :  * If allow_password_reuse is true, we will try to re-use any password
      27                 :             :  * given during previous calls to this routine.  (Callers should not pass
      28                 :             :  * allow_password_reuse=true unless reconnecting to the same host+port+user
      29                 :             :  * as before, else we might create password exposure hazards.)
      30                 :             :  */
      31                 :             : PGconn *
      32                 :         403 : connectDatabase(const ConnParams *cparams, const char *progname,
      33                 :             :                 bool echo, bool fail_ok, bool allow_password_reuse)
      34                 :             : {
      35                 :             :     PGconn     *conn;
      36                 :             :     bool        new_pass;
      37                 :             :     static char *password = NULL;
      38                 :             : 
      39                 :             :     /* Callers must supply at least dbname; other params can be NULL */
      40                 :             :     Assert(cparams->dbname);
      41                 :             : 
      42   [ +  +  -  + ]:         403 :     if (!allow_password_reuse && password)
      43                 :             :     {
      44                 :           0 :         free(password);
      45                 :           0 :         password = NULL;
      46                 :             :     }
      47                 :             : 
      48   [ -  +  -  - ]:         403 :     if (cparams->prompt_password == TRI_YES && password == NULL)
      49                 :           0 :         password = simple_prompt("Password: ", false);
      50                 :             : 
      51                 :             :     /*
      52                 :             :      * Start the connection.  Loop until we have a password if requested by
      53                 :             :      * backend.
      54                 :             :      */
      55                 :             :     do
      56                 :             :     {
      57                 :             :         const char *keywords[8];
      58                 :             :         const char *values[8];
      59                 :         403 :         int         i = 0;
      60                 :             : 
      61                 :             :         /*
      62                 :             :          * If dbname is a connstring, its entries can override the other
      63                 :             :          * values obtained from cparams; but in turn, override_dbname can
      64                 :             :          * override the dbname component of it.
      65                 :             :          */
      66                 :         403 :         keywords[i] = "host";
      67                 :         403 :         values[i++] = cparams->pghost;
      68                 :         403 :         keywords[i] = "port";
      69                 :         403 :         values[i++] = cparams->pgport;
      70                 :         403 :         keywords[i] = "user";
      71                 :         403 :         values[i++] = cparams->pguser;
      72                 :         403 :         keywords[i] = "password";
      73                 :         403 :         values[i++] = password;
      74                 :         403 :         keywords[i] = "dbname";
      75                 :         403 :         values[i++] = cparams->dbname;
      76         [ +  + ]:         403 :         if (cparams->override_dbname)
      77                 :             :         {
      78                 :         141 :             keywords[i] = "dbname";
      79                 :         141 :             values[i++] = cparams->override_dbname;
      80                 :             :         }
      81                 :         403 :         keywords[i] = "fallback_application_name";
      82                 :         403 :         values[i++] = progname;
      83                 :         403 :         keywords[i] = NULL;
      84                 :         403 :         values[i++] = NULL;
      85                 :             :         Assert(i <= lengthof(keywords));
      86                 :             : 
      87                 :         403 :         new_pass = false;
      88                 :         403 :         conn = PQconnectdbParams(keywords, values, true);
      89                 :             : 
      90         [ -  + ]:         403 :         if (!conn)
      91                 :           0 :             pg_fatal("could not connect to database %s: out of memory",
      92                 :             :                      cparams->dbname);
      93                 :             : 
      94                 :             :         /*
      95                 :             :          * No luck?  Trying asking (again) for a password.
      96                 :             :          */
      97   [ +  +  -  + ]:         408 :         if (PQstatus(conn) == CONNECTION_BAD &&
      98                 :           5 :             PQconnectionNeedsPassword(conn) &&
      99         [ #  # ]:           0 :             cparams->prompt_password != TRI_NO)
     100                 :             :         {
     101                 :           0 :             PQfinish(conn);
     102                 :           0 :             free(password);
     103                 :           0 :             password = simple_prompt("Password: ", false);
     104                 :           0 :             new_pass = true;
     105                 :             :         }
     106         [ -  + ]:         403 :     } while (new_pass);
     107                 :             : 
     108                 :             :     /* check to see that the backend connection was successfully made */
     109         [ +  + ]:         403 :     if (PQstatus(conn) == CONNECTION_BAD)
     110                 :             :     {
     111         [ -  + ]:           5 :         if (fail_ok)
     112                 :             :         {
     113                 :           0 :             PQfinish(conn);
     114                 :           0 :             return NULL;
     115                 :             :         }
     116                 :           5 :         pg_fatal("%s", PQerrorMessage(conn));
     117                 :             :     }
     118                 :             : 
     119                 :             :     /* Start strict; callers may override this. */
     120                 :         398 :     PQclear(executeQuery(conn, ALWAYS_SECURE_SEARCH_PATH_SQL, echo));
     121                 :             : 
     122                 :         398 :     return conn;
     123                 :             : }
     124                 :             : 
     125                 :             : /*
     126                 :             :  * Try to connect to the appropriate maintenance database.
     127                 :             :  *
     128                 :             :  * This differs from connectDatabase only in that it has a rule for
     129                 :             :  * inserting a default "dbname" if none was given (which is why cparams
     130                 :             :  * is not const).  Note that cparams->dbname should typically come from
     131                 :             :  * a --maintenance-db command line parameter.
     132                 :             :  */
     133                 :             : PGconn *
     134                 :         138 : connectMaintenanceDatabase(ConnParams *cparams,
     135                 :             :                            const char *progname, bool echo)
     136                 :             : {
     137                 :             :     PGconn     *conn;
     138                 :             : 
     139                 :             :     /* If a maintenance database name was specified, just connect to it. */
     140         [ -  + ]:         138 :     if (cparams->dbname)
     141                 :           0 :         return connectDatabase(cparams, progname, echo, false, false);
     142                 :             : 
     143                 :             :     /* Otherwise, try postgres first and then template1. */
     144                 :         138 :     cparams->dbname = "postgres";
     145                 :         138 :     conn = connectDatabase(cparams, progname, echo, true, false);
     146         [ -  + ]:         138 :     if (!conn)
     147                 :             :     {
     148                 :           0 :         cparams->dbname = "template1";
     149                 :           0 :         conn = connectDatabase(cparams, progname, echo, false, false);
     150                 :             :     }
     151                 :         138 :     return conn;
     152                 :             : }
     153                 :             : 
     154                 :             : /*
     155                 :             :  * Disconnect the given connection, canceling any statement if one is active.
     156                 :             :  */
     157                 :             : void
     158                 :         252 : disconnectDatabase(PGconn *conn)
     159                 :             : {
     160                 :             :     Assert(conn != NULL);
     161                 :             : 
     162         [ -  + ]:         252 :     if (PQtransactionStatus(conn) == PQTRANS_ACTIVE)
     163                 :             :     {
     164                 :           0 :         PGcancelConn *cancelConn = PQcancelCreate(conn);
     165                 :             : 
     166                 :           0 :         (void) PQcancelBlocking(cancelConn);
     167                 :           0 :         PQcancelFinish(cancelConn);
     168                 :             :     }
     169                 :             : 
     170                 :         252 :     PQfinish(conn);
     171                 :         252 : }
        

Generated by: LCOV version 2.0-1