1 /*-------------------------------------------------------------------------
3 * Facilities for frontend code to connect to and disconnect from databases.
5 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
6 * Portions Copyright (c) 1994, Regents of the University of California
8 * src/fe_utils/connect_utils.c
10 *-------------------------------------------------------------------------
12 #include "postgres_fe.h"
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"
21 * Make a database connection with the given parameters.
23 * An interactive password prompt is automatically issued if needed and
24 * allowed by cparams->prompt_password.
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.)
32 connectDatabase(const ConnParams
*cparams
, const char *progname
,
33 bool echo
, bool fail_ok
, bool allow_password_reuse
)
37 static char *password
= NULL
;
39 /* Callers must supply at least dbname; other params can be NULL */
40 Assert(cparams
->dbname
);
42 if (!allow_password_reuse
&& password
)
48 if (cparams
->prompt_password
== TRI_YES
&& password
== NULL
)
49 password
= simple_prompt("Password: ", false);
52 * Start the connection. Loop until we have a password if requested by
57 const char *keywords
[8];
58 const char *values
[8];
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.
67 values
[i
++] = cparams
->pghost
;
69 values
[i
++] = cparams
->pgport
;
71 values
[i
++] = cparams
->pguser
;
72 keywords
[i
] = "password";
73 values
[i
++] = password
;
74 keywords
[i
] = "dbname";
75 values
[i
++] = cparams
->dbname
;
76 if (cparams
->override_dbname
)
78 keywords
[i
] = "dbname";
79 values
[i
++] = cparams
->override_dbname
;
81 keywords
[i
] = "fallback_application_name";
82 values
[i
++] = progname
;
85 Assert(i
<= lengthof(keywords
));
88 conn
= PQconnectdbParams(keywords
, values
, true);
91 pg_fatal("could not connect to database %s: out of memory",
95 * No luck? Trying asking (again) for a password.
97 if (PQstatus(conn
) == CONNECTION_BAD
&&
98 PQconnectionNeedsPassword(conn
) &&
99 cparams
->prompt_password
!= TRI_NO
)
103 password
= simple_prompt("Password: ", false);
108 /* check to see that the backend connection was successfully made */
109 if (PQstatus(conn
) == CONNECTION_BAD
)
116 pg_fatal("%s", PQerrorMessage(conn
));
119 /* Start strict; callers may override this. */
120 PQclear(executeQuery(conn
, ALWAYS_SECURE_SEARCH_PATH_SQL
, echo
));
126 * Try to connect to the appropriate maintenance database.
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.
134 connectMaintenanceDatabase(ConnParams
*cparams
,
135 const char *progname
, bool echo
)
139 /* If a maintenance database name was specified, just connect to it. */
141 return connectDatabase(cparams
, progname
, echo
, false, false);
143 /* Otherwise, try postgres first and then template1. */
144 cparams
->dbname
= "postgres";
145 conn
= connectDatabase(cparams
, progname
, echo
, true, false);
148 cparams
->dbname
= "template1";
149 conn
= connectDatabase(cparams
, progname
, echo
, false, false);
155 * Disconnect the given connection, canceling any statement if one is active.
158 disconnectDatabase(PGconn
*conn
)
160 Assert(conn
!= NULL
);
162 if (PQtransactionStatus(conn
) == PQTRANS_ACTIVE
)
164 PGcancelConn
*cancelConn
= PQcancelCreate(conn
);
166 (void) PQcancelBlocking(cancelConn
);
167 PQcancelFinish(cancelConn
);