Fix recently-introduced breakage in psql's \connect command.
authorTom Lane <tgl@sss.pgh.pa.us>
Sun, 29 Nov 2020 20:22:04 +0000 (15:22 -0500)
committerTom Lane <tgl@sss.pgh.pa.us>
Sun, 29 Nov 2020 20:22:04 +0000 (15:22 -0500)
Through my misreading of what the existing code actually did,
commits 85c54287a et al. broke psql's behavior for the case where
"\c connstring" provides a password in the connstring.  We should
use that password in such a case, but as of 85c54287a we ignored it
(and instead, prompted for a password).

Commit 94929f1cf fixed that in HEAD, but since I thought it was
cleaning up a longstanding misbehavior and not one I'd just created,
I didn't back-patch it.

Hence, back-patch the portions of 94929f1cf having to do with
password management.  In addition to fixing the introduced bug,
this means that "\c -reuse-previous=on connstring" will allow
re-use of an existing connection's password if the connstring
doesn't change user/host/port.  That didn't happen before, but
it seems like a bug fix, and anyway I'm loath to have significant
differences in this code across versions.

Also fix an error with the same root cause about whether or not to
override a connstring's setting of client_encoding.  As of 85c54287a
we always did so; restore the previous behavior of overriding only
when stdin/stdout are a terminal and there's no environment setting
of PGCLIENTENCODING.  (I find that definition a bit surprising, but
right now doesn't seem like the time to revisit it.)

Per bug #16746 from Krzysztof Gradek.  As with the previous patch,
back-patch to all supported branches.

Discussion: https://postgr.es/m/16746-44b30e2edf4335d4@postgresql.org

src/bin/psql/command.c

index 55b349d55a35bfa94d7df079455cc1006f471303..38b588882d154af6da7a5bad03083640c719b78e 100644 (file)
@@ -3030,6 +3030,7 @@ do_connect(enum trivalue reuse_previous_specification,
    int         nconnopts = 0;
    bool        same_host = false;
    char       *password = NULL;
+   char       *client_encoding;
    bool        success = true;
    bool        keep_password = true;
    bool        has_connection_string;
@@ -3239,6 +3240,16 @@ do_connect(enum trivalue reuse_previous_specification,
        password = prompt_for_password(has_connection_string ? NULL : user);
    }
 
+   /*
+    * Consider whether to force client_encoding to "auto" (overriding
+    * anything in the connection string).  We do so if we have a terminal
+    * connection and there is no PGCLIENTENCODING environment setting.
+    */
+   if (pset.notty || getenv("PGCLIENTENCODING"))
+       client_encoding = NULL;
+   else
+       client_encoding = "auto";
+
    /* Loop till we have a connection or fail, which we might've already */
    while (success)
    {
@@ -3279,8 +3290,9 @@ do_connect(enum trivalue reuse_previous_specification,
                values[paramnum++] = password;
            else if (strcmp(ci->keyword, "fallback_application_name") == 0)
                values[paramnum++] = pset.progname;
-           else if (strcmp(ci->keyword, "client_encoding") == 0)
-               values[paramnum++] = (pset.notty || getenv("PGCLIENTENCODING")) ? NULL : "auto";
+           else if (client_encoding &&
+                    strcmp(ci->keyword, "client_encoding") == 0)
+               values[paramnum++] = client_encoding;
            else if (ci->val)
                values[paramnum++] = ci->val;
            /* else, don't bother making libpq parse this keyword */