1 /*-------------------------------------------------------------------------
3 * Facilities for frontend code to connect to and disconnect from databases.
5 * Portions Copyright (c) 1996-2022, 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 database+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);
92 pg_log_error("could not connect to database %s: out of memory",
98 * No luck? Trying asking (again) for a password.
100 if (PQstatus(conn
) == CONNECTION_BAD
&&
101 PQconnectionNeedsPassword(conn
) &&
102 cparams
->prompt_password
!= TRI_NO
)
107 password
= simple_prompt("Password: ", false);
112 /* check to see that the backend connection was successfully made */
113 if (PQstatus(conn
) == CONNECTION_BAD
)
120 pg_log_error("%s", PQerrorMessage(conn
));
124 /* Start strict; callers may override this. */
125 PQclear(executeQuery(conn
, ALWAYS_SECURE_SEARCH_PATH_SQL
, echo
));
131 * Try to connect to the appropriate maintenance database.
133 * This differs from connectDatabase only in that it has a rule for
134 * inserting a default "dbname" if none was given (which is why cparams
135 * is not const). Note that cparams->dbname should typically come from
136 * a --maintenance-db command line parameter.
139 connectMaintenanceDatabase(ConnParams
*cparams
,
140 const char *progname
, bool echo
)
144 /* If a maintenance database name was specified, just connect to it. */
146 return connectDatabase(cparams
, progname
, echo
, false, false);
148 /* Otherwise, try postgres first and then template1. */
149 cparams
->dbname
= "postgres";
150 conn
= connectDatabase(cparams
, progname
, echo
, true, false);
153 cparams
->dbname
= "template1";
154 conn
= connectDatabase(cparams
, progname
, echo
, false, false);
160 * Disconnect the given connection, canceling any statement if one is active.
163 disconnectDatabase(PGconn
*conn
)
167 Assert(conn
!= NULL
);
169 if (PQtransactionStatus(conn
) == PQTRANS_ACTIVE
)
173 if ((cancel
= PQgetCancel(conn
)))
175 (void) PQcancel(cancel
, errbuf
, sizeof(errbuf
));
176 PQfreeCancel(cancel
);