Please find attached a patch to enable more intuitive titles when using
psql and doing the following actions:

\dt \di \dv \dm \ds \dE

In other words, everything in listTables()

We still default to "List or relations", but if we know that the user has
requested exactly one specific type of relation, we use that instead. So
instead of

greg=# \dv
                List of relations
 Schema |          Name           | Type | Owner
--------+-------------------------+------+-------
 public | pg_stat_statements      | view | greg
 public | pg_stat_statements_info | view | greg

we get:

greg=# \dv
                  List of views
 Schema |          Name           | Type | Owner
--------+-------------------------+------+-------
 public | pg_stat_statements      | view | greg
 public | pg_stat_statements_info | view | greg
(2 rows)

The same applies for "misses" as well:

greg=# \di
Did not find any indexes.

greg=# \di foo*
Did not find any indexes named "foo*".

I thought about keeping that last one as singular, as it is replacing "Did
not find any relation named", but not only does it make more sense as a
plural given that wildcards can produce multiple relations, it makes the
code cleaner. :)

Inspired by a recent thread[0] over in pgsql-bugs entitled "Bug in psql".
(while not a bug, it is certainly a welcome enhancement, IMHO).

Cheers,
Greg

[0]
https://www.postgresql.org/message-id/CADrHaBEVSYwemoJWtry2%2B82KHy9tZirH2PVfi-uD96R5J8FCsw%40mail.gmail.com
From eaf1097eb0ac02d2ab093e4e4261d0a15adf8ac2 Mon Sep 17 00:00:00 2001
From: Greg Sabino Mullane <greg@turnstep.com>
Date: Mon, 3 Feb 2025 12:19:14 -0500
Subject: [PATCH] Show more intuitive titles for psql commands \dt \di \dv \dm
 \ds and \dE

This applies to the modified versions as well e.g. \dt+ \dtS+

Rather than say "List of relations", if someone has entered in a \di, we say "List of indexes"

Per complaint on the bugs list on Jan 29, 2025 from xpusostomos@gmail.com
---
 src/bin/psql/describe.c | 21 +++++++++++++++++----
 1 file changed, 17 insertions(+), 4 deletions(-)

diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index aa4363b200..19366be2c8 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -4012,9 +4012,11 @@ listTables(const char *tabtypes, const char *pattern, bool verbose, bool showSys
 	bool		showForeign = strchr(tabtypes, 'E') != NULL;
 
 	PQExpBufferData buf;
+	PQExpBufferData title;
 	PGresult   *res;
 	printQueryOpt myopt = pset.popt;
 	int			cols_so_far;
+	char	   *item_type;
 	bool		translate_columns[] = {false, false, true, false, false, false, false, false, false};
 
 	/* If tabtypes is empty, we default to \dtvmsE (but see also command.c) */
@@ -4161,6 +4163,15 @@ listTables(const char *tabtypes, const char *pattern, bool verbose, bool showSys
 	if (!res)
 		return false;
 
+	item_type = psprintf("%s",
+						 (strspn(tabtypes, "tS+") == strlen(tabtypes)) ? "tables" :
+						 (strspn(tabtypes, "iS+") == strlen(tabtypes)) ? "indexes" :
+						 (strspn(tabtypes, "vS+") == strlen(tabtypes)) ? "views" :
+						 (strspn(tabtypes, "mS+") == strlen(tabtypes)) ? "materialized view" :
+						 (strspn(tabtypes, "sS+") == strlen(tabtypes)) ? "sequences" :
+						 (strspn(tabtypes, "ES+") == strlen(tabtypes)) ? "foreign tables" :
+						 "relations");
+
 	/*
 	 * Most functions in this file are content to print an empty table when
 	 * there are no matching objects.  We intentionally deviate from that
@@ -4169,14 +4180,16 @@ listTables(const char *tabtypes, const char *pattern, bool verbose, bool showSys
 	if (PQntuples(res) == 0 && !pset.quiet)
 	{
 		if (pattern)
-			pg_log_error("Did not find any relation named \"%s\".",
-						 pattern);
+			pg_log_error("Did not find any %s named \"%s\".", item_type, pattern);
 		else
-			pg_log_error("Did not find any relations.");
+			pg_log_error("Did not find any %s.", item_type);
 	}
 	else
 	{
-		myopt.title = _("List of relations");
+		initPQExpBuffer(&title);
+		printfPQExpBuffer(&title, _("List of %s"), item_type);
+
+		myopt.title = title.data;
 		myopt.translate_header = true;
 		myopt.translate_columns = translate_columns;
 		myopt.n_translate_columns = lengthof(translate_columns);
-- 
2.30.2

Reply via email to