On Wed, Jul 14, 2021 at 07:42:33AM +0200, Laurenz Albe wrote:
> Besides, schemas are not physical, but logical containers.  So I see a point 
> in
> measuring the storage used in a certain tablespace, but not so much by all 
> objects
> in a certain schema.  It might be useful for accounting purposes, though.

We use only a few schemas, 1) to hide child tables; 2) to exclude some extended
stats from backups, and 1-2 other things.  But it's useful to be able to see
how storage is used by schema, and better to do it conveniently.

I think it'd be even more useful for people who use schemas more widely than we
do:
    "Who's using all our space?"
    \dn++
    "Oh, it's that one - let me clean that up..."

Or, "what's the pg_toast stuff, and do I need to do something about it?"

> But I don't expect it to be in frequent enough demand to add a psql command.
> 
> What about inventing a function pg_schema_size(regnamespace)?

But for "physical" storage it's also possible to get the size from the OS, much
more efficiently, using /bin/df or zfs list (assuming nothing else is using
those filesystems).  The pg_*_size functions are inefficient, but psql \db+ and
\l+ already call them anyway.

For schemas, there's no way to get the size from the OS, so it's nice to make
the size available from psql, conveniently.

v3 patch:
 - fixes an off by one in forkNum loop;
 - removes an unnecessary subquery in describe.c;
 - returns 0 rather than NULL if the schema is empty;
 - adds pg_am_size;

regression=# \dA++
                                  List of access methods
  Name  | Type  |       Handler        |              Description               
|  Size   
--------+-------+----------------------+----------------------------------------+---------
 brin   | Index | brinhandler          | block range index (BRIN) access method 
| 744 kB
 btree  | Index | bthandler            | b-tree index access method             
| 21 MB
 gin    | Index | ginhandler           | GIN index access method                
| 2672 kB
 gist   | Index | gisthandler          | GiST index access method               
| 2800 kB
 hash   | Index | hashhandler          | hash index access method               
| 2112 kB
 heap   | Table | heap_tableam_handler | heap table access method               
| 60 MB
 heap2  | Table | heap_tableam_handler |                                        
| 120 kB
 spgist | Index | spghandler           | SP-GiST index access method            
| 5840 kB
(8 rows)

regression=# \dn++
                                   List of schemas
        Name        |  Owner  | Access privileges  |      Description       |  
Size   
--------------------+---------+--------------------+------------------------+---------
 fkpart3            | pryzbyj |                    |                        | 
168 kB
 fkpart4            | pryzbyj |                    |                        | 
104 kB
 fkpart5            | pryzbyj |                    |                        | 
40 kB
 fkpart6            | pryzbyj |                    |                        | 
48 kB
 mvtest_mvschema    | pryzbyj |                    |                        | 
16 kB
 public             | pryzbyj | pryzbyj=UC/pryzbyj+| standard public schema | 
69 MB
                    |         | =UC/pryzbyj        |                        | 
 regress_indexing   | pryzbyj |                    |                        | 
48 kB
 regress_rls_schema | pryzbyj |                    |                        | 0 
bytes
 regress_schema_2   | pryzbyj |                    |                        | 0 
bytes
 testxmlschema      | pryzbyj |                    |                        | 
24 kB
(10 rows)

-- 
Justin
>From d7f5446c0aa1a12a512482d2ed121eb44f6e2f59 Mon Sep 17 00:00:00 2001
From: Justin Pryzby <pryz...@telsasoft.com>
Date: Tue, 13 Jul 2021 21:25:48 -0500
Subject: [PATCH v3 1/4] psql: show size of schemas and AMs in \dn+ and \dA+..

See also: 358a897fa, 528ac10c7

Add pg_am_size() and psql \dA++
---
 src/backend/utils/adt/dbsize.c  | 138 ++++++++++++++++++++++++++++++++
 src/bin/psql/describe.c         |  12 ++-
 src/include/catalog/pg_proc.dat |  19 +++++
 3 files changed, 168 insertions(+), 1 deletion(-)

diff --git a/src/backend/utils/adt/dbsize.c b/src/backend/utils/adt/dbsize.c
index d5a7fb13f3..62273d4f15 100644
--- a/src/backend/utils/adt/dbsize.c
+++ b/src/backend/utils/adt/dbsize.c
@@ -13,18 +13,23 @@
 
 #include <sys/stat.h>
 
+#include "access/genam.h"
 #include "access/htup_details.h"
 #include "access/relation.h"
+#include "access/table.h"
 #include "catalog/catalog.h"
 #include "catalog/namespace.h"
 #include "catalog/pg_authid.h"
 #include "catalog/pg_tablespace.h"
 #include "commands/dbcommands.h"
+#include "commands/defrem.h"
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "storage/fd.h"
 #include "utils/acl.h"
 #include "utils/builtins.h"
+#include "utils/fmgroids.h"
+#include "utils/lsyscache.h"
 #include "utils/numeric.h"
 #include "utils/rel.h"
 #include "utils/relfilenodemap.h"
@@ -832,6 +837,139 @@ pg_size_bytes(PG_FUNCTION_ARGS)
 	PG_RETURN_INT64(result);
 }
 
+/* Return the sum of size of relations for which the given attribute has the specified OID */
+static int64
+calculate_size_attvalue(int attnum, Oid attval)
+{
+	int64		totalsize = 0;
+	ScanKeyData 	skey;
+	Relation	pg_class;
+	SysScanDesc	scan;
+	HeapTuple	tuple;
+
+	ScanKeyInit(&skey, attnum,
+			BTEqualStrategyNumber, F_OIDEQ, attval);
+
+	pg_class = table_open(RelationRelationId, AccessShareLock);
+	scan = systable_beginscan(pg_class, InvalidOid, false, NULL, 1, &skey);
+	while (HeapTupleIsValid(tuple = systable_getnext(scan)))
+	{
+		Relation rel;
+		Form_pg_class classtuple = (Form_pg_class) GETSTRUCT(tuple);
+
+		rel = try_relation_open(classtuple->oid, AccessShareLock);
+		if (!rel)
+			continue;
+
+		for (int forkNum = 0; forkNum <= MAX_FORKNUM; forkNum++)
+			totalsize += calculate_relation_size(&rel->rd_node, rel->rd_backend, forkNum);
+
+		relation_close(rel, AccessShareLock);
+	}
+
+	systable_endscan(scan);
+	table_close(pg_class, AccessShareLock);
+	return totalsize;
+}
+
+/* Compute the size of relations in a schema (namespace) */
+static int64
+calculate_namespace_size(Oid nspOid)
+{
+	/*
+	 * User must be a member of pg_read_all_stats or have CREATE privilege for
+	 * target namespace.
+	 */
+	if (!is_member_of_role(GetUserId(), ROLE_PG_READ_ALL_STATS))
+	{
+		AclResult aclresult;
+		aclresult = pg_namespace_aclcheck(nspOid, GetUserId(), ACL_CREATE);
+		if (aclresult != ACLCHECK_OK)
+			aclcheck_error(aclresult, OBJECT_SCHEMA,
+						   get_namespace_name(nspOid));
+	}
+
+	return calculate_size_attvalue(Anum_pg_class_relnamespace, nspOid);
+}
+
+Datum
+pg_namespace_size_oid(PG_FUNCTION_ARGS)
+{
+	int64		size;
+	Oid			nspOid = PG_GETARG_OID(0);
+
+	size = calculate_namespace_size(nspOid);
+
+	if (size < 0)
+		PG_RETURN_NULL();
+
+	PG_RETURN_INT64(size);
+}
+
+Datum
+pg_namespace_size_name(PG_FUNCTION_ARGS)
+{
+	int64		size;
+	Name		nspName = PG_GETARG_NAME(0);
+	Oid			nspOid = get_namespace_oid(NameStr(*nspName), false);
+
+	size = calculate_namespace_size(nspOid);
+
+	if (size < 0)
+		PG_RETURN_NULL();
+
+	PG_RETURN_INT64(size);
+}
+
+/* Compute the size of relations using an access method */
+static int64
+calculate_am_size(Oid amOid)
+{
+	/*
+	 * User must be a member of pg_read_all_stats or have CREATE privilege for
+	 * target namespace.
+	 */
+	if (!is_member_of_role(GetUserId(), ROLE_PG_READ_ALL_STATS))
+	{
+		AclResult aclresult;
+		aclresult = pg_namespace_aclcheck(amOid, GetUserId(), ACL_CREATE);
+		if (aclresult != ACLCHECK_OK)
+			aclcheck_error(aclresult, OBJECT_SCHEMA,
+						   get_am_name(amOid));
+	}
+
+	return calculate_size_attvalue(Anum_pg_class_relam, amOid);
+}
+
+Datum
+pg_am_size_oid(PG_FUNCTION_ARGS)
+{
+	int64		size;
+	Oid			amOid = PG_GETARG_OID(0);
+
+	size = calculate_am_size(amOid);
+
+	if (size < 0)
+		PG_RETURN_NULL();
+
+	PG_RETURN_INT64(size);
+}
+
+Datum
+pg_am_size_name(PG_FUNCTION_ARGS)
+{
+	int64		size;
+	Name		amName = PG_GETARG_NAME(0);
+	Oid			amOid = get_am_oid(NameStr(*amName), false);
+
+	size = calculate_am_size(amOid);
+
+	if (size < 0)
+		PG_RETURN_NULL();
+
+	PG_RETURN_INT64(size);
+}
+
 /*
  * Get the filenode of a relation
  *
diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index ba658f731b..fe5d88a2b7 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -152,7 +152,7 @@ describeAccessMethods(const char *pattern, bool verbose)
 	PQExpBufferData buf;
 	PGresult   *res;
 	printQueryOpt myopt = pset.popt;
-	static const bool translate_columns[] = {false, true, false, false};
+	static const bool translate_columns[] = {false, true, false, false, false};
 
 	if (pset.sversion < 90600)
 	{
@@ -184,6 +184,11 @@ describeAccessMethods(const char *pattern, bool verbose)
 						  "  pg_catalog.obj_description(oid, 'pg_am') AS \"%s\"",
 						  gettext_noop("Handler"),
 						  gettext_noop("Description"));
+
+		if (pset.sversion >= 150000)
+			appendPQExpBuffer(&buf,
+							  ",\n  pg_catalog.pg_size_pretty(pg_catalog.pg_am_size(oid)) AS \"%s\"",
+							  gettext_noop("Size"));
 	}
 
 	appendPQExpBufferStr(&buf,
@@ -5036,6 +5041,11 @@ listSchemas(const char *pattern, bool verbose, bool showSystem)
 		appendPQExpBuffer(&buf,
 						  ",\n  pg_catalog.obj_description(n.oid, 'pg_namespace') AS \"%s\"",
 						  gettext_noop("Description"));
+
+		if (verbose && pset.sversion >= 150000)
+			appendPQExpBuffer(&buf,
+							  ",\n  pg_catalog.pg_size_pretty(pg_namespace_size(n.oid)) AS \"%s\"",
+							  gettext_noop("Size"));
 	}
 
 	appendPQExpBufferStr(&buf,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index fde251fa4f..4518aad200 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -7158,6 +7158,25 @@
   descr => 'total disk space usage for the specified tablespace',
   proname => 'pg_tablespace_size', provolatile => 'v', prorettype => 'int8',
   proargtypes => 'name', prosrc => 'pg_tablespace_size_name' },
+
+{ oid => '9410',
+  descr => 'total disk space usage for the specified namespace',
+  proname => 'pg_namespace_size', provolatile => 'v', prorettype => 'int8',
+  proargtypes => 'oid', prosrc => 'pg_namespace_size_oid' },
+{ oid => '9411',
+  descr => 'total disk space usage for the specified namespace',
+  proname => 'pg_namespace_size', provolatile => 'v', prorettype => 'int8',
+  proargtypes => 'name', prosrc => 'pg_namespace_size_name' },
+
+{ oid => '9412',
+  descr => 'total disk space usage for the specified access method',
+  proname => 'pg_am_size', provolatile => 'v', prorettype => 'int8',
+  proargtypes => 'oid', prosrc => 'pg_am_size_oid' },
+{ oid => '9413',
+  descr => 'total disk space usage for the specified access method',
+  proname => 'pg_am_size', provolatile => 'v', prorettype => 'int8',
+  proargtypes => 'name', prosrc => 'pg_am_size_name' },
+
 { oid => '2324', descr => 'total disk space usage for the specified database',
   proname => 'pg_database_size', provolatile => 'v', prorettype => 'int8',
   proargtypes => 'oid', prosrc => 'pg_database_size_oid' },
-- 
2.17.0

>From 351de9f97334467b5513b2245e62ea3edad3d1f5 Mon Sep 17 00:00:00 2001
From: Justin Pryzby <pryz...@telsasoft.com>
Date: Thu, 15 Jul 2021 03:14:20 -0500
Subject: [PATCH v3 2/4] psql \dn, \dA, \db and \l to show the size only with
 ++..

\dt+ and \dP+ are not changed, since showing the table sizes is their primary
purpose.
---
 src/bin/psql/command.c  | 22 ++++++++++++++--------
 src/bin/psql/describe.c | 16 ++++++++--------
 src/bin/psql/describe.h |  8 ++++----
 3 files changed, 26 insertions(+), 20 deletions(-)

diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index 49d4c0e3ce..bfb10d91e4 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -362,7 +362,8 @@ exec_command(const char *cmd,
 	else if (strcmp(cmd, "if") == 0)
 		status = exec_command_if(scan_state, cstack, query_buf);
 	else if (strcmp(cmd, "l") == 0 || strcmp(cmd, "list") == 0 ||
-			 strcmp(cmd, "l+") == 0 || strcmp(cmd, "list+") == 0)
+			 strcmp(cmd, "l+") == 0 || strcmp(cmd, "l++") == 0 ||
+			 strcmp(cmd, "list+") == 0 || strcmp(cmd, "list++") == 0)
 		status = exec_command_list(scan_state, active_branch, cmd);
 	else if (strncmp(cmd, "lo_", 3) == 0)
 		status = exec_command_lo(scan_state, active_branch, cmd);
@@ -707,6 +708,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd)
 	if (active_branch)
 	{
 		char	   *pattern;
+		int			verbose = 0;
 		bool		show_verbose,
 					show_system;
 
@@ -714,7 +716,10 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd)
 		pattern = psql_scan_slash_option(scan_state,
 										 OT_NORMAL, NULL, true);
 
-		show_verbose = strchr(cmd, '+') ? true : false;
+		for (const char *t = cmd; *t != '\0'; ++t)
+			verbose += *t == '+' ? 1 : 0;
+
+		show_verbose = (bool) (verbose != 0);
 		show_system = strchr(cmd, 'S') ? true : false;
 
 		switch (cmd[1])
@@ -739,7 +744,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd)
 					{
 						case '\0':
 						case '+':
-							success = describeAccessMethods(pattern, show_verbose);
+							success = describeAccessMethods(pattern, verbose);
 							break;
 						case 'c':
 							success = listOperatorClasses(pattern, pattern2, show_verbose);
@@ -766,7 +771,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd)
 				success = describeAggregates(pattern, show_verbose, show_system);
 				break;
 			case 'b':
-				success = describeTablespaces(pattern, show_verbose);
+				success = describeTablespaces(pattern, verbose);
 				break;
 			case 'c':
 				success = listConversions(pattern, show_verbose, show_system);
@@ -813,7 +818,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd)
 				success = listLanguages(pattern, show_verbose, show_system);
 				break;
 			case 'n':
-				success = listSchemas(pattern, show_verbose, show_system);
+				success = listSchemas(pattern, verbose, show_system);
 				break;
 			case 'o':
 				success = exec_command_dfo(scan_state, cmd, pattern,
@@ -1870,14 +1875,15 @@ exec_command_list(PsqlScanState scan_state, bool active_branch, const char *cmd)
 	if (active_branch)
 	{
 		char	   *pattern;
-		bool		show_verbose;
+		int		verbose = 0;
 
 		pattern = psql_scan_slash_option(scan_state,
 										 OT_NORMAL, NULL, true);
 
-		show_verbose = strchr(cmd, '+') ? true : false;
+		for (const char *t = cmd; *t != '\0'; ++t)
+			verbose += *t == '+' ? 1 : 0;
 
-		success = listAllDbs(pattern, show_verbose);
+		success = listAllDbs(pattern, verbose);
 
 		if (pattern)
 			free(pattern);
diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index fe5d88a2b7..ce04dbb9ce 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -147,7 +147,7 @@ describeAggregates(const char *pattern, bool verbose, bool showSystem)
  * Takes an optional regexp to select particular access methods
  */
 bool
-describeAccessMethods(const char *pattern, bool verbose)
+describeAccessMethods(const char *pattern, int verbose)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -185,7 +185,7 @@ describeAccessMethods(const char *pattern, bool verbose)
 						  gettext_noop("Handler"),
 						  gettext_noop("Description"));
 
-		if (pset.sversion >= 150000)
+		if (verbose > 1 && pset.sversion >= 150000)
 			appendPQExpBuffer(&buf,
 							  ",\n  pg_catalog.pg_size_pretty(pg_catalog.pg_am_size(oid)) AS \"%s\"",
 							  gettext_noop("Size"));
@@ -222,7 +222,7 @@ describeAccessMethods(const char *pattern, bool verbose)
  * Takes an optional regexp to select particular tablespaces
  */
 bool
-describeTablespaces(const char *pattern, bool verbose)
+describeTablespaces(const char *pattern, int verbose)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -268,7 +268,7 @@ describeTablespaces(const char *pattern, bool verbose)
 						  ",\n  spcoptions AS \"%s\"",
 						  gettext_noop("Options"));
 
-	if (verbose && pset.sversion >= 90200)
+	if (verbose > 1 && pset.sversion >= 90200)
 		appendPQExpBuffer(&buf,
 						  ",\n  pg_catalog.pg_size_pretty(pg_catalog.pg_tablespace_size(oid)) AS \"%s\"",
 						  gettext_noop("Size"));
@@ -1028,7 +1028,7 @@ describeOperators(const char *oper_pattern,
  * for \l, \list, and -l switch
  */
 bool
-listAllDbs(const char *pattern, bool verbose)
+listAllDbs(const char *pattern, int verbose)
 {
 	PGresult   *res;
 	PQExpBufferData buf;
@@ -1051,7 +1051,7 @@ listAllDbs(const char *pattern, bool verbose)
 						  gettext_noop("Ctype"));
 	appendPQExpBufferStr(&buf, "       ");
 	printACLColumn(&buf, "d.datacl");
-	if (verbose && pset.sversion >= 80200)
+	if (verbose > 1 && pset.sversion >= 80200)
 		appendPQExpBuffer(&buf,
 						  ",\n       CASE WHEN pg_catalog.has_database_privilege(d.datname, 'CONNECT')\n"
 						  "            THEN pg_catalog.pg_size_pretty(pg_catalog.pg_database_size(d.datname))\n"
@@ -5021,7 +5021,7 @@ listCollations(const char *pattern, bool verbose, bool showSystem)
  * Describes schemas (namespaces)
  */
 bool
-listSchemas(const char *pattern, bool verbose, bool showSystem)
+listSchemas(const char *pattern, int verbose, bool showSystem)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -5042,7 +5042,7 @@ listSchemas(const char *pattern, bool verbose, bool showSystem)
 						  ",\n  pg_catalog.obj_description(n.oid, 'pg_namespace') AS \"%s\"",
 						  gettext_noop("Description"));
 
-		if (verbose && pset.sversion >= 150000)
+		if (verbose > 1 && pset.sversion >= 150000)
 			appendPQExpBuffer(&buf,
 							  ",\n  pg_catalog.pg_size_pretty(pg_namespace_size(n.oid)) AS \"%s\"",
 							  gettext_noop("Size"));
diff --git a/src/bin/psql/describe.h b/src/bin/psql/describe.h
index 71b320f1fc..edeea38580 100644
--- a/src/bin/psql/describe.h
+++ b/src/bin/psql/describe.h
@@ -13,10 +13,10 @@
 extern bool describeAggregates(const char *pattern, bool verbose, bool showSystem);
 
 /* \dA */
-extern bool describeAccessMethods(const char *pattern, bool verbose);
+extern bool describeAccessMethods(const char *pattern, int verbose);
 
 /* \db */
-extern bool describeTablespaces(const char *pattern, bool verbose);
+extern bool describeTablespaces(const char *pattern, int verbose);
 
 /* \df, \dfa, \dfn, \dft, \dfw, etc. */
 extern bool describeFunctions(const char *functypes, const char *func_pattern,
@@ -62,7 +62,7 @@ extern bool listTSDictionaries(const char *pattern, bool verbose);
 extern bool listTSTemplates(const char *pattern, bool verbose);
 
 /* \l */
-extern bool listAllDbs(const char *pattern, bool verbose);
+extern bool listAllDbs(const char *pattern, int verbose);
 
 /* \dt, \di, \ds, \dS, etc. */
 extern bool listTables(const char *tabtypes, const char *pattern, bool verbose, bool showSystem);
@@ -83,7 +83,7 @@ extern bool listCasts(const char *pattern, bool verbose);
 extern bool listCollations(const char *pattern, bool verbose, bool showSystem);
 
 /* \dn */
-extern bool listSchemas(const char *pattern, bool verbose, bool showSystem);
+extern bool listSchemas(const char *pattern, int verbose, bool showSystem);
 
 /* \dew */
 extern bool listForeignDataWrappers(const char *pattern, bool verbose);
-- 
2.17.0

>From 79b02af25ba0253b6025cef6b3e94abb2ddfe2eb Mon Sep 17 00:00:00 2001
From: Justin Pryzby <pryz...@telsasoft.com>
Date: Thu, 15 Jul 2021 03:19:58 -0500
Subject: [PATCH v3 3/4] f!convert the other verbose to int, too

---
 src/bin/psql/command.c  |  74 +++++++++--------
 src/bin/psql/describe.c | 172 ++++++++++++++++++++--------------------
 src/bin/psql/describe.h |  54 ++++++-------
 3 files changed, 149 insertions(+), 151 deletions(-)

diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index bfb10d91e4..c3738a106f 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -75,7 +75,7 @@ static backslashResult exec_command_d(PsqlScanState scan_state, bool active_bran
 									  const char *cmd);
 static bool exec_command_dfo(PsqlScanState scan_state, const char *cmd,
 							 const char *pattern,
-							 bool show_verbose, bool show_system);
+							 int verbose, bool show_system);
 static backslashResult exec_command_edit(PsqlScanState scan_state, bool active_branch,
 										 PQExpBuffer query_buf, PQExpBuffer previous_buf);
 static backslashResult exec_command_ef_ev(PsqlScanState scan_state, bool active_branch,
@@ -709,8 +709,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd)
 	{
 		char	   *pattern;
 		int			verbose = 0;
-		bool		show_verbose,
-					show_system;
+		bool		show_system;
 
 		/* We don't do SQLID reduction on the pattern yet */
 		pattern = psql_scan_slash_option(scan_state,
@@ -719,7 +718,6 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd)
 		for (const char *t = cmd; *t != '\0'; ++t)
 			verbose += *t == '+' ? 1 : 0;
 
-		show_verbose = (bool) (verbose != 0);
 		show_system = strchr(cmd, 'S') ? true : false;
 
 		switch (cmd[1])
@@ -728,10 +726,10 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd)
 			case '+':
 			case 'S':
 				if (pattern)
-					success = describeTableDetails(pattern, show_verbose, show_system);
+					success = describeTableDetails(pattern, verbose, show_system);
 				else
 					/* standard listing of interesting things */
-					success = listTables("tvmsE", NULL, show_verbose, show_system);
+					success = listTables("tvmsE", NULL, verbose, show_system);
 				break;
 			case 'A':
 				{
@@ -747,16 +745,16 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd)
 							success = describeAccessMethods(pattern, verbose);
 							break;
 						case 'c':
-							success = listOperatorClasses(pattern, pattern2, show_verbose);
+							success = listOperatorClasses(pattern, pattern2, verbose);
 							break;
 						case 'f':
-							success = listOperatorFamilies(pattern, pattern2, show_verbose);
+							success = listOperatorFamilies(pattern, pattern2, verbose);
 							break;
 						case 'o':
-							success = listOpFamilyOperators(pattern, pattern2, show_verbose);
+							success = listOpFamilyOperators(pattern, pattern2, verbose);
 							break;
 						case 'p':
-							success = listOpFamilyFunctions(pattern, pattern2, show_verbose);
+							success = listOpFamilyFunctions(pattern, pattern2, verbose);
 							break;
 						default:
 							status = PSQL_CMD_UNKNOWN;
@@ -768,16 +766,16 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd)
 				}
 				break;
 			case 'a':
-				success = describeAggregates(pattern, show_verbose, show_system);
+				success = describeAggregates(pattern, verbose, show_system);
 				break;
 			case 'b':
 				success = describeTablespaces(pattern, verbose);
 				break;
 			case 'c':
-				success = listConversions(pattern, show_verbose, show_system);
+				success = listConversions(pattern, verbose, show_system);
 				break;
 			case 'C':
-				success = listCasts(pattern, show_verbose);
+				success = listCasts(pattern, verbose);
 				break;
 			case 'd':
 				if (strncmp(cmd, "ddp", 3) == 0)
@@ -786,7 +784,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd)
 					success = objectDescription(pattern, show_system);
 				break;
 			case 'D':
-				success = listDomains(pattern, show_verbose, show_system);
+				success = listDomains(pattern, verbose, show_system);
 				break;
 			case 'f':			/* function subsystem */
 				switch (cmd[2])
@@ -800,7 +798,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd)
 					case 't':
 					case 'w':
 						success = exec_command_dfo(scan_state, cmd, pattern,
-												   show_verbose, show_system);
+												   verbose, show_system);
 						break;
 					default:
 						status = PSQL_CMD_UNKNOWN;
@@ -809,23 +807,23 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd)
 				break;
 			case 'g':
 				/* no longer distinct from \du */
-				success = describeRoles(pattern, show_verbose, show_system);
+				success = describeRoles(pattern, verbose, show_system);
 				break;
 			case 'l':
 				success = do_lo_list();
 				break;
 			case 'L':
-				success = listLanguages(pattern, show_verbose, show_system);
+				success = listLanguages(pattern, verbose, show_system);
 				break;
 			case 'n':
 				success = listSchemas(pattern, verbose, show_system);
 				break;
 			case 'o':
 				success = exec_command_dfo(scan_state, cmd, pattern,
-										   show_verbose, show_system);
+										   verbose, show_system);
 				break;
 			case 'O':
-				success = listCollations(pattern, show_verbose, show_system);
+				success = listCollations(pattern, verbose, show_system);
 				break;
 			case 'p':
 				success = permissionsList(pattern);
@@ -839,7 +837,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd)
 						case 't':
 						case 'i':
 						case 'n':
-							success = listPartitionedTables(&cmd[2], pattern, show_verbose);
+							success = listPartitionedTables(&cmd[2], pattern, verbose);
 							break;
 						default:
 							status = PSQL_CMD_UNKNOWN;
@@ -848,7 +846,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd)
 				}
 				break;
 			case 'T':
-				success = describeTypes(pattern, show_verbose, show_system);
+				success = describeTypes(pattern, verbose, show_system);
 				break;
 			case 't':
 			case 'v':
@@ -856,7 +854,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd)
 			case 'i':
 			case 's':
 			case 'E':
-				success = listTables(&cmd[1], pattern, show_verbose, show_system);
+				success = listTables(&cmd[1], pattern, verbose, show_system);
 				break;
 			case 'r':
 				if (cmd[2] == 'd' && cmd[3] == 's')
@@ -878,36 +876,36 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd)
 				switch (cmd[2])
 				{
 					case 'p':
-						if (show_verbose)
+						if (verbose > 0)
 							success = describePublications(pattern);
 						else
 							success = listPublications(pattern);
 						break;
 					case 's':
-						success = describeSubscriptions(pattern, show_verbose);
+						success = describeSubscriptions(pattern, verbose);
 						break;
 					default:
 						status = PSQL_CMD_UNKNOWN;
 				}
 				break;
 			case 'u':
-				success = describeRoles(pattern, show_verbose, show_system);
+				success = describeRoles(pattern, verbose, show_system);
 				break;
 			case 'F':			/* text search subsystem */
 				switch (cmd[2])
 				{
 					case '\0':
 					case '+':
-						success = listTSConfigs(pattern, show_verbose);
+						success = listTSConfigs(pattern, verbose);
 						break;
 					case 'p':
-						success = listTSParsers(pattern, show_verbose);
+						success = listTSParsers(pattern, verbose);
 						break;
 					case 'd':
-						success = listTSDictionaries(pattern, show_verbose);
+						success = listTSDictionaries(pattern, verbose);
 						break;
 					case 't':
-						success = listTSTemplates(pattern, show_verbose);
+						success = listTSTemplates(pattern, verbose);
 						break;
 					default:
 						status = PSQL_CMD_UNKNOWN;
@@ -918,16 +916,16 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd)
 				switch (cmd[2])
 				{
 					case 's':
-						success = listForeignServers(pattern, show_verbose);
+						success = listForeignServers(pattern, verbose);
 						break;
 					case 'u':
-						success = listUserMappings(pattern, show_verbose);
+						success = listUserMappings(pattern, verbose);
 						break;
 					case 'w':
-						success = listForeignDataWrappers(pattern, show_verbose);
+						success = listForeignDataWrappers(pattern, verbose);
 						break;
 					case 't':
-						success = listForeignTables(pattern, show_verbose);
+						success = listForeignTables(pattern, verbose);
 						break;
 					default:
 						status = PSQL_CMD_UNKNOWN;
@@ -935,7 +933,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd)
 				}
 				break;
 			case 'x':			/* Extensions */
-				if (show_verbose)
+				if (verbose > 0)
 					success = listExtensionContents(pattern);
 				else
 					success = listExtensions(pattern);
@@ -944,7 +942,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd)
 				success = listExtendedStats(pattern);
 				break;
 			case 'y':			/* Event Triggers */
-				success = listEventTriggers(pattern, show_verbose);
+				success = listEventTriggers(pattern, verbose);
 				break;
 			default:
 				status = PSQL_CMD_UNKNOWN;
@@ -966,7 +964,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd)
 static bool
 exec_command_dfo(PsqlScanState scan_state, const char *cmd,
 				 const char *pattern,
-				 bool show_verbose, bool show_system)
+				 int verbose, bool show_system)
 {
 	bool		success;
 	char	   *arg_patterns[FUNC_MAX_ARGS];
@@ -989,11 +987,11 @@ exec_command_dfo(PsqlScanState scan_state, const char *cmd,
 	if (cmd[1] == 'f')
 		success = describeFunctions(&cmd[2], pattern,
 									arg_patterns, num_arg_patterns,
-									show_verbose, show_system);
+									verbose, show_system);
 	else
 		success = describeOperators(pattern,
 									arg_patterns, num_arg_patterns,
-									show_verbose, show_system);
+									verbose, show_system);
 
 	while (--num_arg_patterns >= 0)
 		free(arg_patterns[num_arg_patterns]);
diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index ce04dbb9ce..d6e3fee154 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -32,7 +32,7 @@ static const char *map_typename_pattern(const char *pattern);
 static bool describeOneTableDetails(const char *schemaname,
 									const char *relationname,
 									const char *oid,
-									bool verbose);
+									int verbose);
 static void add_tablespace_footer(printTableContent *const cont, char relkind,
 								  Oid tablespace, const bool newline);
 static void add_role_attribute(PQExpBuffer buf, const char *const str);
@@ -61,7 +61,7 @@ static bool listOneExtensionContents(const char *extname, const char *oid);
  * Takes an optional regexp to select particular aggregates
  */
 bool
-describeAggregates(const char *pattern, bool verbose, bool showSystem)
+describeAggregates(const char *pattern, int verbose, bool showSystem)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -177,7 +177,7 @@ describeAccessMethods(const char *pattern, int verbose)
 					  gettext_noop("Table"),
 					  gettext_noop("Type"));
 
-	if (verbose)
+	if (verbose > 0)
 	{
 		appendPQExpBuffer(&buf,
 						  ",\n  amhandler AS \"%s\",\n"
@@ -257,13 +257,13 @@ describeTablespaces(const char *pattern, int verbose)
 						  gettext_noop("Owner"),
 						  gettext_noop("Location"));
 
-	if (verbose)
+	if (verbose > 0)
 	{
 		appendPQExpBufferStr(&buf, ",\n  ");
 		printACLColumn(&buf, "spcacl");
 	}
 
-	if (verbose && pset.sversion >= 90000)
+	if (verbose > 0 && pset.sversion >= 90000)
 		appendPQExpBuffer(&buf,
 						  ",\n  spcoptions AS \"%s\"",
 						  gettext_noop("Options"));
@@ -273,7 +273,7 @@ describeTablespaces(const char *pattern, int verbose)
 						  ",\n  pg_catalog.pg_size_pretty(pg_catalog.pg_tablespace_size(oid)) AS \"%s\"",
 						  gettext_noop("Size"));
 
-	if (verbose && pset.sversion >= 80200)
+	if (verbose > 0 && pset.sversion >= 80200)
 		appendPQExpBuffer(&buf,
 						  ",\n  pg_catalog.shobj_description(oid, 'pg_tablespace') AS \"%s\"",
 						  gettext_noop("Description"));
@@ -320,7 +320,7 @@ describeTablespaces(const char *pattern, int verbose)
 bool
 describeFunctions(const char *functypes, const char *func_pattern,
 				  char **arg_patterns, int num_arg_patterns,
-				  bool verbose, bool showSystem)
+				  int verbose, bool showSystem)
 {
 	bool		showAggregate = strchr(functypes, 'a') != NULL;
 	bool		showNormal = strchr(functypes, 'n') != NULL;
@@ -480,7 +480,7 @@ describeFunctions(const char *functypes, const char *func_pattern,
 						  gettext_noop("func"),
 						  gettext_noop("Type"));
 
-	if (verbose)
+	if (verbose > 0)
 	{
 		appendPQExpBuffer(&buf,
 						  ",\n CASE\n"
@@ -540,7 +540,7 @@ describeFunctions(const char *functypes, const char *func_pattern,
 						  i, i, i, i, i, i);
 	}
 
-	if (verbose)
+	if (verbose > 0)
 		appendPQExpBufferStr(&buf,
 							 "     LEFT JOIN pg_catalog.pg_language l ON l.oid = p.prolang\n");
 
@@ -719,7 +719,7 @@ describeFunctions(const char *functypes, const char *func_pattern,
  * describe types
  */
 bool
-describeTypes(const char *pattern, bool verbose, bool showSystem)
+describeTypes(const char *pattern, int verbose, bool showSystem)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -732,7 +732,7 @@ describeTypes(const char *pattern, bool verbose, bool showSystem)
 					  "  pg_catalog.format_type(t.oid, NULL) AS \"%s\",\n",
 					  gettext_noop("Schema"),
 					  gettext_noop("Name"));
-	if (verbose)
+	if (verbose > 0)
 		appendPQExpBuffer(&buf,
 						  "  t.typname AS \"%s\",\n"
 						  "  CASE WHEN t.typrelid != 0\n"
@@ -743,7 +743,7 @@ describeTypes(const char *pattern, bool verbose, bool showSystem)
 						  "  END AS \"%s\",\n",
 						  gettext_noop("Internal name"),
 						  gettext_noop("Size"));
-	if (verbose && pset.sversion >= 80300)
+	if (verbose > 0 && pset.sversion >= 80300)
 	{
 		appendPQExpBufferStr(&buf,
 							 "  pg_catalog.array_to_string(\n"
@@ -765,13 +765,13 @@ describeTypes(const char *pattern, bool verbose, bool showSystem)
 						  "  ) AS \"%s\",\n",
 						  gettext_noop("Elements"));
 	}
-	if (verbose)
+	if (verbose > 0)
 	{
 		appendPQExpBuffer(&buf,
 						  "  pg_catalog.pg_get_userbyid(t.typowner) AS \"%s\",\n",
 						  gettext_noop("Owner"));
 	}
-	if (verbose && pset.sversion >= 90200)
+	if (verbose > 0 && pset.sversion >= 90200)
 	{
 		printACLColumn(&buf, "t.typacl");
 		appendPQExpBufferStr(&buf, ",\n  ");
@@ -895,7 +895,7 @@ map_typename_pattern(const char *pattern)
 bool
 describeOperators(const char *oper_pattern,
 				  char **arg_patterns, int num_arg_patterns,
-				  bool verbose, bool showSystem)
+				  int verbose, bool showSystem)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -932,7 +932,7 @@ describeOperators(const char *oper_pattern,
 					  gettext_noop("Right arg type"),
 					  gettext_noop("Result type"));
 
-	if (verbose)
+	if (verbose > 0)
 		appendPQExpBuffer(&buf,
 						  "  o.oprcode AS \"%s\",\n",
 						  gettext_noop("Function"));
@@ -1058,17 +1058,17 @@ listAllDbs(const char *pattern, int verbose)
 						  "            ELSE 'No Access'\n"
 						  "       END as \"%s\"",
 						  gettext_noop("Size"));
-	if (verbose && pset.sversion >= 80000)
+	if (verbose > 0 && pset.sversion >= 80000)
 		appendPQExpBuffer(&buf,
 						  ",\n       t.spcname as \"%s\"",
 						  gettext_noop("Tablespace"));
-	if (verbose && pset.sversion >= 80200)
+	if (verbose > 0 && pset.sversion >= 80200)
 		appendPQExpBuffer(&buf,
 						  ",\n       pg_catalog.shobj_description(d.oid, 'pg_database') as \"%s\"",
 						  gettext_noop("Description"));
 	appendPQExpBufferStr(&buf,
 						 "\nFROM pg_catalog.pg_database d\n");
-	if (verbose && pset.sversion >= 80000)
+	if (verbose > 0 && pset.sversion >= 80000)
 		appendPQExpBufferStr(&buf,
 							 "  JOIN pg_catalog.pg_tablespace t on d.dattablespace = t.oid\n");
 
@@ -1532,10 +1532,10 @@ objectDescription(const char *pattern, bool showSystem)
  * This routine finds the tables to be displayed, and calls
  * describeOneTableDetails for each one.
  *
- * verbose: if true, this is \d+
+ * verbose: this is \d+ (or \d++)
  */
 bool
-describeTableDetails(const char *pattern, bool verbose, bool showSystem)
+describeTableDetails(const char *pattern, int verbose, bool showSystem)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -1616,7 +1616,7 @@ static bool
 describeOneTableDetails(const char *schemaname,
 						const char *relationname,
 						const char *oid,
-						bool verbose)
+						int verbose)
 {
 	bool		retval = false;
 	PQExpBufferData buf;
@@ -2055,7 +2055,7 @@ describeOneTableDetails(const char *schemaname,
 							 "  pg_catalog.pg_options_to_table(attfdwoptions)), ', ') || ')' END AS attfdwoptions");
 		fdwopts_col = cols++;
 	}
-	if (verbose)
+	if (verbose > 0)
 	{
 		appendPQExpBufferStr(&buf, ",\n  a.attstorage");
 		attstorage_col = cols++;
@@ -2318,7 +2318,7 @@ describeOneTableDetails(const char *schemaname,
 						  "false as inhdetachpending");
 
 		/* If verbose, also request the partition constraint definition */
-		if (verbose)
+		if (verbose > 0)
 			appendPQExpBufferStr(&buf,
 								 ",\n  pg_catalog.pg_get_partition_constraintdef(c.oid)");
 		appendPQExpBuffer(&buf,
@@ -2341,7 +2341,7 @@ describeOneTableDetails(const char *schemaname,
 							  strcmp(detached, "t") == 0 ? " DETACH PENDING" : "");
 			printTableAddFooter(&cont, tmpbuf.data);
 
-			if (verbose)
+			if (verbose > 0)
 			{
 				char	   *partconstraintdef = NULL;
 
@@ -3548,7 +3548,7 @@ describeOneTableDetails(const char *schemaname,
 			printfPQExpBuffer(&buf, _("Number of partitions: %d"), tuples);
 			printTableAddFooter(&cont, buf.data);
 		}
-		else if (!verbose)
+		else if (verbose == 0)
 		{
 			/* print the number of child tables, if any */
 			if (tuples > 0)
@@ -3598,7 +3598,7 @@ describeOneTableDetails(const char *schemaname,
 			printTableAddFooter(&cont, buf.data);
 		}
 
-		if (verbose &&
+		if (verbose > 0 &&
 			(tableinfo.relkind == RELKIND_RELATION ||
 			 tableinfo.relkind == RELKIND_MATVIEW) &&
 
@@ -3622,7 +3622,7 @@ describeOneTableDetails(const char *schemaname,
 		}
 
 		/* OIDs, if verbose and not a materialized view */
-		if (verbose && tableinfo.relkind != RELKIND_MATVIEW && tableinfo.hasoids)
+		if (verbose > 0 && tableinfo.relkind != RELKIND_MATVIEW && tableinfo.hasoids)
 			printTableAddFooter(&cont, _("Has OIDs: yes"));
 
 		/* Tablespace info */
@@ -3630,7 +3630,7 @@ describeOneTableDetails(const char *schemaname,
 							  true);
 
 		/* Access method info */
-		if (verbose && tableinfo.relam != NULL && !pset.hide_tableam)
+		if (verbose > 0 && tableinfo.relam != NULL && !pset.hide_tableam)
 		{
 			printfPQExpBuffer(&buf, _("Access method: %s"), tableinfo.relam);
 			printTableAddFooter(&cont, buf.data);
@@ -3638,7 +3638,7 @@ describeOneTableDetails(const char *schemaname,
 	}
 
 	/* reloptions, if verbose */
-	if (verbose &&
+	if (verbose > 0 &&
 		tableinfo.reloptions && tableinfo.reloptions[0] != '\0')
 	{
 		const char *t = _("Options");
@@ -3741,7 +3741,7 @@ add_tablespace_footer(printTableContent *const cont, char relkind,
  * Describes roles.  Any schema portion of the pattern is ignored.
  */
 bool
-describeRoles(const char *pattern, bool verbose, bool showSystem)
+describeRoles(const char *pattern, int verbose, bool showSystem)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -3769,7 +3769,7 @@ describeRoles(const char *pattern, bool verbose, bool showSystem)
 						  "        JOIN pg_catalog.pg_roles b ON (m.roleid = b.oid)\n"
 						  "        WHERE m.member = r.oid) as memberof");
 
-		if (verbose && pset.sversion >= 80200)
+		if (verbose > 0 && pset.sversion >= 80200)
 		{
 			appendPQExpBufferStr(&buf, "\n, pg_catalog.shobj_description(r.oid, 'pg_authid') AS description");
 			ncols++;
@@ -3824,7 +3824,7 @@ describeRoles(const char *pattern, bool verbose, bool showSystem)
 	/* ignores implicit memberships from superuser & pg_database_owner */
 	printTableAddHeader(&cont, gettext_noop("Member of"), true, align);
 
-	if (verbose && pset.sversion >= 80200)
+	if (verbose > 0 && pset.sversion >= 80200)
 		printTableAddHeader(&cont, gettext_noop("Description"), true, align);
 
 	for (i = 0; i < nrows; i++)
@@ -3884,7 +3884,7 @@ describeRoles(const char *pattern, bool verbose, bool showSystem)
 
 		printTableAddCell(&cont, PQgetvalue(res, i, 8), false, false);
 
-		if (verbose && pset.sversion >= 80200)
+		if (verbose > 0 && pset.sversion >= 80200)
 			printTableAddCell(&cont, PQgetvalue(res, i, 9), false, false);
 	}
 	termPQExpBuffer(&buf);
@@ -3997,7 +3997,7 @@ listDbRoleSettings(const char *pattern, const char *pattern2)
  * (any order of the above is fine)
  */
 bool
-listTables(const char *tabtypes, const char *pattern, bool verbose, bool showSystem)
+listTables(const char *tabtypes, const char *pattern, int verbose, bool showSystem)
 {
 	bool		showTables = strchr(tabtypes, 't') != NULL;
 	bool		showIndexes = strchr(tabtypes, 'i') != NULL;
@@ -4062,7 +4062,7 @@ listTables(const char *tabtypes, const char *pattern, bool verbose, bool showSys
 		cols_so_far++;
 	}
 
-	if (verbose)
+	if (verbose > 0)
 	{
 		/*
 		 * Show whether a relation is permanent, temporary, or unlogged.  Like
@@ -4213,7 +4213,7 @@ listTables(const char *tabtypes, const char *pattern, bool verbose, bool showSys
  * and you can mix and match these in any order.
  */
 bool
-listPartitionedTables(const char *reltypes, const char *pattern, bool verbose)
+listPartitionedTables(const char *reltypes, const char *pattern, int verbose)
 {
 	bool		showTables = strchr(reltypes, 't') != NULL;
 	bool		showIndexes = strchr(reltypes, 'i') != NULL;
@@ -4288,7 +4288,7 @@ listPartitionedTables(const char *reltypes, const char *pattern, bool verbose)
 						  ",\n c2.oid::regclass as \"%s\"",
 						  gettext_noop("Table"));
 
-	if (verbose)
+	if (verbose > 0)
 	{
 		if (showNested)
 		{
@@ -4323,7 +4323,7 @@ listPartitionedTables(const char *reltypes, const char *pattern, bool verbose)
 		appendPQExpBufferStr(&buf,
 							 "\n     LEFT JOIN pg_catalog.pg_inherits inh ON c.oid = inh.inhrelid");
 
-	if (verbose)
+	if (verbose > 0)
 	{
 		if (pset.sversion < 120000)
 		{
@@ -4409,7 +4409,7 @@ listPartitionedTables(const char *reltypes, const char *pattern, bool verbose)
  * Describes languages.
  */
 bool
-listLanguages(const char *pattern, bool verbose, bool showSystem)
+listLanguages(const char *pattern, int verbose, bool showSystem)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -4429,7 +4429,7 @@ listLanguages(const char *pattern, bool verbose, bool showSystem)
 					  "       l.lanpltrusted AS \"%s\"",
 					  gettext_noop("Trusted"));
 
-	if (verbose)
+	if (verbose > 0)
 	{
 		appendPQExpBuffer(&buf,
 						  ",\n       NOT l.lanispl AS \"%s\",\n"
@@ -4484,7 +4484,7 @@ listLanguages(const char *pattern, bool verbose, bool showSystem)
  * Describes domains.
  */
 bool
-listDomains(const char *pattern, bool verbose, bool showSystem)
+listDomains(const char *pattern, int verbose, bool showSystem)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -4515,7 +4515,7 @@ listDomains(const char *pattern, bool verbose, bool showSystem)
 					  gettext_noop("Default"),
 					  gettext_noop("Check"));
 
-	if (verbose)
+	if (verbose > 0)
 	{
 		if (pset.sversion >= 90200)
 		{
@@ -4531,7 +4531,7 @@ listDomains(const char *pattern, bool verbose, bool showSystem)
 						 "\nFROM pg_catalog.pg_type t\n"
 						 "     LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace\n");
 
-	if (verbose)
+	if (verbose > 0)
 		appendPQExpBufferStr(&buf,
 							 "     LEFT JOIN pg_catalog.pg_description d "
 							 "ON d.classoid = t.tableoid AND d.objoid = t.oid "
@@ -4570,7 +4570,7 @@ listDomains(const char *pattern, bool verbose, bool showSystem)
  * Describes conversions.
  */
 bool
-listConversions(const char *pattern, bool verbose, bool showSystem)
+listConversions(const char *pattern, int verbose, bool showSystem)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -4594,7 +4594,7 @@ listConversions(const char *pattern, bool verbose, bool showSystem)
 					  gettext_noop("yes"), gettext_noop("no"),
 					  gettext_noop("Default?"));
 
-	if (verbose)
+	if (verbose > 0)
 		appendPQExpBuffer(&buf,
 						  ",\n       d.description AS \"%s\"",
 						  gettext_noop("Description"));
@@ -4604,7 +4604,7 @@ listConversions(const char *pattern, bool verbose, bool showSystem)
 						 "     JOIN pg_catalog.pg_namespace n "
 						 "ON n.oid = c.connamespace\n");
 
-	if (verbose)
+	if (verbose > 0)
 		appendPQExpBufferStr(&buf,
 							 "LEFT JOIN pg_catalog.pg_description d "
 							 "ON d.classoid = c.tableoid\n"
@@ -4646,7 +4646,7 @@ listConversions(const char *pattern, bool verbose, bool showSystem)
  * Describes Event Triggers.
  */
 bool
-listEventTriggers(const char *pattern, bool verbose)
+listEventTriggers(const char *pattern, int verbose)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -4677,7 +4677,7 @@ listEventTriggers(const char *pattern, bool verbose)
 					  gettext_noop("Enabled"),
 					  gettext_noop("Function"),
 					  gettext_noop("Tags"));
-	if (verbose)
+	if (verbose > 0)
 		appendPQExpBuffer(&buf,
 						  ",\npg_catalog.obj_description(e.oid, 'pg_event_trigger') as \"%s\"",
 						  gettext_noop("Description"));
@@ -4804,7 +4804,7 @@ listExtendedStats(const char *pattern)
  * Describes casts.
  */
 bool
-listCasts(const char *pattern, bool verbose)
+listCasts(const char *pattern, int verbose)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -4852,7 +4852,7 @@ listCasts(const char *pattern, bool verbose)
 					  gettext_noop("yes"),
 					  gettext_noop("Implicit?"));
 
-	if (verbose)
+	if (verbose > 0)
 		appendPQExpBuffer(&buf,
 						  ",\n       d.description AS \"%s\"",
 						  gettext_noop("Description"));
@@ -4873,7 +4873,7 @@ listCasts(const char *pattern, bool verbose)
 						 "     LEFT JOIN pg_catalog.pg_namespace nt\n"
 						 "     ON nt.oid = tt.typnamespace\n");
 
-	if (verbose)
+	if (verbose > 0)
 		appendPQExpBufferStr(&buf,
 							 "     LEFT JOIN pg_catalog.pg_description d\n"
 							 "     ON d.classoid = c.tableoid AND d.objoid = "
@@ -4922,7 +4922,7 @@ listCasts(const char *pattern, bool verbose)
  * Describes collations.
  */
 bool
-listCollations(const char *pattern, bool verbose, bool showSystem)
+listCollations(const char *pattern, int verbose, bool showSystem)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -4971,7 +4971,7 @@ listCollations(const char *pattern, bool verbose, bool showSystem)
 						  gettext_noop("yes"),
 						  gettext_noop("Deterministic?"));
 
-	if (verbose)
+	if (verbose > 0)
 		appendPQExpBuffer(&buf,
 						  ",\n       pg_catalog.obj_description(c.oid, 'pg_collation') AS \"%s\"",
 						  gettext_noop("Description"));
@@ -5034,7 +5034,7 @@ listSchemas(const char *pattern, int verbose, bool showSystem)
 					  gettext_noop("Name"),
 					  gettext_noop("Owner"));
 
-	if (verbose)
+	if (verbose > 0)
 	{
 		appendPQExpBufferStr(&buf, ",\n  ");
 		printACLColumn(&buf, "n.nspacl");
@@ -5083,7 +5083,7 @@ listSchemas(const char *pattern, int verbose, bool showSystem)
  * list text search parsers
  */
 bool
-listTSParsers(const char *pattern, bool verbose)
+listTSParsers(const char *pattern, int verbose)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -5099,7 +5099,7 @@ listTSParsers(const char *pattern, bool verbose)
 		return true;
 	}
 
-	if (verbose)
+	if (verbose > 0)
 		return listTSParsersVerbose(pattern);
 
 	initPQExpBuffer(&buf);
@@ -5330,7 +5330,7 @@ describeOneTSParser(const char *oid, const char *nspname, const char *prsname)
  * list text search dictionaries
  */
 bool
-listTSDictionaries(const char *pattern, bool verbose)
+listTSDictionaries(const char *pattern, int verbose)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -5355,7 +5355,7 @@ listTSDictionaries(const char *pattern, bool verbose)
 					  gettext_noop("Schema"),
 					  gettext_noop("Name"));
 
-	if (verbose)
+	if (verbose > 0)
 	{
 		appendPQExpBuffer(&buf,
 						  "  ( SELECT COALESCE(nt.nspname, '(null)')::pg_catalog.text || '.' || t.tmplname FROM\n"
@@ -5401,7 +5401,7 @@ listTSDictionaries(const char *pattern, bool verbose)
  * list text search templates
  */
 bool
-listTSTemplates(const char *pattern, bool verbose)
+listTSTemplates(const char *pattern, int verbose)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -5419,7 +5419,7 @@ listTSTemplates(const char *pattern, bool verbose)
 
 	initPQExpBuffer(&buf);
 
-	if (verbose)
+	if (verbose > 0)
 		printfPQExpBuffer(&buf,
 						  "SELECT\n"
 						  "  n.nspname AS \"%s\",\n"
@@ -5472,7 +5472,7 @@ listTSTemplates(const char *pattern, bool verbose)
  * list text search configurations
  */
 bool
-listTSConfigs(const char *pattern, bool verbose)
+listTSConfigs(const char *pattern, int verbose)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -5488,7 +5488,7 @@ listTSConfigs(const char *pattern, bool verbose)
 		return true;
 	}
 
-	if (verbose)
+	if (verbose > 0)
 		return listTSConfigsVerbose(pattern);
 
 	initPQExpBuffer(&buf);
@@ -5678,7 +5678,7 @@ describeOneTSConfig(const char *oid, const char *nspname, const char *cfgname,
  * Describes foreign-data wrappers
  */
 bool
-listForeignDataWrappers(const char *pattern, bool verbose)
+listForeignDataWrappers(const char *pattern, int verbose)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -5708,7 +5708,7 @@ listForeignDataWrappers(const char *pattern, bool verbose)
 					  "  fdw.fdwvalidator::pg_catalog.regproc AS \"%s\"",
 					  gettext_noop("Validator"));
 
-	if (verbose)
+	if (verbose > 0)
 	{
 		appendPQExpBufferStr(&buf, ",\n  ");
 		printACLColumn(&buf, "fdwacl");
@@ -5729,7 +5729,7 @@ listForeignDataWrappers(const char *pattern, bool verbose)
 
 	appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_foreign_data_wrapper fdw\n");
 
-	if (verbose && pset.sversion >= 90100)
+	if (verbose > 0 && pset.sversion >= 90100)
 		appendPQExpBufferStr(&buf,
 							 "LEFT JOIN pg_catalog.pg_description d\n"
 							 "       ON d.classoid = fdw.tableoid "
@@ -5761,7 +5761,7 @@ listForeignDataWrappers(const char *pattern, bool verbose)
  * Describes foreign servers.
  */
 bool
-listForeignServers(const char *pattern, bool verbose)
+listForeignServers(const char *pattern, int verbose)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -5786,7 +5786,7 @@ listForeignServers(const char *pattern, bool verbose)
 					  gettext_noop("Owner"),
 					  gettext_noop("Foreign-data wrapper"));
 
-	if (verbose)
+	if (verbose > 0)
 	{
 		appendPQExpBufferStr(&buf, ",\n  ");
 		printACLColumn(&buf, "s.srvacl");
@@ -5811,7 +5811,7 @@ listForeignServers(const char *pattern, bool verbose)
 						 "\nFROM pg_catalog.pg_foreign_server s\n"
 						 "     JOIN pg_catalog.pg_foreign_data_wrapper f ON f.oid=s.srvfdw\n");
 
-	if (verbose)
+	if (verbose > 0)
 		appendPQExpBufferStr(&buf,
 							 "LEFT JOIN pg_catalog.pg_description d\n       "
 							 "ON d.classoid = s.tableoid AND d.objoid = s.oid "
@@ -5843,7 +5843,7 @@ listForeignServers(const char *pattern, bool verbose)
  * Describes user mappings.
  */
 bool
-listUserMappings(const char *pattern, bool verbose)
+listUserMappings(const char *pattern, int verbose)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -5866,7 +5866,7 @@ listUserMappings(const char *pattern, bool verbose)
 					  gettext_noop("Server"),
 					  gettext_noop("User name"));
 
-	if (verbose)
+	if (verbose > 0)
 		appendPQExpBuffer(&buf,
 						  ",\n CASE WHEN umoptions IS NULL THEN '' ELSE "
 						  "  '(' || pg_catalog.array_to_string(ARRAY(SELECT "
@@ -5904,7 +5904,7 @@ listUserMappings(const char *pattern, bool verbose)
  * Describes foreign tables.
  */
 bool
-listForeignTables(const char *pattern, bool verbose)
+listForeignTables(const char *pattern, int verbose)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -5929,7 +5929,7 @@ listForeignTables(const char *pattern, bool verbose)
 					  gettext_noop("Table"),
 					  gettext_noop("Server"));
 
-	if (verbose)
+	if (verbose > 0)
 		appendPQExpBuffer(&buf,
 						  ",\n CASE WHEN ftoptions IS NULL THEN '' ELSE "
 						  "  '(' || pg_catalog.array_to_string(ARRAY(SELECT "
@@ -5949,7 +5949,7 @@ listForeignTables(const char *pattern, bool verbose)
 						 " ON n.oid = c.relnamespace\n"
 						 "  INNER JOIN pg_catalog.pg_foreign_server s"
 						 " ON s.oid = ft.ftserver\n");
-	if (verbose)
+	if (verbose > 0)
 		appendPQExpBufferStr(&buf,
 							 "   LEFT JOIN pg_catalog.pg_description d\n"
 							 "          ON d.classoid = c.tableoid AND "
@@ -6393,7 +6393,7 @@ describePublications(const char *pattern)
  * Takes an optional regexp to select particular subscriptions
  */
 bool
-describeSubscriptions(const char *pattern, bool verbose)
+describeSubscriptions(const char *pattern, int verbose)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -6423,7 +6423,7 @@ describeSubscriptions(const char *pattern, bool verbose)
 					  gettext_noop("Enabled"),
 					  gettext_noop("Publication"));
 
-	if (verbose)
+	if (verbose > 0)
 	{
 		/* Binary mode and streaming are only supported in v14 and higher */
 		if (pset.sversion >= 140000)
@@ -6504,7 +6504,7 @@ printACLColumn(PQExpBuffer buf, const char *colname)
  */
 bool
 listOperatorClasses(const char *access_method_pattern,
-					const char *type_pattern, bool verbose)
+					const char *type_pattern, int verbose)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -6539,7 +6539,7 @@ listOperatorClasses(const char *access_method_pattern,
 					  gettext_noop("yes"),
 					  gettext_noop("no"),
 					  gettext_noop("Default?"));
-	if (verbose)
+	if (verbose > 0)
 		appendPQExpBuffer(&buf,
 						  ",\n  CASE\n"
 						  "    WHEN pg_catalog.pg_opfamily_is_visible(of.oid)\n"
@@ -6555,7 +6555,7 @@ listOperatorClasses(const char *access_method_pattern,
 						 "  LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.opcnamespace\n"
 						 "  LEFT JOIN pg_catalog.pg_type t ON t.oid = c.opcintype\n"
 						 "  LEFT JOIN pg_catalog.pg_namespace tn ON tn.oid = t.typnamespace\n");
-	if (verbose)
+	if (verbose > 0)
 		appendPQExpBufferStr(&buf,
 							 "  LEFT JOIN pg_catalog.pg_opfamily of ON of.oid = c.opcfamily\n"
 							 "  LEFT JOIN pg_catalog.pg_namespace ofn ON ofn.oid = of.opfnamespace\n");
@@ -6598,7 +6598,7 @@ listOperatorClasses(const char *access_method_pattern,
  */
 bool
 listOperatorFamilies(const char *access_method_pattern,
-					 const char *type_pattern, bool verbose)
+					 const char *type_pattern, int verbose)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -6623,7 +6623,7 @@ listOperatorFamilies(const char *access_method_pattern,
 					  gettext_noop("AM"),
 					  gettext_noop("Operator family"),
 					  gettext_noop("Applicable types"));
-	if (verbose)
+	if (verbose > 0)
 		appendPQExpBuffer(&buf,
 						  ",\n  pg_catalog.pg_get_userbyid(f.opfowner) AS \"%s\"\n",
 						  gettext_noop("Owner"));
@@ -6680,7 +6680,7 @@ listOperatorFamilies(const char *access_method_pattern,
  */
 bool
 listOpFamilyOperators(const char *access_method_pattern,
-					  const char *family_pattern, bool verbose)
+					  const char *family_pattern, int verbose)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -6713,7 +6713,7 @@ listOpFamilyOperators(const char *access_method_pattern,
 					  gettext_noop("search"),
 					  gettext_noop("Purpose"));
 
-	if (verbose)
+	if (verbose > 0)
 		appendPQExpBuffer(&buf,
 						  ", ofs.opfname AS \"%s\"\n",
 						  gettext_noop("Sort opfamily"));
@@ -6722,7 +6722,7 @@ listOpFamilyOperators(const char *access_method_pattern,
 						 "  LEFT JOIN pg_catalog.pg_opfamily of ON of.oid = o.amopfamily\n"
 						 "  LEFT JOIN pg_catalog.pg_am am ON am.oid = of.opfmethod AND am.oid = o.amopmethod\n"
 						 "  LEFT JOIN pg_catalog.pg_namespace nsf ON of.opfnamespace = nsf.oid\n");
-	if (verbose)
+	if (verbose > 0)
 		appendPQExpBufferStr(&buf,
 							 "  LEFT JOIN pg_catalog.pg_opfamily ofs ON ofs.oid = o.amopsortfamily\n");
 
@@ -6767,7 +6767,7 @@ listOpFamilyOperators(const char *access_method_pattern,
  */
 bool
 listOpFamilyFunctions(const char *access_method_pattern,
-					  const char *family_pattern, bool verbose)
+					  const char *family_pattern, int verbose)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -6794,7 +6794,7 @@ listOpFamilyFunctions(const char *access_method_pattern,
 					  gettext_noop("Registered right type"),
 					  gettext_noop("Number"));
 
-	if (!verbose)
+	if (verbose == 0)
 		appendPQExpBuffer(&buf,
 						  ", p.proname AS \"%s\"\n",
 						  gettext_noop("Function"));
diff --git a/src/bin/psql/describe.h b/src/bin/psql/describe.h
index edeea38580..cdf286242b 100644
--- a/src/bin/psql/describe.h
+++ b/src/bin/psql/describe.h
@@ -10,7 +10,7 @@
 
 
 /* \da */
-extern bool describeAggregates(const char *pattern, bool verbose, bool showSystem);
+extern bool describeAggregates(const char *pattern, int verbose, bool showSystem);
 
 /* \dA */
 extern bool describeAccessMethods(const char *pattern, int verbose);
@@ -21,18 +21,18 @@ extern bool describeTablespaces(const char *pattern, int verbose);
 /* \df, \dfa, \dfn, \dft, \dfw, etc. */
 extern bool describeFunctions(const char *functypes, const char *func_pattern,
 							  char **arg_patterns, int num_arg_patterns,
-							  bool verbose, bool showSystem);
+							  int verbose, bool showSystem);
 
 /* \dT */
-extern bool describeTypes(const char *pattern, bool verbose, bool showSystem);
+extern bool describeTypes(const char *pattern, int verbose, bool showSystem);
 
 /* \do */
 extern bool describeOperators(const char *oper_pattern,
 							  char **arg_patterns, int num_arg_patterns,
-							  bool verbose, bool showSystem);
+							  int verbose, bool showSystem);
 
 /* \du, \dg */
-extern bool describeRoles(const char *pattern, bool verbose, bool showSystem);
+extern bool describeRoles(const char *pattern, int verbose, bool showSystem);
 
 /* \drds */
 extern bool listDbRoleSettings(const char *pattern, const char *pattern2);
@@ -47,58 +47,58 @@ extern bool listDefaultACLs(const char *pattern);
 extern bool objectDescription(const char *pattern, bool showSystem);
 
 /* \d foo */
-extern bool describeTableDetails(const char *pattern, bool verbose, bool showSystem);
+extern bool describeTableDetails(const char *pattern, int verbose, bool showSystem);
 
 /* \dF */
-extern bool listTSConfigs(const char *pattern, bool verbose);
+extern bool listTSConfigs(const char *pattern, int verbose);
 
 /* \dFp */
-extern bool listTSParsers(const char *pattern, bool verbose);
+extern bool listTSParsers(const char *pattern, int verbose);
 
 /* \dFd */
-extern bool listTSDictionaries(const char *pattern, bool verbose);
+extern bool listTSDictionaries(const char *pattern, int verbose);
 
 /* \dFt */
-extern bool listTSTemplates(const char *pattern, bool verbose);
+extern bool listTSTemplates(const char *pattern, int verbose);
 
 /* \l */
 extern bool listAllDbs(const char *pattern, int verbose);
 
 /* \dt, \di, \ds, \dS, etc. */
-extern bool listTables(const char *tabtypes, const char *pattern, bool verbose, bool showSystem);
+extern bool listTables(const char *tabtypes, const char *pattern, int verbose, bool showSystem);
 
 /* \dP */
-extern bool listPartitionedTables(const char *reltypes, const char *pattern, bool verbose);
+extern bool listPartitionedTables(const char *reltypes, const char *pattern, int verbose);
 
 /* \dD */
-extern bool listDomains(const char *pattern, bool verbose, bool showSystem);
+extern bool listDomains(const char *pattern, int verbose, bool showSystem);
 
 /* \dc */
-extern bool listConversions(const char *pattern, bool verbose, bool showSystem);
+extern bool listConversions(const char *pattern, int verbose, bool showSystem);
 
 /* \dC */
-extern bool listCasts(const char *pattern, bool verbose);
+extern bool listCasts(const char *pattern, int verbose);
 
 /* \dO */
-extern bool listCollations(const char *pattern, bool verbose, bool showSystem);
+extern bool listCollations(const char *pattern, int verbose, bool showSystem);
 
 /* \dn */
 extern bool listSchemas(const char *pattern, int verbose, bool showSystem);
 
 /* \dew */
-extern bool listForeignDataWrappers(const char *pattern, bool verbose);
+extern bool listForeignDataWrappers(const char *pattern, int verbose);
 
 /* \des */
-extern bool listForeignServers(const char *pattern, bool verbose);
+extern bool listForeignServers(const char *pattern, int verbose);
 
 /* \deu */
-extern bool listUserMappings(const char *pattern, bool verbose);
+extern bool listUserMappings(const char *pattern, int verbose);
 
 /* \det */
-extern bool listForeignTables(const char *pattern, bool verbose);
+extern bool listForeignTables(const char *pattern, int verbose);
 
 /* \dL */
-extern bool listLanguages(const char *pattern, bool verbose, bool showSystem);
+extern bool listLanguages(const char *pattern, int verbose, bool showSystem);
 
 /* \dx */
 extern bool listExtensions(const char *pattern);
@@ -110,7 +110,7 @@ extern bool listExtensionContents(const char *pattern);
 extern bool listExtendedStats(const char *pattern);
 
 /* \dy */
-extern bool listEventTriggers(const char *pattern, bool verbose);
+extern bool listEventTriggers(const char *pattern, int verbose);
 
 /* \dRp */
 bool		listPublications(const char *pattern);
@@ -119,25 +119,25 @@ bool		listPublications(const char *pattern);
 bool		describePublications(const char *pattern);
 
 /* \dRs */
-bool		describeSubscriptions(const char *pattern, bool verbose);
+bool		describeSubscriptions(const char *pattern, int verbose);
 
 /* \dAc */
 extern bool listOperatorClasses(const char *access_method_pattern,
 								const char *opclass_pattern,
-								bool verbose);
+								int verbose);
 
 /* \dAf */
 extern bool listOperatorFamilies(const char *access_method_pattern,
 								 const char *opclass_pattern,
-								 bool verbose);
+								 int verbose);
 
 /* \dAo */
 extern bool listOpFamilyOperators(const char *accessMethod_pattern,
-								  const char *family_pattern, bool verbose);
+								  const char *family_pattern, int verbose);
 
 /* \dAp */
 extern bool listOpFamilyFunctions(const char *access_method_pattern,
-								  const char *family_pattern, bool verbose);
+								  const char *family_pattern, int verbose);
 
 
 #endif							/* DESCRIBE_H */
-- 
2.17.0

>From 4dd48f8ce389d176bf153dcfce601558b9e823fb Mon Sep 17 00:00:00 2001
From: Justin Pryzby <pryz...@telsasoft.com>
Date: Thu, 15 Jul 2021 13:35:26 -0500
Subject: [PATCH v3 4/4] Move the double-plus verbose options to the right-most
 column

---
 src/bin/psql/describe.c | 27 +++++++++++++++------------
 1 file changed, 15 insertions(+), 12 deletions(-)

diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index d6e3fee154..2829d3c0f1 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -268,16 +268,16 @@ describeTablespaces(const char *pattern, int verbose)
 						  ",\n  spcoptions AS \"%s\"",
 						  gettext_noop("Options"));
 
-	if (verbose > 1 && pset.sversion >= 90200)
-		appendPQExpBuffer(&buf,
-						  ",\n  pg_catalog.pg_size_pretty(pg_catalog.pg_tablespace_size(oid)) AS \"%s\"",
-						  gettext_noop("Size"));
-
 	if (verbose > 0 && pset.sversion >= 80200)
 		appendPQExpBuffer(&buf,
 						  ",\n  pg_catalog.shobj_description(oid, 'pg_tablespace') AS \"%s\"",
 						  gettext_noop("Description"));
 
+	if (verbose > 1 && pset.sversion >= 90200)
+		appendPQExpBuffer(&buf,
+						  ",\n  pg_catalog.pg_size_pretty(pg_catalog.pg_tablespace_size(oid)) AS \"%s\"",
+						  gettext_noop("Size"));
+
 	appendPQExpBufferStr(&buf,
 						 "\nFROM pg_catalog.pg_tablespace\n");
 
@@ -1051,13 +1051,7 @@ listAllDbs(const char *pattern, int verbose)
 						  gettext_noop("Ctype"));
 	appendPQExpBufferStr(&buf, "       ");
 	printACLColumn(&buf, "d.datacl");
-	if (verbose > 1 && pset.sversion >= 80200)
-		appendPQExpBuffer(&buf,
-						  ",\n       CASE WHEN pg_catalog.has_database_privilege(d.datname, 'CONNECT')\n"
-						  "            THEN pg_catalog.pg_size_pretty(pg_catalog.pg_database_size(d.datname))\n"
-						  "            ELSE 'No Access'\n"
-						  "       END as \"%s\"",
-						  gettext_noop("Size"));
+
 	if (verbose > 0 && pset.sversion >= 80000)
 		appendPQExpBuffer(&buf,
 						  ",\n       t.spcname as \"%s\"",
@@ -1066,6 +1060,15 @@ listAllDbs(const char *pattern, int verbose)
 		appendPQExpBuffer(&buf,
 						  ",\n       pg_catalog.shobj_description(d.oid, 'pg_database') as \"%s\"",
 						  gettext_noop("Description"));
+
+	if (verbose > 1 && pset.sversion >= 80200)
+		appendPQExpBuffer(&buf,
+						  ",\n       CASE WHEN pg_catalog.has_database_privilege(d.datname, 'CONNECT')\n"
+						  "            THEN pg_catalog.pg_size_pretty(pg_catalog.pg_database_size(d.datname))\n"
+						  "            ELSE 'No Access'\n"
+						  "       END as \"%s\"",
+						  gettext_noop("Size"));
+
 	appendPQExpBufferStr(&buf,
 						 "\nFROM pg_catalog.pg_database d\n");
 	if (verbose > 0 && pset.sversion >= 80000)
-- 
2.17.0

Reply via email to