keep-dead-connection-for-reconnects-1.patch
text/x-diff
Filename: keep-dead-connection-for-reconnects-1.patch
Type: text/x-diff
Part: 0
Patch
Format: unified
| File | + | − |
|---|---|---|
| src/bin/psql/command.c | 29 | 15 |
| src/bin/psql/common.c | 6 | 2 |
| src/bin/psql/settings.h | 7 | 0 |
| src/bin/psql/startup.c | 5 | 1 |
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index 39a460d85c..a6b1d7533d 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -3060,26 +3060,29 @@ 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,
+ * old connection, then replace individual values as necessary. (We may
+ * need to resort to looking at pset.dead_conn, if the connection died
+ * previously or a previous non-interactive \connect failed.) 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 should be unreachable, but just in case ... */
+ pg_log_error("No database connection exists to re-use parameters from");
+ return false;
+ }
+ }
else
cinfo = PQconndefaults();
@@ -3360,10 +3363,14 @@ 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 live connection; but stash away the
+ * previous connection so that we can still refer to its
+ * parameters in a later \connect attempt. Keep this bit in
+ * sync with CheckConnection().
*/
- PQfinish(o_conn);
+ if (pset.dead_conn)
+ PQfinish(pset.dead_conn);
+ pset.dead_conn = o_conn;
pset.db = NULL;
ResetCancelConn();
UnsyncVariables();
@@ -3421,8 +3428,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;
}
diff --git a/src/bin/psql/common.c b/src/bin/psql/common.c
index 6323a35c91..80fcd6a0d6 100644
--- a/src/bin/psql/common.c
+++ b/src/bin/psql/common.c
@@ -313,10 +313,14 @@ CheckConnection(void)
fprintf(stderr, _("Failed.\n"));
/*
- * Transition to having no connection. Keep this bit in sync with
+ * Transition to having no connection; but stash away the failed
+ * connection so that we can still refer to its parameters in a
+ * later \connect attempt. Keep this bit in sync with
* do_connect().
*/
- PQfinish(pset.db);
+ if (pset.dead_conn)
+ PQfinish(pset.dead_conn);
+ pset.dead_conn = pset.db;
pset.db = NULL;
ResetCancelConn();
UnsyncVariables();
diff --git a/src/bin/psql/settings.h b/src/bin/psql/settings.h
index 97941aa10c..9601f6e90c 100644
--- a/src/bin/psql/settings.h
+++ b/src/bin/psql/settings.h
@@ -117,6 +117,13 @@ typedef struct _psqlSettings
VariableSpace vars; /* "shell variable" repository */
+ /*
+ * If we get a connection failure, the now-unusable PGconn is stashed here
+ * until we can successfully reconnect. Never attempt to do anything with
+ * this PGconn except extract parameters for a \connect attempt.
+ */
+ PGconn *dead_conn; /* previous connection to backend */
+
/*
* The remaining fields are set by assign hooks associated with entries in
* "vars". They should not be set directly except by those hook
diff --git a/src/bin/psql/startup.c b/src/bin/psql/startup.c
index 8232a0143b..e8d35a108f 100644
--- a/src/bin/psql/startup.c
+++ b/src/bin/psql/startup.c
@@ -145,6 +145,7 @@ main(int argc, char *argv[])
pset.progname = get_progname(argv[0]);
pset.db = NULL;
+ pset.dead_conn = NULL;
setDecimalLocale();
pset.encoding = PQenv2encoding();
pset.queryFout = stdout;
@@ -442,7 +443,10 @@ error:
/* clean up */
if (pset.logfile)
fclose(pset.logfile);
- PQfinish(pset.db);
+ if (pset.db)
+ PQfinish(pset.db);
+ if (pset.dead_conn)
+ PQfinish(pset.dead_conn);
setQFout(NULL);
return successResult;