public inbox for [email protected]  
help / color / mirror / Atom feed
Re: Psql meta-command conninfo+
43+ messages / 8 participants
[nested] [flat]

* Re: Psql meta-command conninfo+
@ 2024-02-06 21:50 Nathan Bossart <[email protected]>
  2024-02-07 04:13 ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  0 siblings, 1 reply; 43+ messages in thread

From: Nathan Bossart @ 2024-02-06 21:50 UTC (permalink / raw)
  To: Maiquel Grassi <[email protected]>; +Cc: Erik Wienhold <[email protected]>; pgsql-hackers

On Tue, Feb 06, 2024 at 09:45:54PM +0000, Maiquel Grassi wrote:
> My initial idea has always been that they should continue to appear
> because \conninfo+ should show all the things that \conninfo shows and
> add more information. I think that's the purpose of the 'plus.' Now we're
> on a better path than the initial one. We can still add the socket
> directory and the host.

Agreed.

-- 
Nathan Bossart
Amazon Web Services: https://aws.amazon.com






^ permalink  raw  reply  [nested|flat] 43+ messages in thread

* RE: Psql meta-command conninfo+
  2024-02-06 21:50 Re: Psql meta-command conninfo+ Nathan Bossart <[email protected]>
@ 2024-02-07 04:13 ` Maiquel Grassi <[email protected]>
  2024-02-07 09:54   ` Re: Psql meta-command conninfo+ Erik Wienhold <[email protected]>
  2024-02-07 12:35   ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  0 siblings, 2 replies; 43+ messages in thread

From: Maiquel Grassi @ 2024-02-07 04:13 UTC (permalink / raw)
  To: Nathan Bossart <[email protected]>; +Cc: Erik Wienhold <[email protected]>; pgsql-hackers

  On Tue, Feb 06, 2024 at 09:45:54PM +0000, Maiquel Grassi wrote:
  > My initial idea has always been that they should continue to appear
  > because \conninfo+ should show all the things that \conninfo shows and
  > add more information. I think that's the purpose of the 'plus.' Now we're
  > on a better path than the initial one. We can still add the socket
  > directory and the host.

  Agreed.

--//--

I believe it's resolved reasonably well this way:

SELECT
  pg_catalog.current_database() AS "Database",
  current_user AS "User",
  pg_catalog.current_setting('server_version') AS "Server Version",
  CASE
    WHEN pg_catalog.inet_server_addr() IS NULL
    THEN 'NULL'
    ELSE pg_catalog.inet_server_addr()::text
  END AS "Server Address",
  pg_catalog.current_setting('port') AS "Port",
  CASE
    WHEN pg_catalog.inet_client_addr() IS NULL
    THEN 'NULL'
    ELSE pg_catalog.inet_client_addr()::text
  END AS "Client Address",
  CASE
    WHEN pg_catalog.inet_client_port() IS NULL
    THEN 'NULL'
    ELSE pg_catalog.inet_client_port()::text
  END AS "Client Port",
  pg_catalog.pg_backend_pid() AS "Session PID",
  CASE
    WHEN pg_catalog.current_setting('unix_socket_directories') = ''
    THEN 'NULL'
    ELSE pg_catalog.current_setting('unix_socket_directories')
  END AS "Socket Directory",
  CASE
    WHEN
      pg_catalog.inet_server_addr() IS NULL
      AND pg_catalog.inet_client_addr() IS NULL
    THEN 'NULL'
    WHEN
      pg_catalog.inet_server_addr() = pg_catalog.inet_client_addr()
    THEN 'localhost'
    ELSE pg_catalog.inet_server_addr()::text
  END AS "Host";

See below the tests:

[postgres@localhost bin]$ ./psql
psql (17devel)
Type "help" for help.

postgres=# \conninfo
You are connected to database "postgres" as user "postgres" via socket in "/tmp" at port "5432".
postgres=# \conninfo+
                                                   Current Connection Information
 Database |   User   | Server Version | Server Address | Port | Client Address | Client Port | Session PID | Socket Directory | Host
----------+----------+----------------+----------------+------+----------------+-------------+-------------+------------------+------
 postgres | postgres | 17devel        | NULL           | 5432 | NULL           | NULL        |       14348 | /tmp             | NULL
(1 row)


[postgres@localhost bin]$ ./psql -h localhost
psql (17devel)
Type "help" for help.

postgres=# \conninfo
You are connected to database "postgres" as user "postgres" on host "localhost" (address "::1") at port "5432".
postgres=# \conninfo+
                                                      Current Connection Information
 Database |   User   | Server Version | Server Address | Port | Client Address | Client Port | Session PID | Socket Directory |   Host
----------+----------+----------------+----------------+------+----------------+-------------+-------------+------------------+-----------
 postgres | postgres | 17devel        | ::1/128        | 5432 | ::1/128        | 46988       |       14353 | /tmp             | localhost
(1 row)


[postgres@localhost bin]$ ./psql -h ::1
psql (17devel)
Type "help" for help.

postgres=# \conninfo
You are connected to database "postgres" as user "postgres" on host "::1" at port "5432".
postgres=# \conninfo+
                                                      Current Connection Information
 Database |   User   | Server Version | Server Address | Port | Client Address | Client Port | Session PID | Socket Directory |   Host
----------+----------+----------------+----------------+------+----------------+-------------+-------------+------------------+-----------
 postgres | postgres | 17devel        | ::1/128        | 5432 | ::1/128        | 46990       |       14356 | /tmp             | localhost
(1 row)


[postgres@localhost bin]$ ./psql -h 127.0.0.1
psql (17devel)
Type "help" for help.

postgres=# \conninfo
You are connected to database "postgres" as user "postgres" on host "127.0.0.1" at port "5432".
postgres=# \conninfo+
                                                      Current Connection Information
 Database |   User   | Server Version | Server Address | Port | Client Address | Client Port | Session PID | Socket Directory |   Host
----------+----------+----------------+----------------+------+----------------+-------------+-------------+------------------+-----------
 postgres | postgres | 17devel        | 127.0.0.1/32   | 5432 | 127.0.0.1/32   | 35042       |       14359 | /tmp             | localhost
(1 row)


[postgres@localhost bin]$ ./psql -h 192.168.0.5 -p 5433 -U postgres -d postgres
psql (17devel, server 16.1)
Type "help" for help.

postgres=# \conninfo
You are connected to database "postgres" as user "postgres" on host "192.168.0.5" at port "5433".
postgres=# \conninfo+
                                                      Current Connection Information
 Database |   User   | Server Version | Server Address | Port | Client Address | Client Port | Session PID | Socket Directory |   Host
----------+----------+----------------+----------------+------+----------------+-------------+-------------+------------------+-----------
 postgres | postgres | 16.1           | 192.168.0.5/32 | 5433 | 192.168.0.5/32 | 52783       |       18212 | NULL             | localhost
(1 row)

Regards,
Maiquel O. Grassi.


Attachments:

  [application/octet-stream] v4-0001-psql-meta-command-conninfo-plus.patch (8.7K, ../../CP8P284MB2496A17A9852265A0F363A6AEC452@CP8P284MB2496.BRAP284.PROD.OUTLOOK.COM/3-v4-0001-psql-meta-command-conninfo-plus.patch)
  download | inline diff:
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index 5c906e4..ad8e370 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -68,7 +68,8 @@ static backslashResult exec_command_C(PsqlScanState scan_state, bool active_bran
 static backslashResult exec_command_connect(PsqlScanState scan_state, bool active_branch);
 static backslashResult exec_command_cd(PsqlScanState scan_state, bool active_branch,
 									   const char *cmd);
-static backslashResult exec_command_conninfo(PsqlScanState scan_state, bool active_branch);
+static backslashResult exec_command_conninfo(PsqlScanState scan_state, bool active_branch,
+											 const char *cmd);
 static backslashResult exec_command_copy(PsqlScanState scan_state, bool active_branch);
 static backslashResult exec_command_copyright(PsqlScanState scan_state, bool active_branch);
 static backslashResult exec_command_crosstabview(PsqlScanState scan_state, bool active_branch);
@@ -317,8 +318,8 @@ exec_command(const char *cmd,
 		status = exec_command_connect(scan_state, active_branch);
 	else if (strcmp(cmd, "cd") == 0)
 		status = exec_command_cd(scan_state, active_branch, cmd);
-	else if (strcmp(cmd, "conninfo") == 0)
-		status = exec_command_conninfo(scan_state, active_branch);
+	else if (strcmp(cmd, "conninfo") == 0 || strcmp(cmd, "conninfo+") == 0)
+		status = exec_command_conninfo(scan_state, active_branch, cmd);
 	else if (pg_strcasecmp(cmd, "copy") == 0)
 		status = exec_command_copy(scan_state, active_branch);
 	else if (strcmp(cmd, "copyright") == 0)
@@ -643,47 +644,74 @@ exec_command_cd(PsqlScanState scan_state, bool active_branch, const char *cmd)
 }
 
 /*
- * \conninfo -- display information about the current connection
+ * \conninfo, \conninfo+ -- display information about the current connection
  */
 static backslashResult
-exec_command_conninfo(PsqlScanState scan_state, bool active_branch)
+exec_command_conninfo(PsqlScanState scan_state, bool active_branch, const char *cmd)
 {
+	bool		success = true;
+
 	if (active_branch)
 	{
 		char	   *db = PQdb(pset.db);
+		char	   *pattern;
+		bool		show_verbose;
 
-		if (db == NULL)
-			printf(_("You are currently not connected to a database.\n"));
-		else
+		pattern = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, true);
+
+		show_verbose = strchr(cmd, '+') ? true : false;
+
+		/*
+		 * \conninfo+
+		 */
+		if (show_verbose)
 		{
-			char	   *host = PQhost(pset.db);
-			char	   *hostaddr = PQhostaddr(pset.db);
+			success = listConnectionInformation(pattern, show_verbose);
+			free(pattern);
+			printSSLInfo();
+			printGSSInfo();
+		}
 
-			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));
-			}
+		/*
+		 * \conninfo
+		 */
+		else
+		{
+			if (db == NULL)
+				printf(_("You are currently not connected to a database.\n"));
 			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));
+				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
-					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));
+				{
+					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();
 			}
-			printSSLInfo();
-			printGSSInfo();
 		}
 	}
+	else
+		ignore_slash_options(scan_state);
 
-	return PSQL_CMD_SKIP_LINE;
+	return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
 }
 
 /*
diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index b6a4eb1..93ca62a 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -901,6 +901,71 @@ error_return:
 	return false;
 }
 
+/*
+ * listConnectionInformation
+ *
+ * for \conninfo+
+ */
+bool
+listConnectionInformation(const char *pattern, bool verbose)
+{
+    PGresult   *res;
+    PQExpBufferData buf;
+    printQueryOpt myopt = pset.popt;
+
+    initPQExpBuffer(&buf);
+
+    printfPQExpBuffer(&buf,
+                      "SELECT\n"
+                      "  pg_catalog.current_database() AS \"Database\",\n"
+                      "  current_user AS \"User\",\n"
+                      "  pg_catalog.current_setting('server_version') AS \"Server Version\",\n"
+                      "  CASE\n"
+                      "    WHEN pg_catalog.inet_server_addr() IS NULL\n"
+                      "    THEN 'NULL'\n"
+                      "    ELSE pg_catalog.inet_server_addr()::text\n"
+                      "  END AS \"Server Address\",\n"
+                      "  pg_catalog.current_setting('port') AS \"Port\",\n"
+                      "  CASE\n"
+                      "    WHEN pg_catalog.inet_client_addr() IS NULL\n"ting('unix_socket_directories') = ''\n"
+                      "    THEN 'NULL'\n"
+                      "    ELSE pg_catalog.inet_client_addr()::text\n"
+                      "  END AS \"Client Address\",\n"
+                      "  CASE\n"
+                      "    WHEN pg_catalog.inet_client_port() IS NULL\n"
+                      "    THEN 'NULL'\n"
+                      "    ELSE pg_catalog.inet_client_port()::text\n"
+                      "  END AS \"Client Port\",\n"
+                      "  pg_catalog.pg_backend_pid() AS \"Session PID\",\n"
+                      "  CASE\n"
+                      "    WHEN pg_catalog.current_setting('unix_socket_directories') = ''\n"
+                      "    THEN 'NULL'\n"
+                      "    ELSE pg_catalog.current_setting('unix_socket_directories')\n"
+                      "  END AS \"Socket Directory\",\n"
+                      "  CASE\n"
+                      "    WHEN\n"
+                      "      pg_catalog.inet_server_addr() IS NULL\n"
+                      "      AND pg_catalog.inet_client_addr() IS NULL\n"
+                      "    THEN 'NULL'\n"
+                      "    WHEN\n"
+                      "      pg_catalog.inet_server_addr() = pg_catalog.inet_client_addr()\n"
+                      "    THEN 'localhost'\n"
+                      "    ELSE pg_catalog.inet_server_addr()::text\n"
+                      "  END AS \"Host\";");
+
+    res = PSQLexec(buf.data);
+    termPQExpBuffer(&buf);
+    if (!res)
+        return false;
+
+    myopt.title = _("Current Connection Information");
+    myopt.translate_header = true;
+
+    printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
+
+    PQclear(res);
+    return true;
+}
 
 /*
  * listAllDbs
diff --git a/src/bin/psql/describe.h b/src/bin/psql/describe.h
index 273f974..b638c71 100644
--- a/src/bin/psql/describe.h
+++ b/src/bin/psql/describe.h
@@ -149,4 +149,7 @@ extern bool listOpFamilyFunctions(const char *access_method_pattern,
 /* \dl or \lo_list */
 extern bool listLargeObjects(bool verbose);
 
+/* \conninfo */
+extern bool listConnectionInformation(const char *pattern, bool verbose);
+
 #endif							/* DESCRIBE_H */
diff --git a/src/bin/psql/help.c b/src/bin/psql/help.c
index 4e79a81..2c5426d 100644
--- a/src/bin/psql/help.c
+++ b/src/bin/psql/help.c
@@ -310,7 +310,7 @@ slashUsage(unsigned short int pager)
 	else
 		HELP0("  \\c[onnect] {[DBNAME|- USER|- HOST|- PORT|-] | conninfo}\n"
 			  "                         connect to new database (currently no connection)\n");
-	HELP0("  \\conninfo              display information about current connection\n");
+	HELP0("  \\conninfo[+]           display information about current connection\n");
 	HELP0("  \\encoding [ENCODING]   show or set client encoding\n");
 	HELP0("  \\password [USERNAME]   securely change the password for a user\n");
 	HELP0("\n");


^ permalink  raw  reply  [nested|flat] 43+ messages in thread

* Re: Psql meta-command conninfo+
  2024-02-06 21:50 Re: Psql meta-command conninfo+ Nathan Bossart <[email protected]>
  2024-02-07 04:13 ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
@ 2024-02-07 09:54   ` Erik Wienhold <[email protected]>
  2024-02-07 12:41     ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  1 sibling, 1 reply; 43+ messages in thread

From: Erik Wienhold @ 2024-02-07 09:54 UTC (permalink / raw)
  To: Maiquel Grassi <[email protected]>; +Cc: Nathan Bossart <[email protected]>; pgsql-hackers

On 2024-02-07 05:13 +0100, Maiquel Grassi wrote:
>   On Tue, Feb 06, 2024 at 09:45:54PM +0000, Maiquel Grassi wrote:
>   > My initial idea has always been that they should continue to appear
>   > because \conninfo+ should show all the things that \conninfo shows and
>   > add more information. I think that's the purpose of the 'plus.' Now we're
>   > on a better path than the initial one. We can still add the socket
>   > directory and the host.
> 
>   Agreed.
> 
> --//--
> 
> I believe it's resolved reasonably well this way:
> 
> SELECT
>   pg_catalog.current_database() AS "Database",
>   current_user AS "User",
>   pg_catalog.current_setting('server_version') AS "Server Version",
>   CASE
>     WHEN pg_catalog.inet_server_addr() IS NULL
>     THEN 'NULL'
>     ELSE pg_catalog.inet_server_addr()::text
>   END AS "Server Address",

Should be NULL instead of string 'NULL'.  So the entire CASE expression
is redundant and you can just return pg_catalog.inet_server_addr().

>   pg_catalog.current_setting('port') AS "Port",
>   CASE
>     WHEN pg_catalog.inet_client_addr() IS NULL
>     THEN 'NULL'
>     ELSE pg_catalog.inet_client_addr()::text
>   END AS "Client Address",
>   CASE
>     WHEN pg_catalog.inet_client_port() IS NULL
>     THEN 'NULL'
>     ELSE pg_catalog.inet_client_port()::text
>   END AS "Client Port",

Same here.

>   pg_catalog.pg_backend_pid() AS "Session PID",
>   CASE
>     WHEN pg_catalog.current_setting('unix_socket_directories') = ''
>     THEN 'NULL'
>     ELSE pg_catalog.current_setting('unix_socket_directories')
>   END AS "Socket Directory",

The CASE expression can be simplified to:

	nullif(pg_catalog.current_setting('unix_socket_directories'), '')

>   CASE
>     WHEN
>       pg_catalog.inet_server_addr() IS NULL
>       AND pg_catalog.inet_client_addr() IS NULL
>     THEN 'NULL'
>     WHEN
>       pg_catalog.inet_server_addr() = pg_catalog.inet_client_addr()
>     THEN 'localhost'

Is it safe to assume localhost here?  \conninfo prints localhost only
when I connect with psql -hlocalhost:

	$ psql -hlocalhost postgres
	psql (16.1)
	postgres=# \conninfo
	You are connected to database "postgres" as user "ewie" on host "localhost" (address "::1") at port "5432".
	postgres=# \q

	$ psql -h127.0.0.1 postgres
	psql (16.1)
	postgres=# \conninfo
	You are connected to database "postgres" as user "ewie" on host "127.0.0.1" at port "5432".

>     ELSE pg_catalog.inet_server_addr()::text
>   END AS "Host";

-- 
Erik






^ permalink  raw  reply  [nested|flat] 43+ messages in thread

* RE: Psql meta-command conninfo+
  2024-02-06 21:50 Re: Psql meta-command conninfo+ Nathan Bossart <[email protected]>
  2024-02-07 04:13 ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-07 09:54   ` Re: Psql meta-command conninfo+ Erik Wienhold <[email protected]>
@ 2024-02-07 12:41     ` Maiquel Grassi <[email protected]>
  0 siblings, 0 replies; 43+ messages in thread

From: Maiquel Grassi @ 2024-02-07 12:41 UTC (permalink / raw)
  To: Erik Wienhold <[email protected]>; +Cc: Nathan Bossart <[email protected]>; pgsql-hackers

  On 2024-02-07 05:13 +0100, Maiquel Grassi wrote:
  >   On Tue, Feb 06, 2024 at 09:45:54PM +0000, Maiquel Grassi wrote:
  >   > My initial idea has always been that they should continue to appear
  >   > because \conninfo+ should show all the things that \conninfo shows and
  >   > add more information. I think that's the purpose of the 'plus.' Now we're
  >   > on a better path than the initial one. We can still add the socket
  >   > directory and the host.
  >
  >   Agreed.
  >
  > --//--
  >
  > I believe it's resolved reasonably well this way:
  >
  > SELECT
  >   pg_catalog.current_database() AS "Database",
  >   current_user AS "User",
  >   pg_catalog.current_setting('server_version') AS "Server Version",
  >   CASE
  >     WHEN pg_catalog.inet_server_addr() IS NULL
  >     THEN 'NULL'
  >     ELSE pg_catalog.inet_server_addr()::text
  >   END AS "Server Address",

  Should be NULL instead of string 'NULL'.  So the entire CASE expression
  is redundant and you can just return pg_catalog.inet_server_addr().

  >   pg_catalog.current_setting('port') AS "Port",
  >   CASE
  >     WHEN pg_catalog.inet_client_addr() IS NULL
  >     THEN 'NULL'
  >     ELSE pg_catalog.inet_client_addr()::text
  >   END AS "Client Address",
  >   CASE
  >     WHEN pg_catalog.inet_client_port() IS NULL
  >      THEN 'NULL'
  >     ELSE pg_catalog.inet_client_port()::text
  >   END AS "Client Port",

  Same here.

  >   pg_catalog.pg_backend_pid() AS "Session PID",
  >   CASE
  >     WHEN pg_catalog.current_setting('unix_socket_directories') = ''
  >     THEN 'NULL'
  >     ELSE pg_catalog.current_setting('unix_socket_directories')
  >   END AS "Socket Directory",

  The CASE expression can be simplified to:

          nullif(pg_catalog.current_setting('unix_socket_directories'), '')

  >   CASE
  >     WHEN
  >       pg_catalog.inet_server_addr() IS NULL
  >       AND pg_catalog.inet_client_addr() IS NULL
  >     THEN 'NULL'
  >     WHEN
  >       pg_catalog.inet_server_addr() = pg_catalog.inet_client_addr()
  >     THEN 'localhost'

  Is it safe to assume localhost here?  \conninfo prints localhost only
  when I connect with psql -hlocalhost:

          $ psql -hlocalhost postgres
          psql (16.1)
          postgres=# \conninfo
          You are connected to database "postgres" as user "ewie" on host "localhost" (address "::1") at port "5432".
          postgres=# \q

          $ psql -h127.0.0.1 postgres
          psql (16.1)
          postgres=# \conninfo
          You are connected to database "postgres" as user "ewie" on host "127.0.0.1" at port "5432".

  >     ELSE pg_catalog.inet_server_addr()::text
  >   END AS "Host";

--//--

There really was no need for the CASES. However, they helped visualize the psql output since for the null value, no word is printed on the screen. I made the adjustment by removing this redundancy.

Regarding the "Host" column, the most reliable way to solve this, I believe, is by using the "host" variable. So it's necessary to declare char *host = PQhost(pset.db); in listConnectionInformation() and use it in the SQL (see patch v5). This way, we have the same return from \conninfo reliably.

Once again, I ran a series of tests.

[postgres@localhost bin]$ ./psql
psql (17devel)
Type "help" for help.

postgres=# \conninfo
You are connected to database "postgres" as user "postgres" via socket in "/tmp" at port "5432".
postgres=# \conninfo+
                                                       Current Connection Information
 Database |   User   | Server Version | Server Address | Server Port | Client Address | Client Port | Session PID | Socket Directory | Host
----------+----------+----------------+----------------+-------------+----------------+-------------+-------------+------------------+------
 postgres | postgres | 17devel        |                | 5432        |                |             |       15898 | /tmp             |
(1 row)

postgres=# \q
[postgres@localhost bin]$ ./psql -h localhost
psql (17devel)
Type "help" for help.

postgres=# \conninfo
You are connected to database "postgres" as user "postgres" on host "localhost" (address "::1") at port "5432".
postgres=# \conninfo+
                                                         Current Connection Information
 Database |   User   | Server Version | Server Address | Server Port | Client Address | Client Port | Session PID | Socket Directory |   Host
----------+----------+----------------+----------------+-------------+----------------+-------------+-------------+------------------+-----------
 postgres | postgres | 17devel        | ::1            | 5432        | ::1            |       47012 |       15900 | /tmp             | localhost
(1 row)

postgres=# \q
[postgres@localhost bin]$ ./psql -h ::1
psql (17devel)
Type "help" for help.

postgres=# \conninfo
You are connected to database "postgres" as user "postgres" on host "::1" at port "5432".
postgres=# \conninfo+
                                                       Current Connection Information
 Database |   User   | Server Version | Server Address | Server Port | Client Address | Client Port | Session PID | Socket Directory | Host
----------+----------+----------------+----------------+-------------+----------------+-------------+-------------+------------------+------
 postgres | postgres | 17devel        | ::1            | 5432        | ::1            |       47014 |       15905 | /tmp             | ::1
(1 row)

postgres=# \q
[postgres@localhost bin]$ ./psql -h 127.0.0.1
psql (17devel)
Type "help" for help.

postgres=# \conninfo
You are connected to database "postgres" as user "postgres" on host "127.0.0.1" at port "5432".
postgres=# \conninfo+
                                                         Current Connection Information
 Database |   User   | Server Version | Server Address | Server Port | Client Address | Client Port | Session PID | Socket Directory |   Host
----------+----------+----------------+----------------+-------------+----------------+-------------+-------------+------------------+-----------
 postgres | postgres | 17devel        | 127.0.0.1      | 5432        | 127.0.0.1      |       35066 |       15908 | /tmp             | 127.0.0.1
(1 row)

postgres=# \q
[postgres@localhost bin]$ ./psql -h 192.168.0.5 -p 5432 -d postgres -U postgres
psql (17devel, server 14.3)
Type "help" for help.

postgres=# \conninfo
You are connected to database "postgres" as user "postgres" on host "192.168.0.5" at port "5432".
postgres=# \conninfo+
                                                          Current Connection Information
 Database |   User   | Server Version | Server Address | Server Port | Client Address | Client Port | Session PID | Socket Directory |    Host
----------+----------+----------------+----------------+-------------+----------------+-------------+-------------+------------------+-------------
 postgres | postgres | 14.3           | 192.168.0.5    | 5432        | 192.168.0.5    |       60904 |       29264 |                  | 192.168.0.5

Regards,
Maiquel O. Grassi.


Attachments:

  [application/octet-stream] v5-0001-psql-meta-command-conninfo-plus.patch (7.8K, ../../CP8P284MB249690D959F698EF3187D8AEEC452@CP8P284MB2496.BRAP284.PROD.OUTLOOK.COM/3-v5-0001-psql-meta-command-conninfo-plus.patch)
  download | inline diff:
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index 5c906e4..ad8e370 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -68,7 +68,8 @@ static backslashResult exec_command_C(PsqlScanState scan_state, bool active_bran
 static backslashResult exec_command_connect(PsqlScanState scan_state, bool active_branch);
 static backslashResult exec_command_cd(PsqlScanState scan_state, bool active_branch,
 									   const char *cmd);
-static backslashResult exec_command_conninfo(PsqlScanState scan_state, bool active_branch);
+static backslashResult exec_command_conninfo(PsqlScanState scan_state, bool active_branch,
+											 const char *cmd);
 static backslashResult exec_command_copy(PsqlScanState scan_state, bool active_branch);
 static backslashResult exec_command_copyright(PsqlScanState scan_state, bool active_branch);
 static backslashResult exec_command_crosstabview(PsqlScanState scan_state, bool active_branch);
@@ -317,8 +318,8 @@ exec_command(const char *cmd,
 		status = exec_command_connect(scan_state, active_branch);
 	else if (strcmp(cmd, "cd") == 0)
 		status = exec_command_cd(scan_state, active_branch, cmd);
-	else if (strcmp(cmd, "conninfo") == 0)
-		status = exec_command_conninfo(scan_state, active_branch);
+	else if (strcmp(cmd, "conninfo") == 0 || strcmp(cmd, "conninfo+") == 0)
+		status = exec_command_conninfo(scan_state, active_branch, cmd);
 	else if (pg_strcasecmp(cmd, "copy") == 0)
 		status = exec_command_copy(scan_state, active_branch);
 	else if (strcmp(cmd, "copyright") == 0)
@@ -643,47 +644,74 @@ exec_command_cd(PsqlScanState scan_state, bool active_branch, const char *cmd)
 }
 
 /*
- * \conninfo -- display information about the current connection
+ * \conninfo, \conninfo+ -- display information about the current connection
  */
 static backslashResult
-exec_command_conninfo(PsqlScanState scan_state, bool active_branch)
+exec_command_conninfo(PsqlScanState scan_state, bool active_branch, const char *cmd)
 {
+	bool		success = true;
+
 	if (active_branch)
 	{
 		char	   *db = PQdb(pset.db);
+		char	   *pattern;
+		bool		show_verbose;
 
-		if (db == NULL)
-			printf(_("You are currently not connected to a database.\n"));
-		else
+		pattern = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, true);
+
+		show_verbose = strchr(cmd, '+') ? true : false;
+
+		/*
+		 * \conninfo+
+		 */
+		if (show_verbose)
 		{
-			char	   *host = PQhost(pset.db);
-			char	   *hostaddr = PQhostaddr(pset.db);
+			success = listConnectionInformation(pattern, show_verbose);
+			free(pattern);
+			printSSLInfo();
+			printGSSInfo();
+		}
 
-			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));
-			}
+		/*
+		 * \conninfo
+		 */
+		else
+		{
+			if (db == NULL)
+				printf(_("You are currently not connected to a database.\n"));
 			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));
+				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
-					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));
+				{
+					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();
 			}
-			printSSLInfo();
-			printGSSInfo();
 		}
 	}
+	else
+		ignore_slash_options(scan_state);
 
-	return PSQL_CMD_SKIP_LINE;
+	return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
 }
 
 /*
diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index b6a4eb1..5ff4e9d 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -901,6 +901,55 @@ error_return:
 	return false;
 }
 
+/*
+ * listConnectionInformation
+ *
+ * for \conninfo+
+ */
+bool
+listConnectionInformation(const char *pattern, bool verbose)
+{
+    PGresult   *res;
+    PQExpBufferData buf;
+    printQueryOpt myopt = pset.popt;
+
+    char       *host = PQhost(pset.db);
+
+    initPQExpBuffer(&buf);
+
+    printfPQExpBuffer(&buf,
+                      "SELECT\n"
+                      "  pg_catalog.current_database() AS \"Database\",\n"
+                      "  current_user AS \"User\",\n"
+                      "  pg_catalog.current_setting('server_version') AS \"Server Version\",\n"
+                      "  pg_catalog.inet_server_addr() AS \"Server Address\",\n"
+                      "  pg_catalog.current_setting('port') AS \"Server Port\",\n"
+                      "  pg_catalog.inet_client_addr() AS \"Client Address\",\n"
+                      "  pg_catalog.inet_client_port() AS \"Client Port\",\n"
+                      "  pg_catalog.pg_backend_pid() AS \"Session PID\",\n"
+                      "  NULLIF(pg_catalog.current_setting('unix_socket_directories'),'') AS \"Socket Directory\",\n"
+                      "  CASE\n"
+                      "    WHEN\n"
+                      "      pg_catalog.inet_server_addr() IS NULL\n"
+                      "      AND pg_catalog.inet_client_addr() IS NULL\n"
+                      "    THEN NULL\n"
+                      "    ELSE '%s'\n"
+                      "  END AS \"Host\";",
+                      host);
+
+    res = PSQLexec(buf.data);
+    termPQExpBuffer(&buf);
+    if (!res)
+        return false;
+
+    myopt.title = _("Current Connection Information");
+    myopt.translate_header = true;
+
+    printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
+
+    PQclear(res);
+    return true;
+}
 
 /*
  * listAllDbs
diff --git a/src/bin/psql/describe.h b/src/bin/psql/describe.h
index 273f974..b638c71 100644
--- a/src/bin/psql/describe.h
+++ b/src/bin/psql/describe.h
@@ -149,4 +149,7 @@ extern bool listOpFamilyFunctions(const char *access_method_pattern,
 /* \dl or \lo_list */
 extern bool listLargeObjects(bool verbose);
 
+/* \conninfo */
+extern bool listConnectionInformation(const char *pattern, bool verbose);
+
 #endif							/* DESCRIBE_H */
diff --git a/src/bin/psql/help.c b/src/bin/psql/help.c
index 4e79a81..2c5426d 100644
--- a/src/bin/psql/help.c
+++ b/src/bin/psql/help.c
@@ -310,7 +310,7 @@ slashUsage(unsigned short int pager)
 	else
 		HELP0("  \\c[onnect] {[DBNAME|- USER|- HOST|- PORT|-] | conninfo}\n"
 			  "                         connect to new database (currently no connection)\n");
-	HELP0("  \\conninfo              display information about current connection\n");
+	HELP0("  \\conninfo[+]           display information about current connection\n");
 	HELP0("  \\encoding [ENCODING]   show or set client encoding\n");
 	HELP0("  \\password [USERNAME]   securely change the password for a user\n");
 	HELP0("\n");


^ permalink  raw  reply  [nested|flat] 43+ messages in thread

* Re: Psql meta-command conninfo+
  2024-02-06 21:50 Re: Psql meta-command conninfo+ Nathan Bossart <[email protected]>
  2024-02-07 04:13 ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
@ 2024-02-07 12:35   ` Pavel Luzanov <[email protected]>
  2024-02-07 14:47     ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  1 sibling, 1 reply; 43+ messages in thread

From: Pavel Luzanov @ 2024-02-07 12:35 UTC (permalink / raw)
  To: Maiquel Grassi <[email protected]>; Nathan Bossart <[email protected]>; +Cc: Erik Wienhold <[email protected]>; pgsql-hackers

This is a good idea about extended connection info.

On 07.02.2024 07:13, Maiquel Grassi wrote:
> SELECT
> ...
> current_user AS "User",

This will be inconsistent with \conninfo.
\conninfo returns authenticated user (PQuser), not the current_user.
It might be worth showing current_user, session_user, and authenticated user,
but I can't find the appropriate sql function for PQuser.

What about to include system_user function? It shows useful authentication details.

Also, it seems that the verbose parameter in the listConnectionInformation
is unnecessary.

-- 
Pavel Luzanov
Postgres Professional:https://postgrespro.com


^ permalink  raw  reply  [nested|flat] 43+ messages in thread

* RE: Psql meta-command conninfo+
  2024-02-06 21:50 Re: Psql meta-command conninfo+ Nathan Bossart <[email protected]>
  2024-02-07 04:13 ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-07 12:35   ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
@ 2024-02-07 14:47     ` Maiquel Grassi <[email protected]>
  2024-02-07 16:40       ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  0 siblings, 1 reply; 43+ messages in thread

From: Maiquel Grassi @ 2024-02-07 14:47 UTC (permalink / raw)
  To: Pavel Luzanov <[email protected]>; Nathan Bossart <[email protected]>; +Cc: Erik Wienhold <[email protected]>; pgsql-hackers

  This is a good idea about extended connection info.

  On 07.02.2024 07:13, Maiquel Grassi wrote:
SELECT
...
  current_user AS "User",

  This will be inconsistent with \conninfo.
  \conninfo returns authenticated user (PQuser), not the current_user.
  It might be worth showing current_user, session_user, and authenticated user,
  but I can't find the appropriate sql function for PQuser.

  What about to include system_user function? It shows useful authentication details.

  Also, it seems that the verbose parameter in the listConnectionInformation
  is unnecessary.

--//--

Hi,

Tks Pavel.

Analyzing the functions' code more thoroughly, it seems to make more sense.
I liked your suggestions and implemented them for validation.
Regarding "system_user," I believe it is valid and also added it to the row.

"Also, it seems that the verbose parameter in the listConnectionInformation is unnecessary."
Could you point out exactly the line or code snippet you are referring to?

To print the string from the "Authenticated User" column, I chose to use PQuser(pset.db) directly. I did the same for the "Host" column, opting for PQhost(pset.db). This does not contradict the result of \conninfo.

Here are the tests as usual, and v6 patch.

[postgres@localhost bin]$ ./psql
psql (17devel)
Type "help" for help.

postgres=# \conninfo
You are connected to database "postgres" as user "postgres" via socket in "/tmp" at port "5432".
postgres=# \conninfo+
                                                                                  Current Connection Information
 Database | Authenticated User | Current User | Session User | System User | Server Version | Server Address | Server Port | Client Address | Client Port | Session PID | Socket Directory | Host
----------+--------------------+--------------+--------------+-------------+----------------+----------------+-------------+----------------+-------------+-------------+------------------+------
 postgres | postgres           | postgres     | postgres     |             | 17devel        |                | 5432        |                |             |       17240 | /tmp             |
(1 row)

postgres=# \q
[postgres@localhost bin]$ ./psql -h ::1
psql (17devel)
Type "help" for help.

postgres=# \conninfo
You are connected to database "postgres" as user "postgres" on host "::1" at port "5432".
postgres=# \conninfo+
                                                                                  Current Connection Information
 Database | Authenticated User | Current User | Session User | System User | Server Version | Server Address | Server Port | Client Address | Client Port | Session PID | Socket Directory | Host
----------+--------------------+--------------+--------------+-------------+----------------+----------------+-------------+----------------+-------------+-------------+------------------+------
 postgres | postgres           | postgres     | postgres     |             | 17devel        | ::1            | 5432        | ::1            |       47024 |       17242 | /tmp             | ::1
(1 row)

postgres=# \q
[postgres@localhost bin]$ ./psql -h 127.0.0.1
psql (17devel)
Type "help" for help.

postgres=# \conninfo
You are connected to database "postgres" as user "postgres" on host "127.0.0.1" at port "5432".
postgres=# \conninfo+
                                                                                    Current Connection Information
 Database | Authenticated User | Current User | Session User | System User | Server Version | Server Address | Server Port | Client Address | Client Port | Session PID | Socket Directory |   Host
----------+--------------------+--------------+--------------+-------------+----------------+----------------+-------------+----------------+-------------+-------------+------------------+-----------
 postgres | postgres           | postgres     | postgres     |             | 17devel        | 127.0.0.1      | 5432        | 127.0.0.1      |       35076 |       17245 | /tmp             | 127.0.0.1
(1 row)

postgres=# \q
[postgres@localhost bin]$ ./psql -h localhost
psql (17devel)
Type "help" for help.

postgres=# \conninfo
You are connected to database "postgres" as user "postgres" on host "localhost" (address "::1") at port "5432".
postgres=# \conninfo+
                                                                                    Current Connection Information
 Database | Authenticated User | Current User | Session User | System User | Server Version | Server Address | Server Port | Client Address | Client Port | Session PID | Socket Directory |   Host
----------+--------------------+--------------+--------------+-------------+----------------+----------------+-------------+----------------+-------------+-------------+------------------+-----------
 postgres | postgres           | postgres     | postgres     |             | 17devel        | ::1            | 5432        | ::1            |       47028 |       17248 | /tmp             | localhost
(1 row)

postgres=# \q
[postgres@localhost bin]$ ./psql -h 192.168.0.5 -p 5433 -d postgres -U postgres
psql (17devel, server 16.1)
Type "help" for help.

postgres=# \conninfo
You are connected to database "postgres" as user "postgres" on host "192.168.0.5" at port "5433".
postgres=# \conninfo+
                                                                                     Current Connection Information
 Database | Authenticated User | Current User | Session User | System User | Server Version | Server Address | Server Port | Client Address | Client Port | Session PID | Socket Directory |    Host
----------+--------------------+--------------+--------------+-------------+----------------+----------------+-------------+----------------+-------------+-------------+------------------+-------------
 postgres | postgres           | postgres     | postgres     |             | 16.1           | 192.168.0.5    | 5433        | 192.168.0.5    |       60115 |       28896 |                  | 192.168.0.5
(1 row)

Regards,
Maiquel O. Grassi.


Attachments:

  [application/octet-stream] v6-0001-psql-meta-command-conninfo-plus.patch (8.0K, ../../CP8P284MB24961361A9C1D32C28A7EC0EEC452@CP8P284MB2496.BRAP284.PROD.OUTLOOK.COM/3-v6-0001-psql-meta-command-conninfo-plus.patch)
  download | inline diff:
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index 5c906e4..ad8e370 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -68,7 +68,8 @@ static backslashResult exec_command_C(PsqlScanState scan_state, bool active_bran
 static backslashResult exec_command_connect(PsqlScanState scan_state, bool active_branch);
 static backslashResult exec_command_cd(PsqlScanState scan_state, bool active_branch,
 									   const char *cmd);
-static backslashResult exec_command_conninfo(PsqlScanState scan_state, bool active_branch);
+static backslashResult exec_command_conninfo(PsqlScanState scan_state, bool active_branch,
+											 const char *cmd);
 static backslashResult exec_command_copy(PsqlScanState scan_state, bool active_branch);
 static backslashResult exec_command_copyright(PsqlScanState scan_state, bool active_branch);
 static backslashResult exec_command_crosstabview(PsqlScanState scan_state, bool active_branch);
@@ -317,8 +318,8 @@ exec_command(const char *cmd,
 		status = exec_command_connect(scan_state, active_branch);
 	else if (strcmp(cmd, "cd") == 0)
 		status = exec_command_cd(scan_state, active_branch, cmd);
-	else if (strcmp(cmd, "conninfo") == 0)
-		status = exec_command_conninfo(scan_state, active_branch);
+	else if (strcmp(cmd, "conninfo") == 0 || strcmp(cmd, "conninfo+") == 0)
+		status = exec_command_conninfo(scan_state, active_branch, cmd);
 	else if (pg_strcasecmp(cmd, "copy") == 0)
 		status = exec_command_copy(scan_state, active_branch);
 	else if (strcmp(cmd, "copyright") == 0)
@@ -643,47 +644,74 @@ exec_command_cd(PsqlScanState scan_state, bool active_branch, const char *cmd)
 }
 
 /*
- * \conninfo -- display information about the current connection
+ * \conninfo, \conninfo+ -- display information about the current connection
  */
 static backslashResult
-exec_command_conninfo(PsqlScanState scan_state, bool active_branch)
+exec_command_conninfo(PsqlScanState scan_state, bool active_branch, const char *cmd)
 {
+	bool		success = true;
+
 	if (active_branch)
 	{
 		char	   *db = PQdb(pset.db);
+		char	   *pattern;
+		bool		show_verbose;
 
-		if (db == NULL)
-			printf(_("You are currently not connected to a database.\n"));
-		else
+		pattern = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, true);
+
+		show_verbose = strchr(cmd, '+') ? true : false;
+
+		/*
+		 * \conninfo+
+		 */
+		if (show_verbose)
 		{
-			char	   *host = PQhost(pset.db);
-			char	   *hostaddr = PQhostaddr(pset.db);
+			success = listConnectionInformation(pattern, show_verbose);
+			free(pattern);
+			printSSLInfo();
+			printGSSInfo();
+		}
 
-			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));
-			}
+		/*
+		 * \conninfo
+		 */
+		else
+		{
+			if (db == NULL)
+				printf(_("You are currently not connected to a database.\n"));
 			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));
+				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
-					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));
+				{
+					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();
 			}
-			printSSLInfo();
-			printGSSInfo();
 		}
 	}
+	else
+		ignore_slash_options(scan_state);
 
-	return PSQL_CMD_SKIP_LINE;
+	return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
 }
 
 /*
diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index b6a4eb1..c17c4a9 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -901,6 +901,57 @@ error_return:
 	return false;
 }
 
+/*
+ * listConnectionInformation
+ *
+ * for \conninfo+
+ */
+bool
+listConnectionInformation(const char *pattern, bool verbose)
+{
+    PGresult   *res;
+    PQExpBufferData buf;
+    printQueryOpt myopt = pset.popt;
+
+    initPQExpBuffer(&buf);
+
+    printfPQExpBuffer(&buf,
+                      "SELECT\n"
+                      "  pg_catalog.current_database() AS \"Database\",\n"
+                      "  '%s' AS \"Authenticated User\",\n"
+                      "  pg_catalog.current_user() AS \"Current User\",\n"
+                      "  pg_catalog.session_user() AS \"Session User\",\n"
+                      "  pg_catalog.system_user() AS \"System User\",\n"
+                      "  pg_catalog.current_setting('server_version') AS \"Server Version\",\n"
+                      "  pg_catalog.inet_server_addr() AS \"Server Address\",\n"
+                      "  pg_catalog.current_setting('port') AS \"Server Port\",\n"
+                      "  pg_catalog.inet_client_addr() AS \"Client Address\",\n"
+                      "  pg_catalog.inet_client_port() AS \"Client Port\",\n"
+                      "  pg_catalog.pg_backend_pid() AS \"Session PID\",\n"
+                      "  NULLIF(pg_catalog.current_setting('unix_socket_directories'),'') AS \"Socket Directory\",\n"
+                      "  CASE\n"
+                      "    WHEN\n"
+                      "      pg_catalog.inet_server_addr() IS NULL\n"
+                      "      AND pg_catalog.inet_client_addr() IS NULL\n"
+                      "    THEN NULL\n"
+                      "    ELSE '%s'\n"
+                      "  END AS \"Host\";",
+                      PQuser(pset.db),
+                      PQhost(pset.db));
+
+    res = PSQLexec(buf.data);
+    termPQExpBuffer(&buf);
+    if (!res)
+        return false;
+
+    myopt.title = _("Current Connection Information");
+    myopt.translate_header = true;
+
+    printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
+
+    PQclear(res);
+    return true;
+}
 
 /*
  * listAllDbs
diff --git a/src/bin/psql/describe.h b/src/bin/psql/describe.h
index 273f974..b638c71 100644
--- a/src/bin/psql/describe.h
+++ b/src/bin/psql/describe.h
@@ -149,4 +149,7 @@ extern bool listOpFamilyFunctions(const char *access_method_pattern,
 /* \dl or \lo_list */
 extern bool listLargeObjects(bool verbose);
 
+/* \conninfo */
+extern bool listConnectionInformation(const char *pattern, bool verbose);
+
 #endif							/* DESCRIBE_H */
diff --git a/src/bin/psql/help.c b/src/bin/psql/help.c
index 4e79a81..2c5426d 100644
--- a/src/bin/psql/help.c
+++ b/src/bin/psql/help.c
@@ -310,7 +310,7 @@ slashUsage(unsigned short int pager)
 	else
 		HELP0("  \\c[onnect] {[DBNAME|- USER|- HOST|- PORT|-] | conninfo}\n"
 			  "                         connect to new database (currently no connection)\n");
-	HELP0("  \\conninfo              display information about current connection\n");
+	HELP0("  \\conninfo[+]           display information about current connection\n");
 	HELP0("  \\encoding [ENCODING]   show or set client encoding\n");
 	HELP0("  \\password [USERNAME]   securely change the password for a user\n");
 	HELP0("\n");


^ permalink  raw  reply  [nested|flat] 43+ messages in thread

* Re: Psql meta-command conninfo+
  2024-02-06 21:50 Re: Psql meta-command conninfo+ Nathan Bossart <[email protected]>
  2024-02-07 04:13 ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-07 12:35   ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-07 14:47     ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
@ 2024-02-07 16:40       ` Pavel Luzanov <[email protected]>
  2024-02-07 20:13         ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  0 siblings, 1 reply; 43+ messages in thread

From: Pavel Luzanov @ 2024-02-07 16:40 UTC (permalink / raw)
  To: Maiquel Grassi <[email protected]>; Nathan Bossart <[email protected]>; +Cc: Erik Wienhold <[email protected]>; pgsql-hackers

Hi,Maiquel!


On 07.02.2024 17:47, Maiquel Grassi wrote:
> "Also, it seems that the verbose parameter in the 
> listConnectionInformation is unnecessary." Could you point out exactly 
> the line or code snippet you are referring to?

+bool
+listConnectionInformation(const char *pattern,*bool verbose*)

I mean that parameter verbose is not used in the function body and listConnectionInformation called only in verbose mode.

-- 
Pavel Luzanov
Postgres Professional:https://postgrespro.com


^ permalink  raw  reply  [nested|flat] 43+ messages in thread

* RE: Psql meta-command conninfo+
  2024-02-06 21:50 Re: Psql meta-command conninfo+ Nathan Bossart <[email protected]>
  2024-02-07 04:13 ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-07 12:35   ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-07 14:47     ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-07 16:40       ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
@ 2024-02-07 20:13         ` Maiquel Grassi <[email protected]>
  2024-02-08 11:01           ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-08 11:01           ` Re: Psql meta-command conninfo+ Jim Jones <[email protected]>
  0 siblings, 2 replies; 43+ messages in thread

From: Maiquel Grassi @ 2024-02-07 20:13 UTC (permalink / raw)
  To: Pavel Luzanov <[email protected]>; Nathan Bossart <[email protected]>; +Cc: Erik Wienhold <[email protected]>; pgsql-hackers

> Hi, Maiquel!
>
> On 07.02.2024 17:47, Maiquel Grassi wrote:

> "Also, it seems that the verbose parameter in the listConnectionInformation is unnecessary."
> Could you point out exactly the line or code snippet you are referring to?

> +bool
> +listConnectionInformation(const char *pattern, bool verbose)
>
> I mean that parameter verbose is not used in the function body and listConnectionInformation called only in verbose mode.


--//--

There really was no need for the bool verbose. Therefore, it was removed.
Regarding the "system_user" function, as it is relatively new, I added
the necessary handling to avoid conflicts with versions lower than version 16.

I believe in v7 patch we have a quite substantial meta-command feature.

I validated the "System User" column for three versions. This way, we have a sample:

[postgres@localhost bin]$ ./psql -h 192.168.0.5 -p 5432 -U postgres -d postgres

psql (17devel, server 14.3)
Type "help" for help.

postgres=# \conninfo
You are connected to database "postgres" as user "postgres" on host "192.168.0.5" at port "5432".
postgres=# \conninfo+
                                                                              Current Connection Information
 Database | Authenticated User | Current User | Session User | Session PID | Server Version | Server Address | Server Port | Client Address | Client Port | Socket Directory |    Host
----------+--------------------+--------------+--------------+-------------+----------------+----------------+-------------+----------------+-------------+------------------+-------------
 postgres | postgres           | postgres     | postgres     |        9008 | 14.3           | 192.168.0.5    | 5432        | 192.168.0.5    |       63631 |                  | 192.168.0.5
(1 row)

postgres=# \q
[postgres@localhost bin]$ ./psql -h 192.168.0.5 -p 5433 -U postgres -d postgres
psql (17devel, server 16.1)
Type "help" for help.

postgres=# \conninfo
You are connected to database "postgres" as user "postgres" on host "192.168.0.5" at port "5433".
postgres=# \conninfo+
                                                                                     Current Connection Information
 Database | Authenticated User | System User | Current User | Session User | Session PID | Server Version | Server Address | Server Port | Client Address | Client Port | Socket Directory |    Host
----------+--------------------+-------------+--------------+--------------+-------------+----------------+----------------+-------------+----------------+-------------+------------------+-------------
 postgres | postgres           |             | postgres     | postgres     |        3348 | 16.1           | 192.168.0.5    | 5433        | 192.168.0.5    |       63633 |                  | 192.168.0.5
(1 row)

postgres=# \q
[postgres@localhost bin]$ ./psql -h localhost
psql (17devel)
Type "help" for help.

postgres=# \conninfo
You are connected to database "postgres" as user "postgres" on host "localhost" (address "::1") at port "5432".
postgres=# \conninfo+
                                                                                    Current Connection Information
 Database | Authenticated User | System User | Current User | Session User | Session PID | Server Version | Server Address | Server Port | Client Address | Client Port | Socket Directory |   Host
----------+--------------------+-------------+--------------+--------------+-------------+----------------+----------------+-------------+----------------+-------------+------------------+-----------
 postgres | postgres           |             | postgres     | postgres     |       26147 | 17devel        | ::1            | 5432        | ::1            |       47466 | /tmp             | localhost
(1 row)

Regards,
Maiquel O. Grassi.


Attachments:

  [application/octet-stream] v7-0001-psql-meta-command-conninfo-plus.patch (8.1K, ../../CP4P284MB24830F5BF17FFA7F3D733142EC452@CP4P284MB2483.BRAP284.PROD.OUTLOOK.COM/3-v7-0001-psql-meta-command-conninfo-plus.patch)
  download | inline diff:
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index 5c906e4..bf93cb1 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -68,7 +68,8 @@ static backslashResult exec_command_C(PsqlScanState scan_state, bool active_bran
 static backslashResult exec_command_connect(PsqlScanState scan_state, bool active_branch);
 static backslashResult exec_command_cd(PsqlScanState scan_state, bool active_branch,
 									   const char *cmd);
-static backslashResult exec_command_conninfo(PsqlScanState scan_state, bool active_branch);
+static backslashResult exec_command_conninfo(PsqlScanState scan_state, bool active_branch,
+											 const char *cmd);
 static backslashResult exec_command_copy(PsqlScanState scan_state, bool active_branch);
 static backslashResult exec_command_copyright(PsqlScanState scan_state, bool active_branch);
 static backslashResult exec_command_crosstabview(PsqlScanState scan_state, bool active_branch);
@@ -317,8 +318,8 @@ exec_command(const char *cmd,
 		status = exec_command_connect(scan_state, active_branch);
 	else if (strcmp(cmd, "cd") == 0)
 		status = exec_command_cd(scan_state, active_branch, cmd);
-	else if (strcmp(cmd, "conninfo") == 0)
-		status = exec_command_conninfo(scan_state, active_branch);
+	else if (strcmp(cmd, "conninfo") == 0 || strcmp(cmd, "conninfo+") == 0)
+		status = exec_command_conninfo(scan_state, active_branch, cmd);
 	else if (pg_strcasecmp(cmd, "copy") == 0)
 		status = exec_command_copy(scan_state, active_branch);
 	else if (strcmp(cmd, "copyright") == 0)
@@ -643,47 +644,74 @@ exec_command_cd(PsqlScanState scan_state, bool active_branch, const char *cmd)
 }
 
 /*
- * \conninfo -- display information about the current connection
+ * \conninfo, \conninfo+ -- display information about the current connection
  */
 static backslashResult
-exec_command_conninfo(PsqlScanState scan_state, bool active_branch)
+exec_command_conninfo(PsqlScanState scan_state, bool active_branch, const char *cmd)
 {
+	bool		success = true;
+
 	if (active_branch)
 	{
 		char	   *db = PQdb(pset.db);
+		char	   *pattern;
+		bool		show_verbose;
 
-		if (db == NULL)
-			printf(_("You are currently not connected to a database.\n"));
-		else
+		pattern = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, true);
+
+		show_verbose = strchr(cmd, '+') ? true : false;
+
+		/*
+		 * \conninfo+
+		 */
+		if (show_verbose)
 		{
-			char	   *host = PQhost(pset.db);
-			char	   *hostaddr = PQhostaddr(pset.db);
+			success = listConnectionInformation(pattern);
+			free(pattern);
+			printSSLInfo();
+			printGSSInfo();
+		}
 
-			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));
-			}
+		/*
+		 * \conninfo
+		 */
+		else
+		{
+			if (db == NULL)
+				printf(_("You are currently not connected to a database.\n"));
 			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));
+				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
-					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));
+				{
+					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();
 			}
-			printSSLInfo();
-			printGSSInfo();
 		}
 	}
+	else
+		ignore_slash_options(scan_state);
 
-	return PSQL_CMD_SKIP_LINE;
+	return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
 }
 
 /*
diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index b6a4eb1..0476307 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -901,6 +901,60 @@ error_return:
 	return false;
 }
 
+/*
+ * listConnectionInformation
+ *
+ * for \conninfo+
+ */
+bool
+listConnectionInformation(const char *pattern)
+{
+    PGresult   *res;
+    PQExpBufferData buf;
+    printQueryOpt myopt = pset.popt;
+
+    initPQExpBuffer(&buf);
+
+    printfPQExpBuffer(&buf,
+                      "SELECT\n"
+                      "  pg_catalog.current_database() AS \"Database\",\n"
+                      "  '%s' AS \"Authenticated User\",\n",
+                      PQuser(pset.db));
+    if (pset.sversion >= 160000)
+        appendPQExpBuffer(&buf,
+                          "  pg_catalog.system_user() AS \"System User\",\n");
+    appendPQExpBuffer(&buf,
+                      "  pg_catalog.current_user() AS \"Current User\",\n"
+                      "  pg_catalog.session_user() AS \"Session User\",\n"
+                      "  pg_catalog.pg_backend_pid() AS \"Session PID\",\n"
+                      "  pg_catalog.current_setting('server_version') AS \"Server Version\",\n"
+                      "  pg_catalog.inet_server_addr() AS \"Server Address\",\n"
+                      "  pg_catalog.current_setting('port') AS \"Server Port\",\n"
+                      "  pg_catalog.inet_client_addr() AS \"Client Address\",\n"
+                      "  pg_catalog.inet_client_port() AS \"Client Port\",\n"
+                      "  NULLIF(pg_catalog.current_setting('unix_socket_directories'),'') AS \"Socket Directory\",\n"
+                      "  CASE\n"
+                      "    WHEN\n"
+                      "      pg_catalog.inet_server_addr() IS NULL\n"
+                      "      AND pg_catalog.inet_client_addr() IS NULL\n"
+                      "    THEN NULL\n"
+                      "    ELSE '%s'\n"
+                      "  END AS \"Host\";",
+                      PQhost(pset.db));
+
+    res = PSQLexec(buf.data);
+    termPQExpBuffer(&buf);
+    if (!res)
+        return false;
+
+    myopt.title = _("Current Connection Information");
+    myopt.translate_header = true;
+
+    printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
+
+    PQclear(res);
+    return true;
+}
 
 /*
  * listAllDbs
diff --git a/src/bin/psql/describe.h b/src/bin/psql/describe.h
index 273f974..779918b 100644
--- a/src/bin/psql/describe.h
+++ b/src/bin/psql/describe.h
@@ -149,4 +149,7 @@ extern bool listOpFamilyFunctions(const char *access_method_pattern,
 /* \dl or \lo_list */
 extern bool listLargeObjects(bool verbose);
 
+/* \conninfo */
+extern bool listConnectionInformation(const char *pattern);
+
 #endif							/* DESCRIBE_H */
diff --git a/src/bin/psql/help.c b/src/bin/psql/help.c
index 4e79a81..2c5426d 100644
--- a/src/bin/psql/help.c
+++ b/src/bin/psql/help.c
@@ -310,7 +310,7 @@ slashUsage(unsigned short int pager)
 	else
 		HELP0("  \\c[onnect] {[DBNAME|- USER|- HOST|- PORT|-] | conninfo}\n"
 			  "                         connect to new database (currently no connection)\n");
-	HELP0("  \\conninfo              display information about current connection\n");
+	HELP0("  \\conninfo[+]           display information about current connection\n");
 	HELP0("  \\encoding [ENCODING]   show or set client encoding\n");
 	HELP0("  \\password [USERNAME]   securely change the password for a user\n");
 	HELP0("\n");


^ permalink  raw  reply  [nested|flat] 43+ messages in thread

* Re: Psql meta-command conninfo+
  2024-02-06 21:50 Re: Psql meta-command conninfo+ Nathan Bossart <[email protected]>
  2024-02-07 04:13 ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-07 12:35   ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-07 14:47     ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-07 16:40       ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-07 20:13         ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
@ 2024-02-08 11:01           ` Pavel Luzanov <[email protected]>
  2024-02-08 14:58             ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  1 sibling, 1 reply; 43+ messages in thread

From: Pavel Luzanov @ 2024-02-08 11:01 UTC (permalink / raw)
  To: Maiquel Grassi <[email protected]>; Nathan Bossart <[email protected]>; +Cc: Erik Wienhold <[email protected]>; pgsql-hackers

Hi,

On 07.02.2024 23:13, Maiquel Grassi wrote:

> Regarding the "system_user" function, as it is relatively new, I added 
> the necessary handling to avoid conflicts with versions lower than 
> version 16.
>
Yes, that's rights.

A couple of doubts about the implementation details.
But keep in mind that I'm not very good at programming in the C language.
I hope for the help of more experienced developers.


1.
+			if (db == NULL)
+				printf(_("You are currently not connected to a database.\n"));

This check is performed for \conninfo, but not for \conninfo+.


2.
Some values (address, socket) are evaluated separately for \conninfo
(via C functions) and for \conninfo+ (via sql functions).
It may be worth evaluating them in one place. But I'm not sure about that.

The final version of the patch will require changes to the documentation and tests.

-- 
Pavel Luzanov
Postgres Professional:https://postgrespro.com


^ permalink  raw  reply  [nested|flat] 43+ messages in thread

* RE: Psql meta-command conninfo+
  2024-02-06 21:50 Re: Psql meta-command conninfo+ Nathan Bossart <[email protected]>
  2024-02-07 04:13 ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-07 12:35   ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-07 14:47     ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-07 16:40       ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-07 20:13         ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-08 11:01           ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
@ 2024-02-08 14:58             ` Maiquel Grassi <[email protected]>
  2024-02-09 07:58               ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  0 siblings, 1 reply; 43+ messages in thread

From: Maiquel Grassi @ 2024-02-08 14:58 UTC (permalink / raw)
  To: Pavel Luzanov <[email protected]>; Nathan Bossart <[email protected]>; +Cc: Erik Wienhold <[email protected]>; pgsql-hackers

> Hi,

> On 07.02.2024 23:13, Maiquel Grassi wrote:


> Regarding the "system_user" function, as it is relatively new, I added
> the necessary handling to avoid conflicts with versions lower than version 16.


> Yes, that's rights.
>
> A couple of doubts about the implementation details.
> But keep in mind that I'm not very good at programming in the C language.
> I hope for the help of more experienced developers.
>
>
> 1.
> +                     if (db == NULL)
> +                             printf(_("You are currently not connected to a database.\n"));
>
> This check is performed for \conninfo, but not for \conninfo+.
>
>
> 2.
> Some values (address, socket) are evaluated separately for \conninfo
> (via C functions) and for \conninfo+ (via sql functions).
> It may be worth evaluating them in one place. But I'm not sure about that.
>
> The final version of the patch will require changes to the documentation and tests.

--//--

Hi Pavel,

First of all, thank you very much for your observations.

1. The connection check for the case of \conninfo+ is handled by "describe.c" itself since it deals with queries. I might be mistaken, but I believe that by using "printQuery()" via "describe.c", this is already ensured, and there is no need to evaluate the connection status.

2. I believe that by implementing the evaluations separately as they are, it becomes easier to perform future maintenance by minimizing the mixing of C code with SQL code as much as possible. However, certainly, the possibility of a better suggestion than mine remains open.

Regards,
Maiquel O. Grassi.


^ permalink  raw  reply  [nested|flat] 43+ messages in thread

* Re: Psql meta-command conninfo+
  2024-02-06 21:50 Re: Psql meta-command conninfo+ Nathan Bossart <[email protected]>
  2024-02-07 04:13 ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-07 12:35   ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-07 14:47     ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-07 16:40       ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-07 20:13         ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-08 11:01           ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-08 14:58             ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
@ 2024-02-09 07:58               ` Pavel Luzanov <[email protected]>
  2024-02-09 09:18                 ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-12 14:16                 ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  0 siblings, 2 replies; 43+ messages in thread

From: Pavel Luzanov @ 2024-02-09 07:58 UTC (permalink / raw)
  To: Maiquel Grassi <[email protected]>; Nathan Bossart <[email protected]>; +Cc: Erik Wienhold <[email protected]>; pgsql-hackers

Hi, Maiquel!

The patch v10 build ends with a warning:
$ make -j --silent
describe.c:911:1: warning: no previous prototype for ‘listConnectionInformation’ [-Wmissing-prototypes]
   911 | listConnectionInformation()
       | ^~~~~~~~~~~~~~~~~~~~~~~~~

About terms.

postgres@postgres(17.0)=# \x \conninfo+
Expanded display is on.
Current Connection Information
-[ RECORD 1 ]------+---------
Database           | postgres
Authenticated User | postgres
System User        |
Current User       | postgres
Session User       | postgres
*Session PID | 951112 *Server Version     | 17devel
Server Address     |
Server Port        | 5401
Client Address     |
Client Port        |
Socket Directory   | /tmp
Host               |

It looks like "Session PID" is a new term for the server process identifier.
How about changing the name to "Backend PID" (from pg_backend_pid) or even PID (from pg_stat_activity)?

On 08.02.2024 17:58, Maiquel Grassi wrote:
> > 1. > + if (db == NULL) > + printf(_("You are currently not connected to 
> a database.\n")); > > This check is performed for \conninfo, but not 
> for \conninfo+.
> 1. The connection check for the case of \conninfo+ is handled by 
> "describe.c" itself since it deals with queries. I might be mistaken, 
> but I believe that by using "printQuery()" via "describe.c", this is 
> already ensured, and there is no need to evaluate the connection status.

I found that \conninfo and \conninfo+ act differently when the connection is broken.
I used pg_terminate_backend function from another session to terminate an open psql session.
After that, \conninfo does not see the connection break (surprisingly!), and \conninfo+ returns an error:

postgres@postgres(17.0)=# \conninfo+
FATAL:  terminating connection due to administrator command
server closed the connection unexpectedly
	This probably means the server terminated abnormally
	before or while processing the request.
The connection to the server was lost. Attempting reset: Succeeded.

postgres@postgres(17.0)=# \conninfo
You are connected to database "postgres" as user "postgres" via socket in "/tmp" at port "5401".

Another surprise is that this check:if (db == NULL) did not work in both cases.

-- 
Pavel Luzanov
Postgres Professional:https://postgrespro.com


^ permalink  raw  reply  [nested|flat] 43+ messages in thread

* RE: Psql meta-command conninfo+
  2024-02-06 21:50 Re: Psql meta-command conninfo+ Nathan Bossart <[email protected]>
  2024-02-07 04:13 ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-07 12:35   ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-07 14:47     ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-07 16:40       ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-07 20:13         ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-08 11:01           ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-08 14:58             ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-09 07:58               ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
@ 2024-02-09 09:18                 ` Maiquel Grassi <[email protected]>
  1 sibling, 0 replies; 43+ messages in thread

From: Maiquel Grassi @ 2024-02-09 09:18 UTC (permalink / raw)
  To: Pavel Luzanov <[email protected]>; Nathan Bossart <[email protected]>; +Cc: Erik Wienhold <[email protected]>; pgsql-hackers

Hi Pavel!

>The patch v10 build ends with a warning:
>$ make -j --silent
>describe.c:911:1: warning: no previous prototype for ‘listConnectionInformation’ [-Wmissing-prototypes]
>  911 | listConnectionInformation()
      | ^~~~~~~~~~~~~~~~~~~~~~~~~

>About terms.

I resolved this in v11. I had forgotten to put
the 'void' inside the parentheses (describe.h and describe.c).


>postgres@postgres(17.0)=# \x \conninfo+
>Expanded display is on.
>Current Connection Information
>-[ RECORD 1 ]------+---------
>Database           | postgres
>Authenticated User | postgres
>System User        |
>Current User       | postgres
>Session User       | postgres
>Session PID        | 951112
>Server Version     | 17devel
>Server Address     |
>Server Port        | 5401
>Client Address     |
>Client Port        |
>Socket Directory   | /tmp
>Host               |

>It looks like "Session PID" is a new term for the server process identifier.
>How about changing the name to "Backend PID" (from pg_backend_pid) or even PID (from pg_stat_activity)?


You're right, it's better to stick with the proper terms already in use
in PostgreSQL. This ensures that the user doesn't get confused. I've
changed it to "Backend PID".


>On 08.02.2024 17:58, Maiquel Grassi wrote:

> 1.
> +                     if (db == NULL)
> +                             printf(_("You are currently not connected to a database.\n"));
>
> This check is performed for \conninfo, but not for \conninfo+.

1. The connection check for the case of \conninfo+ is handled by "describe.c" itself since it deals with queries. I might be mistaken, but I believe that by using "printQuery()" via "describe.c", this is already ensured, and there is no need to evaluate the connection status.

>I found that \conninfo and \conninfo+ act differently when the connection is broken.
>I used pg_terminate_backend function from another session to terminate an open psql session.
>After that, \conninfo does not see the connection break (surprisingly!), and \conninfo+ returns an error:

>postgres@postgres(17.0)=# \conninfo+
>FATAL:  terminating connection due to administrator command
>server closed the connection unexpectedly
        >This probably means the server terminated abnormally
        >before or while processing the request.
>The connection to the server was lost. Attempting reset: Succeeded.


For this case, I believe it's already resolved, because if you get a
return indicating that the connection was terminated, and indeed it was,
then "describe.c" is handling it correctly. At least that's what
it seems like.

>postgres@postgres(17.0)=# \conninfo
>You are connected to database "postgres" as user "postgres" via socket in "/tmp" at port "5401".


Here it seems like we have an issue to be studied and subsequently resolved.

>Another surprise is that this check: if (db == NULL) did not work in both cases.

I will investigate further and, if necessary, remove it.

Here's v12, in the next version, I'll try to address the above situation.

Thanks a lot!
Maiquel Grassi.


Attachments:

  [application/octet-stream] v12-0001-psql-meta-command-conninfo-plus.patch (8.8K, ../../CP8P284MB2496D0B0946A4C55D7F0825EEC4B2@CP8P284MB2496.BRAP284.PROD.OUTLOOK.COM/3-v12-0001-psql-meta-command-conninfo-plus.patch)
  download | inline diff:
diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml
index cc7d797..4e86ad9 100644
--- a/doc/src/sgml/ref/psql-ref.sgml
+++ b/doc/src/sgml/ref/psql-ref.sgml
@@ -1029,10 +1029,14 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g
       </varlistentry>
 
       <varlistentry id="app-psql-meta-command-conninfo">
-        <term><literal>\conninfo</literal></term>
+        <term><literal>\conninfo[+]</literal></term>
         <listitem>
         <para>
         Outputs information about the current database connection.
+        When no <literal>+</literal> is specified, it simply prints
+        a textual description of a few connection options.
+        When <literal>+</literal> is given, more complete information
+        is displayed as a table.
         </para>
         </listitem>
       </varlistentry>
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index 5c906e4..2c4ea74 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -68,7 +68,8 @@ static backslashResult exec_command_C(PsqlScanState scan_state, bool active_bran
 static backslashResult exec_command_connect(PsqlScanState scan_state, bool active_branch);
 static backslashResult exec_command_cd(PsqlScanState scan_state, bool active_branch,
 									   const char *cmd);
-static backslashResult exec_command_conninfo(PsqlScanState scan_state, bool active_branch);
+static backslashResult exec_command_conninfo(PsqlScanState scan_state, bool active_branch,
+											 const char *cmd);
 static backslashResult exec_command_copy(PsqlScanState scan_state, bool active_branch);
 static backslashResult exec_command_copyright(PsqlScanState scan_state, bool active_branch);
 static backslashResult exec_command_crosstabview(PsqlScanState scan_state, bool active_branch);
@@ -317,8 +318,8 @@ exec_command(const char *cmd,
 		status = exec_command_connect(scan_state, active_branch);
 	else if (strcmp(cmd, "cd") == 0)
 		status = exec_command_cd(scan_state, active_branch, cmd);
-	else if (strcmp(cmd, "conninfo") == 0)
-		status = exec_command_conninfo(scan_state, active_branch);
+	else if (strcmp(cmd, "conninfo") == 0 || strcmp(cmd, "conninfo+") == 0)
+		status = exec_command_conninfo(scan_state, active_branch, cmd);
 	else if (pg_strcasecmp(cmd, "copy") == 0)
 		status = exec_command_copy(scan_state, active_branch);
 	else if (strcmp(cmd, "copyright") == 0)
@@ -643,47 +644,70 @@ exec_command_cd(PsqlScanState scan_state, bool active_branch, const char *cmd)
 }
 
 /*
- * \conninfo -- display information about the current connection
+ * \conninfo, \conninfo+ -- display information about the current connection
  */
 static backslashResult
-exec_command_conninfo(PsqlScanState scan_state, bool active_branch)
+exec_command_conninfo(PsqlScanState scan_state, bool active_branch, const char *cmd)
 {
+	bool		success = true;
+
 	if (active_branch)
 	{
 		char	   *db = PQdb(pset.db);
+		bool		show_verbose;
 
-		if (db == NULL)
-			printf(_("You are currently not connected to a database.\n"));
-		else
+		show_verbose = strchr(cmd, '+') ? true : false;
+
+		/*
+		 * \conninfo+
+		 */
+		if (show_verbose)
 		{
-			char	   *host = PQhost(pset.db);
-			char	   *hostaddr = PQhostaddr(pset.db);
+			success = listConnectionInformation();
+			printSSLInfo();
+			printGSSInfo();
+		}
 
-			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));
-			}
+		/*
+		 * \conninfo
+		 */
+		else
+		{
+			if (db == NULL)
+				printf(_("You are currently not connected to a database.\n"));
 			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));
+				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
-					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));
+				{
+					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();
 			}
-			printSSLInfo();
-			printGSSInfo();
 		}
 	}
+	else
+		ignore_slash_options(scan_state);
 
-	return PSQL_CMD_SKIP_LINE;
+	return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
 }
 
 /*
diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index b6a4eb1..506d9c5 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -26,6 +26,7 @@
 #include "fe_utils/mbprint.h"
 #include "fe_utils/print.h"
 #include "fe_utils/string_utils.h"
+#include "libpq/pqcomm.h"
 #include "settings.h"
 #include "variables.h"
 
@@ -901,6 +902,69 @@ error_return:
 	return false;
 }
 
+/*
+ * listConnectionInformation
+ *
+ * for \conninfo+
+ */
+bool
+listConnectionInformation(void)
+{
+	PGresult   *res;
+	PQExpBufferData buf;
+	printQueryOpt myopt = pset.popt;
+
+	char	   *host = PQhost(pset.db);
+	char	   *hostaddr = PQhostaddr(pset.db);
+
+	initPQExpBuffer(&buf);
+
+	printfPQExpBuffer(&buf,
+					  "SELECT\n"
+					  "  pg_catalog.current_database() AS \"Database\",\n"
+					  "  '%s' AS \"Authenticated User\",\n",
+					  PQuser(pset.db));
+	if (pset.sversion >= 160000)
+		appendPQExpBuffer(&buf,
+						  "  pg_catalog.system_user() AS \"System User\",\n");
+	appendPQExpBuffer(&buf,
+					  "  pg_catalog.current_user() AS \"Current User\",\n"
+					  "  pg_catalog.session_user() AS \"Session User\",\n"
+					  "  pg_catalog.pg_backend_pid() AS \"Backend PID\",\n"
+					  "  pg_catalog.inet_server_addr() AS \"Server Address\",\n"
+					  "  pg_catalog.current_setting('port') AS \"Server Port\",\n"
+					  "  pg_catalog.inet_client_addr() AS \"Client Address\",\n"
+					  "  pg_catalog.inet_client_port() AS \"Client Port\",\n");
+	if (is_unixsock_path(host) && !(hostaddr && *hostaddr))
+		appendPQExpBuffer(&buf,
+						  "  '%s' AS \"Socket Directory\",\n",
+						  host);
+	else
+		appendPQExpBuffer(&buf,
+						  "  NULL AS \"Socket Directory\",\n");
+	appendPQExpBuffer(&buf,
+					  "  CASE\n"
+					  "    WHEN\n"
+					  "      pg_catalog.inet_server_addr() IS NULL\n"
+					  "      AND pg_catalog.inet_client_addr() IS NULL\n"
+					  "    THEN NULL\n"
+					  "    ELSE '%s'\n"
+					  "  END AS \"Host\";",
+					  host);
+
+	res = PSQLexec(buf.data);
+	termPQExpBuffer(&buf);
+	if (!res)
+		return false;
+
+	myopt.title = _("Current Connection Information");
+	myopt.translate_header = true;
+
+	printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
+
+	PQclear(res);
+	return true;
+}
 
 /*
  * listAllDbs
diff --git a/src/bin/psql/describe.h b/src/bin/psql/describe.h
index 273f974..8a4e83f 100644
--- a/src/bin/psql/describe.h
+++ b/src/bin/psql/describe.h
@@ -64,6 +64,9 @@ extern bool listTSDictionaries(const char *pattern, bool verbose);
 /* \dFt */
 extern bool listTSTemplates(const char *pattern, bool verbose);
 
+/* \conninfo */
+extern bool listConnectionInformation(void);
+
 /* \l */
 extern bool listAllDbs(const char *pattern, bool verbose);
 
diff --git a/src/bin/psql/help.c b/src/bin/psql/help.c
index 4e79a81..2c5426d 100644
--- a/src/bin/psql/help.c
+++ b/src/bin/psql/help.c
@@ -310,7 +310,7 @@ slashUsage(unsigned short int pager)
 	else
 		HELP0("  \\c[onnect] {[DBNAME|- USER|- HOST|- PORT|-] | conninfo}\n"
 			  "                         connect to new database (currently no connection)\n");
-	HELP0("  \\conninfo              display information about current connection\n");
+	HELP0("  \\conninfo[+]           display information about current connection\n");
 	HELP0("  \\encoding [ENCODING]   show or set client encoding\n");
 	HELP0("  \\password [USERNAME]   securely change the password for a user\n");
 	HELP0("\n");


^ permalink  raw  reply  [nested|flat] 43+ messages in thread

* RE: Psql meta-command conninfo+
  2024-02-06 21:50 Re: Psql meta-command conninfo+ Nathan Bossart <[email protected]>
  2024-02-07 04:13 ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-07 12:35   ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-07 14:47     ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-07 16:40       ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-07 20:13         ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-08 11:01           ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-08 14:58             ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-09 07:58               ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
@ 2024-02-12 14:16                 ` Maiquel Grassi <[email protected]>
  2024-02-12 21:53                   ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-14 11:36                   ` Re: Psql meta-command conninfo+ Jim Jones <[email protected]>
  1 sibling, 2 replies; 43+ messages in thread

From: Maiquel Grassi @ 2024-02-12 14:16 UTC (permalink / raw)
  To: Pavel Luzanov <[email protected]>; Nathan Bossart <[email protected]>; +Cc: Erik Wienhold <[email protected]>; pgsql-hackers


>I found that \conninfo and \conninfo+ act differently when the connection is broken.
>I used pg_terminate_backend function from another session to terminate an open psql session.
>After that, \conninfo does not see the connection break (surprisingly!), and \conninfo+ returns an error:
>
>postgres@postgres(17.0)=# \conninfo+
>FATAL:  terminating connection due to administrator command
>server closed the connection unexpectedly
>       This probably means the server terminated abnormally
>       before or while processing the request.
>The connection to the server was lost. Attempting reset: Succeeded.
>
>postgres@postgres(17.0)=# \conninfo
>You are connected to database "postgres" as user "postgres" via socket in "/tmp" at port "5401".
>
>Another surprise is that this check: if (db == NULL) did not work in both cases.

--//--

Hi Pavel!

(v14)

The "if (db == NULL)" has been removed, as well
as the message inside it. To always maintain the
same error messages, I changed the validation of
"\conninfo" to match the validation used for "\conninfo+".
Therefore, now "\conninfo" and "\conninfo+" return
the same error when "pg_terminate_backend()" terminates
this session through another session. The result of
the adjustment is as follows:


Case 1 ("\conninfo+"):

[postgres@localhost bin]$ ./psql -x
psql (17devel)
Type "help" for help.

postgres=# \conninfo
You are connected to database "postgres" as user "postgres" via socket in "/tmp" at port "5432".
postgres=# \conninfo+
Current Connection Information
-[ RECORD 1 ]------+---------
Database           | postgres
Authenticated User | postgres
System User        |
Current User       | postgres
Session User       | postgres
Backend PID        | 24381
Server Address     |
Server Port        | 5432
Client Address     |
Client Port        |
Socket Directory   | /tmp
Host               |

postgres=# \conninfo+
FATAL:  terminating connection due to administrator command
server closed the connection unexpectedly
        This probably means the server terminated abnormally
        before or while processing the request.
The connection to the server was lost. Attempting reset: Succeeded.


Case 2 ("\conninfo"):

[postgres@localhost bin]$ ./psql -x
psql (17devel)
Type "help" for help.

postgres=# \conninfo
You are connected to database "postgres" as user "postgres" via socket in "/tmp" at port "5432".
postgres=# \conninfo+
Current Connection Information
-[ RECORD 1 ]------+---------
Database           | postgres
Authenticated User | postgres
System User        |
Current User       | postgres
Session User       | postgres
Backend PID        | 24539
Server Address     |
Server Port        | 5432
Client Address     |
Client Port        |
Socket Directory   | /tmp
Host               |

postgres=# \conninfo
FATAL:  terminating connection due to administrator command
server closed the connection unexpectedly
        This probably means the server terminated abnormally
        before or while processing the request.

The connection to the server was lost. Attempting reset: Succeeded.

In both cases, the sessions were terminated by another session.

Regards,
Maiquel Grassi.


Attachments:

  [application/octet-stream] v14-0001-psql-meta-command-conninfo-plus.patch (9.6K, ../../CP8P284MB2496C7F14594722472C9FEBAEC482@CP8P284MB2496.BRAP284.PROD.OUTLOOK.COM/3-v14-0001-psql-meta-command-conninfo-plus.patch)
  download | inline diff:
diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml
index cc7d797..4e86ad9 100644
--- a/doc/src/sgml/ref/psql-ref.sgml
+++ b/doc/src/sgml/ref/psql-ref.sgml
@@ -1029,10 +1029,14 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g
       </varlistentry>
 
       <varlistentry id="app-psql-meta-command-conninfo">
-        <term><literal>\conninfo</literal></term>
+        <term><literal>\conninfo[+]</literal></term>
         <listitem>
         <para>
         Outputs information about the current database connection.
+        When no <literal>+</literal> is specified, it simply prints
+        a textual description of a few connection options.
+        When <literal>+</literal> is given, more complete information
+        is displayed as a table.
         </para>
         </listitem>
       </varlistentry>
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index 5c906e4..881dfe2 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -68,7 +68,8 @@ static backslashResult exec_command_C(PsqlScanState scan_state, bool active_bran
 static backslashResult exec_command_connect(PsqlScanState scan_state, bool active_branch);
 static backslashResult exec_command_cd(PsqlScanState scan_state, bool active_branch,
 									   const char *cmd);
-static backslashResult exec_command_conninfo(PsqlScanState scan_state, bool active_branch);
+static backslashResult exec_command_conninfo(PsqlScanState scan_state, bool active_branch,
+											 const char *cmd);
 static backslashResult exec_command_copy(PsqlScanState scan_state, bool active_branch);
 static backslashResult exec_command_copyright(PsqlScanState scan_state, bool active_branch);
 static backslashResult exec_command_crosstabview(PsqlScanState scan_state, bool active_branch);
@@ -317,8 +318,8 @@ exec_command(const char *cmd,
 		status = exec_command_connect(scan_state, active_branch);
 	else if (strcmp(cmd, "cd") == 0)
 		status = exec_command_cd(scan_state, active_branch, cmd);
-	else if (strcmp(cmd, "conninfo") == 0)
-		status = exec_command_conninfo(scan_state, active_branch);
+	else if (strcmp(cmd, "conninfo") == 0 || strcmp(cmd, "conninfo+") == 0)
+		status = exec_command_conninfo(scan_state, active_branch, cmd);
 	else if (pg_strcasecmp(cmd, "copy") == 0)
 		status = exec_command_copy(scan_state, active_branch);
 	else if (strcmp(cmd, "copyright") == 0)
@@ -643,47 +644,75 @@ exec_command_cd(PsqlScanState scan_state, bool active_branch, const char *cmd)
 }
 
 /*
- * \conninfo -- display information about the current connection
+ * \conninfo, \conninfo+ -- display information about the current connection
  */
 static backslashResult
-exec_command_conninfo(PsqlScanState scan_state, bool active_branch)
+exec_command_conninfo(PsqlScanState scan_state, bool active_branch, const char *cmd)
 {
+	bool		success = true;
+
 	if (active_branch)
 	{
 		char	   *db = PQdb(pset.db);
+		bool		show_verbose;
+
+		show_verbose = strchr(cmd, '+') ? true : false;
+
+		/*
+		 * \conninfo+
+		 */
+		if (show_verbose)
+			success = listConnectionInformation();
 
-		if (db == NULL)
-			printf(_("You are currently not connected to a database.\n"));
+		/*
+		 * \conninfo
+		 */
 		else
 		{
-			char	   *host = PQhost(pset.db);
-			char	   *hostaddr = PQhostaddr(pset.db);
+			PGresult   *res;
+			PQExpBufferData buf;
 
-			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));
-			}
+			initPQExpBuffer(&buf);
+			printfPQExpBuffer(&buf, "SELECT;");
+			res = PSQLexec(buf.data);
+			termPQExpBuffer(&buf);
+
+			if (!res)
+				return PSQL_CMD_ERROR;
 			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));
+				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
-					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));
+				{
+					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));
+				}
+				PQclear(res);
+				printSSLInfo();
+				printGSSInfo();
 			}
-			printSSLInfo();
-			printGSSInfo();
 		}
 	}
+	else
+		ignore_slash_options(scan_state);
 
-	return PSQL_CMD_SKIP_LINE;
+	return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
 }
 
 /*
diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index b6a4eb1..2ef3db0 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -26,6 +26,7 @@
 #include "fe_utils/mbprint.h"
 #include "fe_utils/print.h"
 #include "fe_utils/string_utils.h"
+#include "libpq/pqcomm.h"
 #include "settings.h"
 #include "variables.h"
 
@@ -901,6 +902,91 @@ error_return:
 	return false;
 }
 
+/*
+ * listConnectionInformation
+ *
+ * for \conninfo+
+ */
+bool
+listConnectionInformation(void)
+{
+	PGresult   *res;
+	PQExpBufferData buf;
+	printQueryOpt myopt = pset.popt;
+
+	char	   *host = PQhost(pset.db);
+	char	   *hostaddr = PQhostaddr(pset.db);
+	const char *protocol;
+	const char *cipher;
+	const char *compression;
+
+	initPQExpBuffer(&buf);
+
+	printfPQExpBuffer(&buf,
+					  "SELECT\n"
+					  "  pg_catalog.current_database() AS \"Database\",\n"
+					  "  '%s' AS \"Authenticated User\",\n",
+					  PQuser(pset.db));
+	if (pset.sversion >= 160000)
+		appendPQExpBuffer(&buf,
+						  "  pg_catalog.system_user() AS \"System User\",\n");
+	appendPQExpBuffer(&buf,
+					  "  pg_catalog.current_user() AS \"Current User\",\n"
+					  "  pg_catalog.session_user() AS \"Session User\",\n"
+					  "  pg_catalog.pg_backend_pid() AS \"Backend PID\",\n"
+					  "  pg_catalog.inet_server_addr() AS \"Server Address\",\n"
+					  "  pg_catalog.current_setting('port') AS \"Server Port\",\n"
+					  "  pg_catalog.inet_client_addr() AS \"Client Address\",\n"
+					  "  pg_catalog.inet_client_port() AS \"Client Port\",\n");
+	if (is_unixsock_path(host) && !(hostaddr && *hostaddr))
+		appendPQExpBuffer(&buf,
+						  "  '%s' AS \"Socket Directory\",\n",
+						  host);
+	else
+		appendPQExpBuffer(&buf,
+						  "  NULL AS \"Socket Directory\",\n");
+	appendPQExpBuffer(&buf,
+					  "  CASE\n"
+					  "    WHEN\n"
+					  "      pg_catalog.inet_server_addr() IS NULL\n"
+					  "      AND pg_catalog.inet_client_addr() IS NULL\n"
+					  "    THEN NULL\n"
+					  "    ELSE '%s'\n"
+					  "  END AS \"Host\"\n",
+					  host);
+	if (PQsslInUse(pset.db))
+	{
+		protocol = PQsslAttribute(pset.db, "protocol");
+		cipher = PQsslAttribute(pset.db, "cipher");
+		compression = PQsslAttribute(pset.db, "compression");
+		appendPQExpBuffer(&buf,
+						  "  ,'SSL' AS \"Encryption\",\n"
+						  "  '%s' AS \"Protocol\",\n"
+						  "  '%s' AS \"Cipher\",\n"
+						  "  '%s' AS \"Compression\"\n",
+						  protocol ? protocol : _("unknown"),
+						  cipher ? cipher : _("unknown"),
+						  (compression && strcmp(compression, "off") != 0) ? _("on") : _("off"));
+	}
+	if (PQgssEncInUse(pset.db))
+		appendPQExpBuffer(&buf,
+						  "  ,'GSSAPI' AS \"Encryption\"\n");
+	appendPQExpBuffer(&buf,
+					  "  ;");
+
+	res = PSQLexec(buf.data);
+	termPQExpBuffer(&buf);
+	if (!res)
+		return false;
+
+	myopt.title = _("Current Connection Information");
+	myopt.translate_header = true;
+
+	printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
+
+	PQclear(res);
+	return true;
+}
 
 /*
  * listAllDbs
diff --git a/src/bin/psql/describe.h b/src/bin/psql/describe.h
index 273f974..8a4e83f 100644
--- a/src/bin/psql/describe.h
+++ b/src/bin/psql/describe.h
@@ -64,6 +64,9 @@ extern bool listTSDictionaries(const char *pattern, bool verbose);
 /* \dFt */
 extern bool listTSTemplates(const char *pattern, bool verbose);
 
+/* \conninfo */
+extern bool listConnectionInformation(void);
+
 /* \l */
 extern bool listAllDbs(const char *pattern, bool verbose);
 
diff --git a/src/bin/psql/help.c b/src/bin/psql/help.c
index 4e79a81..2c5426d 100644
--- a/src/bin/psql/help.c
+++ b/src/bin/psql/help.c
@@ -310,7 +310,7 @@ slashUsage(unsigned short int pager)
 	else
 		HELP0("  \\c[onnect] {[DBNAME|- USER|- HOST|- PORT|-] | conninfo}\n"
 			  "                         connect to new database (currently no connection)\n");
-	HELP0("  \\conninfo              display information about current connection\n");
+	HELP0("  \\conninfo[+]           display information about current connection\n");
 	HELP0("  \\encoding [ENCODING]   show or set client encoding\n");
 	HELP0("  \\password [USERNAME]   securely change the password for a user\n");
 	HELP0("\n");


^ permalink  raw  reply  [nested|flat] 43+ messages in thread

* Re: Psql meta-command conninfo+
  2024-02-06 21:50 Re: Psql meta-command conninfo+ Nathan Bossart <[email protected]>
  2024-02-07 04:13 ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-07 12:35   ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-07 14:47     ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-07 16:40       ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-07 20:13         ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-08 11:01           ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-08 14:58             ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-09 07:58               ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-12 14:16                 ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
@ 2024-02-12 21:53                   ` Pavel Luzanov <[email protected]>
  1 sibling, 0 replies; 43+ messages in thread

From: Pavel Luzanov @ 2024-02-12 21:53 UTC (permalink / raw)
  To: Maiquel Grassi <[email protected]>; Nathan Bossart <[email protected]>; +Cc: Erik Wienhold <[email protected]>; pgsql-hackers

Hi,

On 12.02.2024 17:16, Maiquel Grassi wrote:
>
> The "if (db == NULL)" has been removed, as well as the message inside 
> it. To always maintain the same error messages, I changed the 
> validation of "\conninfo" to match the validation used for 
> "\conninfo+". Therefore, now "\conninfo" and "\conninfo+" return the 
> same error when "pg_terminate_backend()" terminates this session 
> through another session.
>

This make sense to me. Thank you for this work.

-- 
Pavel Luzanov
Postgres Professional:https://postgrespro.com


^ permalink  raw  reply  [nested|flat] 43+ messages in thread

* Re: Psql meta-command conninfo+
  2024-02-06 21:50 Re: Psql meta-command conninfo+ Nathan Bossart <[email protected]>
  2024-02-07 04:13 ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-07 12:35   ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-07 14:47     ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-07 16:40       ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-07 20:13         ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-08 11:01           ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-08 14:58             ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-09 07:58               ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-12 14:16                 ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
@ 2024-02-14 11:36                   ` Jim Jones <[email protected]>
  2024-02-15 19:47                     ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  1 sibling, 1 reply; 43+ messages in thread

From: Jim Jones @ 2024-02-14 11:36 UTC (permalink / raw)
  To: Maiquel Grassi <[email protected]>; Pavel Luzanov <[email protected]>; Nathan Bossart <[email protected]>; +Cc: Erik Wienhold <[email protected]>; pgsql-hackers



On 12.02.24 15:16, Maiquel Grassi wrote:
>
> (v14)
>
>
v14 applies cleanly and the SSL info is now shown as previously
suggested. Here is a more comprehensive test:

$ /usr/local/postgres-dev/bin/psql -x "\
    host=server.uni-muenster.de
    hostaddr=172.19.42.1
    user=jim dbname=postgres
    sslrootcert=server-certificates/server.crt
    sslcert=jim-certificates/jim.crt
    sslkey=jim-certificates/jim.key"
    
psql (17devel)
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384,
compression: off)
Type "help" for help.

postgres=# SET ROLE foo;
SET
postgres=> \conninfo+
Current Connection Information
-[ RECORD 1
]------+---------------------------------------------------------------------------------------------------------------------------
Database           | postgres
Authenticated User | jim
System User        | cert:[email protected],CN=jim,OU=WWU
IT,O=Universitaet Muenster,L=Muenster,ST=Nordrhein-Westfalen,C=DE
Current User       | foo
Session User       | jim
Backend PID        | 278294
Server Address     | 172.19.42.1
Server Port        | 5432
Client Address     | 192.168.178.27
Client Port        | 54948
Socket Directory   |
Host               | server.uni-muenster.de
Encryption         | SSL
Protocol           | TLSv1.3
Cipher             | TLS_AES_256_GCM_SHA384
Compression        | off

postgres=> \conninfo
You are connected to database "postgres" as user "jim" on host
"server.uni-muenster.de" (address "127.0.0.1") at port "5432".
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384,
compression: off)

A little odd is that "Server Address" of \conninfo+ differs from
"address" of \conninfo...

I think the documentation could add a little more info than just this:

> When no + is specified, it simply prints a textual description of a
few connection options. When + is given, more complete information is
displayed as a table.

Perhaps briefly mentioning the returned columns or simply listing them
would be IMHO a nice addition. For some users the semantics of
"Authenticated User", "System User", "Current User" and "Session User"
can be a little confusing. And yes, I realize the current documentation
of \conninfo is already a little vague :).

Thanks for working on this

-- 
Jim







^ permalink  raw  reply  [nested|flat] 43+ messages in thread

* RE: Psql meta-command conninfo+
  2024-02-06 21:50 Re: Psql meta-command conninfo+ Nathan Bossart <[email protected]>
  2024-02-07 04:13 ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-07 12:35   ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-07 14:47     ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-07 16:40       ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-07 20:13         ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-08 11:01           ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-08 14:58             ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-09 07:58               ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-12 14:16                 ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-14 11:36                   ` Re: Psql meta-command conninfo+ Jim Jones <[email protected]>
@ 2024-02-15 19:47                     ` Maiquel Grassi <[email protected]>
  2024-02-15 22:16                       ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  0 siblings, 1 reply; 43+ messages in thread

From: Maiquel Grassi @ 2024-02-15 19:47 UTC (permalink / raw)
  To: Jim Jones <[email protected]>; Pavel Luzanov <[email protected]>; Nathan Bossart <[email protected]>; +Cc: Erik Wienhold <[email protected]>; pgsql-hackers

>v14 applies cleanly and the SSL info is now shown as previously
>suggested. Here is a more comprehensive test:
>
>
>$ /usr/local/postgres-dev/bin/psql -x "\
>    host=server.uni-muenster.de
>    hostaddr=172.19.42.1
>    user=jim dbname=postgres
>    sslrootcert=server-certificates/server.crt
>    sslcert=jim-certificates/jim.crt
>    sslkey=jim-certificates/jim.key"
>
>psql (17devel)
>SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384,
>compression: off)
>Type "help" for help.
>
>postgres=# SET ROLE foo;
>SET
>postgres=> \conninfo+
>Current Connection Information
>-[ RECORD 1
>]------+---------------------------------------------------------------------------------------------------------------------------
>Database           | postgres
>Authenticated User | jim
>System User        | cert:[email protected],CN=jim,OU=WWU
>IT,O=Universitaet Muenster,L=Muenster,ST=Nordrhein-Westfalen,C=DE
>Current User       | foo
>Session User       | jim
>Backend PID        | 278294
>Server Address     | 172.19.42.1
>Server Port        | 5432
>Client Address     | 192.168.178.27
>Client Port        | 54948
>Socket Directory   |
>Host               | server.uni-muenster.de
>Encryption         | SSL
>Protocol           | TLSv1.3
>Cipher             | TLS_AES_256_GCM_SHA384
>Compression        | off
>
>postgres=> \conninfo
>You are connected to database "postgres" as user "jim" on host
>"server.uni-muenster.de" (address "127.0.0.1") at port "5432".
>SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384,
>compression: off)

>A little odd is that "Server Address" of \conninfo+ differs from
>"address" of \conninfo...

----//----

Hi Jim!


Tests performed on CentOS Linux 7.


I made some further observations and concluded that there will
be more cases where the "address" from \conninfo will differ from
the "Server Address" from \conninfo+. Below is a more detailed example.

The input of "hostaddr" or "host" in the psql call can be any pointing to
"loopback local" and the connection will still be established. For example,
all of these are accepted:

Case (inet):
psql -x --host 0
psql -x --host 0.0.0.0
psql -x hostaddr=0
psql -x hostaddr=0.0.0.0
All these examples will have "Server Address" = 127.0.0.1

Case (inet6):
psql -x --host ::
psql -x --host * (this entry is not accepted)
psql -x --host \*

psql -x --host "*"
psql -x hostaddr=::
psql -x hostaddr=*
All these examples will have "Server Address" = ::1

Thus, the inet_server_addr() function will return 127.0.0.1 or ::1 which in some cases will differ from the "address" from \conninfo.

[postgres@localhost bin]$ ./psql -x hostaddr=0

Password for user postgres:
psql (17devel)
SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, compression: off)
Type "help" for help.

postgres=# SET ROLE maiquel;
SET
postgres=> \conninfo
You are connected to database "postgres" as user "postgres" on host "0" (address "0.0.0.0") at port "5432".
SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, compression: off)
postgres=> \conninfo+
Current Connection Information
-[ RECORD 1 ]------+----------------------------
Database           | postgres
Authenticated User | postgres
System User        | scram-sha-256:postgres
Current User       | maiquel
Session User       | postgres
Backend PID        | 15205
Server Address     | 127.0.0.1
Server Port        | 5432
Client Address     | 127.0.0.1
Client Port        | 57598
Socket Directory   |
Host               | 0
Encryption         | SSL
Protocol           | TLSv1.2
Cipher             | ECDHE-RSA-AES256-GCM-SHA384
Compression        | off

postgres=> \q
[postgres@localhost bin]$ ping 0.0.0.0
PING 0.0.0.0 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.061 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.069 ms
64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.071 ms
64 bytes from 127.0.0.1: icmp_seq=4 ttl=64 time=0.107 ms
^C
--- 0.0.0.0 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3003ms
rtt min/avg/max/mdev = 0.061/0.077/0.107/0.017 ms

As demonstrated above, "address" = 0.0.0.0 and "Server Address" = 127.0.0.1 are divergent.

In practice, these IPs are the "same", and the ping from the example proves it.


However, we are concerned here with the psql user, and this may seem confusing to them at
first glance. I would like to propose a change in "address" so that it always returns the same as
"Server Address", that is, to use the inet_server_address() function in "address".

Result:

[postgres@localhost bin]$ ./psql -x hostaddr=0

psql (17devel)
Type "help" for help.

postgres=# \conninfo
You are connected to database "postgres" as user "postgres" on host "0" (address "127.0.0.1") at port "5432".
postgres=# \conninfo+
Current Connection Information
-[ RECORD 1 ]------+----------
Database           | postgres
Authenticated User | postgres
System User        |
Current User       | postgres
Session User       | postgres
Backend PID        | 26859
Server Address     | 127.0.0.1
Server Port        | 5432
Client Address     | 127.0.0.1
Client Port        | 58254
Socket Directory   |
Host               | 0

----//----

>I think the documentation could add a little more info than just this:

>> When no + is specified, it simply prints a textual description of a
>>few connection options. When + is given, more complete information is
>>displayed as a table.

>Perhaps briefly mentioning the returned columns or simply listing them
>would be IMHO a nice addition. For some users the semantics of
>"Authenticated User", "System User", "Current User" and "Session User"
>can be a little confusing. And yes, I realize the current documentation
>of \conninfo is already a little vague :).

Your suggestion was well received, and I'will made the adjustment to make
the command description more comprehensive.

Here is version v15 where I sought to correct 'Adress' to make it the same
as 'Server Address'.

Could you perform the same test and validate?

Thank you so much!
Maiquel Grassi.


Attachments:

  [application/octet-stream] v15-0001-psql-meta-command-conninfo-plus.patch (9.6K, ../../CP8P284MB24969B39579E808F9F44CCF8EC4D2@CP8P284MB2496.BRAP284.PROD.OUTLOOK.COM/3-v15-0001-psql-meta-command-conninfo-plus.patch)
  download | inline diff:
diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml
index cc7d797..4e86ad9 100644
--- a/doc/src/sgml/ref/psql-ref.sgml
+++ b/doc/src/sgml/ref/psql-ref.sgml
@@ -1029,10 +1029,14 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g
       </varlistentry>
 
       <varlistentry id="app-psql-meta-command-conninfo">
-        <term><literal>\conninfo</literal></term>
+        <term><literal>\conninfo[+]</literal></term>
         <listitem>
         <para>
         Outputs information about the current database connection.
+        When no <literal>+</literal> is specified, it simply prints
+        a textual description of a few connection options.
+        When <literal>+</literal> is given, more complete information
+        is displayed as a table.
         </para>
         </listitem>
       </varlistentry>
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index 5c906e4..af69b74 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -68,7 +68,8 @@ static backslashResult exec_command_C(PsqlScanState scan_state, bool active_bran
 static backslashResult exec_command_connect(PsqlScanState scan_state, bool active_branch);
 static backslashResult exec_command_cd(PsqlScanState scan_state, bool active_branch,
 									   const char *cmd);
-static backslashResult exec_command_conninfo(PsqlScanState scan_state, bool active_branch);
+static backslashResult exec_command_conninfo(PsqlScanState scan_state, bool active_branch,
+											 const char *cmd);
 static backslashResult exec_command_copy(PsqlScanState scan_state, bool active_branch);
 static backslashResult exec_command_copyright(PsqlScanState scan_state, bool active_branch);
 static backslashResult exec_command_crosstabview(PsqlScanState scan_state, bool active_branch);
@@ -317,8 +318,8 @@ exec_command(const char *cmd,
 		status = exec_command_connect(scan_state, active_branch);
 	else if (strcmp(cmd, "cd") == 0)
 		status = exec_command_cd(scan_state, active_branch, cmd);
-	else if (strcmp(cmd, "conninfo") == 0)
-		status = exec_command_conninfo(scan_state, active_branch);
+	else if (strcmp(cmd, "conninfo") == 0 || strcmp(cmd, "conninfo+") == 0)
+		status = exec_command_conninfo(scan_state, active_branch, cmd);
 	else if (pg_strcasecmp(cmd, "copy") == 0)
 		status = exec_command_copy(scan_state, active_branch);
 	else if (strcmp(cmd, "copyright") == 0)
@@ -643,47 +644,75 @@ exec_command_cd(PsqlScanState scan_state, bool active_branch, const char *cmd)
 }
 
 /*
- * \conninfo -- display information about the current connection
+ * \conninfo, \conninfo+ -- display information about the current connection
  */
 static backslashResult
-exec_command_conninfo(PsqlScanState scan_state, bool active_branch)
+exec_command_conninfo(PsqlScanState scan_state, bool active_branch, const char *cmd)
 {
+	bool		success = true;
+
 	if (active_branch)
 	{
 		char	   *db = PQdb(pset.db);
+		bool		show_verbose;
+
+		show_verbose = strchr(cmd, '+') ? true : false;
+
+		/*
+		 * \conninfo+
+		 */
+		if (show_verbose)
+			success = listConnectionInformation();
 
-		if (db == NULL)
-			printf(_("You are currently not connected to a database.\n"));
+		/*
+		 * \conninfo
+		 */
 		else
 		{
-			char	   *host = PQhost(pset.db);
-			char	   *hostaddr = PQhostaddr(pset.db);
+			PGresult   *res;
+			PQExpBufferData buf;
 
-			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));
-			}
+			initPQExpBuffer(&buf);
+			printfPQExpBuffer(&buf, "SELECT inet_server_addr();");
+			res = PSQLexec(buf.data);
+			termPQExpBuffer(&buf);
+
+			if (!res)
+				return PSQL_CMD_ERROR;
 			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));
+				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), PQgetvalue(res, 0, 0), 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
-					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));
+				{
+					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, PQgetvalue(res, 0, 0), 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));
+				}
+				PQclear(res);
+				printSSLInfo();
+				printGSSInfo();
 			}
-			printSSLInfo();
-			printGSSInfo();
 		}
 	}
+	else
+		ignore_slash_options(scan_state);
 
-	return PSQL_CMD_SKIP_LINE;
+	return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
 }
 
 /*
diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index b6a4eb1..2ef3db0 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -26,6 +26,7 @@
 #include "fe_utils/mbprint.h"
 #include "fe_utils/print.h"
 #include "fe_utils/string_utils.h"
+#include "libpq/pqcomm.h"
 #include "settings.h"
 #include "variables.h"
 
@@ -901,6 +902,91 @@ error_return:
 	return false;
 }
 
+/*
+ * listConnectionInformation
+ *
+ * for \conninfo+
+ */
+bool
+listConnectionInformation(void)
+{
+	PGresult   *res;
+	PQExpBufferData buf;
+	printQueryOpt myopt = pset.popt;
+
+	char	   *host = PQhost(pset.db);
+	char	   *hostaddr = PQhostaddr(pset.db);
+	const char *protocol;
+	const char *cipher;
+	const char *compression;
+
+	initPQExpBuffer(&buf);
+
+	printfPQExpBuffer(&buf,
+					  "SELECT\n"
+					  "  pg_catalog.current_database() AS \"Database\",\n"
+					  "  '%s' AS \"Authenticated User\",\n",
+					  PQuser(pset.db));
+	if (pset.sversion >= 160000)
+		appendPQExpBuffer(&buf,
+						  "  pg_catalog.system_user() AS \"System User\",\n");
+	appendPQExpBuffer(&buf,
+					  "  pg_catalog.current_user() AS \"Current User\",\n"
+					  "  pg_catalog.session_user() AS \"Session User\",\n"
+					  "  pg_catalog.pg_backend_pid() AS \"Backend PID\",\n"
+					  "  pg_catalog.inet_server_addr() AS \"Server Address\",\n"
+					  "  pg_catalog.current_setting('port') AS \"Server Port\",\n"
+					  "  pg_catalog.inet_client_addr() AS \"Client Address\",\n"
+					  "  pg_catalog.inet_client_port() AS \"Client Port\",\n");
+	if (is_unixsock_path(host) && !(hostaddr && *hostaddr))
+		appendPQExpBuffer(&buf,
+						  "  '%s' AS \"Socket Directory\",\n",
+						  host);
+	else
+		appendPQExpBuffer(&buf,
+						  "  NULL AS \"Socket Directory\",\n");
+	appendPQExpBuffer(&buf,
+					  "  CASE\n"
+					  "    WHEN\n"
+					  "      pg_catalog.inet_server_addr() IS NULL\n"
+					  "      AND pg_catalog.inet_client_addr() IS NULL\n"
+					  "    THEN NULL\n"
+					  "    ELSE '%s'\n"
+					  "  END AS \"Host\"\n",
+					  host);
+	if (PQsslInUse(pset.db))
+	{
+		protocol = PQsslAttribute(pset.db, "protocol");
+		cipher = PQsslAttribute(pset.db, "cipher");
+		compression = PQsslAttribute(pset.db, "compression");
+		appendPQExpBuffer(&buf,
+						  "  ,'SSL' AS \"Encryption\",\n"
+						  "  '%s' AS \"Protocol\",\n"
+						  "  '%s' AS \"Cipher\",\n"
+						  "  '%s' AS \"Compression\"\n",
+						  protocol ? protocol : _("unknown"),
+						  cipher ? cipher : _("unknown"),
+						  (compression && strcmp(compression, "off") != 0) ? _("on") : _("off"));
+	}
+	if (PQgssEncInUse(pset.db))
+		appendPQExpBuffer(&buf,
+						  "  ,'GSSAPI' AS \"Encryption\"\n");
+	appendPQExpBuffer(&buf,
+					  "  ;");
+
+	res = PSQLexec(buf.data);
+	termPQExpBuffer(&buf);
+	if (!res)
+		return false;
+
+	myopt.title = _("Current Connection Information");
+	myopt.translate_header = true;
+
+	printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
+
+	PQclear(res);
+	return true;
+}
 
 /*
  * listAllDbs
diff --git a/src/bin/psql/describe.h b/src/bin/psql/describe.h
index 273f974..8a4e83f 100644
--- a/src/bin/psql/describe.h
+++ b/src/bin/psql/describe.h
@@ -64,6 +64,9 @@ extern bool listTSDictionaries(const char *pattern, bool verbose);
 /* \dFt */
 extern bool listTSTemplates(const char *pattern, bool verbose);
 
+/* \conninfo */
+extern bool listConnectionInformation(void);
+
 /* \l */
 extern bool listAllDbs(const char *pattern, bool verbose);
 
diff --git a/src/bin/psql/help.c b/src/bin/psql/help.c
index 4e79a81..2c5426d 100644
--- a/src/bin/psql/help.c
+++ b/src/bin/psql/help.c
@@ -310,7 +310,7 @@ slashUsage(unsigned short int pager)
 	else
 		HELP0("  \\c[onnect] {[DBNAME|- USER|- HOST|- PORT|-] | conninfo}\n"
 			  "                         connect to new database (currently no connection)\n");
-	HELP0("  \\conninfo              display information about current connection\n");
+	HELP0("  \\conninfo[+]           display information about current connection\n");
 	HELP0("  \\encoding [ENCODING]   show or set client encoding\n");
 	HELP0("  \\password [USERNAME]   securely change the password for a user\n");
 	HELP0("\n");


^ permalink  raw  reply  [nested|flat] 43+ messages in thread

* RE: Psql meta-command conninfo+
  2024-02-06 21:50 Re: Psql meta-command conninfo+ Nathan Bossart <[email protected]>
  2024-02-07 04:13 ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-07 12:35   ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-07 14:47     ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-07 16:40       ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-07 20:13         ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-08 11:01           ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-08 14:58             ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-09 07:58               ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-12 14:16                 ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-14 11:36                   ` Re: Psql meta-command conninfo+ Jim Jones <[email protected]>
  2024-02-15 19:47                     ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
@ 2024-02-15 22:16                       ` Maiquel Grassi <[email protected]>
  2024-02-16 11:18                         ` Re: Psql meta-command conninfo+ Jim Jones <[email protected]>
  0 siblings, 1 reply; 43+ messages in thread

From: Maiquel Grassi @ 2024-02-15 22:16 UTC (permalink / raw)
  To: Jim Jones <[email protected]>; Pavel Luzanov <[email protected]>; Nathan Bossart <[email protected]>; +Cc: Erik Wienhold <[email protected]>; pgsql-hackers

Hi!

(v16)

In this version, I made a small adjustment to the indentation
of the \conninfo code and described the columns as returned
by \conninfo+ as suggested by Jim Jones.

Regards,
Maiquel Grassi.


Attachments:

  [application/octet-stream] v16-0001-psql-meta-command-conninfo-plus.patch (10.3K, ../../CP8P284MB249664C44A1793823C4546F8EC4D2@CP8P284MB2496.BRAP284.PROD.OUTLOOK.COM/3-v16-0001-psql-meta-command-conninfo-plus.patch)
  download | inline diff:
diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml
index cc7d797..3594acf 100644
--- a/doc/src/sgml/ref/psql-ref.sgml
+++ b/doc/src/sgml/ref/psql-ref.sgml
@@ -1029,10 +1029,24 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g
       </varlistentry>
 
       <varlistentry id="app-psql-meta-command-conninfo">
-        <term><literal>\conninfo</literal></term>
+        <term><literal>\conninfo[+]</literal></term>
         <listitem>
         <para>
         Outputs information about the current database connection.
+        When no <literal>+</literal> is specified, it simply prints
+        a textual description of a few connection options.
+        When <literal>+</literal> is given, more complete information
+        is displayed as a table.
+        </para>
+
+        <para>
+        "Database", "Authenticated User", "System User" (only for PostgreSQL 16 or higher),
+        "Current User", "Session User", "Backend PID", "Server Address", "Server Port",
+        "Client Address", "Client Port", "Socket Directory", and "Host" columns are listed
+        by default when <literal>\conninfo+</literal> is invoked. The columns "Encryption",
+        "Protocol", "Cipher", and "Compression" are added to this output when TLS (SSL)
+        authentication is used. The same applies to GSS authentication is used, where the
+        "GSSAPI" column is also added to the <literal>\conninfo+</literal> output.
         </para>
         </listitem>
       </varlistentry>
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index 5c906e4..cb5429f 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -68,7 +68,8 @@ static backslashResult exec_command_C(PsqlScanState scan_state, bool active_bran
 static backslashResult exec_command_connect(PsqlScanState scan_state, bool active_branch);
 static backslashResult exec_command_cd(PsqlScanState scan_state, bool active_branch,
 									   const char *cmd);
-static backslashResult exec_command_conninfo(PsqlScanState scan_state, bool active_branch);
+static backslashResult exec_command_conninfo(PsqlScanState scan_state, bool active_branch,
+											 const char *cmd);
 static backslashResult exec_command_copy(PsqlScanState scan_state, bool active_branch);
 static backslashResult exec_command_copyright(PsqlScanState scan_state, bool active_branch);
 static backslashResult exec_command_crosstabview(PsqlScanState scan_state, bool active_branch);
@@ -317,8 +318,8 @@ exec_command(const char *cmd,
 		status = exec_command_connect(scan_state, active_branch);
 	else if (strcmp(cmd, "cd") == 0)
 		status = exec_command_cd(scan_state, active_branch, cmd);
-	else if (strcmp(cmd, "conninfo") == 0)
-		status = exec_command_conninfo(scan_state, active_branch);
+	else if (strcmp(cmd, "conninfo") == 0 || strcmp(cmd, "conninfo+") == 0)
+		status = exec_command_conninfo(scan_state, active_branch, cmd);
 	else if (pg_strcasecmp(cmd, "copy") == 0)
 		status = exec_command_copy(scan_state, active_branch);
 	else if (strcmp(cmd, "copyright") == 0)
@@ -643,47 +644,80 @@ exec_command_cd(PsqlScanState scan_state, bool active_branch, const char *cmd)
 }
 
 /*
- * \conninfo -- display information about the current connection
+ * \conninfo, \conninfo+ -- display information about the current connection
  */
 static backslashResult
-exec_command_conninfo(PsqlScanState scan_state, bool active_branch)
+exec_command_conninfo(PsqlScanState scan_state, bool active_branch, const char *cmd)
 {
+	bool		success = true;
+
 	if (active_branch)
 	{
 		char	   *db = PQdb(pset.db);
+		bool		show_verbose;
+
+		show_verbose = strchr(cmd, '+') ? true : false;
 
-		if (db == NULL)
-			printf(_("You are currently not connected to a database.\n"));
+		/*
+		 * \conninfo+
+		 */
+		if (show_verbose)
+			success = listConnectionInformation();
+
+		/*
+		 * \conninfo
+		 */
 		else
 		{
-			char	   *host = PQhost(pset.db);
-			char	   *hostaddr = PQhostaddr(pset.db);
+			PGresult   *res;
+			PQExpBufferData buf;
 
-			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));
-			}
+			initPQExpBuffer(&buf);
+
+			printfPQExpBuffer(&buf,
+							  "SELECT\n"
+							  "  inet_server_addr();");
+
+			res = PSQLexec(buf.data);
+
+			termPQExpBuffer(&buf);
+
+			if (!res)
+				return PSQL_CMD_ERROR;
 			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));
+				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), PQgetvalue(res, 0, 0), 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
-					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));
+				{
+					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, PQgetvalue(res, 0, 0), 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));
+				}
+				PQclear(res);
+				printSSLInfo();
+				printGSSInfo();
 			}
-			printSSLInfo();
-			printGSSInfo();
 		}
 	}
+	else
+		ignore_slash_options(scan_state);
 
-	return PSQL_CMD_SKIP_LINE;
+	return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
 }
 
 /*
diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index b6a4eb1..2ef3db0 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -26,6 +26,7 @@
 #include "fe_utils/mbprint.h"
 #include "fe_utils/print.h"
 #include "fe_utils/string_utils.h"
+#include "libpq/pqcomm.h"
 #include "settings.h"
 #include "variables.h"
 
@@ -901,6 +902,91 @@ error_return:
 	return false;
 }
 
+/*
+ * listConnectionInformation
+ *
+ * for \conninfo+
+ */
+bool
+listConnectionInformation(void)
+{
+	PGresult   *res;
+	PQExpBufferData buf;
+	printQueryOpt myopt = pset.popt;
+
+	char	   *host = PQhost(pset.db);
+	char	   *hostaddr = PQhostaddr(pset.db);
+	const char *protocol;
+	const char *cipher;
+	const char *compression;
+
+	initPQExpBuffer(&buf);
+
+	printfPQExpBuffer(&buf,
+					  "SELECT\n"
+					  "  pg_catalog.current_database() AS \"Database\",\n"
+					  "  '%s' AS \"Authenticated User\",\n",
+					  PQuser(pset.db));
+	if (pset.sversion >= 160000)
+		appendPQExpBuffer(&buf,
+						  "  pg_catalog.system_user() AS \"System User\",\n");
+	appendPQExpBuffer(&buf,
+					  "  pg_catalog.current_user() AS \"Current User\",\n"
+					  "  pg_catalog.session_user() AS \"Session User\",\n"
+					  "  pg_catalog.pg_backend_pid() AS \"Backend PID\",\n"
+					  "  pg_catalog.inet_server_addr() AS \"Server Address\",\n"
+					  "  pg_catalog.current_setting('port') AS \"Server Port\",\n"
+					  "  pg_catalog.inet_client_addr() AS \"Client Address\",\n"
+					  "  pg_catalog.inet_client_port() AS \"Client Port\",\n");
+	if (is_unixsock_path(host) && !(hostaddr && *hostaddr))
+		appendPQExpBuffer(&buf,
+						  "  '%s' AS \"Socket Directory\",\n",
+						  host);
+	else
+		appendPQExpBuffer(&buf,
+						  "  NULL AS \"Socket Directory\",\n");
+	appendPQExpBuffer(&buf,
+					  "  CASE\n"
+					  "    WHEN\n"
+					  "      pg_catalog.inet_server_addr() IS NULL\n"
+					  "      AND pg_catalog.inet_client_addr() IS NULL\n"
+					  "    THEN NULL\n"
+					  "    ELSE '%s'\n"
+					  "  END AS \"Host\"\n",
+					  host);
+	if (PQsslInUse(pset.db))
+	{
+		protocol = PQsslAttribute(pset.db, "protocol");
+		cipher = PQsslAttribute(pset.db, "cipher");
+		compression = PQsslAttribute(pset.db, "compression");
+		appendPQExpBuffer(&buf,
+						  "  ,'SSL' AS \"Encryption\",\n"
+						  "  '%s' AS \"Protocol\",\n"
+						  "  '%s' AS \"Cipher\",\n"
+						  "  '%s' AS \"Compression\"\n",
+						  protocol ? protocol : _("unknown"),
+						  cipher ? cipher : _("unknown"),
+						  (compression && strcmp(compression, "off") != 0) ? _("on") : _("off"));
+	}
+	if (PQgssEncInUse(pset.db))
+		appendPQExpBuffer(&buf,
+						  "  ,'GSSAPI' AS \"Encryption\"\n");
+	appendPQExpBuffer(&buf,
+					  "  ;");
+
+	res = PSQLexec(buf.data);
+	termPQExpBuffer(&buf);
+	if (!res)
+		return false;
+
+	myopt.title = _("Current Connection Information");
+	myopt.translate_header = true;
+
+	printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
+
+	PQclear(res);
+	return true;
+}
 
 /*
  * listAllDbs
diff --git a/src/bin/psql/describe.h b/src/bin/psql/describe.h
index 273f974..8a4e83f 100644
--- a/src/bin/psql/describe.h
+++ b/src/bin/psql/describe.h
@@ -64,6 +64,9 @@ extern bool listTSDictionaries(const char *pattern, bool verbose);
 /* \dFt */
 extern bool listTSTemplates(const char *pattern, bool verbose);
 
+/* \conninfo */
+extern bool listConnectionInformation(void);
+
 /* \l */
 extern bool listAllDbs(const char *pattern, bool verbose);
 
diff --git a/src/bin/psql/help.c b/src/bin/psql/help.c
index 4e79a81..2c5426d 100644
--- a/src/bin/psql/help.c
+++ b/src/bin/psql/help.c
@@ -310,7 +310,7 @@ slashUsage(unsigned short int pager)
 	else
 		HELP0("  \\c[onnect] {[DBNAME|- USER|- HOST|- PORT|-] | conninfo}\n"
 			  "                         connect to new database (currently no connection)\n");
-	HELP0("  \\conninfo              display information about current connection\n");
+	HELP0("  \\conninfo[+]           display information about current connection\n");
 	HELP0("  \\encoding [ENCODING]   show or set client encoding\n");
 	HELP0("  \\password [USERNAME]   securely change the password for a user\n");
 	HELP0("\n");


^ permalink  raw  reply  [nested|flat] 43+ messages in thread

* Re: Psql meta-command conninfo+
  2024-02-06 21:50 Re: Psql meta-command conninfo+ Nathan Bossart <[email protected]>
  2024-02-07 04:13 ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-07 12:35   ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-07 14:47     ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-07 16:40       ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-07 20:13         ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-08 11:01           ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-08 14:58             ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-09 07:58               ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-12 14:16                 ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-14 11:36                   ` Re: Psql meta-command conninfo+ Jim Jones <[email protected]>
  2024-02-15 19:47                     ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-15 22:16                       ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
@ 2024-02-16 11:18                         ` Jim Jones <[email protected]>
  2024-02-16 15:54                           ` Re: Psql meta-command conninfo+ Nathan Bossart <[email protected]>
  2024-02-16 21:48                           ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  0 siblings, 2 replies; 43+ messages in thread

From: Jim Jones @ 2024-02-16 11:18 UTC (permalink / raw)
  To: Maiquel Grassi <[email protected]>; Pavel Luzanov <[email protected]>; Nathan Bossart <[email protected]>; +Cc: Erik Wienhold <[email protected]>; pgsql-hackers



On 15.02.24 23:16, Maiquel Grassi wrote:
>
> Hi!
>
> (v16)
>
> In this version, I made a small adjustment to the indentation
> of the \conninfo code and described the columns as returned
> by \conninfo+ as suggested by Jim Jones.
>
>

I've performed the following tests with v16:

1) hostaddr=172.19.42.1

$ /usr/local/postgres-dev/bin/psql -x "\
    host=server.uni-muenster.de
    hostaddr=172.19.42.1
    user=jim dbname=postgres
    sslrootcert=server-certificates/server.crt
    sslcert=jim-certificates/jim.crt
    sslkey=jim-certificates/jim.key" -c "\conninfo+" -c "\conninfo"

Current Connection Information
-[ RECORD 1
]------+---------------------------------------------------------------------------------------------------------------------------
Database           | postgres
Authenticated User | jim
System User        |
cert:[email protected],CN=jim,OU=WWU
IT,O=Universitaet Muenster,L=Muenster,ST=Nordrhein-Westfalen,C=DE
Current User       | jim
Session User       | jim
Backend PID        | 386839
Server Address     | 172.19.42.1
Server Port        | 5432
Client Address     | 192.168.178.27
Client Port        | 35602
Socket Directory   |
Host               | server.uni-muenster.de
Encryption         | SSL
Protocol           | TLSv1.3
Cipher             | TLS_AES_256_GCM_SHA384
Compression        | off

You are connected to database "postgres" as user "jim" on host
"server.uni-muenster.de" (address "172.19.42.1") at port "5432".
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384,
compression: off)


The same with non-superusers

$ /usr/local/postgres-dev/bin/psql -x "\
    host=server.uni-muenster.de
    hostaddr=172.19.42.1
    user=jim dbname=postgres
    sslrootcert=server-certificates/server.crt
    sslcert=jim-certificates/jim.crt
    sslkey=jim-certificates/jim.key" -c "SET ROLE foo" -c "\conninfo+"
-c "\conninfo"
SET
Current Connection Information
-[ RECORD 1
]------+---------------------------------------------------------------------------------------------------------------------------
Database           | postgres
Authenticated User | jim
System User        |
cert:[email protected],CN=jim,OU=WWU
IT,O=Universitaet Muenster,L=Muenster,ST=Nordrhein-Westfalen,C=DE
Current User       | foo
Session User       | jim
Backend PID        | 547733
Server Address     | 172.19.42.1
Server Port        | 5432
Client Address     | 192.168.178.27
Client Port        | 58508
Socket Directory   |
Host               | server.uni-muenster.de
Encryption         | SSL
Protocol           | TLSv1.3
Cipher             | TLS_AES_256_GCM_SHA384
Compression        | off

You are connected to database "postgres" as user "jim" on host
"server.uni-muenster.de" (address "172.19.42.1") at port "5432".
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384,
compression: off)


2) -h 192.168.178.27

$ /usr/local/postgres-dev/bin/psql -x -U postgres -h 192.168.178.27 -c
"\conninfo+" -c "\conninfo"
Current Connection Information
-[ RECORD 1 ]------+-----------------------
Database           | postgres
Authenticated User | postgres
System User        |
Current User       | postgres
Session User       | postgres
Backend PID        | 399670
Server Address     | 192.168.178.27
Server Port        | 5432
Client Address     | 192.168.178.27
Client Port        | 44174
Socket Directory   |
Host               | 192.168.178.27
Encryption         | SSL
Protocol           | TLSv1.3
Cipher             | TLS_AES_256_GCM_SHA384
Compression        | off

You are connected to database "postgres" as user "postgres" on host
"192.168.178.27" at port "5432".
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384,
compression: off)


3) via socket

$ /usr/local/postgres-dev/bin/psql -x -U postgres -c "\conninfo+" -c
"\conninfo"
Current Connection Information
-[ RECORD 1 ]------+---------
Database           | postgres
Authenticated User | postgres
System User        |
Current User       | postgres
Session User       | postgres
Backend PID        | 394273
Server Address     |
Server Port        | 5432
Client Address     |
Client Port        |
Socket Directory   | /tmp
Host               |

You are connected to database "postgres" as user "postgres" via socket
in "/tmp" at port "5432".

4) -h 127.0.0.1

$ /usr/local/postgres-dev/bin/psql -x -U postgres -h 127.0.0.1 -c
"\conninfo+" -c "\conninfo"
Current Connection Information
-[ RECORD 1 ]------+-----------------------
Database           | postgres
Authenticated User | postgres
System User        |
Current User       | postgres
Session User       | postgres
Backend PID        | 396070
Server Address     | 127.0.0.1
Server Port        | 5432
Client Address     | 127.0.0.1
Client Port        | 52528
Socket Directory   |
Host               | 127.0.0.1
Encryption         | SSL
Protocol           | TLSv1.3
Cipher             | TLS_AES_256_GCM_SHA384
Compression        | off

You are connected to database "postgres" as user "postgres" on host
"127.0.0.1" at port "5432".
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384,
compression: off)


5) -h localhost

$ /usr/local/postgres-dev/bin/psql -x -U postgres -h localhost -c
"\conninfo+" -c "\conninfo"
Current Connection Information
-[ RECORD 1 ]------+-----------------------
Database           | postgres
Authenticated User | postgres
System User        |
Current User       | postgres
Session User       | postgres
Backend PID        | 397056
Server Address     | 127.0.0.1
Server Port        | 5432
Client Address     | 127.0.0.1
Client Port        | 53578
Socket Directory   |
Host               | localhost
Encryption         | SSL
Protocol           | TLSv1.3
Cipher             | TLS_AES_256_GCM_SHA384
Compression        | off

You are connected to database "postgres" as user "postgres" on host
"localhost" (address "127.0.0.1") at port "5432".
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384,
compression: off)

6) -h 0

$ /usr/local/postgres-dev/bin/psql -x -U postgres -h 0 -c "\conninfo+"
-c "\conninfo"
Current Connection Information
-[ RECORD 1 ]------+-----------------------
Database           | postgres
Authenticated User | postgres
System User        |
Current User       | postgres
Session User       | postgres
Backend PID        | 406342
Server Address     | 127.0.0.1
Server Port        | 5432
Client Address     | 127.0.0.1
Client Port        | 38674
Socket Directory   |
Host               | 0
Encryption         | SSL
Protocol           | TLSv1.3
Cipher             | TLS_AES_256_GCM_SHA384
Compression        | off

You are connected to database "postgres" as user "postgres" on host "0"
(address "127.0.0.1") at port "5432".
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384,
compression: off)

7) -h 0.0.0.0 - As you mentioned, this is one of the cases where host
and "server address" differ.
   I am not sure if it is an issue. Perhaps the other reviewers might
have an opinion on it

$ /usr/local/postgres-dev/bin/psql -x -U postgres -h 0.0.0.0 -c
"\conninfo+" -c "\conninfo"
Current Connection Information
-[ RECORD 1 ]------+-----------------------
Database           | postgres
Authenticated User | postgres
System User        |
Current User       | postgres
Session User       | postgres
Backend PID        | 404395
Server Address     | 127.0.0.1
Server Port        | 5432
Client Address     | 127.0.0.1
Client Port        | 54806
Socket Directory   |
Host               | 0.0.0.0
Encryption         | SSL
Protocol           | TLSv1.3
Cipher             | TLS_AES_256_GCM_SHA384
Compression        | off

You are connected to database "postgres" as user "postgres" on host
"0.0.0.0" at port "5432".
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384,
compression: off)


> I would like to propose a change in "address" so that it always
returns the same as
> "Server Address", that is, to use the inet_server_address() function
in "address".

I'm not sure of the impact of this change in the existing \conninfo - at
least the cfbot and "make -j check-world" didn't complain.
I'll take a closer look at it as soon we have test cases.

Docs:

+        <term><literal>\conninfo[+]</literal></term>
         <listitem>
         <para>
         Outputs information about the current database connection.
+        When no <literal>+</literal> is specified, it simply prints
+        a textual description of a few connection options.
+        When <literal>+</literal> is given, more complete information
+        is displayed as a table.
+        </para>


To keep it consistent with the other options, we might wanna use "+ is
appended" instead of "+ is specified" or "+ is given"


+        When <literal>+</literal> is given, more complete information
+        is displayed as a table.
+        </para>
+
+        <para>
+        "Database", "Authenticated User", "System User" (only for
PostgreSQL 16 or higher),
+        "Current User", "Session User", "Backend PID", "Server
Address", "Server Port",
+        "Client Address", "Client Port", "Socket Directory", and "Host"
columns are listed
+        by default when <literal>\conninfo+</literal> is invoked. The
columns "Encryption",
+        "Protocol", "Cipher", and "Compression" are added to this
output when TLS (SSL)
+        authentication is used. The same applies to GSS authentication
is used, where the
+        "GSSAPI" column is also added to the
<literal>\conninfo+</literal> output.


I think that a list with a brief description of all columns would be
more interesting in this case (it is just a suggestion based on personal
taste, so feel to ignore it)

I had something along these lines in mind:

Outputs a string containing information about the current database
connection.
When + is appended, it outputs a table containing the following columns:

* Database: lorem ipsum
* Authenticated User:lorem ipsum
* System User: lorem ipsum
* Current User: lorem ipsum
* Session User: lorem ipsum
* Backend PID: lorem ipsum
* Server Address: lorem ipsum
* Server Port: lorem ipsum
* Client Address:lorem ipsum
* Client Port: lorem ipsum
* Socket Directory: lorem ipsum
* Host: lorem ipsum

TLS (SSL) authentication

These columns are added to the table TLS (SSL) authentication is used

* Encryption:lorem ipsum
* Cipher:lorem ipsum
* Protocol:lorem ipsum

GSS authentication ...
...


Thanks


-- 
Jim







^ permalink  raw  reply  [nested|flat] 43+ messages in thread

* Re: Psql meta-command conninfo+
  2024-02-06 21:50 Re: Psql meta-command conninfo+ Nathan Bossart <[email protected]>
  2024-02-07 04:13 ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-07 12:35   ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-07 14:47     ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-07 16:40       ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-07 20:13         ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-08 11:01           ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-08 14:58             ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-09 07:58               ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-12 14:16                 ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-14 11:36                   ` Re: Psql meta-command conninfo+ Jim Jones <[email protected]>
  2024-02-15 19:47                     ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-15 22:16                       ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-16 11:18                         ` Re: Psql meta-command conninfo+ Jim Jones <[email protected]>
@ 2024-02-16 15:54                           ` Nathan Bossart <[email protected]>
  2024-02-17 14:53                             ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  1 sibling, 1 reply; 43+ messages in thread

From: Nathan Bossart @ 2024-02-16 15:54 UTC (permalink / raw)
  To: Jim Jones <[email protected]>; +Cc: Maiquel Grassi <[email protected]>; Pavel Luzanov <[email protected]>; Erik Wienhold <[email protected]>; pgsql-hackers

Thanks for your work on this.  I haven't been keeping up with the
discussion, but I took a quick look at the latest patch.

+        <para>
+        "Database", "Authenticated User", "System User" (only for PostgreSQL 16 or higher),
+        "Current User", "Session User", "Backend PID", "Server Address", "Server Port",
+        "Client Address", "Client Port", "Socket Directory", and "Host" columns are listed
+        by default when <literal>\conninfo+</literal> is invoked. The columns "Encryption",
+        "Protocol", "Cipher", and "Compression" are added to this output when TLS (SSL)
+        authentication is used. The same applies to GSS authentication is used, where the
+        "GSSAPI" column is also added to the <literal>\conninfo+</literal> output.
         </para>

I might be alone on this, but I think this command should output the same
columns regardless of the version, whether it's using SSL, etc. and just
put NULL in any that do not apply.  IMHO that would simplify the code and
help prevent confusion.  Plus, I'm not aware of any existing meta-commands
that provide certain columns conditionally.

+	if (PQsslInUse(pset.db))
+	{
+		protocol = PQsslAttribute(pset.db, "protocol");
+		cipher = PQsslAttribute(pset.db, "cipher");
+		compression = PQsslAttribute(pset.db, "compression");
+		appendPQExpBuffer(&buf,
+						  "  ,'SSL' AS \"Encryption\",\n"
+						  "  '%s' AS \"Protocol\",\n"
+						  "  '%s' AS \"Cipher\",\n"
+						  "  '%s' AS \"Compression\"\n",
+						  protocol ? protocol : _("unknown"),
+						  cipher ? cipher : _("unknown"),
+						  (compression && strcmp(compression, "off") != 0) ? _("on") : _("off"));
+	}

Could we pull some of this information from pg_stat_ssl instead of from
libpq?  The reason I suggest this is because I think it would be nice if
the query that \conninfo+ uses could be copy/pasted as needed and not rely
on hard-coded values chosen by the client.

-- 
Nathan Bossart
Amazon Web Services: https://aws.amazon.com






^ permalink  raw  reply  [nested|flat] 43+ messages in thread

* RE: Psql meta-command conninfo+
  2024-02-06 21:50 Re: Psql meta-command conninfo+ Nathan Bossart <[email protected]>
  2024-02-07 04:13 ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-07 12:35   ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-07 14:47     ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-07 16:40       ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-07 20:13         ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-08 11:01           ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-08 14:58             ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-09 07:58               ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-12 14:16                 ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-14 11:36                   ` Re: Psql meta-command conninfo+ Jim Jones <[email protected]>
  2024-02-15 19:47                     ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-15 22:16                       ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-16 11:18                         ` Re: Psql meta-command conninfo+ Jim Jones <[email protected]>
  2024-02-16 15:54                           ` Re: Psql meta-command conninfo+ Nathan Bossart <[email protected]>
@ 2024-02-17 14:53                             ` Maiquel Grassi <[email protected]>
  2024-02-21 23:30                               ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-24 20:44                               ` Re: Psql meta-command conninfo+ Nathan Bossart <[email protected]>
  0 siblings, 2 replies; 43+ messages in thread

From: Maiquel Grassi @ 2024-02-17 14:53 UTC (permalink / raw)
  To: Nathan Bossart <[email protected]>; Jim Jones <[email protected]>; +Cc: Pavel Luzanov <[email protected]>; Erik Wienhold <[email protected]>; pgsql-hackers

Hi Nathan!

(v18)

>I might be alone on this, but I think this command should output the same
>columns regardless of the version, whether it's using SSL, etc. and just
>put NULL in any that do not apply. IMHO that would simplify the code and
>help prevent confusion. Plus, I'm not aware of any existing meta-commands
>that provide certain columns conditionally.

I implemented your suggestion. Now, whenever the \conninfo+ command is
invoked, all columns will appear. Contextually inappropriate cases will return
NULL. I also adjusted the names of the columns related to SSL to make this
information clearer for the user. I haven't focused on documenting the
columns yet. I will do that soon.

>Could we pull some of this information from pg_stat_ssl instead of from
>libpq? The reason I suggest this is because I think it would be nice if
>the query that \conninfo+ uses could be copy/pasted as needed and not rely
>on hard-coded values chosen by the client.

I've been considering using the views "pg_stat_ssl" and "pg_stat_gssapi"; however,
I realized that dealing with version-related cases using them is more complicated.

Let me explain the reasons:

The "pg_stat_ssl" view is available from >= PG 9.5, and the "pg_stat_gssapi" view is
available from >= PG 12. The "compression" column was removed from the
"pg_stat_ssl" from >= PG 14. All of these cases introduce greater complexity in
maintaining the SQL. The central idea from the beginning has always been to show
the user all the information from \conninfo and extend it in \conninfo+. The absence
of the "compression" column in version 14 and above makes dealing with this even
more complicated, and not showing it seems to contradict \conninfo.


SSL support has been available since version 7.1 (see documentation); if there was

support before that, I can't say. In this regard, it may seem strange, but there are still
many legacy systems running older versions of PostgreSQL. Just yesterday, I assisted
a client who is still using PG 8.2. In these cases, using the "pg_stat_ssl" and
"pg_stat_gssapi" views would not be possible because they don't exist on the server.
I believe that psql should cover as many cases as possible when it comes to compatibility
with older versions (even those no longer supported). In this case, concerning SSL and
GSS, I think libpq is better prepared to handle this.

I may be mistaken in my statement and I welcome any better suggestions. For now, I've
maintained the implementation using libpq as it seems to be working well and is not
contradicting \conninfo. If you have any suggestions on how to work around the absence
of the "compression" column, we can reconsider how to implement it without using libpq.

Tests:

[postgres@localhost bin]$ ./psql -x -h 127.0.0.1 -p 5432

Password for user postgres:
psql (17devel)
Type "help" for help.

postgres=# \conninfo
You are connected to database "postgres" as user "postgres" on host "127.0.0.1" at port "5432".
postgres=# \conninfo+
Current Connection Information
-[ RECORD 1 ]------+-----------------------
Database           | postgres
Authenticated User | postgres
System User        | scram-sha-256:postgres
Current User       | postgres
Session User       | postgres
Backend PID        | 22431
Server Address     | 127.0.0.1
Server Port        | 5432
Client Address     | 127.0.0.1
Client Port        | 51300
Socket Directory   |
Host               | 127.0.0.1
SSL Connection     | f
SSL Protocol       |
SSL Cipher         |
SSL Compression    |
GSSAPI             | f


[postgres@localhost bin]$ ./psql -x -h 127.0.0.1 -p 5433
Password for user postgres:
psql (17devel, server 15.6)
SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, compression: off)
Type "help" for help.

postgres=# \conninfo
You are connected to database "postgres" as user "postgres" on host "127.0.0.1" at port "5433".
SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, compression: off)
postgres=# \conninfo+
Current Connection Information
-[ RECORD 1 ]------+----------------------------
Database           | postgres
Authenticated User | postgres
System User        |
Current User       | postgres
Session User       | postgres
Backend PID        | 22438
Server Address     | 127.0.0.1
Server Port        | 5433
Client Address     | 127.0.0.1
Client Port        | 36016
Socket Directory   |
Host               | 127.0.0.1
SSL Connection     | t
SSL Protocol       | TLSv1.2
SSL Cipher         | ECDHE-RSA-AES256-GCM-SHA384
SSL Compression    | off
GSSAPI             | f

Thank you very much for your sugestions and help!
Maiquel Grassi.


Attachments:

  [application/octet-stream] v18-0001-psql-meta-command-conninfo-plus.patch (11.6K, ../../CP8P284MB2496AAFB879ABC5B1CD01CF4EC532@CP8P284MB2496.BRAP284.PROD.OUTLOOK.COM/3-v18-0001-psql-meta-command-conninfo-plus.patch)
  download | inline diff:
diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml
index cc7d797..d6b92fb 100644
--- a/doc/src/sgml/ref/psql-ref.sgml
+++ b/doc/src/sgml/ref/psql-ref.sgml
@@ -1029,11 +1029,84 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g
       </varlistentry>
 
       <varlistentry id="app-psql-meta-command-conninfo">
-        <term><literal>\conninfo</literal></term>
+        <term><literal>\conninfo[+]</literal></term>
         <listitem>
         <para>
         Outputs information about the current database connection.
+        When no <literal>+</literal> is appended, it simply prints
+        a textual (string) description of a few connection options.
+        When <literal>+</literal> is given, more complete information
+        is displayed as a table containing the following columns:
         </para>
+
+        <para>
+        <literal>Database:</literal> blah blah blah
+        </para>
+
+        <para>
+        <literal>Authenticated User:</literal> blah blah blah
+        </para>
+
+        <para>
+        <literal>System User:</literal> blah blah blah
+        </para>
+
+        <para>
+        <literal>Current User:</literal> blah blah blah
+        </para>
+
+        <para>
+        <literal>Session User:</literal> blah blah blah
+        </para>
+
+        <para>
+        <literal>Backend PID:</literal> blah blah blah
+        </para>
+
+        <para>
+        <literal>Server Address:</literal> blah blah blah
+        </para>
+
+        <para>
+        <literal>Server Port:</literal> blah blah blah
+        </para>
+
+        <para>
+        <literal>Client Address:</literal> blah blah blah
+        </para>
+
+        <para>
+        <literal>Client Port:</literal> blah blah blah
+        </para>
+
+        <para>
+        <literal>Socket Directory:</literal> blah blah blah
+        </para>
+
+        <para>
+        <literal>Host:</literal> blah blah blah
+        </para>
+
+        <para>
+        <literal>SSL Connection:</literal> blah blah blah
+        </para>
+
+        <para>
+        <literal>SSL Protocol:</literal> blah blah blah
+        </para>
+
+        <para>
+        <literal>SSL Cipher:</literal> blah blah blah
+        </para>
+
+        <para>
+        <literal>SLL Compression:</literal> blah blah blah
+        </para>
+
+        <para>
+        <literal>GSSAPI:</literal> blah blah blah
+        </para>
+
         </listitem>
       </varlistentry>
 
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index 5c906e4..cb5429f 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -68,7 +68,8 @@ static backslashResult exec_command_C(PsqlScanState scan_state, bool active_bran
 static backslashResult exec_command_connect(PsqlScanState scan_state, bool active_branch);
 static backslashResult exec_command_cd(PsqlScanState scan_state, bool active_branch,
 									   const char *cmd);
-static backslashResult exec_command_conninfo(PsqlScanState scan_state, bool active_branch);
+static backslashResult exec_command_conninfo(PsqlScanState scan_state, bool active_branch,
+											 const char *cmd);
 static backslashResult exec_command_copy(PsqlScanState scan_state, bool active_branch);
 static backslashResult exec_command_copyright(PsqlScanState scan_state, bool active_branch);
 static backslashResult exec_command_crosstabview(PsqlScanState scan_state, bool active_branch);
@@ -317,8 +318,8 @@ exec_command(const char *cmd,
 		status = exec_command_connect(scan_state, active_branch);
 	else if (strcmp(cmd, "cd") == 0)
 		status = exec_command_cd(scan_state, active_branch, cmd);
-	else if (strcmp(cmd, "conninfo") == 0)
-		status = exec_command_conninfo(scan_state, active_branch);
+	else if (strcmp(cmd, "conninfo") == 0 || strcmp(cmd, "conninfo+") == 0)
+		status = exec_command_conninfo(scan_state, active_branch, cmd);
 	else if (pg_strcasecmp(cmd, "copy") == 0)
 		status = exec_command_copy(scan_state, active_branch);
 	else if (strcmp(cmd, "copyright") == 0)
@@ -643,47 +644,80 @@ exec_command_cd(PsqlScanState scan_state, bool active_branch, const char *cmd)
 }
 
 /*
- * \conninfo -- display information about the current connection
+ * \conninfo, \conninfo+ -- display information about the current connection
  */
 static backslashResult
-exec_command_conninfo(PsqlScanState scan_state, bool active_branch)
+exec_command_conninfo(PsqlScanState scan_state, bool active_branch, const char *cmd)
 {
+	bool		success = true;
+
 	if (active_branch)
 	{
 		char	   *db = PQdb(pset.db);
+		bool		show_verbose;
+
+		show_verbose = strchr(cmd, '+') ? true : false;
 
-		if (db == NULL)
-			printf(_("You are currently not connected to a database.\n"));
+		/*
+		 * \conninfo+
+		 */
+		if (show_verbose)
+			success = listConnectionInformation();
+
+		/*
+		 * \conninfo
+		 */
 		else
 		{
-			char	   *host = PQhost(pset.db);
-			char	   *hostaddr = PQhostaddr(pset.db);
+			PGresult   *res;
+			PQExpBufferData buf;
 
-			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));
-			}
+			initPQExpBuffer(&buf);
+
+			printfPQExpBuffer(&buf,
+							  "SELECT\n"
+							  "  inet_server_addr();");
+
+			res = PSQLexec(buf.data);
+
+			termPQExpBuffer(&buf);
+
+			if (!res)
+				return PSQL_CMD_ERROR;
 			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));
+				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), PQgetvalue(res, 0, 0), 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
-					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));
+				{
+					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, PQgetvalue(res, 0, 0), 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));
+				}
+				PQclear(res);
+				printSSLInfo();
+				printGSSInfo();
 			}
-			printSSLInfo();
-			printGSSInfo();
 		}
 	}
+	else
+		ignore_slash_options(scan_state);
 
-	return PSQL_CMD_SKIP_LINE;
+	return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
 }
 
 /*
diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index b6a4eb1..9a83592 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -26,6 +26,7 @@
 #include "fe_utils/mbprint.h"
 #include "fe_utils/print.h"
 #include "fe_utils/string_utils.h"
+#include "libpq/pqcomm.h"
 #include "settings.h"
 #include "variables.h"
 
@@ -901,6 +902,105 @@ error_return:
 	return false;
 }
 
+/*
+ * listConnectionInformation
+ *
+ * for \conninfo+
+ */
+bool
+listConnectionInformation(void)
+{
+	PGresult   *res;
+	PQExpBufferData buf;
+	printQueryOpt myopt = pset.popt;
+
+	char	   *host = PQhost(pset.db);
+	char	   *hostaddr = PQhostaddr(pset.db);
+
+	const char *protocol;
+	const char *cipher;
+	const char *compression;
+
+	initPQExpBuffer(&buf);
+
+	printfPQExpBuffer(&buf,
+					  "SELECT\n"
+					  "  pg_catalog.current_database() AS \"Database\",\n"
+					  "  '%s' AS \"Authenticated User\",\n",
+					  PQuser(pset.db));
+	if (pset.sversion >= 160000)
+		appendPQExpBuffer(&buf,
+						  "  pg_catalog.system_user() AS \"System User\",\n");
+	else
+		appendPQExpBuffer(&buf,
+						  "  NULL AS \"System User\",\n");
+	appendPQExpBuffer(&buf,
+					  "  pg_catalog.current_user() AS \"Current User\",\n"
+					  "  pg_catalog.session_user() AS \"Session User\",\n"
+					  "  pg_catalog.pg_backend_pid() AS \"Backend PID\",\n"
+					  "  pg_catalog.inet_server_addr() AS \"Server Address\",\n"
+					  "  pg_catalog.current_setting('port') AS \"Server Port\",\n"
+					  "  pg_catalog.inet_client_addr() AS \"Client Address\",\n"
+					  "  pg_catalog.inet_client_port() AS \"Client Port\",\n");
+	if (is_unixsock_path(host) && !(hostaddr && *hostaddr))
+		appendPQExpBuffer(&buf,
+						  "  '%s' AS \"Socket Directory\",\n",
+						  host);
+	else
+		appendPQExpBuffer(&buf,
+						  "  NULL AS \"Socket Directory\",\n");
+	appendPQExpBuffer(&buf,
+					  "  CASE\n"
+					  "    WHEN\n"
+					  "      pg_catalog.inet_server_addr() IS NULL\n"
+					  "      AND pg_catalog.inet_client_addr() IS NULL\n"
+					  "    THEN NULL\n"
+					  "    ELSE '%s'\n"
+					  "  END AS \"Host\",\n",
+					  host);
+	if (PQsslInUse(pset.db))
+	{
+		protocol = PQsslAttribute(pset.db, "protocol");
+		cipher = PQsslAttribute(pset.db, "cipher");
+		compression = PQsslAttribute(pset.db, "compression");
+
+		appendPQExpBuffer(&buf,
+						  "  true AS \"SSL Connection\",\n"
+						  "  '%s' AS \"SSL Protocol\",\n"
+						  "  '%s' AS \"SSL Cipher\",\n"
+						  "  '%s' AS \"SSL Compression\",\n",
+						  protocol ? protocol : _("unknown"),
+						  cipher ? cipher : _("unknown"),
+						  (compression && strcmp(compression, "off") != 0) ? _("on") : _("off"));
+	}
+	else
+		appendPQExpBuffer(&buf,
+						  "  false AS \"SSL Connection\",\n"
+						  "  NULL AS \"SSL Protocol\",\n"
+						  "  NULL AS \"SSL Cipher\",\n"
+						  "  NULL AS \"SSL Compression\",\n");
+	if (PQgssEncInUse(pset.db))
+		appendPQExpBuffer(&buf,
+						  "  true AS \"GSSAPI\"\n");
+	else
+		appendPQExpBuffer(&buf,
+						  "  false AS \"GSSAPI\"\n");
+	appendPQExpBuffer(&buf,
+					  ";");
+
+	res = PSQLexec(buf.data);
+	termPQExpBuffer(&buf);
+	if (!res)
+		return false;
+
+	myopt.title = _("Current Connection Information");
+	myopt.translate_header = true;
+
+	printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
+
+	PQclear(res);
+	return true;
+}
 
 /*
  * listAllDbs
diff --git a/src/bin/psql/describe.h b/src/bin/psql/describe.h
index 273f974..8a4e83f 100644
--- a/src/bin/psql/describe.h
+++ b/src/bin/psql/describe.h
@@ -64,6 +64,9 @@ extern bool listTSDictionaries(const char *pattern, bool verbose);
 /* \dFt */
 extern bool listTSTemplates(const char *pattern, bool verbose);
 
+/* \conninfo */
+extern bool listConnectionInformation(void);
+
 /* \l */
 extern bool listAllDbs(const char *pattern, bool verbose);
 
diff --git a/src/bin/psql/help.c b/src/bin/psql/help.c
index 4e79a81..2c5426d 100644
--- a/src/bin/psql/help.c
+++ b/src/bin/psql/help.c
@@ -310,7 +310,7 @@ slashUsage(unsigned short int pager)
 	else
 		HELP0("  \\c[onnect] {[DBNAME|- USER|- HOST|- PORT|-] | conninfo}\n"
 			  "                         connect to new database (currently no connection)\n");
-	HELP0("  \\conninfo              display information about current connection\n");
+	HELP0("  \\conninfo[+]           display information about current connection\n");
 	HELP0("  \\encoding [ENCODING]   show or set client encoding\n");
 	HELP0("  \\password [USERNAME]   securely change the password for a user\n");
 	HELP0("\n");


^ permalink  raw  reply  [nested|flat] 43+ messages in thread

* RE: Psql meta-command conninfo+
  2024-02-06 21:50 Re: Psql meta-command conninfo+ Nathan Bossart <[email protected]>
  2024-02-07 04:13 ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-07 12:35   ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-07 14:47     ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-07 16:40       ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-07 20:13         ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-08 11:01           ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-08 14:58             ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-09 07:58               ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-12 14:16                 ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-14 11:36                   ` Re: Psql meta-command conninfo+ Jim Jones <[email protected]>
  2024-02-15 19:47                     ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-15 22:16                       ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-16 11:18                         ` Re: Psql meta-command conninfo+ Jim Jones <[email protected]>
  2024-02-16 15:54                           ` Re: Psql meta-command conninfo+ Nathan Bossart <[email protected]>
  2024-02-17 14:53                             ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
@ 2024-02-21 23:30                               ` Maiquel Grassi <[email protected]>
  1 sibling, 0 replies; 43+ messages in thread

From: Maiquel Grassi @ 2024-02-21 23:30 UTC (permalink / raw)
  To: Nathan Bossart <[email protected]>; Jim Jones <[email protected]>; +Cc: Pavel Luzanov <[email protected]>; Erik Wienhold <[email protected]>; pgsql-hackers

Hi!

(v19)

Adjusted the description of each column in the documentation as promised.
I used the existing documentation as a basis for each SQL function used,
as well as for functions and views related to SSL and GSSAPI (documentation).

If you can validate, I appreciate it.

Regards,
Maiquel Grassi.


Attachments:

  [application/octet-stream] v19-0001-psql-meta-command-conninfo-plus.patch (13.3K, ../../CP8P284MB24966F78652FCCCA7E8AD751EC572@CP8P284MB2496.BRAP284.PROD.OUTLOOK.COM/3-v19-0001-psql-meta-command-conninfo-plus.patch)
  download | inline diff:
diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml
index cc7d797..48dddbc 100644
--- a/doc/src/sgml/ref/psql-ref.sgml
+++ b/doc/src/sgml/ref/psql-ref.sgml
@@ -1029,11 +1029,106 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g
       </varlistentry>
 
       <varlistentry id="app-psql-meta-command-conninfo">
-        <term><literal>\conninfo</literal></term>
+        <term><literal>\conninfo[+]</literal></term>
         <listitem>
         <para>
         Outputs information about the current database connection.
+        When no <literal>+</literal> is appended, it simply prints
+        a textual (string) description of a few connection options.
+        When <literal>+</literal> is given, more complete information
+        is displayed as a table containing the following columns:
         </para>
+
+        <para>
+        <literal>Database:</literal> Displays the name of the current
+        database on this connection.
+        </para>
+
+        <para>
+        <literal>Authenticated User:</literal> Displays the authenticated
+        user at the time of psql connection with the server.
+        </para>
+
+        <para>
+        <literal>System User:</literal> Returns the authentication method
+        and the identity (if any) that the user presented during the
+        authentication cycle before they were assigned a database role. It
+        is represented as auth_method:identity or NULL if the user has not
+        been authenticated.
+        </para>
+
+        <para>
+        <literal>Current User:</literal> Displays the user name of the
+        current execution context.
+        </para>
+
+        <para>
+        <literal>Session User:</literal> Displays the session user's name.
+        </para>
+
+        <para>
+        <literal>Backend PID:</literal> Displays the process ID of the server
+        process attached to the current session.
+        </para>
+
+        <para>
+        <literal>Server Address:</literal> Displays the IP address on which
+        the server accepted the current connection, or NULL if the current
+        connection is via a Unix-domain socket.
+        </para>
+
+        <para>
+        <literal>Server Port:</literal> Displays the IP port number on which
+        the server accepted the current connection, or NULL if the current
+        connection is via a Unix-domain socket.
+        </para>
+
+        <para>
+        <literal>Client Address:</literal> Displays the IP address of the
+        current client, or NULL if the current connection is via a Unix-domain socket.
+        </para>
+
+        <para>
+        <literal>Client Port:</literal> Displays the IP port number of the
+        current client, or NULL if the current connection is via a Unix-domain socket.
+        </para>
+
+        <para>
+        <literal>Socket Directory:</literal> Displays the directory where
+        Unix-domain socket was created.
+        </para>
+
+        <para>
+        <literal>Host:</literal> Displays the host of the connection,
+        which refers to the address or name of the machine where the server
+        is running. When a socket connection is established, it displays NULL.
+        </para>
+
+        <para>
+        <literal>SSL Connection:</literal> Displays "true" if the current
+        connection to the server uses SSL, and "false" otherwise.
+        </para>
+
+        <para>
+        <literal>SSL Protocol:</literal> Displays the name of the protocol
+        used for the SSL connection (e.g., TLSv1.0, TLSv1.1, TLSv1.2 or TLSv1.3).
+        </para>
+
+        <para>
+        <literal>SSL Cipher:</literal> Displays the name of the cipher used
+        for the SSL connection (e.g., DHE-RSA-AES256-SHA).
+        </para>
+
+        <para>
+        <literal>SLL Compression:</literal> Displays "on" if SSL compression
+        is in use, "off" if not, or NULL if SSL is not in use on this connection.
+        </para>
+
+        <para>
+        <literal>GSSAPI:</literal> Displays "true" if GSSAPI is in use, or "false"
+        if GSSAPI is not in use on this connection.
+        </para>
+
         </listitem>
       </varlistentry>
 
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index 5c906e4..cb5429f 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -68,7 +68,8 @@ static backslashResult exec_command_C(PsqlScanState scan_state, bool active_bran
 static backslashResult exec_command_connect(PsqlScanState scan_state, bool active_branch);
 static backslashResult exec_command_cd(PsqlScanState scan_state, bool active_branch,
 									   const char *cmd);
-static backslashResult exec_command_conninfo(PsqlScanState scan_state, bool active_branch);
+static backslashResult exec_command_conninfo(PsqlScanState scan_state, bool active_branch,
+											 const char *cmd);
 static backslashResult exec_command_copy(PsqlScanState scan_state, bool active_branch);
 static backslashResult exec_command_copyright(PsqlScanState scan_state, bool active_branch);
 static backslashResult exec_command_crosstabview(PsqlScanState scan_state, bool active_branch);
@@ -317,8 +318,8 @@ exec_command(const char *cmd,
 		status = exec_command_connect(scan_state, active_branch);
 	else if (strcmp(cmd, "cd") == 0)
 		status = exec_command_cd(scan_state, active_branch, cmd);
-	else if (strcmp(cmd, "conninfo") == 0)
-		status = exec_command_conninfo(scan_state, active_branch);
+	else if (strcmp(cmd, "conninfo") == 0 || strcmp(cmd, "conninfo+") == 0)
+		status = exec_command_conninfo(scan_state, active_branch, cmd);
 	else if (pg_strcasecmp(cmd, "copy") == 0)
 		status = exec_command_copy(scan_state, active_branch);
 	else if (strcmp(cmd, "copyright") == 0)
@@ -643,47 +644,80 @@ exec_command_cd(PsqlScanState scan_state, bool active_branch, const char *cmd)
 }
 
 /*
- * \conninfo -- display information about the current connection
+ * \conninfo, \conninfo+ -- display information about the current connection
  */
 static backslashResult
-exec_command_conninfo(PsqlScanState scan_state, bool active_branch)
+exec_command_conninfo(PsqlScanState scan_state, bool active_branch, const char *cmd)
 {
+	bool		success = true;
+
 	if (active_branch)
 	{
 		char	   *db = PQdb(pset.db);
+		bool		show_verbose;
+
+		show_verbose = strchr(cmd, '+') ? true : false;
 
-		if (db == NULL)
-			printf(_("You are currently not connected to a database.\n"));
+		/*
+		 * \conninfo+
+		 */
+		if (show_verbose)
+			success = listConnectionInformation();
+
+		/*
+		 * \conninfo
+		 */
 		else
 		{
-			char	   *host = PQhost(pset.db);
-			char	   *hostaddr = PQhostaddr(pset.db);
+			PGresult   *res;
+			PQExpBufferData buf;
 
-			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));
-			}
+			initPQExpBuffer(&buf);
+
+			printfPQExpBuffer(&buf,
+							  "SELECT\n"
+							  "  inet_server_addr();");
+
+			res = PSQLexec(buf.data);
+
+			termPQExpBuffer(&buf);
+
+			if (!res)
+				return PSQL_CMD_ERROR;
 			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));
+				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), PQgetvalue(res, 0, 0), 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
-					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));
+				{
+					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, PQgetvalue(res, 0, 0), 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));
+				}
+				PQclear(res);
+				printSSLInfo();
+				printGSSInfo();
 			}
-			printSSLInfo();
-			printGSSInfo();
 		}
 	}
+	else
+		ignore_slash_options(scan_state);
 
-	return PSQL_CMD_SKIP_LINE;
+	return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
 }
 
 /*
diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index b6a4eb1..9a83592 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -26,6 +26,7 @@
 #include "fe_utils/mbprint.h"
 #include "fe_utils/print.h"
 #include "fe_utils/string_utils.h"
+#include "libpq/pqcomm.h"
 #include "settings.h"
 #include "variables.h"
 
@@ -901,6 +902,105 @@ error_return:
 	return false;
 }
 
+/*
+ * listConnectionInformation
+ *
+ * for \conninfo+
+ */
+bool
+listConnectionInformation(void)
+{
+	PGresult   *res;
+	PQExpBufferData buf;
+	printQueryOpt myopt = pset.popt;
+
+	char	   *host = PQhost(pset.db);
+	char	   *hostaddr = PQhostaddr(pset.db);
+
+	const char *protocol;
+	const char *cipher;
+	const char *compression;
+
+	initPQExpBuffer(&buf);
+
+	printfPQExpBuffer(&buf,
+					  "SELECT\n"
+					  "  pg_catalog.current_database() AS \"Database\",\n"
+					  "  '%s' AS \"Authenticated User\",\n",
+					  PQuser(pset.db));
+	if (pset.sversion >= 160000)
+		appendPQExpBuffer(&buf,
+						  "  pg_catalog.system_user() AS \"System User\",\n");
+	else
+		appendPQExpBuffer(&buf,
+						  "  NULL AS \"System User\",\n");
+	appendPQExpBuffer(&buf,
+					  "  pg_catalog.current_user() AS \"Current User\",\n"
+					  "  pg_catalog.session_user() AS \"Session User\",\n"
+					  "  pg_catalog.pg_backend_pid() AS \"Backend PID\",\n"
+					  "  pg_catalog.inet_server_addr() AS \"Server Address\",\n"
+					  "  pg_catalog.current_setting('port') AS \"Server Port\",\n"
+					  "  pg_catalog.inet_client_addr() AS \"Client Address\",\n"
+					  "  pg_catalog.inet_client_port() AS \"Client Port\",\n");
+	if (is_unixsock_path(host) && !(hostaddr && *hostaddr))
+		appendPQExpBuffer(&buf,
+						  "  '%s' AS \"Socket Directory\",\n",
+						  host);
+	else
+		appendPQExpBuffer(&buf,
+						  "  NULL AS \"Socket Directory\",\n");
+	appendPQExpBuffer(&buf,
+					  "  CASE\n"
+					  "    WHEN\n"
+					  "      pg_catalog.inet_server_addr() IS NULL\n"
+					  "      AND pg_catalog.inet_client_addr() IS NULL\n"
+					  "    THEN NULL\n"
+					  "    ELSE '%s'\n"
+					  "  END AS \"Host\",\n",
+					  host);
+	if (PQsslInUse(pset.db))
+	{
+		protocol = PQsslAttribute(pset.db, "protocol");
+		cipher = PQsslAttribute(pset.db, "cipher");
+		compression = PQsslAttribute(pset.db, "compression");
+
+		appendPQExpBuffer(&buf,
+						  "  true AS \"SSL Connection\",\n"
+						  "  '%s' AS \"SSL Protocol\",\n"
+						  "  '%s' AS \"SSL Cipher\",\n"
+						  "  '%s' AS \"SSL Compression\",\n",
+						  protocol ? protocol : _("unknown"),
+						  cipher ? cipher : _("unknown"),
+						  (compression && strcmp(compression, "off") != 0) ? _("on") : _("off"));
+	}
+	else
+		appendPQExpBuffer(&buf,
+						  "  false AS \"SSL Connection\",\n"
+						  "  NULL AS \"SSL Protocol\",\n"
+						  "  NULL AS \"SSL Cipher\",\n"
+						  "  NULL AS \"SSL Compression\",\n");
+	if (PQgssEncInUse(pset.db))
+		appendPQExpBuffer(&buf,
+						  "  true AS \"GSSAPI\"\n");
+	else
+		appendPQExpBuffer(&buf,
+						  "  false AS \"GSSAPI\"\n");
+	appendPQExpBuffer(&buf,
+					  ";");
+
+	res = PSQLexec(buf.data);
+	termPQExpBuffer(&buf);
+	if (!res)
+		return false;
+
+	myopt.title = _("Current Connection Information");
+	myopt.translate_header = true;
+
+	printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
+
+	PQclear(res);
+	return true;
+}
 
 /*
  * listAllDbs
diff --git a/src/bin/psql/describe.h b/src/bin/psql/describe.h
index 273f974..8a4e83f 100644
--- a/src/bin/psql/describe.h
+++ b/src/bin/psql/describe.h
@@ -64,6 +64,9 @@ extern bool listTSDictionaries(const char *pattern, bool verbose);
 /* \dFt */
 extern bool listTSTemplates(const char *pattern, bool verbose);
 
+/* \conninfo */
+extern bool listConnectionInformation(void);
+
 /* \l */
 extern bool listAllDbs(const char *pattern, bool verbose);
 
diff --git a/src/bin/psql/help.c b/src/bin/psql/help.c
index 4e79a81..2c5426d 100644
--- a/src/bin/psql/help.c
+++ b/src/bin/psql/help.c
@@ -310,7 +310,7 @@ slashUsage(unsigned short int pager)
 	else
 		HELP0("  \\c[onnect] {[DBNAME|- USER|- HOST|- PORT|-] | conninfo}\n"
 			  "                         connect to new database (currently no connection)\n");
-	HELP0("  \\conninfo              display information about current connection\n");
+	HELP0("  \\conninfo[+]           display information about current connection\n");
 	HELP0("  \\encoding [ENCODING]   show or set client encoding\n");
 	HELP0("  \\password [USERNAME]   securely change the password for a user\n");
 	HELP0("\n");


^ permalink  raw  reply  [nested|flat] 43+ messages in thread

* Re: Psql meta-command conninfo+
  2024-02-06 21:50 Re: Psql meta-command conninfo+ Nathan Bossart <[email protected]>
  2024-02-07 04:13 ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-07 12:35   ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-07 14:47     ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-07 16:40       ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-07 20:13         ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-08 11:01           ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-08 14:58             ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-09 07:58               ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-12 14:16                 ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-14 11:36                   ` Re: Psql meta-command conninfo+ Jim Jones <[email protected]>
  2024-02-15 19:47                     ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-15 22:16                       ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-16 11:18                         ` Re: Psql meta-command conninfo+ Jim Jones <[email protected]>
  2024-02-16 15:54                           ` Re: Psql meta-command conninfo+ Nathan Bossart <[email protected]>
  2024-02-17 14:53                             ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
@ 2024-02-24 20:44                               ` Nathan Bossart <[email protected]>
  2024-02-29 22:02                                 ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  1 sibling, 1 reply; 43+ messages in thread

From: Nathan Bossart @ 2024-02-24 20:44 UTC (permalink / raw)
  To: Maiquel Grassi <[email protected]>; +Cc: Jim Jones <[email protected]>; Pavel Luzanov <[email protected]>; Erik Wienhold <[email protected]>; pgsql-hackers

On Sat, Feb 17, 2024 at 02:53:43PM +0000, Maiquel Grassi wrote:
> The "pg_stat_ssl" view is available from >= PG 9.5, and the "pg_stat_gssapi" view is
> available from >= PG 12. The "compression" column was removed from the
> "pg_stat_ssl" from >= PG 14. All of these cases introduce greater complexity in
> maintaining the SQL. The central idea from the beginning has always been to show
> the user all the information from \conninfo and extend it in \conninfo+.

IMHO we should use the views whenever possible (for the reason stated
above [0]).  I think it's okay if we need to fall back to a different
approach for older versions.  But presumably we'll discontinue psql support
for these old server versions at some point, at which point we can simply
delete the dead code that doesn't use the views.

> The absence
> of the "compression" column in version 14 and above makes dealing with this even
> more complicated, and not showing it seems to contradict \conninfo.

I would be okay with using PQsslAttribute() for all versions for this one
since any remaining support for this feature is on its way out.  Once psql
no longer supports any versions that allow SSL compression, we could
probably remove it from \conninfo[+] completely or hard-code it to "off".

> SSL support has been available since version 7.1 (see documentation); if there was
> 
> support before that, I can't say. In this regard, it may seem strange, but there are still
> many legacy systems running older versions of PostgreSQL. Just yesterday, I assisted
> a client who is still using PG 8.2. In these cases, using the "pg_stat_ssl" and
> "pg_stat_gssapi" views would not be possible because they don't exist on the server.
> I believe that psql should cover as many cases as possible when it comes to compatibility
> with older versions (even those no longer supported). In this case, concerning SSL and
> GSS, I think libpq is better prepared to handle this.

At the moment, the psql support cutoff appears to be v9.2 (see commit
cf0cab8), which has been out of support for over 6 years.  If \conninfo+
happens to work for older versions, then great, but I don't think we should
expend too much energy in this area.

[0] https://postgr.es/m/20240216155449.GA1236054%40nathanxps13

-- 
Nathan Bossart
Amazon Web Services: https://aws.amazon.com






^ permalink  raw  reply  [nested|flat] 43+ messages in thread

* RE: Psql meta-command conninfo+
  2024-02-06 21:50 Re: Psql meta-command conninfo+ Nathan Bossart <[email protected]>
  2024-02-07 04:13 ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-07 12:35   ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-07 14:47     ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-07 16:40       ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-07 20:13         ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-08 11:01           ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-08 14:58             ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-09 07:58               ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-12 14:16                 ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-14 11:36                   ` Re: Psql meta-command conninfo+ Jim Jones <[email protected]>
  2024-02-15 19:47                     ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-15 22:16                       ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-16 11:18                         ` Re: Psql meta-command conninfo+ Jim Jones <[email protected]>
  2024-02-16 15:54                           ` Re: Psql meta-command conninfo+ Nathan Bossart <[email protected]>
  2024-02-17 14:53                             ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-24 20:44                               ` Re: Psql meta-command conninfo+ Nathan Bossart <[email protected]>
@ 2024-02-29 22:02                                 ` Maiquel Grassi <[email protected]>
  2024-02-29 22:41                                   ` Re: Psql meta-command conninfo+ Nathan Bossart <[email protected]>
  2024-03-14 16:46                                   ` Re: Psql meta-command conninfo+ Nathan Bossart <[email protected]>
  0 siblings, 2 replies; 43+ messages in thread

From: Maiquel Grassi @ 2024-02-29 22:02 UTC (permalink / raw)
  To: Nathan Bossart <[email protected]>; +Cc: Jim Jones <[email protected]>; Pavel Luzanov <[email protected]>; Erik Wienhold <[email protected]>; pgsql-hackers

On Sat, Feb 17, 2024 at 02:53:43PM +0000, Maiquel Grassi wrote:
>> The "pg_stat_ssl" view is available from >= PG 9.5, and the "pg_stat_gssapi" view is
>> available from >= PG 12. The "compression" column was removed from the
>> "pg_stat_ssl" from >= PG 14. All of these cases introduce greater complexity in
>> maintaining the SQL. The central idea from the beginning has always been to show
>> the user all the information from \conninfo and extend it in \conninfo+.

>IMHO we should use the views whenever possible (for the reason stated
>above [0]).  I think it's okay if we need to fall back to a different
>approach for older versions.  But presumably we'll discontinue psql support
>for these old server versions at some point, at which point we can simply
>delete the dead code that doesn't use the views.

>> The absence
>> of the "compression" column in version 14 and above makes dealing with this even
>> more complicated, and not showing it seems to contradict \conninfo.

>I would be okay with using PQsslAttribute() for all versions for this one
>since any remaining support for this feature is on its way out.  Once psql
>no longer supports any versions that allow SSL compression, we could
>probably remove it from \conninfo[+] completely or hard-code it to "off".

>> SSL support has been available since version 7.1 (see documentation); if there was
>> support before that, I can't say. In this regard, it may seem strange, but there are still
>> many legacy systems running older versions of PostgreSQL. Just yesterday, I assisted
>> a client who is still using PG 8.2. In these cases, using the "pg_stat_ssl" and
>> "pg_stat_gssapi" views would not be possible because they don't exist on the server.
>> I believe that psql should cover as many cases as possible when it comes to compatibility
>> with older versions (even those no longer supported). In this case, concerning SSL and
>> GSS, I think libpq is better prepared to handle this.

>At the moment, the psql support cutoff appears to be v9.2 (see commit
>cf0cab8), which has been out of support for over 6 years.  If \conninfo+
>happens to work for older versions, then great, but I don't think we should
>expend too much energy in this area.

[0] https://postgr.es/m/20240216155449.GA1236054%40nathanxps13

----//----

Hi Nathan!

Sorry for the delay. I will make the adjustments as requested soon.

Regards,
Maiquel Grassi.


^ permalink  raw  reply  [nested|flat] 43+ messages in thread

* Re: Psql meta-command conninfo+
  2024-02-06 21:50 Re: Psql meta-command conninfo+ Nathan Bossart <[email protected]>
  2024-02-07 04:13 ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-07 12:35   ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-07 14:47     ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-07 16:40       ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-07 20:13         ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-08 11:01           ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-08 14:58             ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-09 07:58               ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-12 14:16                 ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-14 11:36                   ` Re: Psql meta-command conninfo+ Jim Jones <[email protected]>
  2024-02-15 19:47                     ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-15 22:16                       ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-16 11:18                         ` Re: Psql meta-command conninfo+ Jim Jones <[email protected]>
  2024-02-16 15:54                           ` Re: Psql meta-command conninfo+ Nathan Bossart <[email protected]>
  2024-02-17 14:53                             ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-24 20:44                               ` Re: Psql meta-command conninfo+ Nathan Bossart <[email protected]>
  2024-02-29 22:02                                 ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
@ 2024-02-29 22:41                                   ` Nathan Bossart <[email protected]>
  2024-03-18 22:05                                     ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  1 sibling, 1 reply; 43+ messages in thread

From: Nathan Bossart @ 2024-02-29 22:41 UTC (permalink / raw)
  To: Maiquel Grassi <[email protected]>; +Cc: Jim Jones <[email protected]>; Pavel Luzanov <[email protected]>; Erik Wienhold <[email protected]>; pgsql-hackers

On Thu, Feb 29, 2024 at 10:02:21PM +0000, Maiquel Grassi wrote:
> Sorry for the delay. I will make the adjustments as requested soon.

Looking forward to it.

-- 
Nathan Bossart
Amazon Web Services: https://aws.amazon.com






^ permalink  raw  reply  [nested|flat] 43+ messages in thread

* RE: Psql meta-command conninfo+
  2024-02-06 21:50 Re: Psql meta-command conninfo+ Nathan Bossart <[email protected]>
  2024-02-07 04:13 ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-07 12:35   ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-07 14:47     ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-07 16:40       ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-07 20:13         ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-08 11:01           ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-08 14:58             ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-09 07:58               ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-12 14:16                 ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-14 11:36                   ` Re: Psql meta-command conninfo+ Jim Jones <[email protected]>
  2024-02-15 19:47                     ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-15 22:16                       ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-16 11:18                         ` Re: Psql meta-command conninfo+ Jim Jones <[email protected]>
  2024-02-16 15:54                           ` Re: Psql meta-command conninfo+ Nathan Bossart <[email protected]>
  2024-02-17 14:53                             ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-24 20:44                               ` Re: Psql meta-command conninfo+ Nathan Bossart <[email protected]>
  2024-02-29 22:02                                 ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-29 22:41                                   ` Re: Psql meta-command conninfo+ Nathan Bossart <[email protected]>
@ 2024-03-18 22:05                                     ` Maiquel Grassi <[email protected]>
  2024-03-27 13:23                                       ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  0 siblings, 1 reply; 43+ messages in thread

From: Maiquel Grassi @ 2024-03-18 22:05 UTC (permalink / raw)
  To: Nathan Bossart <[email protected]>; +Cc: Jim Jones <[email protected]>; Pavel Luzanov <[email protected]>; Erik Wienhold <[email protected]>; pgsql-hackers

On Thu, Feb 29, 2024 at 10:02:21PM +0000, Maiquel Grassi wrote:
> Sorry for the delay. I will make the adjustments as requested soon.

Looking forward to it.

----//----

Hi Nathan!

Sorry for the delay, I was busy with other professional as well as personal activities.

I made all the changes you suggested. I removed the variables and started using
views "pg_stat_ssl" and "pg_stat_gssapi". I handled the PostgreSQL versioning regarding the views used.

Here's a brief demonstration of the result:

[postgres@localhost ~]$ /home/pgsql-17devel/bin/psql -E -x -p 5433

psql (17devel)
Type "help" for help.

postgres=# \conninfo+
/******** QUERY *********/
SELECT
  pg_catalog.current_database() AS "Database",
  'postgres' AS "Authenticated User",
  pg_catalog.system_user() AS "System User",
  pg_catalog.current_user() AS "Current User",
  pg_catalog.session_user() AS "Session User",
  pg_catalog.pg_backend_pid() AS "Backend PID",
  pg_catalog.inet_server_addr() AS "Server Address",
  pg_catalog.current_setting('port') AS "Server Port",
  pg_catalog.inet_client_addr() AS "Client Address",
  pg_catalog.inet_client_port() AS "Client Port",
  '/tmp' AS "Socket Directory",
  CASE
    WHEN
      pg_catalog.inet_server_addr() IS NULL
      AND pg_catalog.inet_client_addr() IS NULL
    THEN NULL
    ELSE '/tmp'
  END AS "Host",
  (SELECT gss_authenticated AS "GSSAPI"
  FROM pg_catalog.pg_stat_gssapi
  WHERE pid = pg_catalog.pg_backend_pid()),
  ssl.ssl AS "SSL Connection",
  ssl.version AS "SSL Protocol",
  ssl.cipher AS "SSL Cipher",
  NULL AS "SSL Compression"
FROM
  pg_catalog.pg_stat_ssl ssl
WHERE
  pid = pg_catalog.pg_backend_pid()
;
/************************/

Current Connection Information
-[ RECORD 1 ]------+---------
Database           | postgres
Authenticated User | postgres
System User        |
Current User       | postgres
Session User       | postgres
Backend PID        | 29007
Server Address     |
Server Port        | 5433
Client Address     |
Client Port        |
Socket Directory   | /tmp
Host               |
GSSAPI             | f
SSL Connection     | f
SSL Protocol       |
SSL Cipher         |
SSL Compression    |

Rergards,
Maiquel Grassi.


Attachments:

  [application/octet-stream] v20-0001-psql-meta-command-conninfo-plus.patch (13.6K, ../../CP8P284MB24961A4A0AFD1050391EBAF9EC2D2@CP8P284MB2496.BRAP284.PROD.OUTLOOK.COM/3-v20-0001-psql-meta-command-conninfo-plus.patch)
  download | inline diff:
diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml
index cc7d797..ebb1f4a 100644
--- a/doc/src/sgml/ref/psql-ref.sgml
+++ b/doc/src/sgml/ref/psql-ref.sgml
@@ -1029,11 +1029,106 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g
       </varlistentry>
 
       <varlistentry id="app-psql-meta-command-conninfo">
-        <term><literal>\conninfo</literal></term>
+        <term><literal>\conninfo[+]</literal></term>
         <listitem>
         <para>
         Outputs information about the current database connection.
+        When no <literal>+</literal> is appended, it simply prints
+        a textual (string) description of a few connection options.
+        When <literal>+</literal> is given, more complete information
+        is displayed as a table containing the following columns:
         </para>
+
+        <para>
+        <literal>Database:</literal> Displays the name of the current
+        database on this connection.
+        </para>
+
+        <para>
+        <literal>Authenticated User:</literal> Displays the authenticated
+        user at the time of psql connection with the server.
+        </para>
+
+        <para>
+        <literal>System User:</literal> Returns the authentication method
+        and the identity (if any) that the user presented during the
+        authentication cycle before they were assigned a database role. It
+        is represented as auth_method:identity or NULL if the user has not
+        been authenticated.
+        </para>
+
+        <para>
+        <literal>Current User:</literal> Displays the user name of the
+        current execution context.
+        </para>
+
+        <para>
+        <literal>Session User:</literal> Displays the session user's name.
+        </para>
+
+        <para>
+        <literal>Backend PID:</literal> Displays the process ID of the server
+        process attached to the current session.
+        </para>
+
+        <para>
+        <literal>Server Address:</literal> Displays the IP address on which
+        the server accepted the current connection, or NULL if the current
+        connection is via a Unix-domain socket.
+        </para>
+
+        <para>
+        <literal>Server Port:</literal> Displays the IP port number on which
+        the server accepted the current connection, or NULL if the current
+        connection is via a Unix-domain socket.
+        </para>
+
+        <para>
+        <literal>Client Address:</literal> Displays the IP address of the
+        current client, or NULL if the current connection is via a Unix-domain socket.
+        </para>
+
+        <para>
+        <literal>Client Port:</literal> Displays the IP port number of the
+        current client, or NULL if the current connection is via a Unix-domain socket.
+        </para>
+
+        <para>
+        <literal>Socket Directory:</literal> Displays the directory where
+        Unix-domain socket was created.
+        </para>
+
+        <para>
+        <literal>Host:</literal> Displays the host of the connection,
+        which refers to the address or name of the machine where the server
+        is running. When a socket connection is established, it displays NULL.
+        </para>
+
+        <para>
+        <literal>GSSAPI:</literal> Displays "true" if GSSAPI is in use, or "false"
+        if GSSAPI is not in use on this connection.
+        </para>
+
+        <para>
+        <literal>SSL Connection:</literal> Displays "true" if the current
+        connection to the server uses SSL, and "false" otherwise.
+        </para>
+
+        <para>
+        <literal>SSL Protocol:</literal> Displays the name of the protocol
+        used for the SSL connection (e.g., TLSv1.0, TLSv1.1, TLSv1.2 or TLSv1.3).
+        </para>
+
+        <para>
+        <literal>SSL Cipher:</literal> Displays the name of the cipher used
+        for the SSL connection (e.g., DHE-RSA-AES256-SHA).
+        </para>
+
+        <para>
+        <literal>SLL Compression:</literal> Displays "on" if SSL compression
+        is in use, "off" if not, or NULL if SSL is not in use on this connection.
+        </para>
+
         </listitem>
       </varlistentry>
 
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index 9b0fa04..fb5f63d 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -68,7 +68,8 @@ static backslashResult exec_command_C(PsqlScanState scan_state, bool active_bran
 static backslashResult exec_command_connect(PsqlScanState scan_state, bool active_branch);
 static backslashResult exec_command_cd(PsqlScanState scan_state, bool active_branch,
 									   const char *cmd);
-static backslashResult exec_command_conninfo(PsqlScanState scan_state, bool active_branch);
+static backslashResult exec_command_conninfo(PsqlScanState scan_state, bool active_branch,
+											 const char *cmd);
 static backslashResult exec_command_copy(PsqlScanState scan_state, bool active_branch);
 static backslashResult exec_command_copyright(PsqlScanState scan_state, bool active_branch);
 static backslashResult exec_command_crosstabview(PsqlScanState scan_state, bool active_branch);
@@ -317,8 +318,8 @@ exec_command(const char *cmd,
 		status = exec_command_connect(scan_state, active_branch);
 	else if (strcmp(cmd, "cd") == 0)
 		status = exec_command_cd(scan_state, active_branch, cmd);
-	else if (strcmp(cmd, "conninfo") == 0)
-		status = exec_command_conninfo(scan_state, active_branch);
+	else if (strcmp(cmd, "conninfo") == 0 || strcmp(cmd, "conninfo+") == 0)
+		status = exec_command_conninfo(scan_state, active_branch, cmd);
 	else if (pg_strcasecmp(cmd, "copy") == 0)
 		status = exec_command_copy(scan_state, active_branch);
 	else if (strcmp(cmd, "copyright") == 0)
@@ -643,47 +644,80 @@ exec_command_cd(PsqlScanState scan_state, bool active_branch, const char *cmd)
 }
 
 /*
- * \conninfo -- display information about the current connection
+ * \conninfo, \conninfo+ -- display information about the current connection
  */
 static backslashResult
-exec_command_conninfo(PsqlScanState scan_state, bool active_branch)
+exec_command_conninfo(PsqlScanState scan_state, bool active_branch, const char *cmd)
 {
+	bool		success = true;
+
 	if (active_branch)
 	{
 		char	   *db = PQdb(pset.db);
+		bool		show_verbose;
+
+		show_verbose = strchr(cmd, '+') ? true : false;
 
-		if (db == NULL)
-			printf(_("You are currently not connected to a database.\n"));
+		/*
+		 * \conninfo+
+		 */
+		if (show_verbose)
+			success = listConnectionInformation();
+
+		/*
+		 * \conninfo
+		 */
 		else
 		{
-			char	   *host = PQhost(pset.db);
-			char	   *hostaddr = PQhostaddr(pset.db);
+			PGresult   *res;
+			PQExpBufferData buf;
 
-			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));
-			}
+			initPQExpBuffer(&buf);
+
+			printfPQExpBuffer(&buf,
+							  "SELECT\n"
+							  "  inet_server_addr();");
+
+			res = PSQLexec(buf.data);
+
+			termPQExpBuffer(&buf);
+
+			if (!res)
+				return PSQL_CMD_ERROR;
 			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));
+				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), PQgetvalue(res, 0, 0), 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
-					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));
+				{
+					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, PQgetvalue(res, 0, 0), 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));
+				}
+				PQclear(res);
+				printSSLInfo();
+				printGSSInfo();
 			}
-			printSSLInfo();
-			printGSSInfo();
 		}
 	}
+	else
+		ignore_slash_options(scan_state);
 
-	return PSQL_CMD_SKIP_LINE;
+	return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
 }
 
 /*
diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index 6433497..3b0d913 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -26,6 +26,7 @@
 #include "fe_utils/mbprint.h"
 #include "fe_utils/print.h"
 #include "fe_utils/string_utils.h"
+#include "libpq/pqcomm.h"
 #include "settings.h"
 #include "variables.h"
 
@@ -901,6 +902,111 @@ error_return:
 	return false;
 }
 
+/*
+ * listConnectionInformation
+ *
+ * for \conninfo+
+ */
+bool
+listConnectionInformation(void)
+{
+	PGresult   *res;
+	PQExpBufferData buf;
+	printQueryOpt myopt = pset.popt;
+
+	char	   *host = PQhost(pset.db);
+	char	   *hostaddr = PQhostaddr(pset.db);
+
+	initPQExpBuffer(&buf);
+
+	printfPQExpBuffer(&buf,
+					  "SELECT\n"
+					  "  pg_catalog.current_database() AS \"Database\",\n"
+					  "  '%s' AS \"Authenticated User\",\n",
+					  PQuser(pset.db));
+	if (pset.sversion >= 160000)
+		appendPQExpBuffer(&buf,
+						  "  pg_catalog.system_user() AS \"System User\",\n");
+	else
+		appendPQExpBuffer(&buf,
+						  "  NULL AS \"System User\",\n");
+	appendPQExpBuffer(&buf,
+					  "  pg_catalog.current_user() AS \"Current User\",\n"
+					  "  pg_catalog.session_user() AS \"Session User\",\n"
+					  "  pg_catalog.pg_backend_pid() AS \"Backend PID\",\n"
+					  "  pg_catalog.inet_server_addr() AS \"Server Address\",\n"
+					  "  pg_catalog.current_setting('port') AS \"Server Port\",\n"
+					  "  pg_catalog.inet_client_addr() AS \"Client Address\",\n"
+					  "  pg_catalog.inet_client_port() AS \"Client Port\",\n");
+	if (is_unixsock_path(host) && !(hostaddr && *hostaddr))
+		appendPQExpBuffer(&buf,
+						  "  '%s' AS \"Socket Directory\",\n",
+						  host);
+	else
+		appendPQExpBuffer(&buf,
+						  "  NULL AS \"Socket Directory\",\n");
+	appendPQExpBuffer(&buf,
+					  "  CASE\n"
+					  "    WHEN\n"
+					  "      pg_catalog.inet_server_addr() IS NULL\n"
+					  "      AND pg_catalog.inet_client_addr() IS NULL\n"
+					  "    THEN NULL\n"
+					  "    ELSE '%s'\n"
+					  "  END AS \"Host\",\n",
+					  host);
+	if (pset.sversion >= 120000)
+		appendPQExpBuffer(&buf,
+						  "  (SELECT gss_authenticated AS \"GSSAPI\"\n"
+						  "  FROM pg_catalog.pg_stat_gssapi\n"
+						  "  WHERE pid = pg_catalog.pg_backend_pid()),\n");
+	else
+		appendPQExpBuffer(&buf,
+						  "  NULL AS \"GSSAPI\",\n");
+	if (pset.sversion >= 90500)
+	{
+		if (pset.sversion < 140000)
+			appendPQExpBuffer(&buf,
+							  "  ssl.ssl AS \"SSL Connection\",\n"
+							  "  ssl.version AS \"SSL Protocol\",\n"
+							  "  ssl.cipher AS \"SSL Cipher\",\n"
+							  "  ssl.compression AS \"SSL Compression\"\n"
+							  "FROM\n"
+							  "  pg_catalog.pg_stat_ssl ssl\n"
+							  "WHERE\n"
+							  "  pid = pg_catalog.pg_backend_pid()\n");
+		if (pset.sversion >= 140000)
+			appendPQExpBuffer(&buf,
+							  "  ssl.ssl AS \"SSL Connection\",\n"
+							  "  ssl.version AS \"SSL Protocol\",\n"
+							  "  ssl.cipher AS \"SSL Cipher\",\n"
+							  "  NULL AS \"SSL Compression\"\n"
+							  "FROM\n"
+							  "  pg_catalog.pg_stat_ssl ssl\n"
+							  "WHERE\n"
+							  "  pid = pg_catalog.pg_backend_pid()\n");
+	}
+	else
+		appendPQExpBuffer(&buf,
+						  "  NULL AS \"SSL Connection\",\n"
+						  "  NULL AS \"SSL Protocol\",\n"
+						  "  NULL AS \"SSL Cipher\",\n"
+						  "  NULL AS \"SSL Compression\"\n");
+	appendPQExpBuffer(&buf,
+					  ";");
+
+	res = PSQLexec(buf.data);
+	termPQExpBuffer(&buf);
+	if (!res)
+		return false;
+
+	myopt.title = _("Current Connection Information");
+	myopt.translate_header = true;
+
+	printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
+
+	PQclear(res);
+	return true;
+}
 
 /*
  * listAllDbs
diff --git a/src/bin/psql/describe.h b/src/bin/psql/describe.h
index 273f974..8a4e83f 100644
--- a/src/bin/psql/describe.h
+++ b/src/bin/psql/describe.h
@@ -64,6 +64,9 @@ extern bool listTSDictionaries(const char *pattern, bool verbose);
 /* \dFt */
 extern bool listTSTemplates(const char *pattern, bool verbose);
 
+/* \conninfo */
+extern bool listConnectionInformation(void);
+
 /* \l */
 extern bool listAllDbs(const char *pattern, bool verbose);
 
diff --git a/src/bin/psql/help.c b/src/bin/psql/help.c
index 4e79a81..2c5426d 100644
--- a/src/bin/psql/help.c
+++ b/src/bin/psql/help.c
@@ -310,7 +310,7 @@ slashUsage(unsigned short int pager)
 	else
 		HELP0("  \\c[onnect] {[DBNAME|- USER|- HOST|- PORT|-] | conninfo}\n"
 			  "                         connect to new database (currently no connection)\n");
-	HELP0("  \\conninfo              display information about current connection\n");
+	HELP0("  \\conninfo[+]           display information about current connection\n");
 	HELP0("  \\encoding [ENCODING]   show or set client encoding\n");
 	HELP0("  \\password [USERNAME]   securely change the password for a user\n");
 	HELP0("\n");


^ permalink  raw  reply  [nested|flat] 43+ messages in thread

* RE: Psql meta-command conninfo+
  2024-02-06 21:50 Re: Psql meta-command conninfo+ Nathan Bossart <[email protected]>
  2024-02-07 04:13 ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-07 12:35   ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-07 14:47     ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-07 16:40       ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-07 20:13         ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-08 11:01           ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-08 14:58             ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-09 07:58               ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-12 14:16                 ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-14 11:36                   ` Re: Psql meta-command conninfo+ Jim Jones <[email protected]>
  2024-02-15 19:47                     ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-15 22:16                       ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-16 11:18                         ` Re: Psql meta-command conninfo+ Jim Jones <[email protected]>
  2024-02-16 15:54                           ` Re: Psql meta-command conninfo+ Nathan Bossart <[email protected]>
  2024-02-17 14:53                             ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-24 20:44                               ` Re: Psql meta-command conninfo+ Nathan Bossart <[email protected]>
  2024-02-29 22:02                                 ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-29 22:41                                   ` Re: Psql meta-command conninfo+ Nathan Bossart <[email protected]>
  2024-03-18 22:05                                     ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
@ 2024-03-27 13:23                                       ` Maiquel Grassi <[email protected]>
  0 siblings, 0 replies; 43+ messages in thread

From: Maiquel Grassi @ 2024-03-27 13:23 UTC (permalink / raw)
  To: Nathan Bossart <[email protected]>; +Cc: Jim Jones <[email protected]>; Pavel Luzanov <[email protected]>; Erik Wienhold <[email protected]>; pgsql-hackers

> Hi Nathan!

>
> Sorry for the delay, I was busy with other professional as well as personal activities.

> I made all the changes you suggested. I removed the variables and started using
> views "pg_stat_ssl" and "pg_stat_gssapi". I handled the PostgreSQL versioning regarding the views used.

--//--

Olá Nathan!

I think we are very close to possibly finishing this patch, and
I would like your help to do it. Is there any correction you
deem necessary still?

Regards,
Maiquel Grassi.


^ permalink  raw  reply  [nested|flat] 43+ messages in thread

* Re: Psql meta-command conninfo+
  2024-02-06 21:50 Re: Psql meta-command conninfo+ Nathan Bossart <[email protected]>
  2024-02-07 04:13 ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-07 12:35   ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-07 14:47     ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-07 16:40       ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-07 20:13         ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-08 11:01           ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-08 14:58             ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-09 07:58               ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-12 14:16                 ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-14 11:36                   ` Re: Psql meta-command conninfo+ Jim Jones <[email protected]>
  2024-02-15 19:47                     ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-15 22:16                       ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-16 11:18                         ` Re: Psql meta-command conninfo+ Jim Jones <[email protected]>
  2024-02-16 15:54                           ` Re: Psql meta-command conninfo+ Nathan Bossart <[email protected]>
  2024-02-17 14:53                             ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-24 20:44                               ` Re: Psql meta-command conninfo+ Nathan Bossart <[email protected]>
  2024-02-29 22:02                                 ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
@ 2024-03-14 16:46                                   ` Nathan Bossart <[email protected]>
  1 sibling, 0 replies; 43+ messages in thread

From: Nathan Bossart @ 2024-03-14 16:46 UTC (permalink / raw)
  To: Maiquel Grassi <[email protected]>; +Cc: Jim Jones <[email protected]>; Pavel Luzanov <[email protected]>; Erik Wienhold <[email protected]>; pgsql-hackers

Hi Maiquel,

On Thu, Feb 29, 2024 at 10:02:21PM +0000, Maiquel Grassi wrote:
> Sorry for the delay. I will make the adjustments as requested soon.

We have only a few weeks left before feature-freeze for v17.  Do you think
you will be able to send an updated patch soon?

-- 
Nathan Bossart
Amazon Web Services: https://aws.amazon.com






^ permalink  raw  reply  [nested|flat] 43+ messages in thread

* RE: Psql meta-command conninfo+
  2024-02-06 21:50 Re: Psql meta-command conninfo+ Nathan Bossart <[email protected]>
  2024-02-07 04:13 ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-07 12:35   ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-07 14:47     ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-07 16:40       ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-07 20:13         ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-08 11:01           ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-08 14:58             ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-09 07:58               ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-12 14:16                 ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-14 11:36                   ` Re: Psql meta-command conninfo+ Jim Jones <[email protected]>
  2024-02-15 19:47                     ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-15 22:16                       ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-16 11:18                         ` Re: Psql meta-command conninfo+ Jim Jones <[email protected]>
@ 2024-02-16 21:48                           ` Maiquel Grassi <[email protected]>
  1 sibling, 0 replies; 43+ messages in thread

From: Maiquel Grassi @ 2024-02-16 21:48 UTC (permalink / raw)
  To: Jim Jones <[email protected]>; Pavel Luzanov <[email protected]>; Nathan Bossart <[email protected]>; +Cc: Erik Wienhold <[email protected]>; pgsql-hackers

Hi!

>7) -h 0.0.0.0 - As you mentioned, this is one of the cases where host
>and "server address" differ.
>   I am not sure if it is an issue. Perhaps the other reviewers might
>have an opinion on it

>$ /usr/local/postgres-dev/bin/psql -x -U postgres -h 0.0.0.0 -c
>"\conninfo+" -c "\conninfo"
>Current Connection Information
>-[ RECORD 1 ]------+-----------------------
>Database           | postgres
>Authenticated User | postgres
>System User        |
>Current User       | postgres
>Session User       | postgres
>Backend PID        | 404395
>Server Address     | 127.0.0.1
>Server Port        | 5432
>Client Address     | 127.0.0.1
>Client Port        | 54806
>Socket Directory   |
>Host               | 0.0.0.0
>Encryption         | SSL
>Protocol           | TLSv1.3
>Cipher             | TLS_AES_256_GCM_SHA384
>Compression        | off

I believe we don't actually have a problem here. To me, this makes sense.
I'm not a Networking expert, but from my standpoint, any string or IP
accepted by the "host" parameter of psql, pointing to "127.0.0.1" or to "::1", is correct.
I see it as a convention (would need to revisit Tanenbaum's books haha),
and I don't think there's a need to modify it. But as you mentioned, if someone
with more Networking knowledge could weigh in, a suggestion would be welcome.

>I'm not sure of the impact of this change in the existing \conninfo - at
>least the cfbot and "make -j check-world" didn't complain.
>I'll take a closer look at it as soon we have test cases.

This type of modification, in principle, does not generate errors as we
are only changing the display on screen of the strings already previously stored.

>To keep it consistent with the other options, we might wanna use "+ is
>appended" instead of "+ is specified" or "+ is given"

It seems to me that "appended" sounds good. I opted for it.
Following your suggestion, and merging this with the existing
previous ideas from the documentation, I've created a provisional
prototype of the column descriptions. At a later stage, I'll place the
descriptions correctly by removing placeholders (blah blah blah).
Along with this, I'll evaluate an iteration suggested by Nathan Bossart,

who also proposed changes.

Thank you for your work.

Regards,
Maiquel Grassi.


Attachments:

  [application/octet-stream] v17-0001-psql-meta-command-conninfo-plus.patch (11.4K, ../../CP8P284MB2496093A2E465801D5B8134BEC4C2@CP8P284MB2496.BRAP284.PROD.OUTLOOK.COM/3-v17-0001-psql-meta-command-conninfo-plus.patch)
  download | inline diff:
diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml
index cc7d797..10732b2 100644
--- a/doc/src/sgml/ref/psql-ref.sgml
+++ b/doc/src/sgml/ref/psql-ref.sgml
@@ -1029,11 +1029,96 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g
       </varlistentry>
 
       <varlistentry id="app-psql-meta-command-conninfo">
-        <term><literal>\conninfo</literal></term>
+        <term><literal>\conninfo[+]</literal></term>
         <listitem>
         <para>
         Outputs information about the current database connection.
+        When no <literal>+</literal> is appended, it simply prints
+        a textual (string) description of a few connection options.
+        When <literal>+</literal> is given, more complete information
+        is displayed as a table containing the following columns.
         </para>
+
+        <para>
+        General columns:
+        </para>
+
+        <para>
+        <literal>Database:</literal> blah blah blah
+        </para>
+
+        <para>
+        <literal>Authenticated User:</literal> blah blah blah
+        </para>
+
+        <para>
+        <literal>System User:</literal> blah blah blah
+        </para>
+
+        <para>
+        <literal>Current User:</literal> blah blah blah
+        </para>
+
+        <para>
+        <literal>Session User:</literal> blah blah blah
+        </para>
+
+        <para>
+        <literal>Backend PID:</literal> blah blah blah
+        </para>
+
+        <para>
+        <literal>Server Address:</literal> blah blah blah
+        </para>
+
+        <para>
+        <literal>Server Port:</literal> blah blah blah
+        </para>
+
+        <para>
+        <literal>Client Address:</literal> blah blah blah
+        </para>
+
+        <para>
+        <literal>Client Port:</literal> blah blah blah
+        </para>
+
+        <para>
+        <literal>Socket Directory:</literal> blah blah blah
+        </para>
+
+        <para>
+        <literal>Host:</literal> blah blah blah
+        </para>
+
+        <para>
+        TLS (SSL) authentication columns:
+        </para>
+
+        <para>
+        <literal>Encryption:</literal> blah blah blah
+        </para>
+
+        <para>
+        <literal>Protocol:</literal> blah blah blah
+        </para>
+
+        <para>
+        <literal>Cipher:</literal> blah blah blah
+        </para>
+
+        <para>
+        <literal>Compression:</literal> blah blah blah
+        </para>
+
+        <para>
+        GSS authentication column:
+        </para>
+
+        <para>
+        <literal>GSSAPI:</literal> blah blah blah
+        </para>
+
         </listitem>
       </varlistentry>
 
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index 5c906e4..cb5429f 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -68,7 +68,8 @@ static backslashResult exec_command_C(PsqlScanState scan_state, bool active_bran
 static backslashResult exec_command_connect(PsqlScanState scan_state, bool active_branch);
 static backslashResult exec_command_cd(PsqlScanState scan_state, bool active_branch,
 									   const char *cmd);
-static backslashResult exec_command_conninfo(PsqlScanState scan_state, bool active_branch);
+static backslashResult exec_command_conninfo(PsqlScanState scan_state, bool active_branch,
+											 const char *cmd);
 static backslashResult exec_command_copy(PsqlScanState scan_state, bool active_branch);
 static backslashResult exec_command_copyright(PsqlScanState scan_state, bool active_branch);
 static backslashResult exec_command_crosstabview(PsqlScanState scan_state, bool active_branch);
@@ -317,8 +318,8 @@ exec_command(const char *cmd,
 		status = exec_command_connect(scan_state, active_branch);
 	else if (strcmp(cmd, "cd") == 0)
 		status = exec_command_cd(scan_state, active_branch, cmd);
-	else if (strcmp(cmd, "conninfo") == 0)
-		status = exec_command_conninfo(scan_state, active_branch);
+	else if (strcmp(cmd, "conninfo") == 0 || strcmp(cmd, "conninfo+") == 0)
+		status = exec_command_conninfo(scan_state, active_branch, cmd);
 	else if (pg_strcasecmp(cmd, "copy") == 0)
 		status = exec_command_copy(scan_state, active_branch);
 	else if (strcmp(cmd, "copyright") == 0)
@@ -643,47 +644,80 @@ exec_command_cd(PsqlScanState scan_state, bool active_branch, const char *cmd)
 }
 
 /*
- * \conninfo -- display information about the current connection
+ * \conninfo, \conninfo+ -- display information about the current connection
  */
 static backslashResult
-exec_command_conninfo(PsqlScanState scan_state, bool active_branch)
+exec_command_conninfo(PsqlScanState scan_state, bool active_branch, const char *cmd)
 {
+	bool		success = true;
+
 	if (active_branch)
 	{
 		char	   *db = PQdb(pset.db);
+		bool		show_verbose;
+
+		show_verbose = strchr(cmd, '+') ? true : false;
 
-		if (db == NULL)
-			printf(_("You are currently not connected to a database.\n"));
+		/*
+		 * \conninfo+
+		 */
+		if (show_verbose)
+			success = listConnectionInformation();
+
+		/*
+		 * \conninfo
+		 */
 		else
 		{
-			char	   *host = PQhost(pset.db);
-			char	   *hostaddr = PQhostaddr(pset.db);
+			PGresult   *res;
+			PQExpBufferData buf;
 
-			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));
-			}
+			initPQExpBuffer(&buf);
+
+			printfPQExpBuffer(&buf,
+							  "SELECT\n"
+							  "  inet_server_addr();");
+
+			res = PSQLexec(buf.data);
+
+			termPQExpBuffer(&buf);
+
+			if (!res)
+				return PSQL_CMD_ERROR;
 			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));
+				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), PQgetvalue(res, 0, 0), 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
-					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));
+				{
+					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, PQgetvalue(res, 0, 0), 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));
+				}
+				PQclear(res);
+				printSSLInfo();
+				printGSSInfo();
 			}
-			printSSLInfo();
-			printGSSInfo();
 		}
 	}
+	else
+		ignore_slash_options(scan_state);
 
-	return PSQL_CMD_SKIP_LINE;
+	return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
 }
 
 /*
diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index b6a4eb1..2ef3db0 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -26,6 +26,7 @@
 #include "fe_utils/mbprint.h"
 #include "fe_utils/print.h"
 #include "fe_utils/string_utils.h"
+#include "libpq/pqcomm.h"
 #include "settings.h"
 #include "variables.h"
 
@@ -901,6 +902,91 @@ error_return:
 	return false;
 }
 
+/*
+ * listConnectionInformation
+ *
+ * for \conninfo+
+ */
+bool
+listConnectionInformation(void)
+{
+	PGresult   *res;
+	PQExpBufferData buf;
+	printQueryOpt myopt = pset.popt;
+
+	char	   *host = PQhost(pset.db);
+	char	   *hostaddr = PQhostaddr(pset.db);
+	const char *protocol;
+	const char *cipher;
+	const char *compression;
+
+	initPQExpBuffer(&buf);
+
+	printfPQExpBuffer(&buf,
+					  "SELECT\n"
+					  "  pg_catalog.current_database() AS \"Database\",\n"
+					  "  '%s' AS \"Authenticated User\",\n",
+					  PQuser(pset.db));
+	if (pset.sversion >= 160000)
+		appendPQExpBuffer(&buf,
+						  "  pg_catalog.system_user() AS \"System User\",\n");
+	appendPQExpBuffer(&buf,
+					  "  pg_catalog.current_user() AS \"Current User\",\n"
+					  "  pg_catalog.session_user() AS \"Session User\",\n"
+					  "  pg_catalog.pg_backend_pid() AS \"Backend PID\",\n"
+					  "  pg_catalog.inet_server_addr() AS \"Server Address\",\n"
+					  "  pg_catalog.current_setting('port') AS \"Server Port\",\n"
+					  "  pg_catalog.inet_client_addr() AS \"Client Address\",\n"
+					  "  pg_catalog.inet_client_port() AS \"Client Port\",\n");
+	if (is_unixsock_path(host) && !(hostaddr && *hostaddr))
+		appendPQExpBuffer(&buf,
+						  "  '%s' AS \"Socket Directory\",\n",
+						  host);
+	else
+		appendPQExpBuffer(&buf,
+						  "  NULL AS \"Socket Directory\",\n");
+	appendPQExpBuffer(&buf,
+					  "  CASE\n"
+					  "    WHEN\n"
+					  "      pg_catalog.inet_server_addr() IS NULL\n"
+					  "      AND pg_catalog.inet_client_addr() IS NULL\n"
+					  "    THEN NULL\n"
+					  "    ELSE '%s'\n"
+					  "  END AS \"Host\"\n",
+					  host);
+	if (PQsslInUse(pset.db))
+	{
+		protocol = PQsslAttribute(pset.db, "protocol");
+		cipher = PQsslAttribute(pset.db, "cipher");
+		compression = PQsslAttribute(pset.db, "compression");
+		appendPQExpBuffer(&buf,
+						  "  ,'SSL' AS \"Encryption\",\n"
+						  "  '%s' AS \"Protocol\",\n"
+						  "  '%s' AS \"Cipher\",\n"
+						  "  '%s' AS \"Compression\"\n",
+						  protocol ? protocol : _("unknown"),
+						  cipher ? cipher : _("unknown"),
+						  (compression && strcmp(compression, "off") != 0) ? _("on") : _("off"));
+	}
+	if (PQgssEncInUse(pset.db))
+		appendPQExpBuffer(&buf,
+						  "  ,'GSSAPI' AS \"Encryption\"\n");
+	appendPQExpBuffer(&buf,
+					  "  ;");
+
+	res = PSQLexec(buf.data);
+	termPQExpBuffer(&buf);
+	if (!res)
+		return false;
+
+	myopt.title = _("Current Connection Information");
+	myopt.translate_header = true;
+
+	printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
+
+	PQclear(res);
+	return true;
+}
 
 /*
  * listAllDbs
diff --git a/src/bin/psql/describe.h b/src/bin/psql/describe.h
index 273f974..8a4e83f 100644
--- a/src/bin/psql/describe.h
+++ b/src/bin/psql/describe.h
@@ -64,6 +64,9 @@ extern bool listTSDictionaries(const char *pattern, bool verbose);
 /* \dFt */
 extern bool listTSTemplates(const char *pattern, bool verbose);
 
+/* \conninfo */
+extern bool listConnectionInformation(void);
+
 /* \l */
 extern bool listAllDbs(const char *pattern, bool verbose);
 
diff --git a/src/bin/psql/help.c b/src/bin/psql/help.c
index 4e79a81..2c5426d 100644
--- a/src/bin/psql/help.c
+++ b/src/bin/psql/help.c
@@ -310,7 +310,7 @@ slashUsage(unsigned short int pager)
 	else
 		HELP0("  \\c[onnect] {[DBNAME|- USER|- HOST|- PORT|-] | conninfo}\n"
 			  "                         connect to new database (currently no connection)\n");
-	HELP0("  \\conninfo              display information about current connection\n");
+	HELP0("  \\conninfo[+]           display information about current connection\n");
 	HELP0("  \\encoding [ENCODING]   show or set client encoding\n");
 	HELP0("  \\password [USERNAME]   securely change the password for a user\n");
 	HELP0("\n");


^ permalink  raw  reply  [nested|flat] 43+ messages in thread

* Re: Psql meta-command conninfo+
  2024-02-06 21:50 Re: Psql meta-command conninfo+ Nathan Bossart <[email protected]>
  2024-02-07 04:13 ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-07 12:35   ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-07 14:47     ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-07 16:40       ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-07 20:13         ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
@ 2024-02-08 11:01           ` Jim Jones <[email protected]>
  2024-02-08 15:50             ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  1 sibling, 1 reply; 43+ messages in thread

From: Jim Jones @ 2024-02-08 11:01 UTC (permalink / raw)
  To: Maiquel Grassi <[email protected]>; Pavel Luzanov <[email protected]>; Nathan Bossart <[email protected]>; +Cc: Erik Wienhold <[email protected]>; pgsql-hackers

Hi Maiquel

On 07.02.24 21:13, Maiquel Grassi wrote:
>
> I believe in v7 patch we have a quite substantial meta-command feature.
>
>
Thanks for implementing this. I find it very handy.

I was just wondering if a "permission denied" error for non-superusers
is the best choice for "\conninfo+":

postgres=> \conninfo+
ERROR:  permission denied to examine "unix_socket_directories"
DETAIL:  Only roles with privileges of the "pg_read_all_settings" role
may examine this parameter.

.. since it is not the case with "\conninfo":

postgres=> \conninfo
You are connected to database "postgres" as user "jim" via socket in
"/tmp" at port "5432".

Perhaps excluding the column from the result set or returning NULL in
the affected columns would be less confusing?

There are also some indentation issues in your patch:

/home/jim/Downloads/v7-0001-psql-meta-command-conninfo-plus.patch:142:
indent with spaces.
    PGresult   *res;
/home/jim/Downloads/v7-0001-psql-meta-command-conninfo-plus.patch:143:
indent with spaces.
    PQExpBufferData buf;
/home/jim/Downloads/v7-0001-psql-meta-command-conninfo-plus.patch:144:
indent with spaces.
    printQueryOpt myopt = pset.popt;
/home/jim/Downloads/v7-0001-psql-meta-command-conninfo-plus.patch:146:
indent with spaces.
    initPQExpBuffer(&buf);
/home/jim/Downloads/v7-0001-psql-meta-command-conninfo-plus.patch:148:
indent with spaces.
    printfPQExpBuffer(&buf,
warning: squelched 34 whitespace errors
warning: 39 lines add whitespace errors.

Looking forward to see the documentation and tests!

-- 
Jim







^ permalink  raw  reply  [nested|flat] 43+ messages in thread

* RE: Psql meta-command conninfo+
  2024-02-06 21:50 Re: Psql meta-command conninfo+ Nathan Bossart <[email protected]>
  2024-02-07 04:13 ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-07 12:35   ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-07 14:47     ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-07 16:40       ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-07 20:13         ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-08 11:01           ` Re: Psql meta-command conninfo+ Jim Jones <[email protected]>
@ 2024-02-08 15:50             ` Maiquel Grassi <[email protected]>
  2024-02-08 19:37               ` Re: Psql meta-command conninfo+ Jim Jones <[email protected]>
  0 siblings, 1 reply; 43+ messages in thread

From: Maiquel Grassi @ 2024-02-08 15:50 UTC (permalink / raw)
  To: Jim Jones <[email protected]>; Pavel Luzanov <[email protected]>; Nathan Bossart <[email protected]>; +Cc: Erik Wienhold <[email protected]>; pgsql-hackers

> On 07.02.24 21:13, Maiquel Grassi wrote:
>>
>> I believe in v7 patch we have a quite substantial meta-command feature.
>>
>>
> Thanks for implementing this. I find it very handy.
>
> I was just wondering if a "permission denied" error for non-superusers
> is the best choice for "\conninfo+":
>
> postgres=> \conninfo+
> ERROR:  permission denied to examine "unix_socket_directories"
> DETAIL:  Only roles with privileges of the "pg_read_all_settings" role
> may examine this parameter.
>
> .. since it is not the case with "\conninfo":
>
> postgres=> \conninfo
> You are connected to database "postgres" as user "jim" via socket in
> "/tmp" at port "5432".
>
> Perhaps excluding the column from the result set or returning NULL in
> the affected columns would be less confusing?
>
> There are also some indentation issues in your patch:
>
> /home/jim/Downloads/v7-0001-psql-meta-command-conninfo-plus.patch:142:
> indent with spaces.
>     PGresult   *res;
> /home/jim/Downloads/v7-0001-psql-meta-command-conninfo-plus.patch:143:
> indent with spaces.
>     PQExpBufferData buf;
> /home/jim/Downloads/v7-0001-psql-meta-command-conninfo-plus.patch:144:
> indent with spaces.
>     printQueryOpt myopt = pset.popt;
> /home/jim/Downloads/v7-0001-psql-meta-command-conninfo-plus.patch:146:
> indent with spaces.
>     initPQExpBuffer(&buf);
> /home/jim/Downloads/v7-0001-psql-meta-command-conninfo-plus.patch:148:
> indent with spaces.
>     printfPQExpBuffer(&buf,
> warning: squelched 34 whitespace errors
> warning: 39 lines add whitespace errors.
>
> Looking forward to see the documentation and tests!

--//--

Hi Jim,
Thank you for your support on this patch!
As I believe in its usability, I have been dedicating efforts to make it really interesting.
I hadn't thought about the permissioning issue for "unix_socket_directories". I appreciate that.
I thought about solving this situation using the same approach as \conninfo. I added the validation if (is_unixsock_path(host) && !(hostaddr && *hostaddr)) in the SQL part along with an "append". In case of a negative result, another "append" adds NULL.
Regarding the whitespace issue, before generating v8 patch file, I used pgindent to adjust each modified file. I believe it should be ok now. If you could verify, I'd be grateful.
Below are the tests after adjusting for the permissioning issues:

[postgres@localhost bin]$ ./psql
psql (17devel)
Type "help" for help.

postgres=# \conninfo
You are connected to database "postgres" as user "postgres" via socket in "/tmp" at port "5432".
postgres=# \conninfo+
                                                                                  Current Connection Information
 Database | Authenticated User | System User | Current User | Session User | Session PID | Server Version | Server Address | Server Port | Client Address | Client Port | Socket Directory | Host
----------+--------------------+-------------+--------------+--------------+-------------+----------------+----------------+-------------+----------------+-------------+------------------+------
 postgres | postgres           |             | postgres     | postgres     |       31479 | 17devel        |                | 5432        |                |             | /tmp             |
(1 row)

postgres=# CREATE USER maiquel;
CREATE ROLE
postgres=# \q
[postgres@localhost bin]$ ./psql -U maiquel -d postgres
psql (17devel)
Type "help" for help.

postgres=> \conninfo
You are connected to database "postgres" as user "maiquel" via socket in "/tmp" at port "5432".
postgres=> \conninfo+
                                                                                  Current Connection Information
 Database | Authenticated User | System User | Current User | Session User | Session PID | Server Version | Server Address | Server Port | Client Address | Client Port | Socket Directory | Host
----------+--------------------+-------------+--------------+--------------+-------------+----------------+----------------+-------------+----------------+-------------+------------------+------
 postgres | maiquel            |             | maiquel      | maiquel      |       31482 | 17devel        |                | 5432        |                |             | /tmp             |
(1 row)

postgres=> \q
[postgres@localhost bin]$ ./psql -h localhost -U maiquel -d postgres
psql (17devel)
Type "help" for help.

postgres=> \conninfo
You are connected to database "postgres" as user "maiquel" on host "localhost" (address "::1") at port "5432".
postgres=> \conninfo+
                                                                                    Current Connection Information
 Database | Authenticated User | System User | Current User | Session User | Session PID | Server Version | Server Address | Server Port | Client Address | Client Port | Socket Directory |   Host
----------+--------------------+-------------+--------------+--------------+-------------+----------------+----------------+-------------+----------------+-------------+------------------+-----------
 postgres | maiquel            |             | maiquel      | maiquel      |       31485 | 17devel        | ::1            | 5432        | ::1            |       47482 |                  | localhost
(1 row)

postgres=> \q
[postgres@localhost bin]$ ./psql -h localhost
psql (17devel)
Type "help" for help.

postgres=# \conninfo
You are connected to database "postgres" as user "postgres" on host "localhost" (address "::1") at port "5432".
postgres=# \conninfo+
                                                                                    Current Connection Information
 Database | Authenticated User | System User | Current User | Session User | Session PID | Server Version | Server Address | Server Port | Client Address | Client Port | Socket Directory |   Host
----------+--------------------+-------------+--------------+--------------+-------------+----------------+----------------+-------------+----------------+-------------+------------------+-----------
 postgres | postgres           |             | postgres     | postgres     |       31488 | 17devel        | ::1            | 5432        | ::1            |       47484 |                  | localhost
(1 row)

Regards,
Maiquel.


Attachments:

  [application/octet-stream] v8-0001-psql-meta-command-conninfo-plus.patch (8.1K, ../../CP8P284MB2496D053FD15C80780B72F46EC442@CP8P284MB2496.BRAP284.PROD.OUTLOOK.COM/3-v8-0001-psql-meta-command-conninfo-plus.patch)
  download | inline diff:
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index 5c906e4..bf93cb1 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -68,7 +68,8 @@ static backslashResult exec_command_C(PsqlScanState scan_state, bool active_bran
 static backslashResult exec_command_connect(PsqlScanState scan_state, bool active_branch);
 static backslashResult exec_command_cd(PsqlScanState scan_state, bool active_branch,
 									   const char *cmd);
-static backslashResult exec_command_conninfo(PsqlScanState scan_state, bool active_branch);
+static backslashResult exec_command_conninfo(PsqlScanState scan_state, bool active_branch,
+											 const char *cmd);
 static backslashResult exec_command_copy(PsqlScanState scan_state, bool active_branch);
 static backslashResult exec_command_copyright(PsqlScanState scan_state, bool active_branch);
 static backslashResult exec_command_crosstabview(PsqlScanState scan_state, bool active_branch);
@@ -317,8 +318,8 @@ exec_command(const char *cmd,
 		status = exec_command_connect(scan_state, active_branch);
 	else if (strcmp(cmd, "cd") == 0)
 		status = exec_command_cd(scan_state, active_branch, cmd);
-	else if (strcmp(cmd, "conninfo") == 0)
-		status = exec_command_conninfo(scan_state, active_branch);
+	else if (strcmp(cmd, "conninfo") == 0 || strcmp(cmd, "conninfo+") == 0)
+		status = exec_command_conninfo(scan_state, active_branch, cmd);
 	else if (pg_strcasecmp(cmd, "copy") == 0)
 		status = exec_command_copy(scan_state, active_branch);
 	else if (strcmp(cmd, "copyright") == 0)
@@ -643,47 +644,74 @@ exec_command_cd(PsqlScanState scan_state, bool active_branch, const char *cmd)
 }
 
 /*
- * \conninfo -- display information about the current connection
+ * \conninfo, \conninfo+ -- display information about the current connection
  */
 static backslashResult
-exec_command_conninfo(PsqlScanState scan_state, bool active_branch)
+exec_command_conninfo(PsqlScanState scan_state, bool active_branch, const char *cmd)
 {
+	bool		success = true;
+
 	if (active_branch)
 	{
 		char	   *db = PQdb(pset.db);
+		char	   *pattern;
+		bool		show_verbose;
 
-		if (db == NULL)
-			printf(_("You are currently not connected to a database.\n"));
-		else
+		pattern = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, true);
+
+		show_verbose = strchr(cmd, '+') ? true : false;
+
+		/*
+		 * \conninfo+
+		 */
+		if (show_verbose)
 		{
-			char	   *host = PQhost(pset.db);
-			char	   *hostaddr = PQhostaddr(pset.db);
+			success = listConnectionInformation(pattern);
+			free(pattern);
+			printSSLInfo();
+			printGSSInfo();
+		}
 
-			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));
-			}
+		/*
+		 * \conninfo
+		 */
+		else
+		{
+			if (db == NULL)
+				printf(_("You are currently not connected to a database.\n"));
 			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));
+				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
-					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));
+				{
+					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();
 			}
-			printSSLInfo();
-			printGSSInfo();
 		}
 	}
+	else
+		ignore_slash_options(scan_state);
 
-	return PSQL_CMD_SKIP_LINE;
+	return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
 }
 
 /*
diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index b6a4eb1..13f0d1f 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -26,6 +26,7 @@
 #include "fe_utils/mbprint.h"
 #include "fe_utils/print.h"
 #include "fe_utils/string_utils.h"
+#include "libpq/pqcomm.h"
 #include "settings.h"
 #include "variables.h"
 
@@ -901,6 +902,70 @@ error_return:
 	return false;
 }
 
+/*
+ * listConnectionInformation
+ *
+ * for \conninfo+
+ */
+bool
+listConnectionInformation(const char *pattern)
+{
+	PGresult   *res;
+	PQExpBufferData buf;
+	printQueryOpt myopt = pset.popt;
+
+	char	   *host = PQhost(pset.db);
+	char	   *hostaddr = PQhostaddr(pset.db);
+
+	initPQExpBuffer(&buf);
+
+	printfPQExpBuffer(&buf,
+					  "SELECT\n"
+					  "  pg_catalog.current_database() AS \"Database\",\n"
+					  "  '%s' AS \"Authenticated User\",\n",
+					  PQuser(pset.db));
+	if (pset.sversion >= 160000)
+		appendPQExpBuffer(&buf,
+						  "  pg_catalog.system_user() AS \"System User\",\n");
+	appendPQExpBuffer(&buf,
+					  "  pg_catalog.current_user() AS \"Current User\",\n"
+					  "  pg_catalog.session_user() AS \"Session User\",\n"
+					  "  pg_catalog.pg_backend_pid() AS \"Session PID\",\n"
+					  "  pg_catalog.current_setting('server_version') AS \"Server Version\",\n"
+					  "  pg_catalog.inet_server_addr() AS \"Server Address\",\n"
+					  "  pg_catalog.current_setting('port') AS \"Server Port\",\n"
+					  "  pg_catalog.inet_client_addr() AS \"Client Address\",\n"
+					  "  pg_catalog.inet_client_port() AS \"Client Port\",\n");
+	if (is_unixsock_path(host) && !(hostaddr && *hostaddr))
+		appendPQExpBuffer(&buf,
+						  "  '%s' AS \"Socket Directory\",\n",
+						  host);
+	else
+		appendPQExpBuffer(&buf,
+						  "  NULL AS \"Socket Directory\",\n");
+	appendPQExpBuffer(&buf,
+					  "  CASE\n"
+					  "    WHEN\n"
+					  "      pg_catalog.inet_server_addr() IS NULL\n"
+					  "      AND pg_catalog.inet_client_addr() IS NULL\n"
+					  "    THEN NULL\n"
+					  "    ELSE '%s'\n"
+					  "  END AS \"Host\";",
+					  host);
+
+	res = PSQLexec(buf.data);
+	termPQExpBuffer(&buf);
+	if (!res)
+		return false;
+
+	myopt.title = _("Current Connection Information");
+	myopt.translate_header = true;
+
+	printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
+
+	PQclear(res);
+	return true;
+}
 
 /*
  * listAllDbs
diff --git a/src/bin/psql/describe.h b/src/bin/psql/describe.h
index 273f974..779918b 100644
--- a/src/bin/psql/describe.h
+++ b/src/bin/psql/describe.h
@@ -149,4 +149,7 @@ extern bool listOpFamilyFunctions(const char *access_method_pattern,
 /* \dl or \lo_list */
 extern bool listLargeObjects(bool verbose);
 
+/* \conninfo */
+extern bool listConnectionInformation(const char *pattern);
+
 #endif							/* DESCRIBE_H */
diff --git a/src/bin/psql/help.c b/src/bin/psql/help.c
index 4e79a81..2c5426d 100644
--- a/src/bin/psql/help.c
+++ b/src/bin/psql/help.c
@@ -310,7 +310,7 @@ slashUsage(unsigned short int pager)
 	else
 		HELP0("  \\c[onnect] {[DBNAME|- USER|- HOST|- PORT|-] | conninfo}\n"
 			  "                         connect to new database (currently no connection)\n");
-	HELP0("  \\conninfo              display information about current connection\n");
+	HELP0("  \\conninfo[+]           display information about current connection\n");
 	HELP0("  \\encoding [ENCODING]   show or set client encoding\n");
 	HELP0("  \\password [USERNAME]   securely change the password for a user\n");
 	HELP0("\n");


^ permalink  raw  reply  [nested|flat] 43+ messages in thread

* Re: Psql meta-command conninfo+
  2024-02-06 21:50 Re: Psql meta-command conninfo+ Nathan Bossart <[email protected]>
  2024-02-07 04:13 ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-07 12:35   ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-07 14:47     ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-07 16:40       ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-07 20:13         ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-08 11:01           ` Re: Psql meta-command conninfo+ Jim Jones <[email protected]>
  2024-02-08 15:50             ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
@ 2024-02-08 19:37               ` Jim Jones <[email protected]>
  2024-02-08 20:37                 ` Re: Psql meta-command conninfo+ Erik Wienhold <[email protected]>
  2024-02-08 20:47                 ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  0 siblings, 2 replies; 43+ messages in thread

From: Jim Jones @ 2024-02-08 19:37 UTC (permalink / raw)
  To: Maiquel Grassi <[email protected]>; Pavel Luzanov <[email protected]>; Nathan Bossart <[email protected]>; +Cc: Erik Wienhold <[email protected]>; pgsql-hackers


On 08.02.24 16:50, Maiquel Grassi wrote:
> Hi Jim,
> Thank you for your support on this patch!
> As I believe in its usability, I have been dedicating efforts to make
> it really interesting.
> I hadn't thought about the permissioning issue for
> "unix_socket_directories". I appreciate that.
> I thought about solving this situation using the same approach as
> \conninfo. I added the validation if (is_unixsock_path(host) &&
> !(hostaddr && *hostaddr)) in the SQL part along with an "append". In
> case of a negative result, another "append" adds NULL.
> Regarding the whitespace issue, before generating v8 patch file, I
> used pgindent to adjust each modified file. I believe it should be ok
> now. If you could verify, I'd be grateful.
> Below are the tests after adjusting for the permissioning issues:
>
> [postgres@localhost bin]$ ./psql
> psql (17devel)
> Type "help" for help.
>
> postgres=# \conninfo
> You are connected to database "postgres" as user "postgres" via socket
> in "/tmp" at port "5432".
> postgres=# \conninfo+
>                                                                      
>             Current Connection Information
>  Database | Authenticated User | System User | Current User | Session
> User | Session PID | Server Version | Server Address | Server Port |
> Client Address | Client Port | Socket Directory | Host
> ----------+--------------------+-------------+--------------+--------------+-------------+----------------+----------------+-------------+----------------+-------------+------------------+------
>  postgres | postgres           |             | postgres     | postgres
>     |       31479 | 17devel        |                | 5432        |  
>              |             | /tmp             |
> (1 row)
>
> postgres=# CREATE USER maiquel;
> CREATE ROLE
> postgres=# \q
> [postgres@localhost bin]$ ./psql -U maiquel -d postgres
> psql (17devel)
> Type "help" for help.
>
> postgres=> \conninfo
> You are connected to database "postgres" as user "maiquel" via socket
> in "/tmp" at port "5432".
> postgres=> \conninfo+
>                                                                      
>             Current Connection Information
>  Database | Authenticated User | System User | Current User | Session
> User | Session PID | Server Version | Server Address | Server Port |
> Client Address | Client Port | Socket Directory | Host
> ----------+--------------------+-------------+--------------+--------------+-------------+----------------+----------------+-------------+----------------+-------------+------------------+------
>  postgres | maiquel            |             | maiquel      | maiquel
>      |       31482 | 17devel        |                | 5432        |  
>              |             | /tmp             |
> (1 row)
>
> postgres=> \q
> [postgres@localhost bin]$ ./psql -h localhost -U maiquel -d postgres
> psql (17devel)
> Type "help" for help.
>
> postgres=> \conninfo
> You are connected to database "postgres" as user "maiquel" on host
> "localhost" (address "::1") at port "5432".
> postgres=> \conninfo+
>                                                                      
>               Current Connection Information
>  Database | Authenticated User | System User | Current User | Session
> User | Session PID | Server Version | Server Address | Server Port |
> Client Address | Client Port | Socket Directory |   Host
> ----------+--------------------+-------------+--------------+--------------+-------------+----------------+----------------+-------------+----------------+-------------+------------------+-----------
>  postgres | maiquel            |             | maiquel      | maiquel
>      |       31485 | 17devel        | ::1            | 5432        |
> ::1            |       47482 |                  | localhost
> (1 row)
>
> postgres=> \q
> [postgres@localhost bin]$ ./psql -h localhost
> psql (17devel)
> Type "help" for help.
>
> postgres=# \conninfo
> You are connected to database "postgres" as user "postgres" on host
> "localhost" (address "::1") at port "5432".
> postgres=# \conninfo+
>                                                                      
>               Current Connection Information
>  Database | Authenticated User | System User | Current User | Session
> User | Session PID | Server Version | Server Address | Server Port |
> Client Address | Client Port | Socket Directory |   Host
> ----------+--------------------+-------------+--------------+--------------+-------------+----------------+----------------+-------------+----------------+-------------+------------------+-----------
>  postgres | postgres           |             | postgres     | postgres
>     |       31488 | 17devel        | ::1            | 5432        |
> ::1            |       47484 |                  | localhost
> (1 row)
>
> Regards,
> Maiquel.

v8 no longer throws a permission denied error for non-superusers - it is
IMHO much nicer this way.

$ /usr/local/postgres-dev/bin/psql postgres -p 5432 -h 127.0.0.1 -U jim
psql (17devel)
Type "help" for help.

postgres=# \x
Expanded display is on.
postgres=# \conninfo+
Current Connection Information
-[ RECORD 1 ]------+----------
Database           | postgres
Authenticated User | jim
System User        |
Current User       | jim
Session User       | jim
Session PID        | 1321493
Server Version     | 17devel
Server Address     | 127.0.0.1
Server Port        | 5432
Client Address     | 127.0.0.1
Client Port        | 49366
Socket Directory   |
Host               | 127.0.0.1

postgres=# SET ROLE foo;
SET
postgres=> \conninfo+
Current Connection Information
-[ RECORD 1 ]------+----------
Database           | postgres
Authenticated User | jim
System User        |
Current User       | foo
Session User       | jim
Session PID        | 1321493
Server Version     | 17devel
Server Address     | 127.0.0.1
Server Port        | 5432
Client Address     | 127.0.0.1
Client Port        | 49366
Socket Directory   |
Host               | 127.0.0.1


The patch now applies cleanly.

One thing I just noticed. The psql autocomplete feature does not suggest
the new + option of \conninfo. For instance, when typing "\connin[TAB]"
it automatically autocompletes to "\conninfo ". I guess it should also
be included in this patch.

I can do a more thorough review of the code when you add the
documentation and tests to the patch.

Thanks!

-- 
Jim







^ permalink  raw  reply  [nested|flat] 43+ messages in thread

* Re: Psql meta-command conninfo+
  2024-02-06 21:50 Re: Psql meta-command conninfo+ Nathan Bossart <[email protected]>
  2024-02-07 04:13 ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-07 12:35   ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-07 14:47     ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-07 16:40       ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-07 20:13         ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-08 11:01           ` Re: Psql meta-command conninfo+ Jim Jones <[email protected]>
  2024-02-08 15:50             ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-08 19:37               ` Re: Psql meta-command conninfo+ Jim Jones <[email protected]>
@ 2024-02-08 20:37                 ` Erik Wienhold <[email protected]>
  2024-02-08 22:28                   ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-08 23:34                   ` Re: Psql meta-command conninfo+ Jim Jones <[email protected]>
  1 sibling, 2 replies; 43+ messages in thread

From: Erik Wienhold @ 2024-02-08 20:37 UTC (permalink / raw)
  To: Jim Jones <[email protected]>; +Cc: Maiquel Grassi <[email protected]>; Pavel Luzanov <[email protected]>; Nathan Bossart <[email protected]>; pgsql-hackers

On 2024-02-08 20:37 +0100, Jim Jones wrote:
> One thing I just noticed. The psql autocomplete feature does not suggest
> the new + option of \conninfo. For instance, when typing "\connin[TAB]"
> it automatically autocompletes to "\conninfo ". I guess it should also
> be included in this patch.

Modifiers such as + or S in \dS are not covered by autocompletion.
src/bin/psql/tab-complete.c only specifies backslash commands in their
basic form (without modifiers).

(\dS<TAB> actually autocompletes to \ds to my surprise)

> I can do a more thorough review of the code when you add the
> documentation and tests to the patch.

I noticed that the pattern parameter in listConnectionInformation is
unused.  exec_command_conninfo scans the pattern but \conninfo should
not accept any argument.  So the pattern can be removed entirely.

-- 
Erik






^ permalink  raw  reply  [nested|flat] 43+ messages in thread

* RE: Psql meta-command conninfo+
  2024-02-06 21:50 Re: Psql meta-command conninfo+ Nathan Bossart <[email protected]>
  2024-02-07 04:13 ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-07 12:35   ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-07 14:47     ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-07 16:40       ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-07 20:13         ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-08 11:01           ` Re: Psql meta-command conninfo+ Jim Jones <[email protected]>
  2024-02-08 15:50             ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-08 19:37               ` Re: Psql meta-command conninfo+ Jim Jones <[email protected]>
  2024-02-08 20:37                 ` Re: Psql meta-command conninfo+ Erik Wienhold <[email protected]>
@ 2024-02-08 22:28                   ` Maiquel Grassi <[email protected]>
  2024-02-09 10:19                     ` Re: Psql meta-command conninfo+ Alvaro Herrera <[email protected]>
  1 sibling, 1 reply; 43+ messages in thread

From: Maiquel Grassi @ 2024-02-08 22:28 UTC (permalink / raw)
  To: Erik Wienhold <[email protected]>; Jim Jones <[email protected]>; +Cc: Pavel Luzanov <[email protected]>; Nathan Bossart <[email protected]>; pgsql-hackers

>On 2024-02-08 20:37 +0100, Jim Jones wrote:
>> One thing I just noticed. The psql autocomplete feature does not suggest
>> the new + option of \conninfo. For instance, when typing "\connin[TAB]"
>> it automatically autocompletes to "\conninfo ". I guess it should also
>> be included in this patch.
>
>Modifiers such as + or S in \dS are not covered by autocompletion.
>src/bin/psql/tab-complete.c only specifies backslash commands in their
>basic form (without modifiers).
>
>(\dS<TAB> actually autocompletes to \ds to my surprise)
>
>> I can do a more thorough review of the code when you add the
>> documentation and tests to the patch.
>
>I noticed that the pattern parameter in listConnectionInformation is
>unused.  exec_command_conninfo scans the pattern but \conninfo should
>not accept any argument.  So the pattern can be removed entirely.

--//--

Hi Erik,


Exactly, in "\conninfo+" the "pattern" argument was not introduced and
therefore "listConnectionInformation()" can be declared (signed) without
any arguments. In the future, if necessary, and if there is a need to add
any "pattern", then that can be done. However, that's not the current
scenario. I removed everything related to the "pattern" from the patch.

Regarding "(\dS<TAB> actually autocompletes to \ds to my surprise)",
I was also surprised. I haven't studied the code yet to understand why
this happens. It seems curious to me. I'll try to understand this
implementation better.

I'm continuing the development of "\conninfo+" and now moving on to tests.

Tks a lot!

Regards,
Maiquel Grassi.


Attachments:

  [application/octet-stream] v10-0001-psql-meta-command-conninfo-plus.patch (8.8K, ../../CP8P284MB249681AA87D9EAF9412439D9EC442@CP8P284MB2496.BRAP284.PROD.OUTLOOK.COM/3-v10-0001-psql-meta-command-conninfo-plus.patch)
  download | inline diff:
diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml
index cc7d797..4e86ad9 100644
--- a/doc/src/sgml/ref/psql-ref.sgml
+++ b/doc/src/sgml/ref/psql-ref.sgml
@@ -1029,10 +1029,14 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g
       </varlistentry>
 
       <varlistentry id="app-psql-meta-command-conninfo">
-        <term><literal>\conninfo</literal></term>
+        <term><literal>\conninfo[+]</literal></term>
         <listitem>
         <para>
         Outputs information about the current database connection.
+        When no <literal>+</literal> is specified, it simply prints
+        a textual description of a few connection options.
+        When <literal>+</literal> is given, more complete information
+        is displayed as a table.
         </para>
         </listitem>
       </varlistentry>
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index 5c906e4..2c4ea74 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -68,7 +68,8 @@ static backslashResult exec_command_C(PsqlScanState scan_state, bool active_bran
 static backslashResult exec_command_connect(PsqlScanState scan_state, bool active_branch);
 static backslashResult exec_command_cd(PsqlScanState scan_state, bool active_branch,
 									   const char *cmd);
-static backslashResult exec_command_conninfo(PsqlScanState scan_state, bool active_branch);
+static backslashResult exec_command_conninfo(PsqlScanState scan_state, bool active_branch,
+											 const char *cmd);
 static backslashResult exec_command_copy(PsqlScanState scan_state, bool active_branch);
 static backslashResult exec_command_copyright(PsqlScanState scan_state, bool active_branch);
 static backslashResult exec_command_crosstabview(PsqlScanState scan_state, bool active_branch);
@@ -317,8 +318,8 @@ exec_command(const char *cmd,
 		status = exec_command_connect(scan_state, active_branch);
 	else if (strcmp(cmd, "cd") == 0)
 		status = exec_command_cd(scan_state, active_branch, cmd);
-	else if (strcmp(cmd, "conninfo") == 0)
-		status = exec_command_conninfo(scan_state, active_branch);
+	else if (strcmp(cmd, "conninfo") == 0 || strcmp(cmd, "conninfo+") == 0)
+		status = exec_command_conninfo(scan_state, active_branch, cmd);
 	else if (pg_strcasecmp(cmd, "copy") == 0)
 		status = exec_command_copy(scan_state, active_branch);
 	else if (strcmp(cmd, "copyright") == 0)
@@ -643,47 +644,70 @@ exec_command_cd(PsqlScanState scan_state, bool active_branch, const char *cmd)
 }
 
 /*
- * \conninfo -- display information about the current connection
+ * \conninfo, \conninfo+ -- display information about the current connection
  */
 static backslashResult
-exec_command_conninfo(PsqlScanState scan_state, bool active_branch)
+exec_command_conninfo(PsqlScanState scan_state, bool active_branch, const char *cmd)
 {
+	bool		success = true;
+
 	if (active_branch)
 	{
 		char	   *db = PQdb(pset.db);
+		bool		show_verbose;
 
-		if (db == NULL)
-			printf(_("You are currently not connected to a database.\n"));
-		else
+		show_verbose = strchr(cmd, '+') ? true : false;
+
+		/*
+		 * \conninfo+
+		 */
+		if (show_verbose)
 		{
-			char	   *host = PQhost(pset.db);
-			char	   *hostaddr = PQhostaddr(pset.db);
+			success = listConnectionInformation();
+			printSSLInfo();
+			printGSSInfo();
+		}
 
-			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));
-			}
+		/*
+		 * \conninfo
+		 */
+		else
+		{
+			if (db == NULL)
+				printf(_("You are currently not connected to a database.\n"));
 			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));
+				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
-					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));
+				{
+					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();
 			}
-			printSSLInfo();
-			printGSSInfo();
 		}
 	}
+	else
+		ignore_slash_options(scan_state);
 
-	return PSQL_CMD_SKIP_LINE;
+	return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
 }
 
 /*
diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index b6a4eb1..0d357a9 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -26,6 +26,7 @@
 #include "fe_utils/mbprint.h"
 #include "fe_utils/print.h"
 #include "fe_utils/string_utils.h"
+#include "libpq/pqcomm.h"
 #include "settings.h"
 #include "variables.h"
 
@@ -901,6 +902,70 @@ error_return:
 	return false;
 }
 
+/*
+ * listConnectionInformation
+ *
+ * for \conninfo+
+ */
+bool
+listConnectionInformation()
+{
+	PGresult   *res;
+	PQExpBufferData buf;
+	printQueryOpt myopt = pset.popt;
+
+	char	   *host = PQhost(pset.db);
+	char	   *hostaddr = PQhostaddr(pset.db);
+
+	initPQExpBuffer(&buf);
+
+	printfPQExpBuffer(&buf,
+					  "SELECT\n"
+					  "  pg_catalog.current_database() AS \"Database\",\n"
+					  "  '%s' AS \"Authenticated User\",\n",
+					  PQuser(pset.db));
+	if (pset.sversion >= 160000)
+		appendPQExpBuffer(&buf,
+						  "  pg_catalog.system_user() AS \"System User\",\n");
+	appendPQExpBuffer(&buf,
+					  "  pg_catalog.current_user() AS \"Current User\",\n"
+					  "  pg_catalog.session_user() AS \"Session User\",\n"
+					  "  pg_catalog.pg_backend_pid() AS \"Session PID\",\n"
+					  "  pg_catalog.current_setting('server_version') AS \"Server Version\",\n"
+					  "  pg_catalog.inet_server_addr() AS \"Server Address\",\n"
+					  "  pg_catalog.current_setting('port') AS \"Server Port\",\n"
+					  "  pg_catalog.inet_client_addr() AS \"Client Address\",\n"
+					  "  pg_catalog.inet_client_port() AS \"Client Port\",\n");
+	if (is_unixsock_path(host) && !(hostaddr && *hostaddr))
+		appendPQExpBuffer(&buf,
+						  "  '%s' AS \"Socket Directory\",\n",
+						  host);
+	else
+		appendPQExpBuffer(&buf,
+						  "  NULL AS \"Socket Directory\",\n");
+	appendPQExpBuffer(&buf,
+					  "  CASE\n"
+					  "    WHEN\n"
+					  "      pg_catalog.inet_server_addr() IS NULL\n"
+					  "      AND pg_catalog.inet_client_addr() IS NULL\n"
+					  "    THEN NULL\n"
+					  "    ELSE '%s'\n"
+					  "  END AS \"Host\";",
+					  host);
+
+	res = PSQLexec(buf.data);
+	termPQExpBuffer(&buf);
+	if (!res)
+		return false;
+
+	myopt.title = _("Current Connection Information");
+	myopt.translate_header = true;
+
+	printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
+
+	PQclear(res);
+	return true;
+}
 
 /*
  * listAllDbs
diff --git a/src/bin/psql/describe.h b/src/bin/psql/describe.h
index 273f974..fa034c4 100644
--- a/src/bin/psql/describe.h
+++ b/src/bin/psql/describe.h
@@ -149,4 +149,7 @@ extern bool listOpFamilyFunctions(const char *access_method_pattern,
 /* \dl or \lo_list */
 extern bool listLargeObjects(bool verbose);
 
+/* \conninfo */
+extern bool listConnectionInformation();
+
 #endif							/* DESCRIBE_H */
diff --git a/src/bin/psql/help.c b/src/bin/psql/help.c
index 4e79a81..2c5426d 100644
--- a/src/bin/psql/help.c
+++ b/src/bin/psql/help.c
@@ -310,7 +310,7 @@ slashUsage(unsigned short int pager)
 	else
 		HELP0("  \\c[onnect] {[DBNAME|- USER|- HOST|- PORT|-] | conninfo}\n"
 			  "                         connect to new database (currently no connection)\n");
-	HELP0("  \\conninfo              display information about current connection\n");
+	HELP0("  \\conninfo[+]           display information about current connection\n");
 	HELP0("  \\encoding [ENCODING]   show or set client encoding\n");
 	HELP0("  \\password [USERNAME]   securely change the password for a user\n");
 	HELP0("\n");


^ permalink  raw  reply  [nested|flat] 43+ messages in thread

* Re: Psql meta-command conninfo+
  2024-02-06 21:50 Re: Psql meta-command conninfo+ Nathan Bossart <[email protected]>
  2024-02-07 04:13 ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-07 12:35   ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-07 14:47     ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-07 16:40       ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-07 20:13         ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-08 11:01           ` Re: Psql meta-command conninfo+ Jim Jones <[email protected]>
  2024-02-08 15:50             ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-08 19:37               ` Re: Psql meta-command conninfo+ Jim Jones <[email protected]>
  2024-02-08 20:37                 ` Re: Psql meta-command conninfo+ Erik Wienhold <[email protected]>
  2024-02-08 22:28                   ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
@ 2024-02-09 10:19                     ` Alvaro Herrera <[email protected]>
  2024-02-09 15:33                       ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-10 17:38                       ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  0 siblings, 2 replies; 43+ messages in thread

From: Alvaro Herrera @ 2024-02-09 10:19 UTC (permalink / raw)
  To: Maiquel Grassi <[email protected]>; +Cc: Erik Wienhold <[email protected]>; Jim Jones <[email protected]>; Pavel Luzanov <[email protected]>; Nathan Bossart <[email protected]>; pgsql-hackers

Hmm, I noticed that this would call printSSLInfo() and printGSSInfo()
after listConnectionInformation.  It would be much better to show these
in tabular format as well and remove the calls to printSSL/GSSInfo.

I propose additional columns to the same \conninfo+ table; when SSL,
like this:

Database           | postgres
[...]
Host               | 127.0.0.1
Encryption         | SSL
Protocol           | PQsslAttribute(protocol)
Cipher             | PQsslAttribute(cipher)
Compression        | PQsslAttribute(compression)

When GSS, like this

Database           | postgres
[...]
Host               | 127.0.0.1
Encryption         | GSS

(why don't we print anything else in printGSSInfo()?  That's weird.)

-- 
Álvaro Herrera         PostgreSQL Developer  —  https://www.EnterpriseDB.com/
"Pido que me den el Nobel por razones humanitarias" (Nicanor Parra)






^ permalink  raw  reply  [nested|flat] 43+ messages in thread

* RE: Psql meta-command conninfo+
  2024-02-06 21:50 Re: Psql meta-command conninfo+ Nathan Bossart <[email protected]>
  2024-02-07 04:13 ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-07 12:35   ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-07 14:47     ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-07 16:40       ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-07 20:13         ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-08 11:01           ` Re: Psql meta-command conninfo+ Jim Jones <[email protected]>
  2024-02-08 15:50             ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-08 19:37               ` Re: Psql meta-command conninfo+ Jim Jones <[email protected]>
  2024-02-08 20:37                 ` Re: Psql meta-command conninfo+ Erik Wienhold <[email protected]>
  2024-02-08 22:28                   ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-09 10:19                     ` Re: Psql meta-command conninfo+ Alvaro Herrera <[email protected]>
@ 2024-02-09 15:33                       ` Maiquel Grassi <[email protected]>
  1 sibling, 0 replies; 43+ messages in thread

From: Maiquel Grassi @ 2024-02-09 15:33 UTC (permalink / raw)
  To: Alvaro Herrera <[email protected]>; +Cc: Erik Wienhold <[email protected]>; Jim Jones <[email protected]>; Pavel Luzanov <[email protected]>; Nathan Bossart <[email protected]>; pgsql-hackers

>Hmm, I noticed that this would call printSSLInfo() and printGSSInfo()
>after listConnectionInformation.  It would be much better to show these
>in tabular format as well and remove the calls to printSSL/GSSInfo.
>
>I propose additional columns to the same \conninfo+ table; when SSL,
>like this:
>
>Database           | postgres
>[...]
>Host               | 127.0.0.1
>Encryption         | SSL
>Protocol           | PQsslAttribute(protocol)
>Cipher             | PQsslAttribute(cipher)
>Compression        | PQsslAttribute(compression)
>
>When GSS, like this
>
>Database           | postgres
>[...]
>Host               | 127.0.0.1
>Encryption         | GSS
>
>(why don't we print anything else in printGSSInfo()?  That's weird.)

--//--

Hi Álvaro,


Thank you for the suggestion. I will remove printSSLInfo() and printGSSInfo() and
incorporate the suggested fields into the tabular result of "\conninfo+".

If it's necessary to adjust printGSSInfo(), we can work on that as well. At first
glance, I leave it open for others to analyze and give their opinion.

I'd also like to ask for help with a difficulty. Currently, I'm working on

resolving this situation (highlighted by Pavel Luzanov). How can we
make \conninfo return the same message as \conninfo+ after closing
the current session in another session with pg_terminate_backend(pid)?

[postgres@localhost bin]$ ./psql

psql (17devel)
Type "help" for help.

postgres=# \conninfo
You are connected to database "postgres" as user "postgres" via socket in "/tmp" at port "5432".
postgres=# \conninfo+
                                                                         Current Connection Information
 Database | Authenticated User | System User | Current User | Session User | Backend PID | Server Address | Server Port | Client Address | Client Port | Socket Directory | Host
----------+--------------------+-------------+--------------+--------------+-------------+----------------+-------------+----------------+-------------+------------------+------
 postgres | postgres           |             | postgres     | postgres     |       17281 |                | 5432        |                |             | /tmp             |
(1 row)

postgres=# 2024-02-09 09:15:24.152 -03 [17281] FATAL:  terminating connection due to administrator command

postgres=# \conninfo
You are connected to database "postgres" as user "postgres" via socket in "/tmp" at port "5432".
postgres=# \conninfo+
FATAL:  terminating connection due to administrator command
server closed the connection unexpectedly
        This probably means the server terminated abnormally
        before or while processing the request.
The connection to the server was lost. Attempting reset: Succeeded.
postgres=#

Tks a lot!
Maiquel Grassi.


^ permalink  raw  reply  [nested|flat] 43+ messages in thread

* RE: Psql meta-command conninfo+
  2024-02-06 21:50 Re: Psql meta-command conninfo+ Nathan Bossart <[email protected]>
  2024-02-07 04:13 ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-07 12:35   ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-07 14:47     ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-07 16:40       ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-07 20:13         ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-08 11:01           ` Re: Psql meta-command conninfo+ Jim Jones <[email protected]>
  2024-02-08 15:50             ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-08 19:37               ` Re: Psql meta-command conninfo+ Jim Jones <[email protected]>
  2024-02-08 20:37                 ` Re: Psql meta-command conninfo+ Erik Wienhold <[email protected]>
  2024-02-08 22:28                   ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-09 10:19                     ` Re: Psql meta-command conninfo+ Alvaro Herrera <[email protected]>
@ 2024-02-10 17:38                       ` Maiquel Grassi <[email protected]>
  1 sibling, 0 replies; 43+ messages in thread

From: Maiquel Grassi @ 2024-02-10 17:38 UTC (permalink / raw)
  To: Alvaro Herrera <[email protected]>; +Cc: Erik Wienhold <[email protected]>; Jim Jones <[email protected]>; Pavel Luzanov <[email protected]>; Nathan Bossart <[email protected]>; pgsql-hackers

>Database           | postgres
>[...]
>Host               | 127.0.0.1
>Encryption         | SSL
>Protocol           | PQsslAttribute(protocol)
>Cipher             | PQsslAttribute(cipher)
>Compression        | PQsslAttribute(compression)
>
>When GSS, like this
>
>Database           | postgres
>[...]
>Host               | 127.0.0.1
>Encryption         | GSS

--//--

Hi PgHackers,

Columns were added for SSL and GSS.


For SSL, I conducted some tests as follows. For GSS, I will perform
them and intend to provide a sample here in the next interaction.

If anyone can and wants to test GSSAPI as well, I appreciate it.

[postgres@localhost bin]$ ./psql -h localhost -p 5432 -x

psql (17devel)
Type "help" for help.

postgres=# \conninfo
You are connected to database "postgres" as user "postgres" on host "localhost" (address "::1") at port "5432".
postgres=# \conninfo+
Current Connection Information
-[ RECORD 1 ]------+----------
Database           | postgres
Authenticated User | postgres
System User        |
Current User       | postgres
Session User       | postgres
Backend PID        | 15809
Server Address     | ::1
Server Port        | 5432
Client Address     | ::1
Client Port        | 56890
Socket Directory   |
Host               | localhost

postgres=# \q
[postgres@localhost bin]$ ./psql -h localhost -p 5433 -x
psql (17devel, server 15.6)
SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, compression: off)
Type "help" for help.

postgres=# \conninfo
You are connected to database "postgres" as user "postgres" on host "localhost" (address "::1") at port "5433".
SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, compression: off)
postgres=# \conninfo+
Current Connection Information
-[ RECORD 1 ]------+----------------------------
Database           | postgres
Authenticated User | postgres
Current User       | postgres
Session User       | postgres
Backend PID        | 15811
Server Address     | ::1
Server Port        | 5433
Client Address     | ::1
Client Port        | 40622
Socket Directory   |
Host               | localhost
Encryption         | SSL
Protocol           | TLSv1.2
Cipher             | ECDHE-RSA-AES256-GCM-SHA384
Compression        | off

Regards,
Maiquel Grassi.


Attachments:

  [application/octet-stream] v13-0001-psql-meta-command-conninfo-plus.patch (9.5K, ../../CP8P284MB24967BCC7B831598BA42B22EEC4A2@CP8P284MB2496.BRAP284.PROD.OUTLOOK.COM/3-v13-0001-psql-meta-command-conninfo-plus.patch)
  download | inline diff:
diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml
index cc7d797..4e86ad9 100644
--- a/doc/src/sgml/ref/psql-ref.sgml
+++ b/doc/src/sgml/ref/psql-ref.sgml
@@ -1029,10 +1029,14 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g
       </varlistentry>
 
       <varlistentry id="app-psql-meta-command-conninfo">
-        <term><literal>\conninfo</literal></term>
+        <term><literal>\conninfo[+]</literal></term>
         <listitem>
         <para>
         Outputs information about the current database connection.
+        When no <literal>+</literal> is specified, it simply prints
+        a textual description of a few connection options.
+        When <literal>+</literal> is given, more complete information
+        is displayed as a table.
         </para>
         </listitem>
       </varlistentry>
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index 5c906e4..08aaa57 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -68,7 +68,8 @@ static backslashResult exec_command_C(PsqlScanState scan_state, bool active_bran
 static backslashResult exec_command_connect(PsqlScanState scan_state, bool active_branch);
 static backslashResult exec_command_cd(PsqlScanState scan_state, bool active_branch,
 									   const char *cmd);
-static backslashResult exec_command_conninfo(PsqlScanState scan_state, bool active_branch);
+static backslashResult exec_command_conninfo(PsqlScanState scan_state, bool active_branch,
+											 const char *cmd);
 static backslashResult exec_command_copy(PsqlScanState scan_state, bool active_branch);
 static backslashResult exec_command_copyright(PsqlScanState scan_state, bool active_branch);
 static backslashResult exec_command_crosstabview(PsqlScanState scan_state, bool active_branch);
@@ -317,8 +318,8 @@ exec_command(const char *cmd,
 		status = exec_command_connect(scan_state, active_branch);
 	else if (strcmp(cmd, "cd") == 0)
 		status = exec_command_cd(scan_state, active_branch, cmd);
-	else if (strcmp(cmd, "conninfo") == 0)
-		status = exec_command_conninfo(scan_state, active_branch);
+	else if (strcmp(cmd, "conninfo") == 0 || strcmp(cmd, "conninfo+") == 0)
+		status = exec_command_conninfo(scan_state, active_branch, cmd);
 	else if (pg_strcasecmp(cmd, "copy") == 0)
 		status = exec_command_copy(scan_state, active_branch);
 	else if (strcmp(cmd, "copyright") == 0)
@@ -643,47 +644,66 @@ exec_command_cd(PsqlScanState scan_state, bool active_branch, const char *cmd)
 }
 
 /*
- * \conninfo -- display information about the current connection
+ * \conninfo, \conninfo+ -- display information about the current connection
  */
 static backslashResult
-exec_command_conninfo(PsqlScanState scan_state, bool active_branch)
+exec_command_conninfo(PsqlScanState scan_state, bool active_branch, const char *cmd)
 {
+	bool		success = true;
+
 	if (active_branch)
 	{
 		char	   *db = PQdb(pset.db);
+		bool		show_verbose;
+
+		show_verbose = strchr(cmd, '+') ? true : false;
+
+		/*
+		 * \conninfo+
+		 */
+		if (show_verbose)
+			success = listConnectionInformation();
 
-		if (db == NULL)
-			printf(_("You are currently not connected to a database.\n"));
+		/*
+		 * \conninfo
+		 */
 		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));
-			}
+			if (db == NULL)
+				printf(_("You are currently not connected to a database.\n"));
 			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));
+				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
-					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));
+				{
+					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();
 			}
-			printSSLInfo();
-			printGSSInfo();
 		}
 	}
+	else
+		ignore_slash_options(scan_state);
 
-	return PSQL_CMD_SKIP_LINE;
+	return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
 }
 
 /*
diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index b6a4eb1..2ef3db0 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -26,6 +26,7 @@
 #include "fe_utils/mbprint.h"
 #include "fe_utils/print.h"
 #include "fe_utils/string_utils.h"
+#include "libpq/pqcomm.h"
 #include "settings.h"
 #include "variables.h"
 
@@ -901,6 +902,91 @@ error_return:
 	return false;
 }
 
+/*
+ * listConnectionInformation
+ *
+ * for \conninfo+
+ */
+bool
+listConnectionInformation(void)
+{
+	PGresult   *res;
+	PQExpBufferData buf;
+	printQueryOpt myopt = pset.popt;
+
+	char	   *host = PQhost(pset.db);
+	char	   *hostaddr = PQhostaddr(pset.db);
+	const char *protocol;
+	const char *cipher;
+	const char *compression;
+
+	initPQExpBuffer(&buf);
+
+	printfPQExpBuffer(&buf,
+					  "SELECT\n"
+					  "  pg_catalog.current_database() AS \"Database\",\n"
+					  "  '%s' AS \"Authenticated User\",\n",
+					  PQuser(pset.db));
+	if (pset.sversion >= 160000)
+		appendPQExpBuffer(&buf,
+						  "  pg_catalog.system_user() AS \"System User\",\n");
+	appendPQExpBuffer(&buf,
+					  "  pg_catalog.current_user() AS \"Current User\",\n"
+					  "  pg_catalog.session_user() AS \"Session User\",\n"
+					  "  pg_catalog.pg_backend_pid() AS \"Backend PID\",\n"
+					  "  pg_catalog.inet_server_addr() AS \"Server Address\",\n"
+					  "  pg_catalog.current_setting('port') AS \"Server Port\",\n"
+					  "  pg_catalog.inet_client_addr() AS \"Client Address\",\n"
+					  "  pg_catalog.inet_client_port() AS \"Client Port\",\n");
+	if (is_unixsock_path(host) && !(hostaddr && *hostaddr))
+		appendPQExpBuffer(&buf,
+						  "  '%s' AS \"Socket Directory\",\n",
+						  host);
+	else
+		appendPQExpBuffer(&buf,
+						  "  NULL AS \"Socket Directory\",\n");
+	appendPQExpBuffer(&buf,
+					  "  CASE\n"
+					  "    WHEN\n"
+					  "      pg_catalog.inet_server_addr() IS NULL\n"
+					  "      AND pg_catalog.inet_client_addr() IS NULL\n"
+					  "    THEN NULL\n"
+					  "    ELSE '%s'\n"
+					  "  END AS \"Host\"\n",
+					  host);
+	if (PQsslInUse(pset.db))
+	{
+		protocol = PQsslAttribute(pset.db, "protocol");
+		cipher = PQsslAttribute(pset.db, "cipher");
+		compression = PQsslAttribute(pset.db, "compression");
+		appendPQExpBuffer(&buf,
+						  "  ,'SSL' AS \"Encryption\",\n"
+						  "  '%s' AS \"Protocol\",\n"
+						  "  '%s' AS \"Cipher\",\n"
+						  "  '%s' AS \"Compression\"\n",
+						  protocol ? protocol : _("unknown"),
+						  cipher ? cipher : _("unknown"),
+						  (compression && strcmp(compression, "off") != 0) ? _("on") : _("off"));
+	}
+	if (PQgssEncInUse(pset.db))
+		appendPQExpBuffer(&buf,
+						  "  ,'GSSAPI' AS \"Encryption\"\n");
+	appendPQExpBuffer(&buf,
+					  "  ;");
+
+	res = PSQLexec(buf.data);
+	termPQExpBuffer(&buf);
+	if (!res)
+		return false;
+
+	myopt.title = _("Current Connection Information");
+	myopt.translate_header = true;
+
+	printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
+
+	PQclear(res);
+	return true;
+}
 
 /*
  * listAllDbs
diff --git a/src/bin/psql/describe.h b/src/bin/psql/describe.h
index 273f974..8a4e83f 100644
--- a/src/bin/psql/describe.h
+++ b/src/bin/psql/describe.h
@@ -64,6 +64,9 @@ extern bool listTSDictionaries(const char *pattern, bool verbose);
 /* \dFt */
 extern bool listTSTemplates(const char *pattern, bool verbose);
 
+/* \conninfo */
+extern bool listConnectionInformation(void);
+
 /* \l */
 extern bool listAllDbs(const char *pattern, bool verbose);
 
diff --git a/src/bin/psql/help.c b/src/bin/psql/help.c
index 4e79a81..2c5426d 100644
--- a/src/bin/psql/help.c
+++ b/src/bin/psql/help.c
@@ -310,7 +310,7 @@ slashUsage(unsigned short int pager)
 	else
 		HELP0("  \\c[onnect] {[DBNAME|- USER|- HOST|- PORT|-] | conninfo}\n"
 			  "                         connect to new database (currently no connection)\n");
-	HELP0("  \\conninfo              display information about current connection\n");
+	HELP0("  \\conninfo[+]           display information about current connection\n");
 	HELP0("  \\encoding [ENCODING]   show or set client encoding\n");
 	HELP0("  \\password [USERNAME]   securely change the password for a user\n");
 	HELP0("\n");


^ permalink  raw  reply  [nested|flat] 43+ messages in thread

* Re: Psql meta-command conninfo+
  2024-02-06 21:50 Re: Psql meta-command conninfo+ Nathan Bossart <[email protected]>
  2024-02-07 04:13 ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-07 12:35   ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-07 14:47     ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-07 16:40       ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-07 20:13         ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-08 11:01           ` Re: Psql meta-command conninfo+ Jim Jones <[email protected]>
  2024-02-08 15:50             ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-08 19:37               ` Re: Psql meta-command conninfo+ Jim Jones <[email protected]>
  2024-02-08 20:37                 ` Re: Psql meta-command conninfo+ Erik Wienhold <[email protected]>
@ 2024-02-08 23:34                   ` Jim Jones <[email protected]>
  2024-02-09 02:00                     ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  1 sibling, 1 reply; 43+ messages in thread

From: Jim Jones @ 2024-02-08 23:34 UTC (permalink / raw)
  To: Erik Wienhold <[email protected]>; +Cc: Maiquel Grassi <[email protected]>; Pavel Luzanov <[email protected]>; Nathan Bossart <[email protected]>; pgsql-hackers

Hi Erik

On 08.02.24 21:37, Erik Wienhold wrote:
> Modifiers such as + or S in \dS are not covered by autocompletion.
> src/bin/psql/tab-complete.c only specifies backslash commands in their
> basic form (without modifiers).
>
> (\dS<TAB> actually autocompletes to \ds to my surprise)
>
Aha... I never noticed it. Well, with most commands having 1 - 3
characters it is not a surprised I never used it :)
That "\dS<TAB>" autocompletes to "\ds " surprises me even more.
Thanks for pointing out!

-- 
Jim







^ permalink  raw  reply  [nested|flat] 43+ messages in thread

* RE: Psql meta-command conninfo+
  2024-02-06 21:50 Re: Psql meta-command conninfo+ Nathan Bossart <[email protected]>
  2024-02-07 04:13 ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-07 12:35   ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-07 14:47     ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-07 16:40       ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-07 20:13         ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-08 11:01           ` Re: Psql meta-command conninfo+ Jim Jones <[email protected]>
  2024-02-08 15:50             ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-08 19:37               ` Re: Psql meta-command conninfo+ Jim Jones <[email protected]>
  2024-02-08 20:37                 ` Re: Psql meta-command conninfo+ Erik Wienhold <[email protected]>
  2024-02-08 23:34                   ` Re: Psql meta-command conninfo+ Jim Jones <[email protected]>
@ 2024-02-09 02:00                     ` Maiquel Grassi <[email protected]>
  2024-02-09 02:41                       ` Re: Psql meta-command conninfo+ Nathan Bossart <[email protected]>
  0 siblings, 1 reply; 43+ messages in thread

From: Maiquel Grassi @ 2024-02-09 02:00 UTC (permalink / raw)
  To: Jim Jones <[email protected]>; Erik Wienhold <[email protected]>; +Cc: Pavel Luzanov <[email protected]>; Nathan Bossart <[email protected]>; pgsql-hackers

On 08.02.24 21:37, Erik Wienhold wrote:
>> Modifiers such as + or S in \dS are not covered by autocompletion.
>> src/bin/psql/tab-complete.c only specifies backslash commands in their
>> basic form (without modifiers).
>>
>> (\dS<TAB> actually autocompletes to \ds to my surprise)
>>
>Aha... I never noticed it. Well, with most commands having 1 - 3
>characters it is not a surprised I never used it :)
>That "\dS<TAB>" autocompletes to "\ds " surprises me even more.
>Thanks for pointing out!

--//--

Good evening, dear all!


Here is the mechanism that implements this:

https://github.com/postgres/postgres/blob/b619852086ed2b5df76631f5678f60d3bebd3745/src/bin/psql/tab-...

.
.
.
1673       /* Match the last N words before point, case-sensitively. */

1674 #define TailMatchesCS(...) \
1675       TailMatchesImpl(true, previous_words_count, previous_words, \

1676                               VA_ARGS_NARGS(__VA_ARGS__), __VA_ARGS__)
.
.
.
4824       else if (TailMatchesCS("\\ds*"))
4825             COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_sequences);
.
.
.

There is a rather large list of meta-commands that are handled by TailMatchesCS(...).

For example:
\ENCODING<TAB> autocompletes to \encoding
\eNcOdInG<TAB> autocompletes to \encoding
\dU<TAB> or \DU<TAB> autocompletes to \du

Including the command under discussion:
\CONNINFO<TAB> autocompletes to \conninfo

For the meta-commands[+], there is no autocomplete.

Regards,
Maiquel Grassi.


^ permalink  raw  reply  [nested|flat] 43+ messages in thread

* Re: Psql meta-command conninfo+
  2024-02-06 21:50 Re: Psql meta-command conninfo+ Nathan Bossart <[email protected]>
  2024-02-07 04:13 ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-07 12:35   ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-07 14:47     ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-07 16:40       ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-07 20:13         ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-08 11:01           ` Re: Psql meta-command conninfo+ Jim Jones <[email protected]>
  2024-02-08 15:50             ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-08 19:37               ` Re: Psql meta-command conninfo+ Jim Jones <[email protected]>
  2024-02-08 20:37                 ` Re: Psql meta-command conninfo+ Erik Wienhold <[email protected]>
  2024-02-08 23:34                   ` Re: Psql meta-command conninfo+ Jim Jones <[email protected]>
  2024-02-09 02:00                     ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
@ 2024-02-09 02:41                       ` Nathan Bossart <[email protected]>
  2024-02-09 08:30                         ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  0 siblings, 1 reply; 43+ messages in thread

From: Nathan Bossart @ 2024-02-09 02:41 UTC (permalink / raw)
  To: Maiquel Grassi <[email protected]>; +Cc: Jim Jones <[email protected]>; Erik Wienhold <[email protected]>; Pavel Luzanov <[email protected]>; pgsql-hackers

Sorry if this has been brought up, but I noticed that some of the
information is listed below the result set:

	postgres=# \conninfo+
	Current Connection Information
	-[ RECORD 1 ]------+---------
	Database           | postgres
	Authenticated User | nathan
	System User        | 
	Current User       | nathan
	Session User       | nathan
	Session PID        | 659410
	Server Version     | 17devel
	Server Address     | ::1
	Server Port        | 5432
	Client Address     | ::1
	Client Port        | 59886
	Socket Directory   | 
	Host               | ::1

	SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, compression: off)

Shouldn't we move this information into the result set?  Separately, does
the server version really belong here?  I'm not sure I would consider that
to be connection information.

-- 
Nathan Bossart
Amazon Web Services: https://aws.amazon.com






^ permalink  raw  reply  [nested|flat] 43+ messages in thread

* RE: Psql meta-command conninfo+
  2024-02-06 21:50 Re: Psql meta-command conninfo+ Nathan Bossart <[email protected]>
  2024-02-07 04:13 ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-07 12:35   ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-07 14:47     ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-07 16:40       ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-07 20:13         ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-08 11:01           ` Re: Psql meta-command conninfo+ Jim Jones <[email protected]>
  2024-02-08 15:50             ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-08 19:37               ` Re: Psql meta-command conninfo+ Jim Jones <[email protected]>
  2024-02-08 20:37                 ` Re: Psql meta-command conninfo+ Erik Wienhold <[email protected]>
  2024-02-08 23:34                   ` Re: Psql meta-command conninfo+ Jim Jones <[email protected]>
  2024-02-09 02:00                     ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-09 02:41                       ` Re: Psql meta-command conninfo+ Nathan Bossart <[email protected]>
@ 2024-02-09 08:30                         ` Maiquel Grassi <[email protected]>
  0 siblings, 0 replies; 43+ messages in thread

From: Maiquel Grassi @ 2024-02-09 08:30 UTC (permalink / raw)
  To: Nathan Bossart <[email protected]>; +Cc: Jim Jones <[email protected]>; Erik Wienhold <[email protected]>; Pavel Luzanov <[email protected]>; pgsql-hackers

>Sorry if this has been brought up, but I noticed that some of the

>information is listed below the result set:
>
  >      postgres=# \conninfo+
  >    Current Connection Information
  >      -[ RECORD 1 ]------+---------
  >     Database           | postgres
  >      Authenticated User | nathan
  >      System User        |
  >      Current User       | nathan
  >      Session User       | nathan
  >     Session PID        | 659410
  >      Server Version     | 17devel
  >      Server Address     | ::1
  >      Server Port        | 5432
  >      Client Address     | ::1
  >      Client Port        | 59886
  >      Socket Directory   |
  >      Host               | ::1

  >      SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, compression: off)

>Shouldn't we move this information into the result set?  Separately, does
>the server version really belong here?  I'm not sure I would consider that
>to be connection information.

--//--


Hi Nathan,

The "Server Version" information is closely related to the connection. However,
it does seem to be an element that does not belong to this set. I removed this
column and left only what is truly connection info.


Regarding the functions "printSSLInfo()" and "printGSSInfo()", I agree that we
should include them in the returned dataset (as two additional columns). A good
argument is that this will make more sense when using \x (Expanded display).
However, they are declared and defined within the "command.c" file. To make
calls to "printSSLInfo()" and "printGSSInfo()" within "describe.c", we would need
to move their declarations to a new header and create a new C file. I believe
something like "ssl_gss_info.h" and "ssl_gss_info.c". I'm not sure, but at first glance,
this is what occurs to me. Do you have any better or more concise suggestions
for resolving this?

Regards,
Maiquel Grassi.


Attachments:

  [application/octet-stream] v11-0001-psql-meta-command-conninfo-plus.patch (8.8K, ../../CP8P284MB24960077EA004AD1258EDE40EC4B2@CP8P284MB2496.BRAP284.PROD.OUTLOOK.COM/3-v11-0001-psql-meta-command-conninfo-plus.patch)
  download | inline diff:
diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml
index cc7d797..4e86ad9 100644
--- a/doc/src/sgml/ref/psql-ref.sgml
+++ b/doc/src/sgml/ref/psql-ref.sgml
@@ -1029,10 +1029,14 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g
       </varlistentry>
 
       <varlistentry id="app-psql-meta-command-conninfo">
-        <term><literal>\conninfo</literal></term>
+        <term><literal>\conninfo[+]</literal></term>
         <listitem>
         <para>
         Outputs information about the current database connection.
+        When no <literal>+</literal> is specified, it simply prints
+        a textual description of a few connection options.
+        When <literal>+</literal> is given, more complete information
+        is displayed as a table.
         </para>
         </listitem>
       </varlistentry>
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index 5c906e4..2c4ea74 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -68,7 +68,8 @@ static backslashResult exec_command_C(PsqlScanState scan_state, bool active_bran
 static backslashResult exec_command_connect(PsqlScanState scan_state, bool active_branch);
 static backslashResult exec_command_cd(PsqlScanState scan_state, bool active_branch,
 									   const char *cmd);
-static backslashResult exec_command_conninfo(PsqlScanState scan_state, bool active_branch);
+static backslashResult exec_command_conninfo(PsqlScanState scan_state, bool active_branch,
+											 const char *cmd);
 static backslashResult exec_command_copy(PsqlScanState scan_state, bool active_branch);
 static backslashResult exec_command_copyright(PsqlScanState scan_state, bool active_branch);
 static backslashResult exec_command_crosstabview(PsqlScanState scan_state, bool active_branch);
@@ -317,8 +318,8 @@ exec_command(const char *cmd,
 		status = exec_command_connect(scan_state, active_branch);
 	else if (strcmp(cmd, "cd") == 0)
 		status = exec_command_cd(scan_state, active_branch, cmd);
-	else if (strcmp(cmd, "conninfo") == 0)
-		status = exec_command_conninfo(scan_state, active_branch);
+	else if (strcmp(cmd, "conninfo") == 0 || strcmp(cmd, "conninfo+") == 0)
+		status = exec_command_conninfo(scan_state, active_branch, cmd);
 	else if (pg_strcasecmp(cmd, "copy") == 0)
 		status = exec_command_copy(scan_state, active_branch);
 	else if (strcmp(cmd, "copyright") == 0)
@@ -643,47 +644,70 @@ exec_command_cd(PsqlScanState scan_state, bool active_branch, const char *cmd)
 }
 
 /*
- * \conninfo -- display information about the current connection
+ * \conninfo, \conninfo+ -- display information about the current connection
  */
 static backslashResult
-exec_command_conninfo(PsqlScanState scan_state, bool active_branch)
+exec_command_conninfo(PsqlScanState scan_state, bool active_branch, const char *cmd)
 {
+	bool		success = true;
+
 	if (active_branch)
 	{
 		char	   *db = PQdb(pset.db);
+		bool		show_verbose;
 
-		if (db == NULL)
-			printf(_("You are currently not connected to a database.\n"));
-		else
+		show_verbose = strchr(cmd, '+') ? true : false;
+
+		/*
+		 * \conninfo+
+		 */
+		if (show_verbose)
 		{
-			char	   *host = PQhost(pset.db);
-			char	   *hostaddr = PQhostaddr(pset.db);
+			success = listConnectionInformation();
+			printSSLInfo();
+			printGSSInfo();
+		}
 
-			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));
-			}
+		/*
+		 * \conninfo
+		 */
+		else
+		{
+			if (db == NULL)
+				printf(_("You are currently not connected to a database.\n"));
 			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));
+				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
-					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));
+				{
+					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();
 			}
-			printSSLInfo();
-			printGSSInfo();
 		}
 	}
+	else
+		ignore_slash_options(scan_state);
 
-	return PSQL_CMD_SKIP_LINE;
+	return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
 }
 
 /*
diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index b6a4eb1..344664b 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -26,6 +26,7 @@
 #include "fe_utils/mbprint.h"
 #include "fe_utils/print.h"
 #include "fe_utils/string_utils.h"
+#include "libpq/pqcomm.h"
 #include "settings.h"
 #include "variables.h"
 
@@ -901,6 +902,69 @@ error_return:
 	return false;
 }
 
+/*
+ * listConnectionInformation
+ *
+ * for \conninfo+
+ */
+bool
+listConnectionInformation(void)
+{
+	PGresult   *res;
+	PQExpBufferData buf;
+	printQueryOpt myopt = pset.popt;
+
+	char	   *host = PQhost(pset.db);
+	char	   *hostaddr = PQhostaddr(pset.db);
+
+	initPQExpBuffer(&buf);
+
+	printfPQExpBuffer(&buf,
+					  "SELECT\n"
+					  "  pg_catalog.current_database() AS \"Database\",\n"
+					  "  '%s' AS \"Authenticated User\",\n",
+					  PQuser(pset.db));
+	if (pset.sversion >= 160000)
+		appendPQExpBuffer(&buf,
+						  "  pg_catalog.system_user() AS \"System User\",\n");
+	appendPQExpBuffer(&buf,
+					  "  pg_catalog.current_user() AS \"Current User\",\n"
+					  "  pg_catalog.session_user() AS \"Session User\",\n"
+					  "  pg_catalog.pg_backend_pid() AS \"Session PID\",\n"
+					  "  pg_catalog.inet_server_addr() AS \"Server Address\",\n"
+					  "  pg_catalog.current_setting('port') AS \"Server Port\",\n"
+					  "  pg_catalog.inet_client_addr() AS \"Client Address\",\n"
+					  "  pg_catalog.inet_client_port() AS \"Client Port\",\n");
+	if (is_unixsock_path(host) && !(hostaddr && *hostaddr))
+		appendPQExpBuffer(&buf,
+						  "  '%s' AS \"Socket Directory\",\n",
+						  host);
+	else
+		appendPQExpBuffer(&buf,
+						  "  NULL AS \"Socket Directory\",\n");
+	appendPQExpBuffer(&buf,
+					  "  CASE\n"
+					  "    WHEN\n"
+					  "      pg_catalog.inet_server_addr() IS NULL\n"
+					  "      AND pg_catalog.inet_client_addr() IS NULL\n"
+					  "    THEN NULL\n"
+					  "    ELSE '%s'\n"
+					  "  END AS \"Host\";",
+					  host);
+
+	res = PSQLexec(buf.data);
+	termPQExpBuffer(&buf);
+	if (!res)
+		return false;
+
+	myopt.title = _("Current Connection Information");
+	myopt.translate_header = true;
+
+	printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
+
+	PQclear(res);
+	return true;
+}
 
 /*
  * listAllDbs
diff --git a/src/bin/psql/describe.h b/src/bin/psql/describe.h
index 273f974..8a4e83f 100644
--- a/src/bin/psql/describe.h
+++ b/src/bin/psql/describe.h
@@ -64,6 +64,9 @@ extern bool listTSDictionaries(const char *pattern, bool verbose);
 /* \dFt */
 extern bool listTSTemplates(const char *pattern, bool verbose);
 
+/* \conninfo */
+extern bool listConnectionInformation(void);
+
 /* \l */
 extern bool listAllDbs(const char *pattern, bool verbose);
 
diff --git a/src/bin/psql/help.c b/src/bin/psql/help.c
index 4e79a81..2c5426d 100644
--- a/src/bin/psql/help.c
+++ b/src/bin/psql/help.c
@@ -310,7 +310,7 @@ slashUsage(unsigned short int pager)
 	else
 		HELP0("  \\c[onnect] {[DBNAME|- USER|- HOST|- PORT|-] | conninfo}\n"
 			  "                         connect to new database (currently no connection)\n");
-	HELP0("  \\conninfo              display information about current connection\n");
+	HELP0("  \\conninfo[+]           display information about current connection\n");
 	HELP0("  \\encoding [ENCODING]   show or set client encoding\n");
 	HELP0("  \\password [USERNAME]   securely change the password for a user\n");
 	HELP0("\n");


  [application/octet-stream] v11-0001-psql-meta-command-conninfo-plus.patch (8.8K, ../../CP8P284MB24960077EA004AD1258EDE40EC4B2@CP8P284MB2496.BRAP284.PROD.OUTLOOK.COM/4-v11-0001-psql-meta-command-conninfo-plus.patch)
  download | inline diff:
diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml
index cc7d797..4e86ad9 100644
--- a/doc/src/sgml/ref/psql-ref.sgml
+++ b/doc/src/sgml/ref/psql-ref.sgml
@@ -1029,10 +1029,14 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g
       </varlistentry>
 
       <varlistentry id="app-psql-meta-command-conninfo">
-        <term><literal>\conninfo</literal></term>
+        <term><literal>\conninfo[+]</literal></term>
         <listitem>
         <para>
         Outputs information about the current database connection.
+        When no <literal>+</literal> is specified, it simply prints
+        a textual description of a few connection options.
+        When <literal>+</literal> is given, more complete information
+        is displayed as a table.
         </para>
         </listitem>
       </varlistentry>
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index 5c906e4..2c4ea74 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -68,7 +68,8 @@ static backslashResult exec_command_C(PsqlScanState scan_state, bool active_bran
 static backslashResult exec_command_connect(PsqlScanState scan_state, bool active_branch);
 static backslashResult exec_command_cd(PsqlScanState scan_state, bool active_branch,
 									   const char *cmd);
-static backslashResult exec_command_conninfo(PsqlScanState scan_state, bool active_branch);
+static backslashResult exec_command_conninfo(PsqlScanState scan_state, bool active_branch,
+											 const char *cmd);
 static backslashResult exec_command_copy(PsqlScanState scan_state, bool active_branch);
 static backslashResult exec_command_copyright(PsqlScanState scan_state, bool active_branch);
 static backslashResult exec_command_crosstabview(PsqlScanState scan_state, bool active_branch);
@@ -317,8 +318,8 @@ exec_command(const char *cmd,
 		status = exec_command_connect(scan_state, active_branch);
 	else if (strcmp(cmd, "cd") == 0)
 		status = exec_command_cd(scan_state, active_branch, cmd);
-	else if (strcmp(cmd, "conninfo") == 0)
-		status = exec_command_conninfo(scan_state, active_branch);
+	else if (strcmp(cmd, "conninfo") == 0 || strcmp(cmd, "conninfo+") == 0)
+		status = exec_command_conninfo(scan_state, active_branch, cmd);
 	else if (pg_strcasecmp(cmd, "copy") == 0)
 		status = exec_command_copy(scan_state, active_branch);
 	else if (strcmp(cmd, "copyright") == 0)
@@ -643,47 +644,70 @@ exec_command_cd(PsqlScanState scan_state, bool active_branch, const char *cmd)
 }
 
 /*
- * \conninfo -- display information about the current connection
+ * \conninfo, \conninfo+ -- display information about the current connection
  */
 static backslashResult
-exec_command_conninfo(PsqlScanState scan_state, bool active_branch)
+exec_command_conninfo(PsqlScanState scan_state, bool active_branch, const char *cmd)
 {
+	bool		success = true;
+
 	if (active_branch)
 	{
 		char	   *db = PQdb(pset.db);
+		bool		show_verbose;
 
-		if (db == NULL)
-			printf(_("You are currently not connected to a database.\n"));
-		else
+		show_verbose = strchr(cmd, '+') ? true : false;
+
+		/*
+		 * \conninfo+
+		 */
+		if (show_verbose)
 		{
-			char	   *host = PQhost(pset.db);
-			char	   *hostaddr = PQhostaddr(pset.db);
+			success = listConnectionInformation();
+			printSSLInfo();
+			printGSSInfo();
+		}
 
-			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));
-			}
+		/*
+		 * \conninfo
+		 */
+		else
+		{
+			if (db == NULL)
+				printf(_("You are currently not connected to a database.\n"));
 			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));
+				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
-					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));
+				{
+					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();
 			}
-			printSSLInfo();
-			printGSSInfo();
 		}
 	}
+	else
+		ignore_slash_options(scan_state);
 
-	return PSQL_CMD_SKIP_LINE;
+	return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
 }
 
 /*
diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index b6a4eb1..344664b 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -26,6 +26,7 @@
 #include "fe_utils/mbprint.h"
 #include "fe_utils/print.h"
 #include "fe_utils/string_utils.h"
+#include "libpq/pqcomm.h"
 #include "settings.h"
 #include "variables.h"
 
@@ -901,6 +902,69 @@ error_return:
 	return false;
 }
 
+/*
+ * listConnectionInformation
+ *
+ * for \conninfo+
+ */
+bool
+listConnectionInformation(void)
+{
+	PGresult   *res;
+	PQExpBufferData buf;
+	printQueryOpt myopt = pset.popt;
+
+	char	   *host = PQhost(pset.db);
+	char	   *hostaddr = PQhostaddr(pset.db);
+
+	initPQExpBuffer(&buf);
+
+	printfPQExpBuffer(&buf,
+					  "SELECT\n"
+					  "  pg_catalog.current_database() AS \"Database\",\n"
+					  "  '%s' AS \"Authenticated User\",\n",
+					  PQuser(pset.db));
+	if (pset.sversion >= 160000)
+		appendPQExpBuffer(&buf,
+						  "  pg_catalog.system_user() AS \"System User\",\n");
+	appendPQExpBuffer(&buf,
+					  "  pg_catalog.current_user() AS \"Current User\",\n"
+					  "  pg_catalog.session_user() AS \"Session User\",\n"
+					  "  pg_catalog.pg_backend_pid() AS \"Session PID\",\n"
+					  "  pg_catalog.inet_server_addr() AS \"Server Address\",\n"
+					  "  pg_catalog.current_setting('port') AS \"Server Port\",\n"
+					  "  pg_catalog.inet_client_addr() AS \"Client Address\",\n"
+					  "  pg_catalog.inet_client_port() AS \"Client Port\",\n");
+	if (is_unixsock_path(host) && !(hostaddr && *hostaddr))
+		appendPQExpBuffer(&buf,
+						  "  '%s' AS \"Socket Directory\",\n",
+						  host);
+	else
+		appendPQExpBuffer(&buf,
+						  "  NULL AS \"Socket Directory\",\n");
+	appendPQExpBuffer(&buf,
+					  "  CASE\n"
+					  "    WHEN\n"
+					  "      pg_catalog.inet_server_addr() IS NULL\n"
+					  "      AND pg_catalog.inet_client_addr() IS NULL\n"
+					  "    THEN NULL\n"
+					  "    ELSE '%s'\n"
+					  "  END AS \"Host\";",
+					  host);
+
+	res = PSQLexec(buf.data);
+	termPQExpBuffer(&buf);
+	if (!res)
+		return false;
+
+	myopt.title = _("Current Connection Information");
+	myopt.translate_header = true;
+
+	printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
+
+	PQclear(res);
+	return true;
+}
 
 /*
  * listAllDbs
diff --git a/src/bin/psql/describe.h b/src/bin/psql/describe.h
index 273f974..8a4e83f 100644
--- a/src/bin/psql/describe.h
+++ b/src/bin/psql/describe.h
@@ -64,6 +64,9 @@ extern bool listTSDictionaries(const char *pattern, bool verbose);
 /* \dFt */
 extern bool listTSTemplates(const char *pattern, bool verbose);
 
+/* \conninfo */
+extern bool listConnectionInformation(void);
+
 /* \l */
 extern bool listAllDbs(const char *pattern, bool verbose);
 
diff --git a/src/bin/psql/help.c b/src/bin/psql/help.c
index 4e79a81..2c5426d 100644
--- a/src/bin/psql/help.c
+++ b/src/bin/psql/help.c
@@ -310,7 +310,7 @@ slashUsage(unsigned short int pager)
 	else
 		HELP0("  \\c[onnect] {[DBNAME|- USER|- HOST|- PORT|-] | conninfo}\n"
 			  "                         connect to new database (currently no connection)\n");
-	HELP0("  \\conninfo              display information about current connection\n");
+	HELP0("  \\conninfo[+]           display information about current connection\n");
 	HELP0("  \\encoding [ENCODING]   show or set client encoding\n");
 	HELP0("  \\password [USERNAME]   securely change the password for a user\n");
 	HELP0("\n");


^ permalink  raw  reply  [nested|flat] 43+ messages in thread

* RE: Psql meta-command conninfo+
  2024-02-06 21:50 Re: Psql meta-command conninfo+ Nathan Bossart <[email protected]>
  2024-02-07 04:13 ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-07 12:35   ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-07 14:47     ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-07 16:40       ` Re: Psql meta-command conninfo+ Pavel Luzanov <[email protected]>
  2024-02-07 20:13         ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-08 11:01           ` Re: Psql meta-command conninfo+ Jim Jones <[email protected]>
  2024-02-08 15:50             ` RE: Psql meta-command conninfo+ Maiquel Grassi <[email protected]>
  2024-02-08 19:37               ` Re: Psql meta-command conninfo+ Jim Jones <[email protected]>
@ 2024-02-08 20:47                 ` Maiquel Grassi <[email protected]>
  1 sibling, 0 replies; 43+ messages in thread

From: Maiquel Grassi @ 2024-02-08 20:47 UTC (permalink / raw)
  To: Jim Jones <[email protected]>; Pavel Luzanov <[email protected]>; Nathan Bossart <[email protected]>; +Cc: Erik Wienhold <[email protected]>; pgsql-hackers

> v8 no longer throws a permission denied error for non-superusers - it is
> IMHO much nicer this way.
>
> $ /usr/local/postgres-dev/bin/psql postgres -p 5432 -h 127.0.0.1 -U jim
> psql (17devel)
> Type "help" for help.
>
> postgres=# \x
> Expanded display is on.
> postgres=# \conninfo+
> Current Connection Information
> -[ RECORD 1 ]------+----------
> Database           | postgres
> Authenticated User | jim
> System User        |
> Current User       | jim
> Session User       | jim
> Session PID        | 1321493
> Server Version     | 17devel
> Server Address     | 127.0.0.1
> Server Port        | 5432
> Client Address     | 127.0.0.1
> Client Port        | 49366
> Socket Directory   |
> Host               | 127.0.0.1
>
> postgres=# SET ROLE foo;
> SET
> postgres=> \conninfo+
> Current Connection Information
> -[ RECORD 1 ]------+----------
> Database           | postgres
> Authenticated User | jim
> System User        |
> Current User       | foo
> Session User       | jim
> Session PID        | 1321493
> Server Version     | 17devel
> Server Address     | 127.0.0.1
> Server Port        | 5432
> Client Address     | 127.0.0.1
> Client Port        | 49366
> Socket Directory   |
> Host               | 127.0.0.1
>
> The patch now applies cleanly.
>
> One thing I just noticed. The psql autocomplete feature does not suggest
> the new + option of \conninfo. For instance, when typing "\connin[TAB]"
> it automatically autocompletes to "\conninfo ". I guess it should also
> be included in this patch.
>
> I can do a more thorough review of the code when you add the
> documentation and tests to the patch.
>
> Thanks!

--//--

Hi Jim,


It's not a psql standard to use tab-complete for commands ending with +.
You can verify this in the /* psql's backslash commands. */ section of
the file "/src/bin/psql/tab-complete.c".

https://github.com/postgres/postgres/blob/fdfb92c0307c95eba10854196628d88e6708901e/src/bin/psql/tab-...

In v9, I started the documentation work and am open to suggestions.


> "I can do a more thorough review of the code when you add the

> documentation and tests to the patch."

Soon I'll be developing the tests. And that will be welcome.

Thanks a lot!

Regards,
Maiquel Grassi.


Attachments:

  [application/octet-stream] v9-0001-psql-meta-command-conninfo-plus.patch (9.0K, ../../CP8P284MB249614E7926043EEF7F063EBEC442@CP8P284MB2496.BRAP284.PROD.OUTLOOK.COM/3-v9-0001-psql-meta-command-conninfo-plus.patch)
  download | inline diff:
diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml
index cc7d797..4e86ad9 100644
--- a/doc/src/sgml/ref/psql-ref.sgml
+++ b/doc/src/sgml/ref/psql-ref.sgml
@@ -1029,10 +1029,14 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g
       </varlistentry>
 
       <varlistentry id="app-psql-meta-command-conninfo">
-        <term><literal>\conninfo</literal></term>
+        <term><literal>\conninfo[+]</literal></term>
         <listitem>
         <para>
         Outputs information about the current database connection.
+        When no <literal>+</literal> is specified, it simply prints
+        a textual description of a few connection options.
+        When <literal>+</literal> is given, more complete information
+        is displayed as a table.
         </para>
         </listitem>
       </varlistentry>
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index 5c906e4..bf93cb1 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -68,7 +68,8 @@ static backslashResult exec_command_C(PsqlScanState scan_state, bool active_bran
 static backslashResult exec_command_connect(PsqlScanState scan_state, bool active_branch);
 static backslashResult exec_command_cd(PsqlScanState scan_state, bool active_branch,
 									   const char *cmd);
-static backslashResult exec_command_conninfo(PsqlScanState scan_state, bool active_branch);
+static backslashResult exec_command_conninfo(PsqlScanState scan_state, bool active_branch,
+											 const char *cmd);
 static backslashResult exec_command_copy(PsqlScanState scan_state, bool active_branch);
 static backslashResult exec_command_copyright(PsqlScanState scan_state, bool active_branch);
 static backslashResult exec_command_crosstabview(PsqlScanState scan_state, bool active_branch);
@@ -317,8 +318,8 @@ exec_command(const char *cmd,
 		status = exec_command_connect(scan_state, active_branch);
 	else if (strcmp(cmd, "cd") == 0)
 		status = exec_command_cd(scan_state, active_branch, cmd);
-	else if (strcmp(cmd, "conninfo") == 0)
-		status = exec_command_conninfo(scan_state, active_branch);
+	else if (strcmp(cmd, "conninfo") == 0 || strcmp(cmd, "conninfo+") == 0)
+		status = exec_command_conninfo(scan_state, active_branch, cmd);
 	else if (pg_strcasecmp(cmd, "copy") == 0)
 		status = exec_command_copy(scan_state, active_branch);
 	else if (strcmp(cmd, "copyright") == 0)
@@ -643,47 +644,74 @@ exec_command_cd(PsqlScanState scan_state, bool active_branch, const char *cmd)
 }
 
 /*
- * \conninfo -- display information about the current connection
+ * \conninfo, \conninfo+ -- display information about the current connection
  */
 static backslashResult
-exec_command_conninfo(PsqlScanState scan_state, bool active_branch)
+exec_command_conninfo(PsqlScanState scan_state, bool active_branch, const char *cmd)
 {
+	bool		success = true;
+
 	if (active_branch)
 	{
 		char	   *db = PQdb(pset.db);
+		char	   *pattern;
+		bool		show_verbose;
 
-		if (db == NULL)
-			printf(_("You are currently not connected to a database.\n"));
-		else
+		pattern = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, true);
+
+		show_verbose = strchr(cmd, '+') ? true : false;
+
+		/*
+		 * \conninfo+
+		 */
+		if (show_verbose)
 		{
-			char	   *host = PQhost(pset.db);
-			char	   *hostaddr = PQhostaddr(pset.db);
+			success = listConnectionInformation(pattern);
+			free(pattern);
+			printSSLInfo();
+			printGSSInfo();
+		}
 
-			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));
-			}
+		/*
+		 * \conninfo
+		 */
+		else
+		{
+			if (db == NULL)
+				printf(_("You are currently not connected to a database.\n"));
 			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));
+				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
-					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));
+				{
+					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();
 			}
-			printSSLInfo();
-			printGSSInfo();
 		}
 	}
+	else
+		ignore_slash_options(scan_state);
 
-	return PSQL_CMD_SKIP_LINE;
+	return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
 }
 
 /*
diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index b6a4eb1..13f0d1f 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -26,6 +26,7 @@
 #include "fe_utils/mbprint.h"
 #include "fe_utils/print.h"
 #include "fe_utils/string_utils.h"
+#include "libpq/pqcomm.h"
 #include "settings.h"
 #include "variables.h"
 
@@ -901,6 +902,70 @@ error_return:
 	return false;
 }
 
+/*
+ * listConnectionInformation
+ *
+ * for \conninfo+
+ */
+bool
+listConnectionInformation(const char *pattern)
+{
+	PGresult   *res;
+	PQExpBufferData buf;
+	printQueryOpt myopt = pset.popt;
+
+	char	   *host = PQhost(pset.db);
+	char	   *hostaddr = PQhostaddr(pset.db);
+
+	initPQExpBuffer(&buf);
+
+	printfPQExpBuffer(&buf,
+					  "SELECT\n"
+					  "  pg_catalog.current_database() AS \"Database\",\n"
+					  "  '%s' AS \"Authenticated User\",\n",
+					  PQuser(pset.db));
+	if (pset.sversion >= 160000)
+		appendPQExpBuffer(&buf,
+						  "  pg_catalog.system_user() AS \"System User\",\n");
+	appendPQExpBuffer(&buf,
+					  "  pg_catalog.current_user() AS \"Current User\",\n"
+					  "  pg_catalog.session_user() AS \"Session User\",\n"
+					  "  pg_catalog.pg_backend_pid() AS \"Session PID\",\n"
+					  "  pg_catalog.current_setting('server_version') AS \"Server Version\",\n"
+					  "  pg_catalog.inet_server_addr() AS \"Server Address\",\n"
+					  "  pg_catalog.current_setting('port') AS \"Server Port\",\n"
+					  "  pg_catalog.inet_client_addr() AS \"Client Address\",\n"
+					  "  pg_catalog.inet_client_port() AS \"Client Port\",\n");
+	if (is_unixsock_path(host) && !(hostaddr && *hostaddr))
+		appendPQExpBuffer(&buf,
+						  "  '%s' AS \"Socket Directory\",\n",
+						  host);
+	else
+		appendPQExpBuffer(&buf,
+						  "  NULL AS \"Socket Directory\",\n");
+	appendPQExpBuffer(&buf,
+					  "  CASE\n"
+					  "    WHEN\n"
+					  "      pg_catalog.inet_server_addr() IS NULL\n"
+					  "      AND pg_catalog.inet_client_addr() IS NULL\n"
+					  "    THEN NULL\n"
+					  "    ELSE '%s'\n"
+					  "  END AS \"Host\";",
+					  host);
+
+	res = PSQLexec(buf.data);
+	termPQExpBuffer(&buf);
+	if (!res)
+		return false;
+
+	myopt.title = _("Current Connection Information");
+	myopt.translate_header = true;
+
+	printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
+
+	PQclear(res);
+	return true;
+}
 
 /*
  * listAllDbs
diff --git a/src/bin/psql/describe.h b/src/bin/psql/describe.h
index 273f974..779918b 100644
--- a/src/bin/psql/describe.h
+++ b/src/bin/psql/describe.h
@@ -149,4 +149,7 @@ extern bool listOpFamilyFunctions(const char *access_method_pattern,
 /* \dl or \lo_list */
 extern bool listLargeObjects(bool verbose);
 
+/* \conninfo */
+extern bool listConnectionInformation(const char *pattern);
+
 #endif							/* DESCRIBE_H */
diff --git a/src/bin/psql/help.c b/src/bin/psql/help.c
index 4e79a81..2c5426d 100644
--- a/src/bin/psql/help.c
+++ b/src/bin/psql/help.c
@@ -310,7 +310,7 @@ slashUsage(unsigned short int pager)
 	else
 		HELP0("  \\c[onnect] {[DBNAME|- USER|- HOST|- PORT|-] | conninfo}\n"
 			  "                         connect to new database (currently no connection)\n");
-	HELP0("  \\conninfo              display information about current connection\n");
+	HELP0("  \\conninfo[+]           display information about current connection\n");
 	HELP0("  \\encoding [ENCODING]   show or set client encoding\n");
 	HELP0("  \\password [USERNAME]   securely change the password for a user\n");
 	HELP0("\n");


^ permalink  raw  reply  [nested|flat] 43+ messages in thread

* Re: COALESCE patch
@ 2026-07-10 09:26 Laurenz Albe <[email protected]>
  2026-07-10 12:54 ` Re: COALESCE patch prankware <[email protected]>
  0 siblings, 1 reply; 43+ messages in thread

From: Laurenz Albe @ 2026-07-10 09:26 UTC (permalink / raw)
  To: prankware <[email protected]>; [email protected]

On Tue, 2026-06-30 at 16:48 +0300, prankware wrote:

> The planner ignores column statistics when an equality has a COALESCE
> expression on one side. For a clause like COALESCE(a, b) = $1, or a join on
> COALESCE(t1.a, t1.b) = COALESCE(t2.c, t2.d), there are no statistics on the
> COALESCE node itself, so eqsel() and eqjoinsel() return the generic 0.005
> estimate while the per-column stats for a, b, c and d sit unused. The only way
> around this today is an expression index or extended statistics on that exact
> expression, which doesn't scale across many different COALESCE clauses.
> estimate_hash_bucket_stats() has the same gap: a COALESCE hash key gets a
> default ndistinct and therefore a default bucket size. Since these expressions
> are common in joins and filters over nullable or fallback columns, the default
> estimate can be far enough off to flip the join order or join method.
>
> The idea is to estimate straight from the existing per-column stats, with no
> extra statistics object. COALESCE(arg_1, ..., arg_n) returns arg_i only when
> arg_1 .. arg_{i-1} are all NULL, so the chance of reaching branch i is the
> product of stanullfrac over the earlier branches. Selectivity of
> COALESCE(l_1..l_M) = COALESCE(r_1..r_N) is then the sum over branch pairs of
> P(reach l_i) * P(reach r_j) * sel(l_i = r_j), and each sel(l_i = r_j) is a
> recursive call back into eqsel()/eqjoinsel(). A non-COALESCE side is treated as
> a one-branch list, so scalar COALESCE(a, b) = const falls out of the same code,
> and the same decomposition feeds estimate_hash_bucket_stats(). If any branch is
> missing stats, the code bails and today's behavior is unchanged.
>
> Feedback is welcome.

I think the idea is good, and the performance cost is incurred only when
coalesce() expressions are present.  I am a bit worried about the execution
time for queries that join two tables over lengthy coalesce clauses, as the
cost is O(n*m) because of the sum.  But I think that such queries are extremely
rare, so I don't worry too much.

I found that the estimates are good if I use expressions like
"coalesce(col1, col2)" in my query, but the estimates are as bad as before
with the common case of "coalesce(col, constant)":

CREATE TABLE b (col1 integer);

/* three quarters NULL, the rest evenly distributed */
INSERT INTO b
   SELECT CASE WHEN random() >= 0.75 THEN random() * 1000 + 1 END
   FROM generate_series(1, 10000);

VACUUM (ANALYZE) b;

/* force a hash join regardless of the estimates */
SET work_mem = '512MB';
SET enable_mergejoin = off;
SET enable_nestloop = off;


EXPLAIN (ANALYZE, SUMMARY OFF, BUFFERS OFF)
SELECT *
FROM b AS b1
   JOIN b AS b2 ON coalesce(b1.col1, 0) = coalesce(b2.col1, 0);

 Hash Join  (... rows=500000 ...) (actual ... rows=55125006.00 ...)
   Hash Cond: (COALESCE(b1.col1, 0) = COALESCE(b2.col1, 0))
   ->  Seq Scan on b b1  (... rows=10000 ...) (actual ... rows=10000.00 ..)
   ->  Hash  (... rows=10000 ...) (actual ... rows=10000.00 ...)
         Buckets: 16384  Batches: 1  Memory Usage: 451kB
         ->  Seq Scan on b b2  (... rows=10000 ...) (actual ... rows=10000.00 ...)

EXPLAIN (ANALYZE, SUMMARY OFF, BUFFERS OFF)
SELECT *
FROM b AS b1
   JOIN b AS b2 ON coalesce(b1.col1, 0) = coalesce(b2.col1, 1);

 Hash Join  (... rows=500000 ...) (actual ... rows=16654.00 ...)
   Hash Cond: (COALESCE(b1.col1, 0) = COALESCE(b2.col1, 1))
   ->  Seq Scan on b b1  (... rows=10000 ...) (actual ... rows=10000.00 ...)
   ->  Hash  (... rows=10000 ...) (actual ... rows=10000.00 ...)
         Buckets: 16384  Batches: 1  Memory Usage: 451kB
         ->  Seq Scan on b b2  (... rows=10000 ...) (actual ... rows=10000.00 ...)


EXPLAIN (ANALYZE, SUMMARY OFF, BUFFERS OFF)
SELECT * FROM b WHERE coalesce(col1, 0) = 0;

 Seq Scan on b  (... rows=40 ...) (actual ... rows=7424.00 ...)
   Filter: (COALESCE(col1, 0) = 0)
   Rows Removed by Filter: 2576

EXPLAIN (ANALYZE, SUMMARY OFF, BUFFERS OFF)
SELECT * FROM b WHERE coalesce(col1, 1) = 0;

 Seq Scan on b  (... rows=40 ...) (actual ... rows=0.00 ...)
   Filter: (COALESCE(col1, 1) = 0)
   Rows Removed by Filter: 10000


I think that the patch would be much more useful if it could improve
such estimates.

Yours,
Laurenz Albe






^ permalink  raw  reply  [nested|flat] 43+ messages in thread

* Re: COALESCE patch
  2026-07-10 09:26 Re: COALESCE patch Laurenz Albe <[email protected]>
@ 2026-07-10 12:54 ` prankware <[email protected]>
  0 siblings, 0 replies; 43+ messages in thread

From: prankware @ 2026-07-10 12:54 UTC (permalink / raw)
  To: [email protected]; +Cc: Laurenz Albe <[email protected]>; [email protected]

Thanks for the review — the test cases were very helpful.
You're right that v1 didn't improve the coalesce(col, const) case. The
reason is that a comparison of two constants got the default 0.005
instead of its real result, and joins with a constant on both sides
were skipped entirely.
v2 (attached) fixes both, and these four examples now estimate close
to the actual row counts.

Regards,
Egor Savelev,
Tantor Labs LLC,
https://tantorlabs.com

пт, 10 июл. 2026 г. в 12:27, Laurenz Albe <[email protected]>:
>
> On Tue, 2026-06-30 at 16:48 +0300, prankware wrote:
>
> > The planner ignores column statistics when an equality has a COALESCE
> > expression on one side. For a clause like COALESCE(a, b) = $1, or a join on
> > COALESCE(t1.a, t1.b) = COALESCE(t2.c, t2.d), there are no statistics on the
> > COALESCE node itself, so eqsel() and eqjoinsel() return the generic 0.005
> > estimate while the per-column stats for a, b, c and d sit unused. The only way
> > around this today is an expression index or extended statistics on that exact
> > expression, which doesn't scale across many different COALESCE clauses.
> > estimate_hash_bucket_stats() has the same gap: a COALESCE hash key gets a
> > default ndistinct and therefore a default bucket size. Since these expressions
> > are common in joins and filters over nullable or fallback columns, the default
> > estimate can be far enough off to flip the join order or join method.
> >
> > The idea is to estimate straight from the existing per-column stats, with no
> > extra statistics object. COALESCE(arg_1, ..., arg_n) returns arg_i only when
> > arg_1 .. arg_{i-1} are all NULL, so the chance of reaching branch i is the
> > product of stanullfrac over the earlier branches. Selectivity of
> > COALESCE(l_1..l_M) = COALESCE(r_1..r_N) is then the sum over branch pairs of
> > P(reach l_i) * P(reach r_j) * sel(l_i = r_j), and each sel(l_i = r_j) is a
> > recursive call back into eqsel()/eqjoinsel(). A non-COALESCE side is treated as
> > a one-branch list, so scalar COALESCE(a, b) = const falls out of the same code,
> > and the same decomposition feeds estimate_hash_bucket_stats(). If any branch is
> > missing stats, the code bails and today's behavior is unchanged.
> >
> > Feedback is welcome.
>
> I think the idea is good, and the performance cost is incurred only when
> coalesce() expressions are present.  I am a bit worried about the execution
> time for queries that join two tables over lengthy coalesce clauses, as the
> cost is O(n*m) because of the sum.  But I think that such queries are extremely
> rare, so I don't worry too much.
>
> I found that the estimates are good if I use expressions like
> "coalesce(col1, col2)" in my query, but the estimates are as bad as before
> with the common case of "coalesce(col, constant)":
>
> CREATE TABLE b (col1 integer);
>
> /* three quarters NULL, the rest evenly distributed */
> INSERT INTO b
>    SELECT CASE WHEN random() >= 0.75 THEN random() * 1000 + 1 END
>    FROM generate_series(1, 10000);
>
> VACUUM (ANALYZE) b;
>
> /* force a hash join regardless of the estimates */
> SET work_mem = '512MB';
> SET enable_mergejoin = off;
> SET enable_nestloop = off;
>
>
> EXPLAIN (ANALYZE, SUMMARY OFF, BUFFERS OFF)
> SELECT *
> FROM b AS b1
>    JOIN b AS b2 ON coalesce(b1.col1, 0) = coalesce(b2.col1, 0);
>
>  Hash Join  (... rows=500000 ...) (actual ... rows=55125006.00 ...)
>    Hash Cond: (COALESCE(b1.col1, 0) = COALESCE(b2.col1, 0))
>    ->  Seq Scan on b b1  (... rows=10000 ...) (actual ... rows=10000.00 ..)
>    ->  Hash  (... rows=10000 ...) (actual ... rows=10000.00 ...)
>          Buckets: 16384  Batches: 1  Memory Usage: 451kB
>          ->  Seq Scan on b b2  (... rows=10000 ...) (actual ... rows=10000.00 ...)
>
> EXPLAIN (ANALYZE, SUMMARY OFF, BUFFERS OFF)
> SELECT *
> FROM b AS b1
>    JOIN b AS b2 ON coalesce(b1.col1, 0) = coalesce(b2.col1, 1);
>
>  Hash Join  (... rows=500000 ...) (actual ... rows=16654.00 ...)
>    Hash Cond: (COALESCE(b1.col1, 0) = COALESCE(b2.col1, 1))
>    ->  Seq Scan on b b1  (... rows=10000 ...) (actual ... rows=10000.00 ...)
>    ->  Hash  (... rows=10000 ...) (actual ... rows=10000.00 ...)
>          Buckets: 16384  Batches: 1  Memory Usage: 451kB
>          ->  Seq Scan on b b2  (... rows=10000 ...) (actual ... rows=10000.00 ...)
>
>
> EXPLAIN (ANALYZE, SUMMARY OFF, BUFFERS OFF)
> SELECT * FROM b WHERE coalesce(col1, 0) = 0;
>
>  Seq Scan on b  (... rows=40 ...) (actual ... rows=7424.00 ...)
>    Filter: (COALESCE(col1, 0) = 0)
>    Rows Removed by Filter: 2576
>
> EXPLAIN (ANALYZE, SUMMARY OFF, BUFFERS OFF)
> SELECT * FROM b WHERE coalesce(col1, 1) = 0;
>
>  Seq Scan on b  (... rows=40 ...) (actual ... rows=0.00 ...)
>    Filter: (COALESCE(col1, 1) = 0)
>    Rows Removed by Filter: 10000
>
>
> I think that the patch would be much more useful if it could improve
> such estimates.
>
> Yours,
> Laurenz Albe


Attachments:

  [text/x-patch] v2-0001-Coalesce-eqsel-eqjoinsel.patch (13.1K, ../../CAF=hKRDQRfXjpfqA_53Y_VNYY5YzFk1mswTHZ1kdBU6Dwj4vpA@mail.gmail.com/2-v2-0001-Coalesce-eqsel-eqjoinsel.patch)
  download | inline diff:
From 553eb9b30376a59e06a91a41ada6d9c6b7bd5a4d Mon Sep 17 00:00:00 2001
From: prankware <[email protected]>
Date: Fri, 10 Jul 2026 13:31:07 +0300
Subject: [PATCH v2] Coalesce eqsel eqjoinsel

---
 src/backend/utils/adt/selfuncs.c | 474 +++++++++++++++++++++++++++++--
 1 file changed, 444 insertions(+), 30 deletions(-)

diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c
index 4ee70ef0b70..7e305da357e 100644
--- a/src/backend/utils/adt/selfuncs.c
+++ b/src/backend/utils/adt/selfuncs.c
@@ -304,6 +304,288 @@ eqsel(PG_FUNCTION_ARGS)
 	PG_RETURN_FLOAT8((float8) eqsel_internal(fcinfo, false));
 }
 
+/*
+ * Extract the estimable branches of a CoalesceExpr.  Strips RelabelType,
+ * skips NULL-constant branches, and stops at the first non-NULL Const
+ * (setting *terminates_with_const).  Returns false if the expression
+ * is constant or no branches remain.
+ */
+static bool
+match_coalesce_join_side(Node *side,
+						 List **stripped_args,
+						 bool *terminates_with_const)
+{
+	CoalesceExpr *c;
+	ListCell   *lc;
+	List	   *result = NIL;
+
+	*terminates_with_const = false;
+	*stripped_args = NIL;
+
+	if (side == NULL || !IsA(side, CoalesceExpr))
+		return false;
+
+	c = (CoalesceExpr *) side;
+
+	if (list_length(c->args) < 2)
+		return false;
+
+	foreach(lc, c->args)
+	{
+		Node	   *arg = (Node *) lfirst(lc);
+
+		/* strip RelabelType */
+		while (arg && IsA(arg, RelabelType))
+			arg = (Node *) ((RelabelType *) arg)->arg;
+
+		/* leading Const makes COALESCE itself constant */
+		if (arg == NULL || (lc == list_head(c->args) && IsA(arg, Const)))
+		{
+			list_free(result);
+			return false;
+		}
+
+		if (IsA(arg, Const))
+		{
+			if (((Const *) arg)->consttype != c->coalescetype)
+			{
+				list_free(result);
+				return false;
+			}
+
+			/* NULL Const is skipped */
+			if (!((Const *) arg)->constisnull)
+			{
+				result = lappend(result, arg);
+				*terminates_with_const = true;
+				break;
+			}
+		}
+		else
+		{
+			if (exprType(arg) != c->coalescetype)
+			{
+				list_free(result);
+				return false;
+			}
+			result = lappend(result, arg);
+		}
+	}
+
+	if (result == NIL)
+		return false;
+
+	*stripped_args = result;
+	return true;
+}
+
+/*
+ * Fill prefix_probs[i] = Prod_{j<i} stanullfrac(args[j]) for a stripped
+ * COALESCE arg list.  Returns false if any non-Const arg lacks statistics.
+ */
+static bool
+get_coalesce_prefix_probs(PlannerInfo *root, List *args, double *prefix_probs)
+{
+	ListCell   *lc;
+	int			i = 0;
+	double		prefix = 1.0;
+
+	foreach(lc, args)
+	{
+		Node	   *arg = (Node *) lfirst(lc);
+
+		prefix_probs[i++] = prefix;
+
+		/* nothing to fold for the last arg or a Const */
+		if (lnext(args, lc) == NULL || IsA(arg, Const))
+			continue;
+
+		{
+			VariableStatData vd;
+			double		p_i;
+
+			examine_variable(root, arg, 0, &vd);
+			if (!HeapTupleIsValid(vd.statsTuple))
+			{
+				ReleaseVariableStats(vd);
+				return false;
+			}
+			p_i = ((Form_pg_statistic) GETSTRUCT(vd.statsTuple))->stanullfrac;
+			ReleaseVariableStats(vd);
+
+			if (p_i < 0.0 || p_i > 1.0)
+				return false;
+
+			prefix *= p_i;
+		}
+	}
+
+	return true;
+}
+
+/*
+ * Common guts of eqsel/eqjoinsel when one or both operands are CoalesceExpr.
+ * Computes:
+ *
+ *   sel(COALESCE(l_1,...,l_M) = COALESCE(r_1,...,r_N)) =
+ *       Sum_{i,j}  P_L(reach i) * P_R(reach j) * sel(l_i = r_j)
+ *
+ * where P(reach i) = Prod_{j<i} stanullfrac(arg_j).  A non-COALESCE operand
+ * is treated as a single-element list.
+ */
+static bool
+try_coalesce_eq(PG_FUNCTION_ARGS, double *selec_out)
+{
+	PlannerInfo *root = (PlannerInfo *) PG_GETARG_POINTER(0);
+	Oid			operator = PG_GETARG_OID(1);
+	List	   *args = (List *) PG_GETARG_POINTER(2);
+	bool		is_eqjoin = (fcinfo->flinfo != NULL &&
+							 fcinfo->flinfo->fn_oid == F_EQJOINSEL);
+	SpecialJoinInfo *sjinfo = is_eqjoin ?
+		(SpecialJoinInfo *) PG_GETARG_POINTER(4) : NULL;
+	int			eqsel_varRelid = is_eqjoin ? 0 : PG_GETARG_INT32(3);
+	Oid			collation = PG_GET_COLLATION();
+	Node	   *left;
+	Node	   *right;
+	List	   *left_args = NIL;
+	List	   *right_args = NIL;
+	bool		left_is_coalesce;
+	bool		right_is_coalesce;
+	bool		left_term_const = false;
+	bool		right_term_const = false;
+	double	   *left_prefix;
+	double	   *right_prefix;
+	double		acc_selec = 0.0;
+	ListCell   *llc;
+	int			li;
+
+	if (list_length(args) != 2)
+		return false;
+
+	left = (Node *) linitial(args);
+	right = (Node *) lsecond(args);
+
+	left_is_coalesce = match_coalesce_join_side(left, &left_args,
+												&left_term_const);
+	right_is_coalesce = match_coalesce_join_side(right, &right_args,
+												 &right_term_const);
+
+	if (!left_is_coalesce && !right_is_coalesce)
+		return false;
+
+	/* one side is a CoalesceExpr that match_coalesce_join_side rejected */
+	if ((left_is_coalesce && !right_is_coalesce && IsA(right, CoalesceExpr)) ||
+		(right_is_coalesce && !left_is_coalesce && IsA(left, CoalesceExpr)))
+	{
+		list_free(left_args);
+		list_free(right_args);
+		return false;
+	}
+
+	if (!left_is_coalesce)
+	{
+		left_args = list_make1(left);
+		left_term_const = IsA(left, Const);
+	}
+	if (!right_is_coalesce)
+	{
+		right_args = list_make1(right);
+		right_term_const = IsA(right, Const);
+	}
+
+	left_prefix = (double *) palloc(sizeof(double) * list_length(left_args));
+	right_prefix = (double *) palloc(sizeof(double) * list_length(right_args));
+
+	if (!get_coalesce_prefix_probs(root, left_args, left_prefix) ||
+		!get_coalesce_prefix_probs(root, right_args, right_prefix))
+	{
+		pfree(left_prefix);
+		pfree(right_prefix);
+		list_free(left_args);
+		list_free(right_args);
+		return false;
+	}
+
+	li = 0;
+	foreach(llc, left_args)
+	{
+		Node	   *larg = (Node *) lfirst(llc);
+		bool		lconst = IsA(larg, Const);
+		ListCell   *rlc;
+		int			ri = 0;
+
+		if (left_prefix[li] < 1.0e-12)
+			break;
+
+		foreach(rlc, right_args)
+		{
+			Node	   *rarg = (Node *) lfirst(rlc);
+			bool		rconst = IsA(rarg, Const);
+			Selectivity contrib;
+
+			if (right_prefix[ri] < 1.0e-12)
+				break;
+
+			if (lconst && rconst)
+			{
+				Const	   *lc = (Const *) larg;
+				Const	   *rc = (Const *) rarg;
+
+				if (lc->constisnull || rc->constisnull)
+					contrib = 0.0;
+				else
+					contrib = DatumGetBool(OidFunctionCall2Coll(get_opcode(operator),
+																collation,
+																lc->constvalue,
+																rc->constvalue)) ? 1.0 : 0.0;
+			}
+			else
+			{
+				List	   *sub_args = list_make2(copyObject(larg),
+												  copyObject(rarg));
+
+				if (!is_eqjoin || lconst || rconst)
+				{
+					contrib = DatumGetFloat8(DirectFunctionCall4Coll(eqsel,
+																	 collation,
+																	 PointerGetDatum(root),
+																	 ObjectIdGetDatum(operator),
+																	 PointerGetDatum(sub_args),
+																	 Int32GetDatum(eqsel_varRelid)));
+				}
+				else
+				{
+					contrib = DatumGetFloat8(DirectFunctionCall5Coll(eqjoinsel,
+																	 collation,
+																	 PointerGetDatum(root),
+																	 ObjectIdGetDatum(operator),
+																	 PointerGetDatum(sub_args),
+																	 Int16GetDatum(JOIN_INNER),
+																	 PointerGetDatum(sjinfo)));
+				}
+
+				list_free(sub_args);
+			}
+
+			CLAMP_PROBABILITY(contrib);
+			acc_selec += left_prefix[li] * right_prefix[ri] * contrib;
+
+			ri++;
+		}
+
+		li++;
+	}
+
+	pfree(left_prefix);
+	pfree(right_prefix);
+	list_free(left_args);
+	list_free(right_args);
+
+	CLAMP_PROBABILITY(acc_selec);
+	*selec_out = acc_selec;
+	return true;
+}
+
 /*
  * Common code for eqsel() and neqsel()
  */
@@ -320,6 +602,9 @@ eqsel_internal(PG_FUNCTION_ARGS, bool negate)
 	bool		varonleft;
 	double		selec;
 
+	if (try_coalesce_eq(fcinfo, &selec))
+		return selec;
+
 	/*
 	 * When asked about <>, we do the estimation using the corresponding =
 	 * operator, then convert to <> via "1.0 - eq_selectivity - nullfrac".
@@ -2420,6 +2705,9 @@ eqjoinsel(PG_FUNCTION_ARGS)
 	bool		join_is_reversed;
 	RelOptInfo *inner_rel;
 
+	if (try_coalesce_eq(fcinfo, &selec))
+		PG_RETURN_FLOAT8((float8) selec);
+
 	get_join_variables(root, args, sjinfo,
 					   &vardata1, &vardata2, &join_is_reversed);
 
@@ -4376,6 +4664,154 @@ estimate_multivariate_bucketsize(PlannerInfo *root, RelOptInfo *inner,
 	return otherclauses;
 }
 
+/*
+ * Most-common-value frequency for vardata.  Falls back to 1/ntuples when
+ * only a histogram slot is present.  Returns 0.0 if no statistics are
+ * available.
+ */
+static void
+get_variable_mcv_freq(VariableStatData *vardata, Selectivity *mcv_freq)
+{
+	AttStatsSlot sslot;
+
+	*mcv_freq = 0.0;
+
+	if (!HeapTupleIsValid(vardata->statsTuple))
+		return;
+
+	if (get_attstatsslot(&sslot, vardata->statsTuple,
+						 STATISTIC_KIND_MCV, InvalidOid,
+						 ATTSTATSSLOT_NUMBERS))
+	{
+		if (sslot.nnumbers > 0)
+			*mcv_freq = sslot.numbers[0];
+		free_attstatsslot(&sslot);
+	}
+	else if (get_attstatsslot(&sslot, vardata->statsTuple,
+							  STATISTIC_KIND_HISTOGRAM, InvalidOid,
+							  0))
+	{
+		/* no MCVs but histogram present: column is likely unique */
+		if (vardata->rel && vardata->rel->tuples > 0)
+			*mcv_freq = 1.0 / vardata->rel->tuples;
+	}
+}
+
+/*
+ * Estimate bucket stats for a CoalesceExpr hashkey when examine_variable()
+ * returned a default ndistinct.  Uses per-branch ndistinct and mcv_freq,
+ * weighted by null fall-through probability.
+ */
+static bool
+hash_bucket_stats_coalesce_dispatch(PlannerInfo *root,
+									Node *hashkey,
+									double nbuckets,
+									Selectivity *mcv_freq,
+									Selectivity *bucketsize_frac)
+{
+	List	   *stripped_args;
+	bool		terminates_with_const;
+	double	   *prefix;
+	int			nargs;
+	int			i;
+	ListCell   *lc;
+	double		nd_mix = 0.0;
+	Selectivity mcv_mix = 0.0;
+	double		rel_rows_proxy = 0.0;
+	double		rel_tuples_proxy = 0.0;
+	double		estfract;
+
+	if (!match_coalesce_join_side(hashkey, &stripped_args, &terminates_with_const))
+		return false;
+
+	nargs = list_length(stripped_args);
+	prefix = (double *) palloc(sizeof(double) * nargs);
+
+	if (!get_coalesce_prefix_probs(root, stripped_args, prefix))
+	{
+		pfree(prefix);
+		list_free(stripped_args);
+		return false;
+	}
+
+	i = 0;
+	foreach(lc, stripped_args)
+	{
+		Node	   *arg = (Node *) lfirst(lc);
+
+		if (IsA(arg, Const))
+		{
+			mcv_mix = Max(mcv_mix, prefix[i]);
+			if (prefix[i] > 0.0)
+				nd_mix += 1.0;
+		}
+		else
+		{
+			VariableStatData vd;
+			double		nd_i;
+			bool		isdefault;
+			Selectivity mcv_i;
+
+			examine_variable(root, arg, 0, &vd);
+			nd_i = get_variable_numdistinct(&vd, &isdefault);
+
+			if (isdefault)
+			{
+				ReleaseVariableStats(vd);
+				pfree(prefix);
+				list_free(stripped_args);
+				return false;
+			}
+
+			get_variable_mcv_freq(&vd, &mcv_i);
+
+			nd_mix = Max(nd_mix, nd_i);
+			mcv_mix = Max(mcv_mix, prefix[i] * mcv_i);
+
+			if (i == 0 && vd.rel && vd.rel->tuples > 0)
+			{
+				rel_rows_proxy = vd.rel->rows;
+				rel_tuples_proxy = vd.rel->tuples;
+			}
+
+			ReleaseVariableStats(vd);
+		}
+
+		i++;
+	}
+
+	pfree(prefix);
+	list_free(stripped_args);
+
+	if (rel_tuples_proxy > 0.0)
+	{
+		nd_mix *= rel_rows_proxy / rel_tuples_proxy;
+		nd_mix = clamp_row_est(nd_mix);
+	}
+
+	if (nd_mix <= 0.0)
+		return false;
+
+	if (nd_mix > nbuckets)
+		estfract = 1.0 / nbuckets;
+	else
+		estfract = 1.0 / nd_mix;
+
+	CLAMP_PROBABILITY(mcv_mix);
+	*mcv_freq = Max(*mcv_freq, mcv_mix);
+	CLAMP_PROBABILITY(*mcv_freq);
+	estfract = Max(estfract, *mcv_freq);
+
+	if (estfract < 1.0e-6)
+		estfract = 1.0e-6;
+	else if (estfract > 1.0)
+		estfract = 1.0;
+
+	*bucketsize_frac = (Selectivity) estfract;
+
+	return true;
+}
+
 /*
  * Estimate hash bucket statistics when the specified expression is used
  * as a hash key for the given number of buckets.
@@ -4429,43 +4865,21 @@ estimate_hash_bucket_stats(PlannerInfo *root, Node *hashkey, double nbuckets,
 	double		estfract,
 				ndistinct;
 	bool		isdefault;
-	AttStatsSlot sslot;
 
 	examine_variable(root, hashkey, 0, &vardata);
 
-	/* Initialize *mcv_freq to "unknown" */
-	*mcv_freq = 0.0;
-
-	/* Look up the frequency of the most common value, if available */
-	if (HeapTupleIsValid(vardata.statsTuple))
-	{
-		if (get_attstatsslot(&sslot, vardata.statsTuple,
-							 STATISTIC_KIND_MCV, InvalidOid,
-							 ATTSTATSSLOT_NUMBERS))
-		{
-			/*
-			 * The first MCV stat is for the most common value.
-			 */
-			if (sslot.nnumbers > 0)
-				*mcv_freq = sslot.numbers[0];
-			free_attstatsslot(&sslot);
-		}
-		else if (get_attstatsslot(&sslot, vardata.statsTuple,
-								  STATISTIC_KIND_HISTOGRAM, InvalidOid,
-								  0))
-		{
-			/*
-			 * If there are no recorded MCVs, but we do have a histogram, then
-			 * assume that ANALYZE determined that the column is unique.
-			 */
-			if (vardata.rel && vardata.rel->tuples > 0)
-				*mcv_freq = 1.0 / vardata.rel->tuples;
-		}
-	}
+	get_variable_mcv_freq(&vardata, mcv_freq);
 
 	/* Get number of distinct values */
 	ndistinct = get_variable_numdistinct(&vardata, &isdefault);
 
+	if (isdefault && hash_bucket_stats_coalesce_dispatch(root, hashkey, nbuckets,
+														 mcv_freq, bucketsize_frac))
+	{
+		ReleaseVariableStats(vardata);
+		return;
+	}
+
 	/*
 	 * If ndistinct isn't real, punt.  We normally return 0.1, but if the
 	 * mcv_freq is known to be even higher than that, use it instead.

base-commit: dfce19c2300ab00a8c41386e49dfdd6a3c8edae9
-- 
2.43.0



^ permalink  raw  reply  [nested|flat] 43+ messages in thread


end of thread, other threads:[~2026-07-10 12:54 UTC | newest]

Thread overview: 43+ messages (download: mbox mbox.gz follow: Atom feed)
-- links below jump to the message on this page --
2024-02-06 21:50 Re: Psql meta-command conninfo+ Nathan Bossart <[email protected]>
2024-02-07 04:13 ` Maiquel Grassi <[email protected]>
2024-02-07 09:54   ` Erik Wienhold <[email protected]>
2024-02-07 12:41     ` Maiquel Grassi <[email protected]>
2024-02-07 12:35   ` Pavel Luzanov <[email protected]>
2024-02-07 14:47     ` Maiquel Grassi <[email protected]>
2024-02-07 16:40       ` Pavel Luzanov <[email protected]>
2024-02-07 20:13         ` Maiquel Grassi <[email protected]>
2024-02-08 11:01           ` Pavel Luzanov <[email protected]>
2024-02-08 14:58             ` Maiquel Grassi <[email protected]>
2024-02-09 07:58               ` Pavel Luzanov <[email protected]>
2024-02-09 09:18                 ` Maiquel Grassi <[email protected]>
2024-02-12 14:16                 ` Maiquel Grassi <[email protected]>
2024-02-12 21:53                   ` Pavel Luzanov <[email protected]>
2024-02-14 11:36                   ` Jim Jones <[email protected]>
2024-02-15 19:47                     ` Maiquel Grassi <[email protected]>
2024-02-15 22:16                       ` Maiquel Grassi <[email protected]>
2024-02-16 11:18                         ` Jim Jones <[email protected]>
2024-02-16 15:54                           ` Nathan Bossart <[email protected]>
2024-02-17 14:53                             ` Maiquel Grassi <[email protected]>
2024-02-21 23:30                               ` Maiquel Grassi <[email protected]>
2024-02-24 20:44                               ` Nathan Bossart <[email protected]>
2024-02-29 22:02                                 ` Maiquel Grassi <[email protected]>
2024-02-29 22:41                                   ` Nathan Bossart <[email protected]>
2024-03-18 22:05                                     ` Maiquel Grassi <[email protected]>
2024-03-27 13:23                                       ` Maiquel Grassi <[email protected]>
2024-03-14 16:46                                   ` Nathan Bossart <[email protected]>
2024-02-16 21:48                           ` Maiquel Grassi <[email protected]>
2024-02-08 11:01           ` Jim Jones <[email protected]>
2024-02-08 15:50             ` Maiquel Grassi <[email protected]>
2024-02-08 19:37               ` Jim Jones <[email protected]>
2024-02-08 20:37                 ` Erik Wienhold <[email protected]>
2024-02-08 22:28                   ` Maiquel Grassi <[email protected]>
2024-02-09 10:19                     ` Alvaro Herrera <[email protected]>
2024-02-09 15:33                       ` Maiquel Grassi <[email protected]>
2024-02-10 17:38                       ` Maiquel Grassi <[email protected]>
2024-02-08 23:34                   ` Jim Jones <[email protected]>
2024-02-09 02:00                     ` Maiquel Grassi <[email protected]>
2024-02-09 02:41                       ` Nathan Bossart <[email protected]>
2024-02-09 08:30                         ` Maiquel Grassi <[email protected]>
2024-02-08 20:47                 ` Maiquel Grassi <[email protected]>
2026-07-10 09:26 Re: COALESCE patch Laurenz Albe <[email protected]>
2026-07-10 12:54 ` Re: COALESCE patch prankware <[email protected]>

This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox