Change \conninfo to use tabular format
authorÁlvaro Herrera
Sat, 22 Feb 2025 09:05:26 +0000 (10:05 +0100)
committerÁlvaro Herrera
Sat, 22 Feb 2025 09:05:26 +0000 (10:05 +0100)
(Initially the proposal was to keep \conninfo alone and add this feature
as \conninfo+, but we decided against keeping the original.)

Also display more fields than before, though not as many as were
suggested during the discussion.  In particular, we don't show 'role'
nor 'session authorization', for both which a case can probably be made.
These can be added as followup commits, if we agree to it.

Some (most?) reviewers actually reviewed rather different versions of
the patch and do not necessarily endorse the current one.

Co-authored-by: Maiquel Grassi
Co-authored-by: Hunaid Sohail
Reviewed-by: Nathan Bossart
Reviewed-by: Peter Eisentraut
Reviewed-by: Sami Imseih
Reviewed-by: David G. Johnston
Reviewed-by: Jim Jones
Reviewed-by: Tom Lane
Reviewed-by: Pavel Luzanov
Reviewed-by: Dean Rasheed
Reviewed-by: Erik Wienhold
Discussion: https://postgr.es/m/CP8P284MB24965CB63DAC00FC0EA4A475EC462@CP8P284MB2496.BRAP284.PROD.OUTLOOK.COM

doc/src/sgml/ref/psql-ref.sgml
src/bin/psql/command.c

index a8a0b694bbf00c9d64bb8a1255deca14a27d8ac0..3edbd65e46cf8cdff4d8976d39bf21ebc8bee051 100644 (file)
@@ -1070,9 +1070,10 @@ INSERT INTO tbls1 VALUES ($1, $2) \parse stmt1
       
         \conninfo
         
-        
-        Outputs information about the current database connection.
-        
+         
+          Outputs information about the current database connection,
+          including TLS-related information if TLS is in use.
+         
         
       
 
index 12d99eec5a343ab1f5e2f8415b1eb30986013488..0f27bf7a91f4d5fe491bfe8a65aaba84c70cadcd 100644 (file)
@@ -763,41 +763,169 @@ exec_command_close(PsqlScanState scan_state, bool active_branch, const char *cmd
 static backslashResult
 exec_command_conninfo(PsqlScanState scan_state, bool active_branch)
 {
-   if (active_branch)
-   {
-       char       *db = PQdb(pset.db);
-
-       if (db == NULL)
-           printf(_("You are currently not connected to a database.\n"));
+   printTableContent cont;
+   int         rows,
+               cols;
+   char       *db;
+   char       *host;
+   bool        print_hostaddr;
+   char       *hostaddr;
+   char       *protocol_version,
+              *backend_pid;
+   int         ssl_in_use,
+               password_used,
+               gssapi_used;
+   char       *paramval;
+
+   if (!active_branch)
+       return PSQL_CMD_SKIP_LINE;
+
+   db = PQdb(pset.db);
+   if (db == NULL)
+   {
+       printf(_("You are currently not connected to a database.\n"));
+       return PSQL_CMD_SKIP_LINE;
+   }
+
+   /* Get values for the parameters */
+   host = PQhost(pset.db);
+   hostaddr = PQhostaddr(pset.db);
+   protocol_version = psprintf("%d", PQprotocolVersion(pset.db));
+   ssl_in_use = PQsslInUse(pset.db);
+   password_used = PQconnectionUsedPassword(pset.db);
+   gssapi_used = PQconnectionUsedGSSAPI(pset.db);
+   backend_pid = psprintf("%d", PQbackendPID(pset.db));
+
+   /* Only print hostaddr if it differs from host, and not if unixsock */
+   print_hostaddr = (!is_unixsock_path(host) &&
+                     hostaddr && *hostaddr && strcmp(host, hostaddr) != 0);
+
+   /* Determine the exact number of rows to print */
+   rows = 12;
+   cols = 2;
+   if (ssl_in_use)
+       rows += 6;
+   if (print_hostaddr)
+       rows++;
+
+   /* Set it all up */
+   printTableInit(&cont, &pset.popt.topt, _("Connection Information"), cols, rows);
+   printTableAddHeader(&cont, _("Parameter"), true, 'l');
+   printTableAddHeader(&cont, _("Value"), true, 'l');
+
+   /* Database */
+   printTableAddCell(&cont, _("Database"), false, false);
+   printTableAddCell(&cont, db, false, false);
+
+   /* Client User */
+   printTableAddCell(&cont, _("Client User"), false, false);
+   printTableAddCell(&cont, PQuser(pset.db), false, false);
+
+   /* Host/hostaddr/socket */
+   if (is_unixsock_path(host))
+   {
+       /* hostaddr if specified overrides socket, so suppress the latter */
+       if (hostaddr && *hostaddr)
+       {
+           printTableAddCell(&cont, _("Host Address"), false, false);
+           printTableAddCell(&cont, hostaddr, false, false);
+       }
        else
        {
-           char       *host = PQhost(pset.db);
-           char       *hostaddr = PQhostaddr(pset.db);
-
-           if (is_unixsock_path(host))
-           {
-               /* hostaddr overrides host */
-               if (hostaddr && *hostaddr)
-                   printf(_("You are connected to database \"%s\" as user \"%s\" on address \"%s\" at port \"%s\".\n"),
-                          db, PQuser(pset.db), hostaddr, PQport(pset.db));
-               else
-                   printf(_("You are connected to database \"%s\" as user \"%s\" via socket in \"%s\" at port \"%s\".\n"),
-                          db, PQuser(pset.db), host, PQport(pset.db));
-           }
-           else
-           {
-               if (hostaddr && *hostaddr && strcmp(host, hostaddr) != 0)
-                   printf(_("You are connected to database \"%s\" as user \"%s\" on host \"%s\" (address \"%s\") at port \"%s\".\n"),
-                          db, PQuser(pset.db), host, hostaddr, PQport(pset.db));
-               else
-                   printf(_("You are connected to database \"%s\" as user \"%s\" on host \"%s\" at port \"%s\".\n"),
-                          db, PQuser(pset.db), host, PQport(pset.db));
-           }
-           printSSLInfo();
-           printGSSInfo();
+           printTableAddCell(&cont, _("Socket Directory"), false, false);
+           printTableAddCell(&cont, host, false, false);
+       }
+   }
+   else
+   {
+       printTableAddCell(&cont, _("Host"), false, false);
+       printTableAddCell(&cont, host, false, false);
+       if (print_hostaddr)
+       {
+           printTableAddCell(&cont, _("Host Address"), false, false);
+           printTableAddCell(&cont, hostaddr, false, false);
        }
    }
 
+   /* Server Port */
+   printTableAddCell(&cont, _("Server Port"), false, false);
+   printTableAddCell(&cont, PQport(pset.db), false, false);
+
+   /* Options */
+   printTableAddCell(&cont, _("Options"), false, false);
+   printTableAddCell(&cont, PQoptions(pset.db), false, false);
+
+   /* Protocol Version */
+   printTableAddCell(&cont, _("Protocol Version"), false, false);
+   printTableAddCell(&cont, protocol_version, false, false);
+
+   /* Password Used */
+   printTableAddCell(&cont, _("Password Used"), false, false);
+   printTableAddCell(&cont, password_used ? _("true") : _("false"), false, false);
+
+   /* GSSAPI Authenticated */
+   printTableAddCell(&cont, _("GSSAPI Authenticated"), false, false);
+   printTableAddCell(&cont, gssapi_used ? _("true") : _("false"), false, false);
+
+   /* Backend PID */
+   printTableAddCell(&cont, _("Backend PID"), false, false);
+   printTableAddCell(&cont, backend_pid, false, false);
+
+   /* TLS Connection */
+   printTableAddCell(&cont, _("TLS Connection"), false, false);
+   printTableAddCell(&cont, ssl_in_use ? _("true") : _("false"), false, false);
+
+   /* TLS Information */
+   if (ssl_in_use)
+   {
+       char       *library,
+                  *protocol,
+                  *key_bits,
+                  *cipher,
+                  *compression,
+                  *alpn;
+
+       library = (char *) PQsslAttribute(pset.db, "library");
+       protocol = (char *) PQsslAttribute(pset.db, "protocol");
+       key_bits = (char *) PQsslAttribute(pset.db, "key_bits");
+       cipher = (char *) PQsslAttribute(pset.db, "cipher");
+       compression = (char *) PQsslAttribute(pset.db, "compression");
+       alpn = (char *) PQsslAttribute(pset.db, "alpn");
+
+       printTableAddCell(&cont, _("TLS Library"), false, false);
+       printTableAddCell(&cont, library ? library : _("unknown"), false, false);
+
+       printTableAddCell(&cont, _("TLS Protocol"), false, false);
+       printTableAddCell(&cont, protocol ? protocol : _("unknown"), false, false);
+
+       printTableAddCell(&cont, _("TLS Key Bits"), false, false);
+       printTableAddCell(&cont, key_bits ? key_bits : _("unknown"), false, false);
+
+       printTableAddCell(&cont, _("TLS Cipher"), false, false);
+       printTableAddCell(&cont, cipher ? cipher : _("unknown"), false, false);
+
+       printTableAddCell(&cont, _("TLS Compression"), false, false);
+       printTableAddCell(&cont, (compression && strcmp(compression, "off") != 0) ?
+                         _("true") : _("false"), false, false);
+
+       printTableAddCell(&cont, _("ALPN"), false, false);
+       printTableAddCell(&cont, (alpn && alpn[0] != '\0') ? alpn : _("none"), false, false);
+   }
+
+   paramval = (char *) PQparameterStatus(pset.db, "is_superuser");
+   printTableAddCell(&cont, "Superuser", false, false);
+   printTableAddCell(&cont, paramval ? paramval : _("unknown"), false, false);
+
+   paramval = (char *) PQparameterStatus(pset.db, "in_hot_standby");
+   printTableAddCell(&cont, "Hot Standby", false, false);
+   printTableAddCell(&cont, paramval ? paramval : _("unknown"), false, false);
+
+   printTable(&cont, pset.queryFout, false, pset.logfile);
+   printTableCleanup(&cont);
+
+   pfree(protocol_version);
+   pfree(backend_pid);
+
    return PSQL_CMD_SKIP_LINE;
 }