mirror of
https://github.com/postgres/postgres.git
synced 2025-12-21 05:21:08 +03:00
Allow psql to re-use connection parameters after a connection loss.
Instead of immediately PQfinish'ing a dead connection, save it aside so that we can still extract its parameters for \connect attempts. (This works because PQconninfo doesn't care whether the PGconn is in CONNECTION_BAD state.) This allows developers to reconnect with just \c after a database crash and restart. It's tempting to use the same approach instead of closing the old connection after a failed non-interactive \connect command. However, that would not be very safe: consider a script containing \c db1 user1 live_server \c db2 user2 dead_server \c db3 The script would be expecting to connect to db3 at dead_server, but if we re-use parameters from the first connection then it might successfully connect to db3 at live_server. This'd defeat the goal of not letting a script accidentally execute commands against the wrong database. Discussion: https://postgr.es/m/38464.1603394584@sss.pgh.pa.us
This commit is contained in:
@@ -3060,26 +3060,28 @@ do_connect(enum trivalue reuse_previous_specification,
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we are to re-use parameters, there'd better be an old connection to
|
||||
* get them from.
|
||||
*/
|
||||
if (reuse_previous && !o_conn)
|
||||
{
|
||||
pg_log_error("No database connection exists to re-use parameters from");
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we intend to re-use connection parameters, collect them out of the
|
||||
* old connection, then replace individual values as necessary. Otherwise,
|
||||
* obtain a PQconninfoOption array containing libpq's defaults, and modify
|
||||
* that. Note this function assumes that PQconninfo, PQconndefaults, and
|
||||
* PQconninfoParse will all produce arrays containing the same options in
|
||||
* the same order.
|
||||
* old connection, then replace individual values as necessary. (We may
|
||||
* need to resort to looking at pset.dead_conn, if the connection died
|
||||
* previously.) Otherwise, obtain a PQconninfoOption array containing
|
||||
* libpq's defaults, and modify that. Note this function assumes that
|
||||
* PQconninfo, PQconndefaults, and PQconninfoParse will all produce arrays
|
||||
* containing the same options in the same order.
|
||||
*/
|
||||
if (reuse_previous)
|
||||
cinfo = PQconninfo(o_conn);
|
||||
{
|
||||
if (o_conn)
|
||||
cinfo = PQconninfo(o_conn);
|
||||
else if (pset.dead_conn)
|
||||
cinfo = PQconninfo(pset.dead_conn);
|
||||
else
|
||||
{
|
||||
/* This is reachable after a non-interactive \connect failure */
|
||||
pg_log_error("No database connection exists to re-use parameters from");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
cinfo = PQconndefaults();
|
||||
|
||||
@@ -3360,14 +3362,26 @@ do_connect(enum trivalue reuse_previous_specification,
|
||||
if (o_conn)
|
||||
{
|
||||
/*
|
||||
* Transition to having no connection. Keep this bit in sync
|
||||
* with CheckConnection().
|
||||
* Transition to having no connection.
|
||||
*
|
||||
* Unlike CheckConnection(), we close the old connection
|
||||
* immediately to prevent its parameters from being re-used.
|
||||
* This is so that a script cannot accidentally reuse
|
||||
* parameters it did not expect to. Otherwise, the state
|
||||
* cleanup should be the same as in CheckConnection().
|
||||
*/
|
||||
PQfinish(o_conn);
|
||||
pset.db = NULL;
|
||||
ResetCancelConn();
|
||||
UnsyncVariables();
|
||||
}
|
||||
|
||||
/* On the same reasoning, release any dead_conn to prevent reuse */
|
||||
if (pset.dead_conn)
|
||||
{
|
||||
PQfinish(pset.dead_conn);
|
||||
pset.dead_conn = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -3421,8 +3435,15 @@ do_connect(enum trivalue reuse_previous_specification,
|
||||
PQdb(pset.db), PQuser(pset.db));
|
||||
}
|
||||
|
||||
/* Drop no-longer-needed connection(s) */
|
||||
if (o_conn)
|
||||
PQfinish(o_conn);
|
||||
if (pset.dead_conn)
|
||||
{
|
||||
PQfinish(pset.dead_conn);
|
||||
pset.dead_conn = NULL;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user