agora inbox for [email protected]  
help / color / mirror / Atom feed
[PATCH v2 2/2] print table associated with given TOAST table
34+ messages / 5 participants
[nested] [flat]

* [PATCH v2 2/2] print table associated with given TOAST table
@ 2019-05-01 00:05  Justin Pryzby <[email protected]>
  0 siblings, 0 replies; 34+ messages in thread

From: Justin Pryzby @ 2019-05-01 00:05 UTC (permalink / raw)

---
 src/bin/psql/describe.c | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index d26d986..ebdf18a 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -2152,6 +2152,28 @@ describeOneTableDetails(const char *schemaname,
 		}
 	}
 
+	/* print table associated with given TOAST table */
+	if (tableinfo.relkind == RELKIND_TOASTVALUE)
+	{
+		PGresult   *result = NULL;
+		printfPQExpBuffer(&buf,
+						  "SELECT relnamespace::pg_catalog.regnamespace, relname FROM pg_class WHERE reltoastrelid = '%s'",
+						  oid);
+		result = PSQLexec(buf.data);
+		if (!result) {
+			goto error_return;
+		} else if (1 != PQntuples(result)) {
+			PQclear(result);
+			goto error_return;
+		} else {
+			char	   *schemaname = PQgetvalue(result, 0, 0);
+			char	   *relname = PQgetvalue(result, 0, 1);
+			appendPQExpBuffer(&tmpbuf, _("For table: \"%s.%s\""),
+						  schemaname, relname);
+			printTableAddFooter(&cont, tmpbuf.data);
+		}
+	}
+
 	if (tableinfo.relkind == RELKIND_PARTITIONED_TABLE)
 	{
 		/* Get the partition key information  */
-- 
2.7.4


--brEuL7wsLY8+TuWz--





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

* [PATCH v5] print table associated with given TOAST table
@ 2019-05-01 00:05  Justin Pryzby <[email protected]>
  0 siblings, 0 replies; 34+ messages in thread

From: Justin Pryzby @ 2019-05-01 00:05 UTC (permalink / raw)

---
 src/bin/psql/describe.c            | 28 ++++++++++++++++++++++++++++
 src/test/regress/expected/psql.out | 10 ++++++++++
 src/test/regress/sql/psql.sql      |  3 +++
 3 files changed, 41 insertions(+)

diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index 3ee9c82..13ed2e1 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -2153,6 +2153,34 @@ describeOneTableDetails(const char *schemaname,
 		}
 	}
 
+	/* print table associated with given TOAST table */
+	if (tableinfo.relkind == RELKIND_TOASTVALUE)
+	{
+		PGresult   *result = NULL;
+		printfPQExpBuffer(&buf,
+						  "SELECT c.relnamespace::pg_catalog.regnamespace, c.relname FROM pg_catalog.pg_class c WHERE reltoastrelid = '%s'",
+						  oid);
+		result = PSQLexec(buf.data);
+		if (!result)
+		{
+			goto error_return;
+		}
+		else if (PQntuples(result) != 1)
+		{
+			PQclear(result);
+			goto error_return;
+		}
+		else
+		{
+			char	   *schemaname = PQgetvalue(result, 0, 0);
+			char	   *relname = PQgetvalue(result, 0, 1);
+			appendPQExpBuffer(&tmpbuf, _("For table: \"%s.%s\""),
+						  schemaname, relname);
+			printTableAddFooter(&cont, tmpbuf.data);
+			PQclear(result);
+		}
+	}
+
 	if (tableinfo.relkind == RELKIND_PARTITIONED_TABLE)
 	{
 		/* Get the partition key information  */
diff --git a/src/test/regress/expected/psql.out b/src/test/regress/expected/psql.out
index 9021c80..5c8e439 100644
--- a/src/test/regress/expected/psql.out
+++ b/src/test/regress/expected/psql.out
@@ -4748,3 +4748,13 @@ drop schema testpart;
 set search_path to default;
 set role to default;
 drop role regress_partitioning_role;
+-- slash dee on toast table:
+\d pg_toast.pg_toast_2619
+TOAST table "pg_toast.pg_toast_2619"
+   Column   |  Type   
+------------+---------
+ chunk_id   | oid
+ chunk_seq  | integer
+ chunk_data | bytea
+For table: "pg_catalog.pg_statistic"
+
diff --git a/src/test/regress/sql/psql.sql b/src/test/regress/sql/psql.sql
index cefe41b..b4a232d 100644
--- a/src/test/regress/sql/psql.sql
+++ b/src/test/regress/sql/psql.sql
@@ -1131,3 +1131,6 @@ set search_path to default;
 
 set role to default;
 drop role regress_partitioning_role;
+
+-- slash dee on toast table:
+\d pg_toast.pg_toast_2619
-- 
2.7.4


--Qxx1br4bt0+wmkIi
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
 filename="v5-0002-make-d-pg_toast.foo-show-its-indices.patch"



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

* [PATCH v3] print table associated with given TOAST table
@ 2019-05-01 00:05  Justin Pryzby <[email protected]>
  0 siblings, 0 replies; 34+ messages in thread

From: Justin Pryzby @ 2019-05-01 00:05 UTC (permalink / raw)

---
 src/bin/psql/describe.c | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index c65bc82..ff98c4f 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -2153,6 +2153,28 @@ describeOneTableDetails(const char *schemaname,
 		}
 	}
 
+	/* print table associated with given TOAST table */
+	if (tableinfo.relkind == RELKIND_TOASTVALUE)
+	{
+		PGresult   *result = NULL;
+		printfPQExpBuffer(&buf,
+						  "SELECT relnamespace::pg_catalog.regnamespace, relname FROM pg_class WHERE reltoastrelid = '%s'",
+						  oid);
+		result = PSQLexec(buf.data);
+		if (!result) {
+			goto error_return;
+		} else if (1 != PQntuples(result)) {
+			PQclear(result);
+			goto error_return;
+		} else {
+			char	   *schemaname = PQgetvalue(result, 0, 0);
+			char	   *relname = PQgetvalue(result, 0, 1);
+			appendPQExpBuffer(&tmpbuf, _("For table: \"%s.%s\""),
+						  schemaname, relname);
+			printTableAddFooter(&cont, tmpbuf.data);
+		}
+	}
+
 	if (tableinfo.relkind == RELKIND_PARTITIONED_TABLE)
 	{
 		/* Get the partition key information  */
-- 
2.7.4


--AqsLC8rIMeq19msA
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
 filename="v3-0001-make-d-pg_toast.foo-show-its-indices.patch"



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

* [PATCH v3] print table associated with given TOAST table
@ 2019-05-01 00:05  Justin Pryzby <[email protected]>
  0 siblings, 0 replies; 34+ messages in thread

From: Justin Pryzby @ 2019-05-01 00:05 UTC (permalink / raw)

---
 src/bin/psql/describe.c | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index c65bc82..ff98c4f 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -2153,6 +2153,28 @@ describeOneTableDetails(const char *schemaname,
 		}
 	}
 
+	/* print table associated with given TOAST table */
+	if (tableinfo.relkind == RELKIND_TOASTVALUE)
+	{
+		PGresult   *result = NULL;
+		printfPQExpBuffer(&buf,
+						  "SELECT relnamespace::pg_catalog.regnamespace, relname FROM pg_class WHERE reltoastrelid = '%s'",
+						  oid);
+		result = PSQLexec(buf.data);
+		if (!result) {
+			goto error_return;
+		} else if (1 != PQntuples(result)) {
+			PQclear(result);
+			goto error_return;
+		} else {
+			char	   *schemaname = PQgetvalue(result, 0, 0);
+			char	   *relname = PQgetvalue(result, 0, 1);
+			appendPQExpBuffer(&tmpbuf, _("For table: \"%s.%s\""),
+						  schemaname, relname);
+			printTableAddFooter(&cont, tmpbuf.data);
+		}
+	}
+
 	if (tableinfo.relkind == RELKIND_PARTITIONED_TABLE)
 	{
 		/* Get the partition key information  */
-- 
2.7.4


--LpQ9ahxlCli8rRTG
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
 filename="v3-0001-make-d-pg_toast.foo-show-its-indices.patch"



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

* [PATCH v7] print table associated with given TOAST table
@ 2019-05-01 00:05  Justin Pryzby <[email protected]>
  0 siblings, 0 replies; 34+ messages in thread

From: Justin Pryzby @ 2019-05-01 00:05 UTC (permalink / raw)

---
 src/bin/psql/describe.c            | 29 +++++++++++++++++++++++++++++
 src/test/regress/expected/psql.out | 10 ++++++++++
 src/test/regress/sql/psql.sql      |  3 +++
 3 files changed, 42 insertions(+)

diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index 3ee9c82..9cd2e7d 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -2153,6 +2153,35 @@ describeOneTableDetails(const char *schemaname,
 		}
 	}
 
+	/* print table associated with given TOAST table */
+	if (tableinfo.relkind == RELKIND_TOASTVALUE)
+	{
+		PGresult   *result = NULL;
+		printfPQExpBuffer(&buf,
+						  "SELECT n.nspname, c.relname FROM pg_catalog.pg_class c"
+						  " JOIN pg_catalog.pg_namespace n ON n.oid=c.relnamespace"
+						  " WHERE reltoastrelid='%s'", oid);
+		result = PSQLexec(buf.data);
+		if (!result)
+		{
+			goto error_return;
+		}
+		else if (PQntuples(result) != 1)
+		{
+			PQclear(result);
+			goto error_return;
+		}
+		else
+		{
+			char	   *schemaname = PQgetvalue(result, 0, 0);
+			char	   *relname = PQgetvalue(result, 0, 1);
+			appendPQExpBuffer(&tmpbuf, _("For table: \"%s.%s\""),
+						  schemaname, relname);
+			printTableAddFooter(&cont, tmpbuf.data);
+			PQclear(result);
+		}
+	}
+
 	if (tableinfo.relkind == RELKIND_PARTITIONED_TABLE)
 	{
 		/* Get the partition key information  */
diff --git a/src/test/regress/expected/psql.out b/src/test/regress/expected/psql.out
index 9021c80..5c8e439 100644
--- a/src/test/regress/expected/psql.out
+++ b/src/test/regress/expected/psql.out
@@ -4748,3 +4748,13 @@ drop schema testpart;
 set search_path to default;
 set role to default;
 drop role regress_partitioning_role;
+-- slash dee on toast table:
+\d pg_toast.pg_toast_2619
+TOAST table "pg_toast.pg_toast_2619"
+   Column   |  Type   
+------------+---------
+ chunk_id   | oid
+ chunk_seq  | integer
+ chunk_data | bytea
+For table: "pg_catalog.pg_statistic"
+
diff --git a/src/test/regress/sql/psql.sql b/src/test/regress/sql/psql.sql
index cefe41b..b4a232d 100644
--- a/src/test/regress/sql/psql.sql
+++ b/src/test/regress/sql/psql.sql
@@ -1131,3 +1131,6 @@ set search_path to default;
 
 set role to default;
 drop role regress_partitioning_role;
+
+-- slash dee on toast table:
+\d pg_toast.pg_toast_2619
-- 
2.7.4


--ryJZkp9/svQ58syV
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
 filename="v7-0002-make-d-pg_toast.foo-show-its-indices.patch"



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

* [PATCH v5] print table associated with given TOAST table
@ 2019-05-01 00:05  Justin Pryzby <[email protected]>
  0 siblings, 0 replies; 34+ messages in thread

From: Justin Pryzby @ 2019-05-01 00:05 UTC (permalink / raw)

---
 src/bin/psql/describe.c            | 28 ++++++++++++++++++++++++++++
 src/test/regress/expected/psql.out | 10 ++++++++++
 src/test/regress/sql/psql.sql      |  3 +++
 3 files changed, 41 insertions(+)

diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index 3ee9c82..13ed2e1 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -2153,6 +2153,34 @@ describeOneTableDetails(const char *schemaname,
 		}
 	}
 
+	/* print table associated with given TOAST table */
+	if (tableinfo.relkind == RELKIND_TOASTVALUE)
+	{
+		PGresult   *result = NULL;
+		printfPQExpBuffer(&buf,
+						  "SELECT c.relnamespace::pg_catalog.regnamespace, c.relname FROM pg_catalog.pg_class c WHERE reltoastrelid = '%s'",
+						  oid);
+		result = PSQLexec(buf.data);
+		if (!result)
+		{
+			goto error_return;
+		}
+		else if (PQntuples(result) != 1)
+		{
+			PQclear(result);
+			goto error_return;
+		}
+		else
+		{
+			char	   *schemaname = PQgetvalue(result, 0, 0);
+			char	   *relname = PQgetvalue(result, 0, 1);
+			appendPQExpBuffer(&tmpbuf, _("For table: \"%s.%s\""),
+						  schemaname, relname);
+			printTableAddFooter(&cont, tmpbuf.data);
+			PQclear(result);
+		}
+	}
+
 	if (tableinfo.relkind == RELKIND_PARTITIONED_TABLE)
 	{
 		/* Get the partition key information  */
diff --git a/src/test/regress/expected/psql.out b/src/test/regress/expected/psql.out
index 9021c80..5c8e439 100644
--- a/src/test/regress/expected/psql.out
+++ b/src/test/regress/expected/psql.out
@@ -4748,3 +4748,13 @@ drop schema testpart;
 set search_path to default;
 set role to default;
 drop role regress_partitioning_role;
+-- slash dee on toast table:
+\d pg_toast.pg_toast_2619
+TOAST table "pg_toast.pg_toast_2619"
+   Column   |  Type   
+------------+---------
+ chunk_id   | oid
+ chunk_seq  | integer
+ chunk_data | bytea
+For table: "pg_catalog.pg_statistic"
+
diff --git a/src/test/regress/sql/psql.sql b/src/test/regress/sql/psql.sql
index cefe41b..b4a232d 100644
--- a/src/test/regress/sql/psql.sql
+++ b/src/test/regress/sql/psql.sql
@@ -1131,3 +1131,6 @@ set search_path to default;
 
 set role to default;
 drop role regress_partitioning_role;
+
+-- slash dee on toast table:
+\d pg_toast.pg_toast_2619
-- 
2.7.4


--dkEUBIird37B8yKS
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
 filename="v5-0002-make-d-pg_toast.foo-show-its-indices.patch"



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

* [PATCH v3 3/4] f!convert the other verbose to int, too
@ 2021-07-15 08:19  Justin Pryzby <[email protected]>
  0 siblings, 0 replies; 34+ messages in thread

From: Justin Pryzby @ 2021-07-15 08:19 UTC (permalink / raw)

---
 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


--S1BNGpv0yoYahz37
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
 filename="v3-0004-Move-the-double-plus-verbose-options-to-the-right.patch"



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

* [PATCH 3/4] f!convert the other verbose to int, too
@ 2021-07-15 08:19  Justin Pryzby <[email protected]>
  0 siblings, 0 replies; 34+ messages in thread

From: Justin Pryzby @ 2021-07-15 08:19 UTC (permalink / raw)

---
 src/bin/psql/command.c  |  82 ++++++++++----------
 src/bin/psql/describe.c | 163 ++++++++++++++++++++--------------------
 src/bin/psql/describe.h |  58 +++++++-------
 3 files changed, 151 insertions(+), 152 deletions(-)

diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index b695e09017d..5f4cde03250 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -76,7 +76,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,
@@ -756,8 +756,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,
@@ -766,7 +765,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])
@@ -775,10 +773,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':
 				{
@@ -794,16 +792,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;
@@ -814,7 +812,7 @@ 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);
@@ -822,15 +820,15 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd)
 			case 'c':
 				if (strncmp(cmd, "dconfig", 7) == 0)
 					success = describeConfigurationParameters(pattern,
-															  show_verbose,
+															  verbose,
 															  show_system);
 				else
 					success = listConversions(pattern,
-											  show_verbose,
+											  verbose,
 											  show_system);
 				break;
 			case 'C':
-				success = listCasts(pattern, show_verbose);
+				success = listCasts(pattern, verbose);
 				break;
 			case 'd':
 				if (strncmp(cmd, "ddp", 3) == 0)
@@ -839,7 +837,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])
@@ -853,7 +851,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;
@@ -862,23 +860,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 = listLargeObjects(show_verbose);
+				success = listLargeObjects(verbose);
 				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, show_system);
@@ -892,7 +890,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;
@@ -901,7 +899,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':
@@ -909,7 +907,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')
@@ -930,36 +928,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;
@@ -970,16 +968,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;
@@ -987,7 +985,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);
@@ -996,7 +994,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;
@@ -1017,7 +1015,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];
@@ -1040,11 +1038,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]);
@@ -2014,9 +2012,9 @@ exec_command_lo(PsqlScanState scan_state, bool active_branch, const char *cmd)
 		}
 
 		else if (strcmp(cmd + 3, "list") == 0)
-			success = listLargeObjects(false);
+			success = listLargeObjects(0);
 		else if (strcmp(cmd + 3, "list+") == 0)
-			success = listLargeObjects(true);
+			success = listLargeObjects(1);
 
 		else if (strcmp(cmd + 3, "unlink") == 0)
 		{
diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index f7f737e8b59..8ab4b4cb46a 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -33,7 +33,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);
@@ -68,7 +68,7 @@ static bool validateSQLNamePattern(PQExpBuffer buf, const char *pattern,
  * 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;
@@ -169,7 +169,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"
@@ -235,7 +235,7 @@ describeTablespaces(const char *pattern, int verbose)
 					  gettext_noop("Owner"),
 					  gettext_noop("Location"));
 
-	if (verbose)
+	if (verbose > 0)
 	{
 		appendPQExpBufferStr(&buf, ",\n  ");
 		printACLColumn(&buf, "spcacl");
@@ -301,7 +301,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;
@@ -386,7 +386,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"
@@ -441,7 +441,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");
 
@@ -627,7 +627,7 @@ error_return:
  * describe types
  */
 bool
-describeTypes(const char *pattern, bool verbose, bool showSystem)
+describeTypes(const char *pattern, int verbose, bool showSystem)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -640,7 +640,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"
@@ -785,7 +785,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;
@@ -821,7 +821,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"));
@@ -1455,10 +1455,10 @@ error_return:
  * 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;
@@ -1544,7 +1544,7 @@ static bool
 describeOneTableDetails(const char *schemaname,
 						const char *relationname,
 						const char *oid,
-						bool verbose)
+						int verbose)
 {
 	bool		retval = false;
 	PQExpBufferData buf;
@@ -1917,7 +1917,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++;
@@ -2175,7 +2175,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,
@@ -2198,7 +2198,7 @@ describeOneTableDetails(const char *schemaname,
 							  strcmp(detached, "t") == 0 ? " DETACH PENDING" : "");
 			printTableAddFooter(&cont, tmpbuf.data);
 
-			if (verbose)
+			if (verbose > 0)
 			{
 				char	   *partconstraintdef = NULL;
 
@@ -3434,7 +3434,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)
@@ -3486,7 +3486,7 @@ describeOneTableDetails(const char *schemaname,
 			printTableAddFooter(&cont, buf.data);
 		}
 
-		if (verbose &&
+		if (verbose > 0 &&
 			(tableinfo.relkind == RELKIND_RELATION ||
 			 tableinfo.relkind == RELKIND_MATVIEW) &&
 
@@ -3510,7 +3510,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 */
@@ -3518,7 +3518,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);
@@ -3526,7 +3526,7 @@ describeOneTableDetails(const char *schemaname,
 	}
 
 	/* reloptions, if verbose */
-	if (verbose &&
+	if (verbose > 0 &&
 		tableinfo.reloptions && tableinfo.reloptions[0] != '\0')
 	{
 		const char *t = _("Options");
@@ -3626,7 +3626,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;
@@ -3652,11 +3652,12 @@ 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)
+	if (verbose > 0)
 	{
 		appendPQExpBufferStr(&buf, "\n, pg_catalog.shobj_description(r.oid, 'pg_authid') AS description");
 		ncols++;
 	}
+
 	appendPQExpBufferStr(&buf, "\n, r.rolreplication");
 
 	if (pset.sversion >= 90500)
@@ -3693,7 +3694,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)
+	if (verbose > 0)
 		printTableAddHeader(&cont, gettext_noop("Description"), true, align);
 
 	for (i = 0; i < nrows; i++)
@@ -3752,7 +3753,7 @@ describeRoles(const char *pattern, bool verbose, bool showSystem)
 
 		printTableAddCell(&cont, PQgetvalue(res, i, 8), false, false);
 
-		if (verbose)
+		if (verbose > 0)
 			printTableAddCell(&cont, PQgetvalue(res, i, 9), false, false);
 	}
 	termPQExpBuffer(&buf);
@@ -3862,7 +3863,7 @@ error_return:
  * (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;
@@ -3921,7 +3922,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.
@@ -4061,7 +4062,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;
@@ -4136,7 +4137,7 @@ listPartitionedTables(const char *reltypes, const char *pattern, bool verbose)
 						  ",\n c2.oid::pg_catalog.regclass as \"%s\"",
 						  gettext_noop("Table"));
 
-	if (verbose)
+	if (verbose > 0)
 	{
 		if (showNested)
 		{
@@ -4171,7 +4172,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)
 		{
@@ -4262,7 +4263,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;
@@ -4278,7 +4279,7 @@ listLanguages(const char *pattern, bool verbose, bool showSystem)
 					  gettext_noop("Owner"),
 					  gettext_noop("Trusted"));
 
-	if (verbose)
+	if (verbose > 0)
 	{
 		appendPQExpBuffer(&buf,
 						  ",\n       NOT l.lanispl AS \"%s\",\n"
@@ -4339,7 +4340,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;
@@ -4366,7 +4367,7 @@ listDomains(const char *pattern, bool verbose, bool showSystem)
 					  gettext_noop("Default"),
 					  gettext_noop("Check"));
 
-	if (verbose)
+	if (verbose > 0)
 	{
 		appendPQExpBufferStr(&buf, ",\n  ");
 		printACLColumn(&buf, "t.typacl");
@@ -4379,7 +4380,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 "
@@ -4423,7 +4424,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;
@@ -4447,7 +4448,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"));
@@ -4457,7 +4458,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"
@@ -4504,7 +4505,7 @@ listConversions(const char *pattern, bool verbose, bool showSystem)
  * Describes configuration parameters.
  */
 bool
-describeConfigurationParameters(const char *pattern, bool verbose,
+describeConfigurationParameters(const char *pattern, int verbose,
 								bool showSystem)
 {
 	PQExpBufferData buf;
@@ -4573,7 +4574,7 @@ describeConfigurationParameters(const char *pattern, bool verbose,
  * Describes Event Triggers.
  */
 bool
-listEventTriggers(const char *pattern, bool verbose)
+listEventTriggers(const char *pattern, int verbose)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -4614,7 +4615,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"));
@@ -4751,7 +4752,7 @@ listExtendedStats(const char *pattern)
  * Describes casts.
  */
 bool
-listCasts(const char *pattern, bool verbose)
+listCasts(const char *pattern, int verbose)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -4792,7 +4793,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"));
@@ -4813,7 +4814,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 = "
@@ -4870,7 +4871,7 @@ error_return:
  * Describes collations.
  */
 bool
-listCollations(const char *pattern, bool verbose, bool showSystem)
+listCollations(const char *pattern, int verbose, bool showSystem)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -4930,7 +4931,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"));
@@ -5000,7 +5001,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");
@@ -5112,13 +5113,13 @@ error_return:
  * list text search parsers
  */
 bool
-listTSParsers(const char *pattern, bool verbose)
+listTSParsers(const char *pattern, int verbose)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
 	printQueryOpt myopt = pset.popt;
 
-	if (verbose)
+	if (verbose > 0)
 		return listTSParsersVerbose(pattern);
 
 	initPQExpBuffer(&buf);
@@ -5362,7 +5363,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;
@@ -5377,7 +5378,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"
@@ -5428,7 +5429,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;
@@ -5436,7 +5437,7 @@ listTSTemplates(const char *pattern, bool verbose)
 
 	initPQExpBuffer(&buf);
 
-	if (verbose)
+	if (verbose > 0)
 		printfPQExpBuffer(&buf,
 						  "SELECT\n"
 						  "  n.nspname AS \"%s\",\n"
@@ -5494,13 +5495,13 @@ 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;
 	printQueryOpt myopt = pset.popt;
 
-	if (verbose)
+	if (verbose > 0)
 		return listTSConfigsVerbose(pattern);
 
 	initPQExpBuffer(&buf);
@@ -5700,7 +5701,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;
@@ -5717,7 +5718,7 @@ listForeignDataWrappers(const char *pattern, bool verbose)
 					  gettext_noop("Handler"),
 					  gettext_noop("Validator"));
 
-	if (verbose)
+	if (verbose > 0)
 	{
 		appendPQExpBufferStr(&buf, ",\n  ");
 		printACLColumn(&buf, "fdwacl");
@@ -5735,7 +5736,7 @@ listForeignDataWrappers(const char *pattern, bool verbose)
 
 	appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_foreign_data_wrapper fdw\n");
 
-	if (verbose)
+	if (verbose > 0)
 		appendPQExpBufferStr(&buf,
 							 "LEFT JOIN pg_catalog.pg_description d\n"
 							 "       ON d.classoid = fdw.tableoid "
@@ -5772,7 +5773,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;
@@ -5787,7 +5788,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");
@@ -5812,7 +5813,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 "
@@ -5849,7 +5850,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;
@@ -5862,7 +5863,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 "
@@ -5905,7 +5906,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;
@@ -5920,7 +5921,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 "
@@ -5940,7 +5941,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 "
@@ -6504,7 +6505,7 @@ error_return:
  * 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;
@@ -6534,7 +6535,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)
@@ -6645,7 +6646,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;
@@ -6680,7 +6681,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"
@@ -6696,7 +6697,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");
@@ -6747,7 +6748,7 @@ error_return:
  */
 bool
 listOperatorFamilies(const char *access_method_pattern,
-					 const char *type_pattern, bool verbose)
+					 const char *type_pattern, int verbose)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -6772,7 +6773,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"));
@@ -6837,7 +6838,7 @@ error_return:
  */
 bool
 listOpFamilyOperators(const char *access_method_pattern,
-					  const char *family_pattern, bool verbose)
+					  const char *family_pattern, int verbose)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -6870,7 +6871,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"));
@@ -6879,7 +6880,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");
 
@@ -6936,7 +6937,7 @@ error_return:
  */
 bool
 listOpFamilyFunctions(const char *access_method_pattern,
-					  const char *family_pattern, bool verbose)
+					  const char *family_pattern, int verbose)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -6963,7 +6964,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"));
@@ -7025,7 +7026,7 @@ error_return:
  * Lists large objects
  */
 bool
-listLargeObjects(bool verbose)
+listLargeObjects(int verbose)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -7039,7 +7040,7 @@ listLargeObjects(bool verbose)
 					  gettext_noop("ID"),
 					  gettext_noop("Owner"));
 
-	if (verbose)
+	if (verbose > 0)
 	{
 		printACLColumn(&buf, "lomacl");
 		appendPQExpBufferStr(&buf, ",\n  ");
diff --git a/src/bin/psql/describe.h b/src/bin/psql/describe.h
index d2fd8a72a36..23d601fbc97 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,62 +47,62 @@ 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);
 
 /* \dconfig */
-extern bool describeConfigurationParameters(const char *pattern, bool verbose,
+extern bool describeConfigurationParameters(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);
@@ -114,7 +114,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);
@@ -123,27 +123,27 @@ 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 *type_pattern,
-								bool verbose);
+								int verbose);
 
 /* \dAf */
 extern bool listOperatorFamilies(const char *access_method_pattern,
 								 const char *type_pattern,
-								 bool verbose);
+								 int verbose);
 
 /* \dAo */
 extern bool listOpFamilyOperators(const char *access_method_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);
 
 /* \dl or \lo_list */
-extern bool listLargeObjects(bool verbose);
+extern bool listLargeObjects(int verbose);
 
 #endif							/* DESCRIBE_H */
-- 
2.34.1


--mDjj41GS8UJ6l/Dp
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="0004-Move-the-double-plus-Size-columns-to-the-right.patch"



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

* [PATCH 3/4] f!convert the other verbose to int, too
@ 2021-07-15 08:19  Justin Pryzby <[email protected]>
  0 siblings, 0 replies; 34+ messages in thread

From: Justin Pryzby @ 2021-07-15 08:19 UTC (permalink / raw)

---
 src/bin/psql/command.c  |  82 ++++++++++----------
 src/bin/psql/describe.c | 165 ++++++++++++++++++++--------------------
 src/bin/psql/describe.h |  58 +++++++-------
 3 files changed, 152 insertions(+), 153 deletions(-)

diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index 40956cc32dc..e73ad7cc3b5 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -76,7 +76,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,
@@ -755,8 +755,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,
@@ -765,7 +764,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])
@@ -774,10 +772,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':
 				{
@@ -793,16 +791,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;
@@ -813,7 +811,7 @@ 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);
@@ -821,15 +819,15 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd)
 			case 'c':
 				if (strncmp(cmd, "dconfig", 7) == 0)
 					success = describeConfigurationParameters(pattern,
-															  show_verbose,
+															  verbose,
 															  show_system);
 				else
 					success = listConversions(pattern,
-											  show_verbose,
+											  verbose,
 											  show_system);
 				break;
 			case 'C':
-				success = listCasts(pattern, show_verbose);
+				success = listCasts(pattern, verbose);
 				break;
 			case 'd':
 				if (strncmp(cmd, "ddp", 3) == 0)
@@ -838,7 +836,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])
@@ -852,7 +850,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;
@@ -861,23 +859,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 = listLargeObjects(show_verbose);
+				success = listLargeObjects(verbose);
 				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);
@@ -891,7 +889,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;
@@ -900,7 +898,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':
@@ -908,7 +906,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')
@@ -929,36 +927,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;
@@ -969,16 +967,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;
@@ -986,7 +984,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);
@@ -995,7 +993,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;
@@ -1016,7 +1014,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];
@@ -1039,11 +1037,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]);
@@ -2013,9 +2011,9 @@ exec_command_lo(PsqlScanState scan_state, bool active_branch, const char *cmd)
 		}
 
 		else if (strcmp(cmd + 3, "list") == 0)
-			success = listLargeObjects(false);
+			success = listLargeObjects(0);
 		else if (strcmp(cmd + 3, "list+") == 0)
-			success = listLargeObjects(true);
+			success = listLargeObjects(1);
 
 		else if (strcmp(cmd + 3, "unlink") == 0)
 		{
diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index 57666d8c5b8..f7b646062bd 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -33,7 +33,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);
@@ -68,7 +68,7 @@ static bool validateSQLNamePattern(PQExpBuffer buf, const char *pattern,
  * 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;
@@ -169,7 +169,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"
@@ -235,7 +235,7 @@ describeTablespaces(const char *pattern, int verbose)
 					  gettext_noop("Owner"),
 					  gettext_noop("Location"));
 
-	if (verbose)
+	if (verbose > 0)
 	{
 		appendPQExpBufferStr(&buf, ",\n  ");
 		printACLColumn(&buf, "spcacl");
@@ -299,7 +299,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;
@@ -384,7 +384,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"
@@ -444,7 +444,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");
 
@@ -630,7 +630,7 @@ error_return:
  * describe types
  */
 bool
-describeTypes(const char *pattern, bool verbose, bool showSystem)
+describeTypes(const char *pattern, int verbose, bool showSystem)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -643,7 +643,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"
@@ -788,7 +788,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;
@@ -824,7 +824,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"));
@@ -974,7 +974,7 @@ listAllDbs(const char *pattern, int verbose)
 						  gettext_noop("Description"));
 	appendPQExpBufferStr(&buf,
 						 "\nFROM pg_catalog.pg_database d\n");
-	if (verbose)
+	if (verbose > 0)
 		appendPQExpBufferStr(&buf,
 							 "  JOIN pg_catalog.pg_tablespace t on d.dattablespace = t.oid\n");
 
@@ -1442,10 +1442,10 @@ error_return:
  * 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;
@@ -1531,7 +1531,7 @@ static bool
 describeOneTableDetails(const char *schemaname,
 						const char *relationname,
 						const char *oid,
-						bool verbose)
+						int verbose)
 {
 	bool		retval = false;
 	PQExpBufferData buf;
@@ -1904,7 +1904,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++;
@@ -2162,7 +2162,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,
@@ -2185,7 +2185,7 @@ describeOneTableDetails(const char *schemaname,
 							  strcmp(detached, "t") == 0 ? " DETACH PENDING" : "");
 			printTableAddFooter(&cont, tmpbuf.data);
 
-			if (verbose)
+			if (verbose > 0)
 			{
 				char	   *partconstraintdef = NULL;
 
@@ -3421,7 +3421,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)
@@ -3473,7 +3473,7 @@ describeOneTableDetails(const char *schemaname,
 			printTableAddFooter(&cont, buf.data);
 		}
 
-		if (verbose &&
+		if (verbose > 0 &&
 			(tableinfo.relkind == RELKIND_RELATION ||
 			 tableinfo.relkind == RELKIND_MATVIEW) &&
 
@@ -3497,7 +3497,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 */
@@ -3505,7 +3505,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);
@@ -3513,7 +3513,7 @@ describeOneTableDetails(const char *schemaname,
 	}
 
 	/* reloptions, if verbose */
-	if (verbose &&
+	if (verbose > 0 &&
 		tableinfo.reloptions && tableinfo.reloptions[0] != '\0')
 	{
 		const char *t = _("Options");
@@ -3613,7 +3613,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;
@@ -3639,11 +3639,12 @@ 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)
+	if (verbose > 0)
 	{
 		appendPQExpBufferStr(&buf, "\n, pg_catalog.shobj_description(r.oid, 'pg_authid') AS description");
 		ncols++;
 	}
+
 	appendPQExpBufferStr(&buf, "\n, r.rolreplication");
 
 	if (pset.sversion >= 90500)
@@ -3680,7 +3681,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)
+	if (verbose > 0)
 		printTableAddHeader(&cont, gettext_noop("Description"), true, align);
 
 	for (i = 0; i < nrows; i++)
@@ -3739,7 +3740,7 @@ describeRoles(const char *pattern, bool verbose, bool showSystem)
 
 		printTableAddCell(&cont, PQgetvalue(res, i, 8), false, false);
 
-		if (verbose)
+		if (verbose > 0)
 			printTableAddCell(&cont, PQgetvalue(res, i, 9), false, false);
 	}
 	termPQExpBuffer(&buf);
@@ -3852,7 +3853,7 @@ error_return:
  * (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;
@@ -3911,7 +3912,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.
@@ -4051,7 +4052,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;
@@ -4126,7 +4127,7 @@ listPartitionedTables(const char *reltypes, const char *pattern, bool verbose)
 						  ",\n c2.oid::pg_catalog.regclass as \"%s\"",
 						  gettext_noop("Table"));
 
-	if (verbose)
+	if (verbose > 0)
 	{
 		if (showNested)
 		{
@@ -4161,7 +4162,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)
 		{
@@ -4252,7 +4253,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;
@@ -4268,7 +4269,7 @@ listLanguages(const char *pattern, bool verbose, bool showSystem)
 					  gettext_noop("Owner"),
 					  gettext_noop("Trusted"));
 
-	if (verbose)
+	if (verbose > 0)
 	{
 		appendPQExpBuffer(&buf,
 						  ",\n       NOT l.lanispl AS \"%s\",\n"
@@ -4329,7 +4330,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;
@@ -4356,7 +4357,7 @@ listDomains(const char *pattern, bool verbose, bool showSystem)
 					  gettext_noop("Default"),
 					  gettext_noop("Check"));
 
-	if (verbose)
+	if (verbose > 0)
 	{
 		appendPQExpBufferStr(&buf, ",\n  ");
 		printACLColumn(&buf, "t.typacl");
@@ -4369,7 +4370,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 "
@@ -4413,7 +4414,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;
@@ -4437,7 +4438,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"));
@@ -4447,7 +4448,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"
@@ -4494,7 +4495,7 @@ listConversions(const char *pattern, bool verbose, bool showSystem)
  * Describes configuration parameters.
  */
 bool
-describeConfigurationParameters(const char *pattern, bool verbose,
+describeConfigurationParameters(const char *pattern, int verbose,
 								bool showSystem)
 {
 	PQExpBufferData buf;
@@ -4563,7 +4564,7 @@ describeConfigurationParameters(const char *pattern, bool verbose,
  * Describes Event Triggers.
  */
 bool
-listEventTriggers(const char *pattern, bool verbose)
+listEventTriggers(const char *pattern, int verbose)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -4604,7 +4605,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"));
@@ -4741,7 +4742,7 @@ listExtendedStats(const char *pattern)
  * Describes casts.
  */
 bool
-listCasts(const char *pattern, bool verbose)
+listCasts(const char *pattern, int verbose)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -4782,7 +4783,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"));
@@ -4803,7 +4804,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 = "
@@ -4860,7 +4861,7 @@ error_return:
  * Describes collations.
  */
 bool
-listCollations(const char *pattern, bool verbose, bool showSystem)
+listCollations(const char *pattern, int verbose, bool showSystem)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -4908,7 +4909,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"));
@@ -4978,7 +4979,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");
@@ -5090,13 +5091,13 @@ error_return:
  * list text search parsers
  */
 bool
-listTSParsers(const char *pattern, bool verbose)
+listTSParsers(const char *pattern, int verbose)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
 	printQueryOpt myopt = pset.popt;
 
-	if (verbose)
+	if (verbose > 0)
 		return listTSParsersVerbose(pattern);
 
 	initPQExpBuffer(&buf);
@@ -5340,7 +5341,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 +5356,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"
@@ -5406,7 +5407,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;
@@ -5414,7 +5415,7 @@ listTSTemplates(const char *pattern, bool verbose)
 
 	initPQExpBuffer(&buf);
 
-	if (verbose)
+	if (verbose > 0)
 		printfPQExpBuffer(&buf,
 						  "SELECT\n"
 						  "  n.nspname AS \"%s\",\n"
@@ -5472,13 +5473,13 @@ 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;
 	printQueryOpt myopt = pset.popt;
 
-	if (verbose)
+	if (verbose > 0)
 		return listTSConfigsVerbose(pattern);
 
 	initPQExpBuffer(&buf);
@@ -5678,7 +5679,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;
@@ -5695,7 +5696,7 @@ listForeignDataWrappers(const char *pattern, bool verbose)
 					  gettext_noop("Handler"),
 					  gettext_noop("Validator"));
 
-	if (verbose)
+	if (verbose > 0)
 	{
 		appendPQExpBufferStr(&buf, ",\n  ");
 		printACLColumn(&buf, "fdwacl");
@@ -5713,7 +5714,7 @@ listForeignDataWrappers(const char *pattern, bool verbose)
 
 	appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_foreign_data_wrapper fdw\n");
 
-	if (verbose)
+	if (verbose > 0)
 		appendPQExpBufferStr(&buf,
 							 "LEFT JOIN pg_catalog.pg_description d\n"
 							 "       ON d.classoid = fdw.tableoid "
@@ -5750,7 +5751,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;
@@ -5765,7 +5766,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");
@@ -5790,7 +5791,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 "
@@ -5827,7 +5828,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;
@@ -5840,7 +5841,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 "
@@ -5883,7 +5884,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;
@@ -5898,7 +5899,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 "
@@ -5918,7 +5919,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 "
@@ -6482,7 +6483,7 @@ error_return:
  * 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;
@@ -6512,7 +6513,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)
@@ -6606,7 +6607,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;
@@ -6641,7 +6642,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"
@@ -6657,7 +6658,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");
@@ -6708,7 +6709,7 @@ error_return:
  */
 bool
 listOperatorFamilies(const char *access_method_pattern,
-					 const char *type_pattern, bool verbose)
+					 const char *type_pattern, int verbose)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -6733,7 +6734,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"));
@@ -6798,7 +6799,7 @@ error_return:
  */
 bool
 listOpFamilyOperators(const char *access_method_pattern,
-					  const char *family_pattern, bool verbose)
+					  const char *family_pattern, int verbose)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -6831,7 +6832,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"));
@@ -6840,7 +6841,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");
 
@@ -6897,7 +6898,7 @@ error_return:
  */
 bool
 listOpFamilyFunctions(const char *access_method_pattern,
-					  const char *family_pattern, bool verbose)
+					  const char *family_pattern, int verbose)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -6924,7 +6925,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"));
@@ -6986,7 +6987,7 @@ error_return:
  * Lists large objects
  */
 bool
-listLargeObjects(bool verbose)
+listLargeObjects(int verbose)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -7000,7 +7001,7 @@ listLargeObjects(bool verbose)
 					  gettext_noop("ID"),
 					  gettext_noop("Owner"));
 
-	if (verbose)
+	if (verbose > 0)
 	{
 		printACLColumn(&buf, "lomacl");
 		appendPQExpBufferStr(&buf, ",\n  ");
diff --git a/src/bin/psql/describe.h b/src/bin/psql/describe.h
index 84df35f4623..7edf30118fd 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,62 +47,62 @@ 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);
 
 /* \dconfig */
-extern bool describeConfigurationParameters(const char *pattern, bool verbose,
+extern bool describeConfigurationParameters(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);
@@ -114,7 +114,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);
@@ -123,27 +123,27 @@ 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 *type_pattern,
-								bool verbose);
+								int verbose);
 
 /* \dAf */
 extern bool listOperatorFamilies(const char *access_method_pattern,
 								 const char *type_pattern,
-								 bool verbose);
+								 int verbose);
 
 /* \dAo */
 extern bool listOpFamilyOperators(const char *access_method_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);
 
 /* \dl or \lo_list */
-extern bool listLargeObjects(bool verbose);
+extern bool listLargeObjects(int verbose);
 
 #endif							/* DESCRIBE_H */
-- 
2.25.1


--H1spWtNR+x+ondvy
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
 filename="0004-Move-the-double-plus-Size-columns-to-the-right.patch"



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

* [PATCH 3/4] f!convert the other verbose to int, too
@ 2021-07-15 08:19  Justin Pryzby <[email protected]>
  0 siblings, 0 replies; 34+ messages in thread

From: Justin Pryzby @ 2021-07-15 08:19 UTC (permalink / raw)

---
 src/bin/psql/command.c  |  82 ++++++++++----------
 src/bin/psql/describe.c | 163 ++++++++++++++++++++--------------------
 src/bin/psql/describe.h |  58 +++++++-------
 3 files changed, 151 insertions(+), 152 deletions(-)

diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index 875b659a26d..7024db26a86 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -76,7 +76,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,
@@ -756,8 +756,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,
@@ -766,7 +765,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])
@@ -775,10 +773,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':
 				{
@@ -794,16 +792,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;
@@ -814,7 +812,7 @@ 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);
@@ -822,15 +820,15 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd)
 			case 'c':
 				if (strncmp(cmd, "dconfig", 7) == 0)
 					success = describeConfigurationParameters(pattern,
-															  show_verbose,
+															  verbose,
 															  show_system);
 				else
 					success = listConversions(pattern,
-											  show_verbose,
+											  verbose,
 											  show_system);
 				break;
 			case 'C':
-				success = listCasts(pattern, show_verbose);
+				success = listCasts(pattern, verbose);
 				break;
 			case 'd':
 				if (strncmp(cmd, "ddp", 3) == 0)
@@ -839,7 +837,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])
@@ -853,7 +851,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;
@@ -862,23 +860,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 = listLargeObjects(show_verbose);
+				success = listLargeObjects(verbose);
 				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, show_system);
@@ -892,7 +890,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;
@@ -901,7 +899,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':
@@ -909,7 +907,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')
@@ -930,36 +928,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;
@@ -970,16 +968,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;
@@ -987,7 +985,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);
@@ -996,7 +994,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;
@@ -1017,7 +1015,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];
@@ -1040,11 +1038,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]);
@@ -2014,9 +2012,9 @@ exec_command_lo(PsqlScanState scan_state, bool active_branch, const char *cmd)
 		}
 
 		else if (strcmp(cmd + 3, "list") == 0)
-			success = listLargeObjects(false);
+			success = listLargeObjects(0);
 		else if (strcmp(cmd + 3, "list+") == 0)
-			success = listLargeObjects(true);
+			success = listLargeObjects(1);
 
 		else if (strcmp(cmd + 3, "unlink") == 0)
 		{
diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index 7de604a894d..5fc4f5774e8 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -33,7 +33,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);
@@ -68,7 +68,7 @@ static bool validateSQLNamePattern(PQExpBuffer buf, const char *pattern,
  * 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;
@@ -169,7 +169,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"
@@ -235,7 +235,7 @@ describeTablespaces(const char *pattern, int verbose)
 					  gettext_noop("Owner"),
 					  gettext_noop("Location"));
 
-	if (verbose)
+	if (verbose > 0)
 	{
 		appendPQExpBufferStr(&buf, ",\n  ");
 		printACLColumn(&buf, "spcacl");
@@ -301,7 +301,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;
@@ -386,7 +386,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"
@@ -441,7 +441,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");
 
@@ -627,7 +627,7 @@ error_return:
  * describe types
  */
 bool
-describeTypes(const char *pattern, bool verbose, bool showSystem)
+describeTypes(const char *pattern, int verbose, bool showSystem)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -640,7 +640,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"
@@ -785,7 +785,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;
@@ -821,7 +821,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"));
@@ -1455,10 +1455,10 @@ error_return:
  * 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;
@@ -1544,7 +1544,7 @@ static bool
 describeOneTableDetails(const char *schemaname,
 						const char *relationname,
 						const char *oid,
-						bool verbose)
+						int verbose)
 {
 	bool		retval = false;
 	PQExpBufferData buf;
@@ -1917,7 +1917,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++;
@@ -2175,7 +2175,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,
@@ -2198,7 +2198,7 @@ describeOneTableDetails(const char *schemaname,
 							  strcmp(detached, "t") == 0 ? " DETACH PENDING" : "");
 			printTableAddFooter(&cont, tmpbuf.data);
 
-			if (verbose)
+			if (verbose > 0)
 			{
 				char	   *partconstraintdef = NULL;
 
@@ -3434,7 +3434,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)
@@ -3486,7 +3486,7 @@ describeOneTableDetails(const char *schemaname,
 			printTableAddFooter(&cont, buf.data);
 		}
 
-		if (verbose &&
+		if (verbose > 0 &&
 			(tableinfo.relkind == RELKIND_RELATION ||
 			 tableinfo.relkind == RELKIND_MATVIEW) &&
 
@@ -3510,7 +3510,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 */
@@ -3518,7 +3518,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);
@@ -3526,7 +3526,7 @@ describeOneTableDetails(const char *schemaname,
 	}
 
 	/* reloptions, if verbose */
-	if (verbose &&
+	if (verbose > 0 &&
 		tableinfo.reloptions && tableinfo.reloptions[0] != '\0')
 	{
 		const char *t = _("Options");
@@ -3626,7 +3626,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;
@@ -3652,11 +3652,12 @@ 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)
+	if (verbose > 0)
 	{
 		appendPQExpBufferStr(&buf, "\n, pg_catalog.shobj_description(r.oid, 'pg_authid') AS description");
 		ncols++;
 	}
+
 	appendPQExpBufferStr(&buf, "\n, r.rolreplication");
 
 	if (pset.sversion >= 90500)
@@ -3693,7 +3694,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)
+	if (verbose > 0)
 		printTableAddHeader(&cont, gettext_noop("Description"), true, align);
 
 	for (i = 0; i < nrows; i++)
@@ -3752,7 +3753,7 @@ describeRoles(const char *pattern, bool verbose, bool showSystem)
 
 		printTableAddCell(&cont, PQgetvalue(res, i, 8), false, false);
 
-		if (verbose)
+		if (verbose > 0)
 			printTableAddCell(&cont, PQgetvalue(res, i, 9), false, false);
 	}
 	termPQExpBuffer(&buf);
@@ -3865,7 +3866,7 @@ error_return:
  * (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;
@@ -3924,7 +3925,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.
@@ -4064,7 +4065,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;
@@ -4139,7 +4140,7 @@ listPartitionedTables(const char *reltypes, const char *pattern, bool verbose)
 						  ",\n c2.oid::pg_catalog.regclass as \"%s\"",
 						  gettext_noop("Table"));
 
-	if (verbose)
+	if (verbose > 0)
 	{
 		if (showNested)
 		{
@@ -4174,7 +4175,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)
 		{
@@ -4265,7 +4266,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;
@@ -4281,7 +4282,7 @@ listLanguages(const char *pattern, bool verbose, bool showSystem)
 					  gettext_noop("Owner"),
 					  gettext_noop("Trusted"));
 
-	if (verbose)
+	if (verbose > 0)
 	{
 		appendPQExpBuffer(&buf,
 						  ",\n       NOT l.lanispl AS \"%s\",\n"
@@ -4342,7 +4343,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;
@@ -4369,7 +4370,7 @@ listDomains(const char *pattern, bool verbose, bool showSystem)
 					  gettext_noop("Default"),
 					  gettext_noop("Check"));
 
-	if (verbose)
+	if (verbose > 0)
 	{
 		appendPQExpBufferStr(&buf, ",\n  ");
 		printACLColumn(&buf, "t.typacl");
@@ -4382,7 +4383,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 "
@@ -4426,7 +4427,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;
@@ -4450,7 +4451,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"));
@@ -4460,7 +4461,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"
@@ -4507,7 +4508,7 @@ listConversions(const char *pattern, bool verbose, bool showSystem)
  * Describes configuration parameters.
  */
 bool
-describeConfigurationParameters(const char *pattern, bool verbose,
+describeConfigurationParameters(const char *pattern, int verbose,
 								bool showSystem)
 {
 	PQExpBufferData buf;
@@ -4576,7 +4577,7 @@ describeConfigurationParameters(const char *pattern, bool verbose,
  * Describes Event Triggers.
  */
 bool
-listEventTriggers(const char *pattern, bool verbose)
+listEventTriggers(const char *pattern, int verbose)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -4617,7 +4618,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"));
@@ -4754,7 +4755,7 @@ listExtendedStats(const char *pattern)
  * Describes casts.
  */
 bool
-listCasts(const char *pattern, bool verbose)
+listCasts(const char *pattern, int verbose)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -4795,7 +4796,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"));
@@ -4816,7 +4817,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 = "
@@ -4873,7 +4874,7 @@ error_return:
  * Describes collations.
  */
 bool
-listCollations(const char *pattern, bool verbose, bool showSystem)
+listCollations(const char *pattern, int verbose, bool showSystem)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -4933,7 +4934,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"));
@@ -5003,7 +5004,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");
@@ -5115,13 +5116,13 @@ error_return:
  * list text search parsers
  */
 bool
-listTSParsers(const char *pattern, bool verbose)
+listTSParsers(const char *pattern, int verbose)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
 	printQueryOpt myopt = pset.popt;
 
-	if (verbose)
+	if (verbose > 0)
 		return listTSParsersVerbose(pattern);
 
 	initPQExpBuffer(&buf);
@@ -5365,7 +5366,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;
@@ -5380,7 +5381,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"
@@ -5431,7 +5432,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;
@@ -5439,7 +5440,7 @@ listTSTemplates(const char *pattern, bool verbose)
 
 	initPQExpBuffer(&buf);
 
-	if (verbose)
+	if (verbose > 0)
 		printfPQExpBuffer(&buf,
 						  "SELECT\n"
 						  "  n.nspname AS \"%s\",\n"
@@ -5497,13 +5498,13 @@ 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;
 	printQueryOpt myopt = pset.popt;
 
-	if (verbose)
+	if (verbose > 0)
 		return listTSConfigsVerbose(pattern);
 
 	initPQExpBuffer(&buf);
@@ -5703,7 +5704,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;
@@ -5720,7 +5721,7 @@ listForeignDataWrappers(const char *pattern, bool verbose)
 					  gettext_noop("Handler"),
 					  gettext_noop("Validator"));
 
-	if (verbose)
+	if (verbose > 0)
 	{
 		appendPQExpBufferStr(&buf, ",\n  ");
 		printACLColumn(&buf, "fdwacl");
@@ -5738,7 +5739,7 @@ listForeignDataWrappers(const char *pattern, bool verbose)
 
 	appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_foreign_data_wrapper fdw\n");
 
-	if (verbose)
+	if (verbose > 0)
 		appendPQExpBufferStr(&buf,
 							 "LEFT JOIN pg_catalog.pg_description d\n"
 							 "       ON d.classoid = fdw.tableoid "
@@ -5775,7 +5776,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;
@@ -5790,7 +5791,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");
@@ -5815,7 +5816,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 "
@@ -5852,7 +5853,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;
@@ -5865,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 "
@@ -5908,7 +5909,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;
@@ -5923,7 +5924,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 "
@@ -5943,7 +5944,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 "
@@ -6507,7 +6508,7 @@ error_return:
  * 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;
@@ -6537,7 +6538,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)
@@ -6644,7 +6645,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;
@@ -6679,7 +6680,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"
@@ -6695,7 +6696,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");
@@ -6746,7 +6747,7 @@ error_return:
  */
 bool
 listOperatorFamilies(const char *access_method_pattern,
-					 const char *type_pattern, bool verbose)
+					 const char *type_pattern, int verbose)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -6771,7 +6772,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"));
@@ -6836,7 +6837,7 @@ error_return:
  */
 bool
 listOpFamilyOperators(const char *access_method_pattern,
-					  const char *family_pattern, bool verbose)
+					  const char *family_pattern, int verbose)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -6869,7 +6870,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"));
@@ -6878,7 +6879,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");
 
@@ -6935,7 +6936,7 @@ error_return:
  */
 bool
 listOpFamilyFunctions(const char *access_method_pattern,
-					  const char *family_pattern, bool verbose)
+					  const char *family_pattern, int verbose)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -6962,7 +6963,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"));
@@ -7024,7 +7025,7 @@ error_return:
  * Lists large objects
  */
 bool
-listLargeObjects(bool verbose)
+listLargeObjects(int verbose)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -7038,7 +7039,7 @@ listLargeObjects(bool verbose)
 					  gettext_noop("ID"),
 					  gettext_noop("Owner"));
 
-	if (verbose)
+	if (verbose > 0)
 	{
 		printACLColumn(&buf, "lomacl");
 		appendPQExpBufferStr(&buf, ",\n  ");
diff --git a/src/bin/psql/describe.h b/src/bin/psql/describe.h
index d2fd8a72a36..23d601fbc97 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,62 +47,62 @@ 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);
 
 /* \dconfig */
-extern bool describeConfigurationParameters(const char *pattern, bool verbose,
+extern bool describeConfigurationParameters(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);
@@ -114,7 +114,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);
@@ -123,27 +123,27 @@ 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 *type_pattern,
-								bool verbose);
+								int verbose);
 
 /* \dAf */
 extern bool listOperatorFamilies(const char *access_method_pattern,
 								 const char *type_pattern,
-								 bool verbose);
+								 int verbose);
 
 /* \dAo */
 extern bool listOpFamilyOperators(const char *access_method_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);
 
 /* \dl or \lo_list */
-extern bool listLargeObjects(bool verbose);
+extern bool listLargeObjects(int verbose);
 
 #endif							/* DESCRIBE_H */
-- 
2.34.1


--OZ1/qgOAlc2dTU8W
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="0004-Move-the-double-plus-Size-columns-to-the-right.patch"



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

* [PATCH v8 3/4] f!convert the other verbose to int, too
@ 2021-07-15 08:19  Justin Pryzby <[email protected]>
  0 siblings, 0 replies; 34+ messages in thread

From: Justin Pryzby @ 2021-07-15 08:19 UTC (permalink / raw)

---
 src/bin/psql/command.c  |  82 ++++++++++----------
 src/bin/psql/describe.c | 165 ++++++++++++++++++++--------------------
 src/bin/psql/describe.h |  58 +++++++-------
 3 files changed, 152 insertions(+), 153 deletions(-)

diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index 99ee47f436a..9f3910cd332 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,
@@ -719,8 +719,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,
@@ -729,7 +728,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])
@@ -738,10 +736,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':
 				{
@@ -757,16 +755,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;
@@ -777,7 +775,7 @@ 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);
@@ -785,15 +783,15 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd)
 			case 'c':
 				if (strncmp(cmd, "dconfig", 7) == 0)
 					success = describeConfigurationParameters(pattern,
-															  show_verbose,
+															  verbose,
 															  show_system);
 				else
 					success = listConversions(pattern,
-											  show_verbose,
+											  verbose,
 											  show_system);
 				break;
 			case 'C':
-				success = listCasts(pattern, show_verbose);
+				success = listCasts(pattern, verbose);
 				break;
 			case 'd':
 				if (strncmp(cmd, "ddp", 3) == 0)
@@ -802,7 +800,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])
@@ -816,7 +814,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;
@@ -825,23 +823,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 = listLargeObjects(show_verbose);
+				success = listLargeObjects(verbose);
 				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);
@@ -855,7 +853,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;
@@ -864,7 +862,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':
@@ -872,7 +870,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')
@@ -893,36 +891,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;
@@ -933,16 +931,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;
@@ -950,7 +948,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);
@@ -959,7 +957,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;
@@ -980,7 +978,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];
@@ -1003,11 +1001,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]);
@@ -1975,9 +1973,9 @@ exec_command_lo(PsqlScanState scan_state, bool active_branch, const char *cmd)
 		}
 
 		else if (strcmp(cmd + 3, "list") == 0)
-			success = listLargeObjects(false);
+			success = listLargeObjects(0);
 		else if (strcmp(cmd + 3, "list+") == 0)
-			success = listLargeObjects(true);
+			success = listLargeObjects(1);
 
 		else if (strcmp(cmd + 3, "unlink") == 0)
 		{
diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index 677dd64cda0..2e47ea448f7 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -33,7 +33,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);
@@ -68,7 +68,7 @@ static bool validateSQLNamePattern(PQExpBuffer buf, const char *pattern,
  * 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;
@@ -169,7 +169,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"
@@ -235,7 +235,7 @@ describeTablespaces(const char *pattern, int verbose)
 					  gettext_noop("Owner"),
 					  gettext_noop("Location"));
 
-	if (verbose)
+	if (verbose > 0)
 	{
 		appendPQExpBufferStr(&buf, ",\n  ");
 		printACLColumn(&buf, "spcacl");
@@ -299,7 +299,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;
@@ -384,7 +384,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"
@@ -444,7 +444,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");
 
@@ -630,7 +630,7 @@ error_return:
  * describe types
  */
 bool
-describeTypes(const char *pattern, bool verbose, bool showSystem)
+describeTypes(const char *pattern, int verbose, bool showSystem)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -643,7 +643,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"
@@ -788,7 +788,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;
@@ -824,7 +824,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"));
@@ -974,7 +974,7 @@ listAllDbs(const char *pattern, int verbose)
 						  gettext_noop("Description"));
 	appendPQExpBufferStr(&buf,
 						 "\nFROM pg_catalog.pg_database d\n");
-	if (verbose)
+	if (verbose > 0)
 		appendPQExpBufferStr(&buf,
 							 "  JOIN pg_catalog.pg_tablespace t on d.dattablespace = t.oid\n");
 
@@ -1442,10 +1442,10 @@ error_return:
  * 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;
@@ -1531,7 +1531,7 @@ static bool
 describeOneTableDetails(const char *schemaname,
 						const char *relationname,
 						const char *oid,
-						bool verbose)
+						int verbose)
 {
 	bool		retval = false;
 	PQExpBufferData buf;
@@ -1904,7 +1904,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++;
@@ -2162,7 +2162,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,
@@ -2185,7 +2185,7 @@ describeOneTableDetails(const char *schemaname,
 							  strcmp(detached, "t") == 0 ? " DETACH PENDING" : "");
 			printTableAddFooter(&cont, tmpbuf.data);
 
-			if (verbose)
+			if (verbose > 0)
 			{
 				char	   *partconstraintdef = NULL;
 
@@ -3421,7 +3421,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)
@@ -3471,7 +3471,7 @@ describeOneTableDetails(const char *schemaname,
 			printTableAddFooter(&cont, buf.data);
 		}
 
-		if (verbose &&
+		if (verbose > 0 &&
 			(tableinfo.relkind == RELKIND_RELATION ||
 			 tableinfo.relkind == RELKIND_MATVIEW) &&
 
@@ -3495,7 +3495,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 */
@@ -3503,7 +3503,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);
@@ -3511,7 +3511,7 @@ describeOneTableDetails(const char *schemaname,
 	}
 
 	/* reloptions, if verbose */
-	if (verbose &&
+	if (verbose > 0 &&
 		tableinfo.reloptions && tableinfo.reloptions[0] != '\0')
 	{
 		const char *t = _("Options");
@@ -3611,7 +3611,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;
@@ -3637,11 +3637,12 @@ 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)
+	if (verbose > 0)
 	{
 		appendPQExpBufferStr(&buf, "\n, pg_catalog.shobj_description(r.oid, 'pg_authid') AS description");
 		ncols++;
 	}
+
 	appendPQExpBufferStr(&buf, "\n, r.rolreplication");
 
 	if (pset.sversion >= 90500)
@@ -3678,7 +3679,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)
+	if (verbose > 0)
 		printTableAddHeader(&cont, gettext_noop("Description"), true, align);
 
 	for (i = 0; i < nrows; i++)
@@ -3737,7 +3738,7 @@ describeRoles(const char *pattern, bool verbose, bool showSystem)
 
 		printTableAddCell(&cont, PQgetvalue(res, i, 8), false, false);
 
-		if (verbose)
+		if (verbose > 0)
 			printTableAddCell(&cont, PQgetvalue(res, i, 9), false, false);
 	}
 	termPQExpBuffer(&buf);
@@ -3847,7 +3848,7 @@ error_return:
  * (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;
@@ -3906,7 +3907,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.
@@ -4046,7 +4047,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;
@@ -4121,7 +4122,7 @@ listPartitionedTables(const char *reltypes, const char *pattern, bool verbose)
 						  ",\n c2.oid::pg_catalog.regclass as \"%s\"",
 						  gettext_noop("Table"));
 
-	if (verbose)
+	if (verbose > 0)
 	{
 		if (showNested)
 		{
@@ -4156,7 +4157,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)
 		{
@@ -4247,7 +4248,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;
@@ -4263,7 +4264,7 @@ listLanguages(const char *pattern, bool verbose, bool showSystem)
 					  gettext_noop("Owner"),
 					  gettext_noop("Trusted"));
 
-	if (verbose)
+	if (verbose > 0)
 	{
 		appendPQExpBuffer(&buf,
 						  ",\n       NOT l.lanispl AS \"%s\",\n"
@@ -4324,7 +4325,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;
@@ -4351,7 +4352,7 @@ listDomains(const char *pattern, bool verbose, bool showSystem)
 					  gettext_noop("Default"),
 					  gettext_noop("Check"));
 
-	if (verbose)
+	if (verbose > 0)
 	{
 		appendPQExpBufferStr(&buf, ",\n  ");
 		printACLColumn(&buf, "t.typacl");
@@ -4364,7 +4365,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 "
@@ -4408,7 +4409,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;
@@ -4432,7 +4433,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"));
@@ -4442,7 +4443,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"
@@ -4489,7 +4490,7 @@ listConversions(const char *pattern, bool verbose, bool showSystem)
  * Describes configuration parameters.
  */
 bool
-describeConfigurationParameters(const char *pattern, bool verbose,
+describeConfigurationParameters(const char *pattern, int verbose,
 								bool showSystem)
 {
 	PQExpBufferData buf;
@@ -4558,7 +4559,7 @@ describeConfigurationParameters(const char *pattern, bool verbose,
  * Describes Event Triggers.
  */
 bool
-listEventTriggers(const char *pattern, bool verbose)
+listEventTriggers(const char *pattern, int verbose)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -4599,7 +4600,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"));
@@ -4736,7 +4737,7 @@ listExtendedStats(const char *pattern)
  * Describes casts.
  */
 bool
-listCasts(const char *pattern, bool verbose)
+listCasts(const char *pattern, int verbose)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -4777,7 +4778,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"));
@@ -4798,7 +4799,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 = "
@@ -4855,7 +4856,7 @@ error_return:
  * Describes collations.
  */
 bool
-listCollations(const char *pattern, bool verbose, bool showSystem)
+listCollations(const char *pattern, int verbose, bool showSystem)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -4903,7 +4904,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"));
@@ -4973,7 +4974,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");
@@ -5085,13 +5086,13 @@ error_return:
  * list text search parsers
  */
 bool
-listTSParsers(const char *pattern, bool verbose)
+listTSParsers(const char *pattern, int verbose)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
 	printQueryOpt myopt = pset.popt;
 
-	if (verbose)
+	if (verbose > 0)
 		return listTSParsersVerbose(pattern);
 
 	initPQExpBuffer(&buf);
@@ -5335,7 +5336,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;
@@ -5350,7 +5351,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 +5402,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;
@@ -5409,7 +5410,7 @@ listTSTemplates(const char *pattern, bool verbose)
 
 	initPQExpBuffer(&buf);
 
-	if (verbose)
+	if (verbose > 0)
 		printfPQExpBuffer(&buf,
 						  "SELECT\n"
 						  "  n.nspname AS \"%s\",\n"
@@ -5467,13 +5468,13 @@ 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;
 	printQueryOpt myopt = pset.popt;
 
-	if (verbose)
+	if (verbose > 0)
 		return listTSConfigsVerbose(pattern);
 
 	initPQExpBuffer(&buf);
@@ -5673,7 +5674,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;
@@ -5690,7 +5691,7 @@ listForeignDataWrappers(const char *pattern, bool verbose)
 					  gettext_noop("Handler"),
 					  gettext_noop("Validator"));
 
-	if (verbose)
+	if (verbose > 0)
 	{
 		appendPQExpBufferStr(&buf, ",\n  ");
 		printACLColumn(&buf, "fdwacl");
@@ -5708,7 +5709,7 @@ listForeignDataWrappers(const char *pattern, bool verbose)
 
 	appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_foreign_data_wrapper fdw\n");
 
-	if (verbose)
+	if (verbose > 0)
 		appendPQExpBufferStr(&buf,
 							 "LEFT JOIN pg_catalog.pg_description d\n"
 							 "       ON d.classoid = fdw.tableoid "
@@ -5745,7 +5746,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;
@@ -5760,7 +5761,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");
@@ -5785,7 +5786,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 "
@@ -5822,7 +5823,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;
@@ -5835,7 +5836,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 "
@@ -5878,7 +5879,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;
@@ -5893,7 +5894,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 "
@@ -5913,7 +5914,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 "
@@ -6477,7 +6478,7 @@ error_return:
  * 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;
@@ -6507,7 +6508,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)
@@ -6601,7 +6602,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;
@@ -6636,7 +6637,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"
@@ -6652,7 +6653,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");
@@ -6703,7 +6704,7 @@ error_return:
  */
 bool
 listOperatorFamilies(const char *access_method_pattern,
-					 const char *type_pattern, bool verbose)
+					 const char *type_pattern, int verbose)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -6728,7 +6729,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"));
@@ -6793,7 +6794,7 @@ error_return:
  */
 bool
 listOpFamilyOperators(const char *access_method_pattern,
-					  const char *family_pattern, bool verbose)
+					  const char *family_pattern, int verbose)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -6826,7 +6827,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"));
@@ -6835,7 +6836,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");
 
@@ -6892,7 +6893,7 @@ error_return:
  */
 bool
 listOpFamilyFunctions(const char *access_method_pattern,
-					  const char *family_pattern, bool verbose)
+					  const char *family_pattern, int verbose)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -6919,7 +6920,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"));
@@ -6981,7 +6982,7 @@ error_return:
  * Lists large objects
  */
 bool
-listLargeObjects(bool verbose)
+listLargeObjects(int verbose)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -6995,7 +6996,7 @@ listLargeObjects(bool verbose)
 					  gettext_noop("ID"),
 					  gettext_noop("Owner"));
 
-	if (verbose)
+	if (verbose > 0)
 	{
 		printACLColumn(&buf, "lomacl");
 		appendPQExpBufferStr(&buf, ",\n  ");
diff --git a/src/bin/psql/describe.h b/src/bin/psql/describe.h
index 4d889c71368..7d0b4a258e2 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,62 +47,62 @@ 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);
 
 /* \dconfig */
-extern bool describeConfigurationParameters(const char *pattern, bool verbose,
+extern bool describeConfigurationParameters(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);
@@ -114,7 +114,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);
@@ -123,27 +123,27 @@ 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);
 
 /* \dl or \lo_list */
-extern bool listLargeObjects(bool verbose);
+extern bool listLargeObjects(int verbose);
 
 #endif							/* DESCRIBE_H */
-- 
2.17.1


--cKDw3XFoqocuprIa
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
 filename="v8-0004-Move-the-double-plus-Size-columns-to-the-right.patch"



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

* [PATCH 3/4] f!convert the other verbose to int, too
@ 2021-07-15 08:19  Justin Pryzby <[email protected]>
  0 siblings, 0 replies; 34+ messages in thread

From: Justin Pryzby @ 2021-07-15 08:19 UTC (permalink / raw)

---
 src/bin/psql/command.c  |  82 ++++++++++----------
 src/bin/psql/describe.c | 165 ++++++++++++++++++++--------------------
 src/bin/psql/describe.h |  58 +++++++-------
 3 files changed, 152 insertions(+), 153 deletions(-)

diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index cb65283547c..592b0bb09ca 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,
@@ -720,8 +720,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,
@@ -730,7 +729,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])
@@ -739,10 +737,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':
 				{
@@ -758,16 +756,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;
@@ -779,7 +777,7 @@ 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);
@@ -787,15 +785,15 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd)
 			case 'c':
 				if (strncmp(cmd, "dconfig", 7) == 0)
 					success = describeConfigurationParameters(pattern,
-															  show_verbose,
+															  verbose,
 															  show_system);
 				else
 					success = listConversions(pattern,
-											  show_verbose,
+											  verbose,
 											  show_system);
 				break;
 			case 'C':
-				success = listCasts(pattern, show_verbose);
+				success = listCasts(pattern, verbose);
 				break;
 			case 'd':
 				if (strncmp(cmd, "ddp", 3) == 0)
@@ -804,7 +802,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])
@@ -818,7 +816,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;
@@ -827,23 +825,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 = listLargeObjects(show_verbose);
+				success = listLargeObjects(verbose);
 				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);
@@ -857,7 +855,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;
@@ -866,7 +864,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':
@@ -874,7 +872,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')
@@ -896,36 +894,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;
@@ -936,16 +934,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;
@@ -953,7 +951,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);
@@ -962,7 +960,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;
@@ -984,7 +982,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];
@@ -1007,11 +1005,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]);
@@ -1983,9 +1981,9 @@ exec_command_lo(PsqlScanState scan_state, bool active_branch, const char *cmd)
 		}
 
 		else if (strcmp(cmd + 3, "list") == 0)
-			success = listLargeObjects(false);
+			success = listLargeObjects(0);
 		else if (strcmp(cmd + 3, "list+") == 0)
-			success = listLargeObjects(true);
+			success = listLargeObjects(1);
 
 		else if (strcmp(cmd + 3, "unlink") == 0)
 		{
diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index 67163e834bc..220262aa84c 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -33,7 +33,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);
@@ -68,7 +68,7 @@ static bool validateSQLNamePattern(PQExpBuffer buf, const char *pattern,
  * 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;
@@ -166,7 +166,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"
@@ -229,7 +229,7 @@ describeTablespaces(const char *pattern, int verbose)
 					  gettext_noop("Owner"),
 					  gettext_noop("Location"));
 
-	if (verbose)
+	if (verbose > 0)
 	{
 		appendPQExpBufferStr(&buf, ",\n  ");
 		printACLColumn(&buf, "spcacl");
@@ -290,7 +290,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;
@@ -375,7 +375,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"
@@ -435,7 +435,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");
 
@@ -617,7 +617,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;
@@ -630,7 +630,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"
@@ -772,7 +772,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;
@@ -808,7 +808,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"));
@@ -954,7 +954,7 @@ listAllDbs(const char *pattern, int verbose)
 						  gettext_noop("Description"));
 	appendPQExpBufferStr(&buf,
 						 "\nFROM pg_catalog.pg_database d\n");
-	if (verbose)
+	if (verbose > 0)
 		appendPQExpBufferStr(&buf,
 							 "  JOIN pg_catalog.pg_tablespace t on d.dattablespace = t.oid\n");
 
@@ -1411,10 +1411,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;
@@ -1497,7 +1497,7 @@ static bool
 describeOneTableDetails(const char *schemaname,
 						const char *relationname,
 						const char *oid,
-						bool verbose)
+						int verbose)
 {
 	bool		retval = false;
 	PQExpBufferData buf;
@@ -1871,7 +1871,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++;
@@ -2129,7 +2129,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,
@@ -2152,7 +2152,7 @@ describeOneTableDetails(const char *schemaname,
 							  strcmp(detached, "t") == 0 ? " DETACH PENDING" : "");
 			printTableAddFooter(&cont, tmpbuf.data);
 
-			if (verbose)
+			if (verbose > 0)
 			{
 				char	   *partconstraintdef = NULL;
 
@@ -3388,7 +3388,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)
@@ -3438,7 +3438,7 @@ describeOneTableDetails(const char *schemaname,
 			printTableAddFooter(&cont, buf.data);
 		}
 
-		if (verbose &&
+		if (verbose > 0 &&
 			(tableinfo.relkind == RELKIND_RELATION ||
 			 tableinfo.relkind == RELKIND_MATVIEW) &&
 
@@ -3462,7 +3462,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 */
@@ -3470,7 +3470,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);
@@ -3478,7 +3478,7 @@ describeOneTableDetails(const char *schemaname,
 	}
 
 	/* reloptions, if verbose */
-	if (verbose &&
+	if (verbose > 0 &&
 		tableinfo.reloptions && tableinfo.reloptions[0] != '\0')
 	{
 		const char *t = _("Options");
@@ -3580,7 +3580,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;
@@ -3606,11 +3606,12 @@ 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)
+	if (verbose > 0)
 	{
 		appendPQExpBufferStr(&buf, "\n, pg_catalog.shobj_description(r.oid, 'pg_authid') AS description");
 		ncols++;
 	}
+
 	appendPQExpBufferStr(&buf, "\n, r.rolreplication");
 
 	if (pset.sversion >= 90500)
@@ -3644,7 +3645,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)
+	if (verbose > 0)
 		printTableAddHeader(&cont, gettext_noop("Description"), true, align);
 
 	for (i = 0; i < nrows; i++)
@@ -3703,7 +3704,7 @@ describeRoles(const char *pattern, bool verbose, bool showSystem)
 
 		printTableAddCell(&cont, PQgetvalue(res, i, 8), false, false);
 
-		if (verbose)
+		if (verbose > 0)
 			printTableAddCell(&cont, PQgetvalue(res, i, 9), false, false);
 	}
 	termPQExpBuffer(&buf);
@@ -3809,7 +3810,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;
@@ -3868,7 +3869,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.
@@ -4005,7 +4006,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;
@@ -4080,7 +4081,7 @@ listPartitionedTables(const char *reltypes, const char *pattern, bool verbose)
 						  ",\n c2.oid::pg_catalog.regclass as \"%s\"",
 						  gettext_noop("Table"));
 
-	if (verbose)
+	if (verbose > 0)
 	{
 		if (showNested)
 		{
@@ -4115,7 +4116,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)
 		{
@@ -4203,7 +4204,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;
@@ -4219,7 +4220,7 @@ listLanguages(const char *pattern, bool verbose, bool showSystem)
 					  gettext_noop("Owner"),
 					  gettext_noop("Trusted"));
 
-	if (verbose)
+	if (verbose > 0)
 	{
 		appendPQExpBuffer(&buf,
 						  ",\n       NOT l.lanispl AS \"%s\",\n"
@@ -4275,7 +4276,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;
@@ -4302,7 +4303,7 @@ listDomains(const char *pattern, bool verbose, bool showSystem)
 					  gettext_noop("Default"),
 					  gettext_noop("Check"));
 
-	if (verbose)
+	if (verbose > 0)
 	{
 		appendPQExpBufferStr(&buf, ",\n  ");
 		printACLColumn(&buf, "t.typacl");
@@ -4315,7 +4316,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 "
@@ -4356,7 +4357,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;
@@ -4380,7 +4381,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"));
@@ -4390,7 +4391,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"
@@ -4434,7 +4435,7 @@ listConversions(const char *pattern, bool verbose, bool showSystem)
  * Describes configuration parameters.
  */
 bool
-describeConfigurationParameters(const char *pattern, bool verbose,
+describeConfigurationParameters(const char *pattern, int verbose,
 								bool showSystem)
 {
 	PQExpBufferData buf;
@@ -4503,7 +4504,7 @@ describeConfigurationParameters(const char *pattern, bool verbose,
  * Describes Event Triggers.
  */
 bool
-listEventTriggers(const char *pattern, bool verbose)
+listEventTriggers(const char *pattern, int verbose)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -4544,7 +4545,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"));
@@ -4675,7 +4676,7 @@ listExtendedStats(const char *pattern)
  * Describes casts.
  */
 bool
-listCasts(const char *pattern, bool verbose)
+listCasts(const char *pattern, int verbose)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -4716,7 +4717,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"));
@@ -4737,7 +4738,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 = "
@@ -4790,7 +4791,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;
@@ -4838,7 +4839,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"));
@@ -4905,7 +4906,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");
@@ -5019,13 +5020,13 @@ 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;
 	printQueryOpt myopt = pset.popt;
 
-	if (verbose)
+	if (verbose > 0)
 		return listTSParsersVerbose(pattern);
 
 	initPQExpBuffer(&buf);
@@ -5260,7 +5261,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;
@@ -5275,7 +5276,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"
@@ -5323,7 +5324,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;
@@ -5331,7 +5332,7 @@ listTSTemplates(const char *pattern, bool verbose)
 
 	initPQExpBuffer(&buf);
 
-	if (verbose)
+	if (verbose > 0)
 		printfPQExpBuffer(&buf,
 						  "SELECT\n"
 						  "  n.nspname AS \"%s\",\n"
@@ -5386,13 +5387,13 @@ 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;
 	printQueryOpt myopt = pset.popt;
 
-	if (verbose)
+	if (verbose > 0)
 		return listTSConfigsVerbose(pattern);
 
 	initPQExpBuffer(&buf);
@@ -5586,7 +5587,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;
@@ -5603,7 +5604,7 @@ listForeignDataWrappers(const char *pattern, bool verbose)
 					  gettext_noop("Handler"),
 					  gettext_noop("Validator"));
 
-	if (verbose)
+	if (verbose > 0)
 	{
 		appendPQExpBufferStr(&buf, ",\n  ");
 		printACLColumn(&buf, "fdwacl");
@@ -5621,7 +5622,7 @@ listForeignDataWrappers(const char *pattern, bool verbose)
 
 	appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_foreign_data_wrapper fdw\n");
 
-	if (verbose)
+	if (verbose > 0)
 		appendPQExpBufferStr(&buf,
 							 "LEFT JOIN pg_catalog.pg_description d\n"
 							 "       ON d.classoid = fdw.tableoid "
@@ -5655,7 +5656,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;
@@ -5670,7 +5671,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");
@@ -5695,7 +5696,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 "
@@ -5729,7 +5730,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;
@@ -5742,7 +5743,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 "
@@ -5782,7 +5783,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;
@@ -5797,7 +5798,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 "
@@ -5817,7 +5818,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 "
@@ -6362,7 +6363,7 @@ error_return:
  * 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;
@@ -6392,7 +6393,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)
@@ -6478,7 +6479,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;
@@ -6513,7 +6514,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"
@@ -6529,7 +6530,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");
@@ -6576,7 +6577,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;
@@ -6601,7 +6602,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"));
@@ -6662,7 +6663,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;
@@ -6695,7 +6696,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"));
@@ -6704,7 +6705,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");
 
@@ -6753,7 +6754,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;
@@ -6780,7 +6781,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"));
@@ -6834,7 +6835,7 @@ listOpFamilyFunctions(const char *access_method_pattern,
  * Lists large objects
  */
 bool
-listLargeObjects(bool verbose)
+listLargeObjects(int verbose)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -6848,7 +6849,7 @@ listLargeObjects(bool verbose)
 					  gettext_noop("ID"),
 					  gettext_noop("Owner"));
 
-	if (verbose)
+	if (verbose > 0)
 	{
 		printACLColumn(&buf, "lomacl");
 		appendPQExpBufferStr(&buf, ",\n  ");
diff --git a/src/bin/psql/describe.h b/src/bin/psql/describe.h
index 4d889c71368..7d0b4a258e2 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,62 +47,62 @@ 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);
 
 /* \dconfig */
-extern bool describeConfigurationParameters(const char *pattern, bool verbose,
+extern bool describeConfigurationParameters(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);
@@ -114,7 +114,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);
@@ -123,27 +123,27 @@ 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);
 
 /* \dl or \lo_list */
-extern bool listLargeObjects(bool verbose);
+extern bool listLargeObjects(int verbose);
 
 #endif							/* DESCRIBE_H */
-- 
2.17.1


--HcAYCG3uE/tztfnV
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
 filename="0004-Move-the-double-plus-Size-columns-to-the-right.patch"



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

* [PATCH v4 3/4] f!convert the other verbose to int, too
@ 2021-07-15 08:19  Justin Pryzby <[email protected]>
  0 siblings, 0 replies; 34+ messages in thread

From: Justin Pryzby @ 2021-07-15 08:19 UTC (permalink / raw)

---
 src/bin/psql/command.c  |  74 +++++++++----------
 src/bin/psql/describe.c | 159 ++++++++++++++++++++--------------------
 src/bin/psql/describe.h |  54 +++++++-------
 3 files changed, 143 insertions(+), 144 deletions(-)

diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index c9b0a01f9d..5654495192 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 c818e657da..710bf8ef91 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -33,7 +33,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);
@@ -62,7 +62,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;
@@ -158,7 +158,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"
@@ -219,7 +219,7 @@ describeTablespaces(const char *pattern, int verbose)
 					  gettext_noop("Owner"),
 					  gettext_noop("Location"));
 
-	if (verbose)
+	if (verbose > 0)
 	{
 		appendPQExpBufferStr(&buf, ",\n  ");
 		printACLColumn(&buf, "spcacl");
@@ -278,7 +278,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;
@@ -363,7 +363,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"
@@ -423,7 +423,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");
 
@@ -601,7 +601,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;
@@ -614,7 +614,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"
@@ -754,7 +754,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;
@@ -790,7 +790,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"));
@@ -920,7 +920,7 @@ listAllDbs(const char *pattern, int verbose)
 						  gettext_noop("Description"));
 	appendPQExpBufferStr(&buf,
 						 "\nFROM pg_catalog.pg_database d\n");
-	if (verbose)
+	if (verbose > 0)
 		appendPQExpBufferStr(&buf,
 							 "  JOIN pg_catalog.pg_tablespace t on d.dattablespace = t.oid\n");
 
@@ -1359,10 +1359,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;
@@ -1443,7 +1443,7 @@ static bool
 describeOneTableDetails(const char *schemaname,
 						const char *relationname,
 						const char *oid,
-						bool verbose)
+						int verbose)
 {
 	bool		retval = false;
 	PQExpBufferData buf;
@@ -1815,7 +1815,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++;
@@ -2073,7 +2073,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,
@@ -2096,7 +2096,7 @@ describeOneTableDetails(const char *schemaname,
 							  strcmp(detached, "t") == 0 ? " DETACH PENDING" : "");
 			printTableAddFooter(&cont, tmpbuf.data);
 
-			if (verbose)
+			if (verbose > 0)
 			{
 				char	   *partconstraintdef = NULL;
 
@@ -3267,7 +3267,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)
@@ -3317,7 +3317,7 @@ describeOneTableDetails(const char *schemaname,
 			printTableAddFooter(&cont, buf.data);
 		}
 
-		if (verbose &&
+		if (verbose > 0 &&
 			(tableinfo.relkind == RELKIND_RELATION ||
 			 tableinfo.relkind == RELKIND_MATVIEW) &&
 
@@ -3341,7 +3341,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 */
@@ -3349,7 +3349,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);
@@ -3357,7 +3357,7 @@ describeOneTableDetails(const char *schemaname,
 	}
 
 	/* reloptions, if verbose */
-	if (verbose &&
+	if (verbose > 0 &&
 		tableinfo.reloptions && tableinfo.reloptions[0] != '\0')
 	{
 		const char *t = _("Options");
@@ -3459,7 +3459,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;
@@ -3485,11 +3485,12 @@ 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)
+	if (verbose > 0)
 	{
 		appendPQExpBufferStr(&buf, "\n, pg_catalog.shobj_description(r.oid, 'pg_authid') AS description");
 		ncols++;
 	}
+
 	appendPQExpBufferStr(&buf, "\n, r.rolreplication");
 
 	if (pset.sversion >= 90500)
@@ -3521,7 +3522,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)
+	if (verbose > 0)
 		printTableAddHeader(&cont, gettext_noop("Description"), true, align);
 
 	for (i = 0; i < nrows; i++)
@@ -3580,7 +3581,7 @@ describeRoles(const char *pattern, bool verbose, bool showSystem)
 
 		printTableAddCell(&cont, PQgetvalue(res, i, 8), false, false);
 
-		if (verbose)
+		if (verbose > 0)
 			printTableAddCell(&cont, PQgetvalue(res, i, 9), false, false);
 	}
 	termPQExpBuffer(&buf);
@@ -3683,7 +3684,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;
@@ -3742,7 +3743,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.
@@ -3877,7 +3878,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;
@@ -3952,7 +3953,7 @@ listPartitionedTables(const char *reltypes, const char *pattern, bool verbose)
 						  ",\n c2.oid::pg_catalog.regclass as \"%s\"",
 						  gettext_noop("Table"));
 
-	if (verbose)
+	if (verbose > 0)
 	{
 		if (showNested)
 		{
@@ -3987,7 +3988,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)
 		{
@@ -4073,7 +4074,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;
@@ -4089,7 +4090,7 @@ listLanguages(const char *pattern, bool verbose, bool showSystem)
 					  gettext_noop("Owner"),
 					  gettext_noop("Trusted"));
 
-	if (verbose)
+	if (verbose > 0)
 	{
 		appendPQExpBuffer(&buf,
 						  ",\n       NOT l.lanispl AS \"%s\",\n"
@@ -4143,7 +4144,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;
@@ -4170,7 +4171,7 @@ listDomains(const char *pattern, bool verbose, bool showSystem)
 					  gettext_noop("Default"),
 					  gettext_noop("Check"));
 
-	if (verbose)
+	if (verbose > 0)
 	{
 		appendPQExpBufferStr(&buf, ",\n  ");
 		printACLColumn(&buf, "t.typacl");
@@ -4183,7 +4184,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 "
@@ -4222,7 +4223,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;
@@ -4246,7 +4247,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"));
@@ -4256,7 +4257,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"
@@ -4298,7 +4299,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;
@@ -4339,7 +4340,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"));
@@ -4466,7 +4467,7 @@ listExtendedStats(const char *pattern)
  * Describes casts.
  */
 bool
-listCasts(const char *pattern, bool verbose)
+listCasts(const char *pattern, int verbose)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -4507,7 +4508,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"));
@@ -4528,7 +4529,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 = "
@@ -4577,7 +4578,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;
@@ -4616,7 +4617,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"));
@@ -4681,7 +4682,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");
@@ -4793,13 +4794,13 @@ 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;
 	printQueryOpt myopt = pset.popt;
 
-	if (verbose)
+	if (verbose > 0)
 		return listTSParsersVerbose(pattern);
 
 	initPQExpBuffer(&buf);
@@ -5030,7 +5031,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;
@@ -5045,7 +5046,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"
@@ -5091,7 +5092,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;
@@ -5099,7 +5100,7 @@ listTSTemplates(const char *pattern, bool verbose)
 
 	initPQExpBuffer(&buf);
 
-	if (verbose)
+	if (verbose > 0)
 		printfPQExpBuffer(&buf,
 						  "SELECT\n"
 						  "  n.nspname AS \"%s\",\n"
@@ -5152,13 +5153,13 @@ 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;
 	printQueryOpt myopt = pset.popt;
 
-	if (verbose)
+	if (verbose > 0)
 		return listTSConfigsVerbose(pattern);
 
 	initPQExpBuffer(&buf);
@@ -5348,7 +5349,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;
@@ -5365,7 +5366,7 @@ listForeignDataWrappers(const char *pattern, bool verbose)
 					  gettext_noop("Handler"),
 					  gettext_noop("Validator"));
 
-	if (verbose)
+	if (verbose > 0)
 	{
 		appendPQExpBufferStr(&buf, ",\n  ");
 		printACLColumn(&buf, "fdwacl");
@@ -5383,7 +5384,7 @@ listForeignDataWrappers(const char *pattern, bool verbose)
 
 	appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_foreign_data_wrapper fdw\n");
 
-	if (verbose)
+	if (verbose > 0)
 		appendPQExpBufferStr(&buf,
 							 "LEFT JOIN pg_catalog.pg_description d\n"
 							 "       ON d.classoid = fdw.tableoid "
@@ -5415,7 +5416,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;
@@ -5430,7 +5431,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");
@@ -5455,7 +5456,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 "
@@ -5487,7 +5488,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;
@@ -5500,7 +5501,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 "
@@ -5538,7 +5539,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;
@@ -5553,7 +5554,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 "
@@ -5573,7 +5574,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 "
@@ -6029,7 +6030,7 @@ error_return:
  * 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;
@@ -6059,7 +6060,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)
@@ -6135,7 +6136,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;
@@ -6170,7 +6171,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"
@@ -6186,7 +6187,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");
@@ -6229,7 +6230,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;
@@ -6254,7 +6255,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"));
@@ -6311,7 +6312,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;
@@ -6344,7 +6345,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"));
@@ -6353,7 +6354,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");
 
@@ -6398,7 +6399,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;
@@ -6425,7 +6426,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


--2fEWJT3hVM9yyfvd
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
 filename="v4-0004-Move-the-double-plus-Size-columns-to-the-right.patch"



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

* [PATCH 3/4] f!convert the other verbose to int, too
@ 2021-07-15 08:19  Justin Pryzby <[email protected]>
  0 siblings, 0 replies; 34+ messages in thread

From: Justin Pryzby @ 2021-07-15 08:19 UTC (permalink / raw)

---
 src/bin/psql/command.c  |  80 ++++++++++----------
 src/bin/psql/describe.c | 163 ++++++++++++++++++++--------------------
 src/bin/psql/describe.h |  56 +++++++-------
 3 files changed, 149 insertions(+), 150 deletions(-)

diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index cfae8fd6d12..2326f4c5d98 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,
@@ -720,8 +720,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,
@@ -730,7 +729,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])
@@ -739,10 +737,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':
 				{
@@ -758,16 +756,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;
@@ -779,16 +777,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)
@@ -797,7 +795,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])
@@ -811,7 +809,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;
@@ -820,23 +818,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 = listLargeObjects(show_verbose);
+				success = listLargeObjects(verbose);
 				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);
@@ -850,7 +848,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;
@@ -859,7 +857,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':
@@ -867,7 +865,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')
@@ -889,36 +887,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;
@@ -929,16 +927,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;
@@ -946,7 +944,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);
@@ -955,7 +953,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;
@@ -977,7 +975,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];
@@ -1000,11 +998,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]);
@@ -1976,9 +1974,9 @@ exec_command_lo(PsqlScanState scan_state, bool active_branch, const char *cmd)
 		}
 
 		else if (strcmp(cmd + 3, "list") == 0)
-			success = listLargeObjects(false);
+			success = listLargeObjects(0);
 		else if (strcmp(cmd + 3, "list+") == 0)
-			success = listLargeObjects(true);
+			success = listLargeObjects(1);
 
 		else if (strcmp(cmd + 3, "unlink") == 0)
 		{
diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index de62822674e..ee7990ab7e4 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -33,7 +33,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);
@@ -62,7 +62,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;
@@ -158,7 +158,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"
@@ -219,7 +219,7 @@ describeTablespaces(const char *pattern, int verbose)
 					  gettext_noop("Owner"),
 					  gettext_noop("Location"));
 
-	if (verbose)
+	if (verbose > 0)
 	{
 		appendPQExpBufferStr(&buf, ",\n  ");
 		printACLColumn(&buf, "spcacl");
@@ -278,7 +278,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;
@@ -363,7 +363,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"
@@ -423,7 +423,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");
 
@@ -601,7 +601,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;
@@ -614,7 +614,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"
@@ -754,7 +754,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;
@@ -790,7 +790,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"));
@@ -920,7 +920,7 @@ listAllDbs(const char *pattern, int verbose)
 						  gettext_noop("Description"));
 	appendPQExpBufferStr(&buf,
 						 "\nFROM pg_catalog.pg_database d\n");
-	if (verbose)
+	if (verbose > 0)
 		appendPQExpBufferStr(&buf,
 							 "  JOIN pg_catalog.pg_tablespace t on d.dattablespace = t.oid\n");
 
@@ -1359,10 +1359,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;
@@ -1443,7 +1443,7 @@ static bool
 describeOneTableDetails(const char *schemaname,
 						const char *relationname,
 						const char *oid,
-						bool verbose)
+						int verbose)
 {
 	bool		retval = false;
 	PQExpBufferData buf;
@@ -1815,7 +1815,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++;
@@ -2073,7 +2073,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,
@@ -2096,7 +2096,7 @@ describeOneTableDetails(const char *schemaname,
 							  strcmp(detached, "t") == 0 ? " DETACH PENDING" : "");
 			printTableAddFooter(&cont, tmpbuf.data);
 
-			if (verbose)
+			if (verbose > 0)
 			{
 				char	   *partconstraintdef = NULL;
 
@@ -3275,7 +3275,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)
@@ -3325,7 +3325,7 @@ describeOneTableDetails(const char *schemaname,
 			printTableAddFooter(&cont, buf.data);
 		}
 
-		if (verbose &&
+		if (verbose > 0 &&
 			(tableinfo.relkind == RELKIND_RELATION ||
 			 tableinfo.relkind == RELKIND_MATVIEW) &&
 
@@ -3349,7 +3349,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 */
@@ -3357,7 +3357,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);
@@ -3365,7 +3365,7 @@ describeOneTableDetails(const char *schemaname,
 	}
 
 	/* reloptions, if verbose */
-	if (verbose &&
+	if (verbose > 0 &&
 		tableinfo.reloptions && tableinfo.reloptions[0] != '\0')
 	{
 		const char *t = _("Options");
@@ -3467,7 +3467,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;
@@ -3493,11 +3493,12 @@ 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)
+	if (verbose > 0)
 	{
 		appendPQExpBufferStr(&buf, "\n, pg_catalog.shobj_description(r.oid, 'pg_authid') AS description");
 		ncols++;
 	}
+
 	appendPQExpBufferStr(&buf, "\n, r.rolreplication");
 
 	if (pset.sversion >= 90500)
@@ -3529,7 +3530,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)
+	if (verbose > 0)
 		printTableAddHeader(&cont, gettext_noop("Description"), true, align);
 
 	for (i = 0; i < nrows; i++)
@@ -3588,7 +3589,7 @@ describeRoles(const char *pattern, bool verbose, bool showSystem)
 
 		printTableAddCell(&cont, PQgetvalue(res, i, 8), false, false);
 
-		if (verbose)
+		if (verbose > 0)
 			printTableAddCell(&cont, PQgetvalue(res, i, 9), false, false);
 	}
 	termPQExpBuffer(&buf);
@@ -3691,7 +3692,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;
@@ -3750,7 +3751,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.
@@ -3885,7 +3886,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;
@@ -3960,7 +3961,7 @@ listPartitionedTables(const char *reltypes, const char *pattern, bool verbose)
 						  ",\n c2.oid::pg_catalog.regclass as \"%s\"",
 						  gettext_noop("Table"));
 
-	if (verbose)
+	if (verbose > 0)
 	{
 		if (showNested)
 		{
@@ -3995,7 +3996,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)
 		{
@@ -4081,7 +4082,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;
@@ -4097,7 +4098,7 @@ listLanguages(const char *pattern, bool verbose, bool showSystem)
 					  gettext_noop("Owner"),
 					  gettext_noop("Trusted"));
 
-	if (verbose)
+	if (verbose > 0)
 	{
 		appendPQExpBuffer(&buf,
 						  ",\n       NOT l.lanispl AS \"%s\",\n"
@@ -4151,7 +4152,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;
@@ -4178,7 +4179,7 @@ listDomains(const char *pattern, bool verbose, bool showSystem)
 					  gettext_noop("Default"),
 					  gettext_noop("Check"));
 
-	if (verbose)
+	if (verbose > 0)
 	{
 		appendPQExpBufferStr(&buf, ",\n  ");
 		printACLColumn(&buf, "t.typacl");
@@ -4191,7 +4192,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 "
@@ -4230,7 +4231,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;
@@ -4254,7 +4255,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"));
@@ -4264,7 +4265,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"
@@ -4306,7 +4307,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;
@@ -4347,7 +4348,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"));
@@ -4474,7 +4475,7 @@ listExtendedStats(const char *pattern)
  * Describes casts.
  */
 bool
-listCasts(const char *pattern, bool verbose)
+listCasts(const char *pattern, int verbose)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -4515,7 +4516,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"));
@@ -4536,7 +4537,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 = "
@@ -4585,7 +4586,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;
@@ -4624,7 +4625,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"));
@@ -4689,7 +4690,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");
@@ -4801,13 +4802,13 @@ 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;
 	printQueryOpt myopt = pset.popt;
 
-	if (verbose)
+	if (verbose > 0)
 		return listTSParsersVerbose(pattern);
 
 	initPQExpBuffer(&buf);
@@ -5038,7 +5039,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;
@@ -5053,7 +5054,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"
@@ -5099,7 +5100,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;
@@ -5107,7 +5108,7 @@ listTSTemplates(const char *pattern, bool verbose)
 
 	initPQExpBuffer(&buf);
 
-	if (verbose)
+	if (verbose > 0)
 		printfPQExpBuffer(&buf,
 						  "SELECT\n"
 						  "  n.nspname AS \"%s\",\n"
@@ -5160,13 +5161,13 @@ 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;
 	printQueryOpt myopt = pset.popt;
 
-	if (verbose)
+	if (verbose > 0)
 		return listTSConfigsVerbose(pattern);
 
 	initPQExpBuffer(&buf);
@@ -5356,7 +5357,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;
@@ -5373,7 +5374,7 @@ listForeignDataWrappers(const char *pattern, bool verbose)
 					  gettext_noop("Handler"),
 					  gettext_noop("Validator"));
 
-	if (verbose)
+	if (verbose > 0)
 	{
 		appendPQExpBufferStr(&buf, ",\n  ");
 		printACLColumn(&buf, "fdwacl");
@@ -5391,7 +5392,7 @@ listForeignDataWrappers(const char *pattern, bool verbose)
 
 	appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_foreign_data_wrapper fdw\n");
 
-	if (verbose)
+	if (verbose > 0)
 		appendPQExpBufferStr(&buf,
 							 "LEFT JOIN pg_catalog.pg_description d\n"
 							 "       ON d.classoid = fdw.tableoid "
@@ -5423,7 +5424,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;
@@ -5438,7 +5439,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");
@@ -5463,7 +5464,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 "
@@ -5495,7 +5496,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;
@@ -5508,7 +5509,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 "
@@ -5546,7 +5547,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;
@@ -5561,7 +5562,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 "
@@ -5581,7 +5582,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 "
@@ -6037,7 +6038,7 @@ error_return:
  * 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;
@@ -6067,7 +6068,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)
@@ -6143,7 +6144,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;
@@ -6178,7 +6179,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"
@@ -6194,7 +6195,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");
@@ -6237,7 +6238,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;
@@ -6262,7 +6263,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"));
@@ -6319,7 +6320,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;
@@ -6352,7 +6353,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"));
@@ -6361,7 +6362,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");
 
@@ -6406,7 +6407,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;
@@ -6433,7 +6434,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"));
@@ -6483,7 +6484,7 @@ listOpFamilyFunctions(const char *access_method_pattern,
  * Lists large objects
  */
 bool
-listLargeObjects(bool verbose)
+listLargeObjects(int verbose)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -6497,7 +6498,7 @@ listLargeObjects(bool verbose)
 					  gettext_noop("ID"),
 					  gettext_noop("Owner"));
 
-	if (verbose)
+	if (verbose > 0)
 	{
 		printACLColumn(&buf, "lomacl");
 		appendPQExpBufferStr(&buf, ",\n  ");
diff --git a/src/bin/psql/describe.h b/src/bin/psql/describe.h
index 5a1b97805df..7795680f31c 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,27 +119,27 @@ 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);
 
 /* \dl or \lo_list */
-extern bool listLargeObjects(bool verbose);
+extern bool listLargeObjects(int verbose);
 
 #endif							/* DESCRIBE_H */
-- 
2.17.1


--XLWMkxR+mZNQ4WTO
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
 filename="0004-Move-the-double-plus-Size-columns-to-the-right.patch"



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

* [PATCH v2 3/5] f!convert the other verbose to int, too
@ 2021-07-15 08:19  Justin Pryzby <[email protected]>
  0 siblings, 0 replies; 34+ messages in thread

From: Justin Pryzby @ 2021-07-15 08:19 UTC (permalink / raw)

---
 src/bin/psql/command.c  | 76 ++++++++++++++++++++---------------------
 src/bin/psql/describe.c | 62 ++++++++++++++++-----------------
 src/bin/psql/describe.h | 56 +++++++++++++++---------------
 3 files changed, 96 insertions(+), 98 deletions(-)

diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index 92952b4d19..34f1ee54b5 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':
 				{
@@ -744,19 +742,19 @@ 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);
+							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)
 							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)
 					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 b6a6a378a4..afdb330d41 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;
@@ -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;
@@ -315,7 +315,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;
@@ -714,7 +714,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;
@@ -890,7 +890,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;
@@ -1527,10 +1527,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;
@@ -1611,7 +1611,7 @@ static bool
 describeOneTableDetails(const char *schemaname,
 						const char *relationname,
 						const char *oid,
-						bool verbose)
+						int verbose)
 {
 	bool		retval = false;
 	PQExpBufferData buf;
@@ -3736,7 +3736,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;
@@ -3992,7 +3992,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;
@@ -4208,7 +4208,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;
@@ -4404,7 +4404,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;
@@ -4479,7 +4479,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;
@@ -4565,7 +4565,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;
@@ -4641,7 +4641,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;
@@ -4799,7 +4799,7 @@ listExtendedStats(const char *pattern)
  * Describes casts.
  */
 bool
-listCasts(const char *pattern, bool verbose)
+listCasts(const char *pattern, int verbose)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -4917,7 +4917,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;
@@ -5080,7 +5080,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;
@@ -5327,7 +5327,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;
@@ -5398,7 +5398,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;
@@ -5469,7 +5469,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;
@@ -5675,7 +5675,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;
@@ -5758,7 +5758,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;
@@ -5840,7 +5840,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;
@@ -5901,7 +5901,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;
@@ -6390,7 +6390,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;
@@ -6501,7 +6501,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;
@@ -6595,7 +6595,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;
@@ -6677,7 +6677,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;
@@ -6764,7 +6764,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;
diff --git a/src/bin/psql/describe.h b/src/bin/psql/describe.h
index a65f111130..cdf286242b 100644
--- a/src/bin/psql/describe.h
+++ b/src/bin/psql/describe.h
@@ -10,10 +10,10 @@
 
 
 /* \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, bool verbose);
+extern bool describeAccessMethods(const char *pattern, int verbose);
 
 /* \db */
 extern bool describeTablespaces(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


--EVF5PPMfhYS0aIcm
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
 filename="v2-0004-f-change-if-verbose-to-if-verbose-0.patch"



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

* [PATCH 3/4] f!convert the other verbose to int, too
@ 2021-07-15 08:19  Justin Pryzby <[email protected]>
  0 siblings, 0 replies; 34+ messages in thread

From: Justin Pryzby @ 2021-07-15 08:19 UTC (permalink / raw)

---
 src/bin/psql/command.c  |  82 ++++++++++----------
 src/bin/psql/describe.c | 163 ++++++++++++++++++++--------------------
 src/bin/psql/describe.h |  58 +++++++-------
 3 files changed, 151 insertions(+), 152 deletions(-)

diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index 667beb1b16e..3039aaca699 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -76,7 +76,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,
@@ -756,8 +756,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,
@@ -766,7 +765,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])
@@ -775,10 +773,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':
 				{
@@ -794,16 +792,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;
@@ -814,7 +812,7 @@ 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);
@@ -822,15 +820,15 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd)
 			case 'c':
 				if (strncmp(cmd, "dconfig", 7) == 0)
 					success = describeConfigurationParameters(pattern,
-															  show_verbose,
+															  verbose,
 															  show_system);
 				else
 					success = listConversions(pattern,
-											  show_verbose,
+											  verbose,
 											  show_system);
 				break;
 			case 'C':
-				success = listCasts(pattern, show_verbose);
+				success = listCasts(pattern, verbose);
 				break;
 			case 'd':
 				if (strncmp(cmd, "ddp", 3) == 0)
@@ -839,7 +837,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])
@@ -853,7 +851,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;
@@ -862,23 +860,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 = listLargeObjects(show_verbose);
+				success = listLargeObjects(verbose);
 				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, show_system);
@@ -892,7 +890,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;
@@ -901,7 +899,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':
@@ -909,7 +907,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')
@@ -932,36 +930,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;
@@ -972,16 +970,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;
@@ -989,7 +987,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);
@@ -998,7 +996,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;
@@ -1019,7 +1017,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];
@@ -1042,11 +1040,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]);
@@ -2016,9 +2014,9 @@ exec_command_lo(PsqlScanState scan_state, bool active_branch, const char *cmd)
 		}
 
 		else if (strcmp(cmd + 3, "list") == 0)
-			success = listLargeObjects(false);
+			success = listLargeObjects(0);
 		else if (strcmp(cmd + 3, "list+") == 0)
-			success = listLargeObjects(true);
+			success = listLargeObjects(1);
 
 		else if (strcmp(cmd + 3, "unlink") == 0)
 		{
diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index 3be7a5b8dc8..7eff1249015 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -33,7 +33,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);
@@ -68,7 +68,7 @@ static bool validateSQLNamePattern(PQExpBuffer buf, const char *pattern,
  * 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;
@@ -169,7 +169,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"
@@ -235,7 +235,7 @@ describeTablespaces(const char *pattern, int verbose)
 					  gettext_noop("Owner"),
 					  gettext_noop("Location"));
 
-	if (verbose)
+	if (verbose > 0)
 	{
 		appendPQExpBufferStr(&buf, ",\n  ");
 		printACLColumn(&buf, "spcacl");
@@ -301,7 +301,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;
@@ -386,7 +386,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"
@@ -441,7 +441,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");
 
@@ -627,7 +627,7 @@ error_return:
  * describe types
  */
 bool
-describeTypes(const char *pattern, bool verbose, bool showSystem)
+describeTypes(const char *pattern, int verbose, bool showSystem)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -640,7 +640,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"
@@ -785,7 +785,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;
@@ -821,7 +821,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"));
@@ -1455,10 +1455,10 @@ error_return:
  * 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;
@@ -1544,7 +1544,7 @@ static bool
 describeOneTableDetails(const char *schemaname,
 						const char *relationname,
 						const char *oid,
-						bool verbose)
+						int verbose)
 {
 	bool		retval = false;
 	PQExpBufferData buf;
@@ -1917,7 +1917,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++;
@@ -2175,7 +2175,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,
@@ -2198,7 +2198,7 @@ describeOneTableDetails(const char *schemaname,
 							  strcmp(detached, "t") == 0 ? " DETACH PENDING" : "");
 			printTableAddFooter(&cont, tmpbuf.data);
 
-			if (verbose)
+			if (verbose > 0)
 			{
 				char	   *partconstraintdef = NULL;
 
@@ -3434,7 +3434,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)
@@ -3486,7 +3486,7 @@ describeOneTableDetails(const char *schemaname,
 			printTableAddFooter(&cont, buf.data);
 		}
 
-		if (verbose &&
+		if (verbose > 0 &&
 			(tableinfo.relkind == RELKIND_RELATION ||
 			 tableinfo.relkind == RELKIND_MATVIEW) &&
 
@@ -3510,7 +3510,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 */
@@ -3518,7 +3518,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);
@@ -3526,7 +3526,7 @@ describeOneTableDetails(const char *schemaname,
 	}
 
 	/* reloptions, if verbose */
-	if (verbose &&
+	if (verbose > 0 &&
 		tableinfo.reloptions && tableinfo.reloptions[0] != '\0')
 	{
 		const char *t = _("Options");
@@ -3626,7 +3626,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;
@@ -3648,11 +3648,12 @@ describeRoles(const char *pattern, bool verbose, bool showSystem)
 					  "  r.rolcreaterole, r.rolcreatedb, r.rolcanlogin,\n"
 					  "  r.rolconnlimit, r.rolvaliduntil");
 
-	if (verbose)
+	if (verbose > 0)
 	{
 		appendPQExpBufferStr(&buf, "\n, pg_catalog.shobj_description(r.oid, 'pg_authid') AS description");
 		ncols++;
 	}
+
 	appendPQExpBufferStr(&buf, "\n, r.rolreplication");
 
 	if (pset.sversion >= 90500)
@@ -3687,7 +3688,7 @@ describeRoles(const char *pattern, bool verbose, bool showSystem)
 	printTableAddHeader(&cont, gettext_noop("Role name"), true, align);
 	printTableAddHeader(&cont, gettext_noop("Attributes"), true, align);
 
-	if (verbose)
+	if (verbose > 0)
 		printTableAddHeader(&cont, gettext_noop("Description"), true, align);
 
 	for (i = 0; i < nrows; i++)
@@ -3744,7 +3745,7 @@ describeRoles(const char *pattern, bool verbose, bool showSystem)
 
 		printTableAddCell(&cont, attr[i], false, false);
 
-		if (verbose)
+		if (verbose > 0)
 			printTableAddCell(&cont, PQgetvalue(res, i, 8), false, false);
 	}
 	termPQExpBuffer(&buf);
@@ -3923,7 +3924,7 @@ describeRoleGrants(const char *pattern, bool showSystem)
  * (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;
@@ -3982,7 +3983,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.
@@ -4122,7 +4123,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;
@@ -4197,7 +4198,7 @@ listPartitionedTables(const char *reltypes, const char *pattern, bool verbose)
 						  ",\n c2.oid::pg_catalog.regclass as \"%s\"",
 						  gettext_noop("Table"));
 
-	if (verbose)
+	if (verbose > 0)
 	{
 		if (showNested)
 		{
@@ -4232,7 +4233,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)
 		{
@@ -4323,7 +4324,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;
@@ -4339,7 +4340,7 @@ listLanguages(const char *pattern, bool verbose, bool showSystem)
 					  gettext_noop("Owner"),
 					  gettext_noop("Trusted"));
 
-	if (verbose)
+	if (verbose > 0)
 	{
 		appendPQExpBuffer(&buf,
 						  ",\n       NOT l.lanispl AS \"%s\",\n"
@@ -4400,7 +4401,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;
@@ -4427,7 +4428,7 @@ listDomains(const char *pattern, bool verbose, bool showSystem)
 					  gettext_noop("Default"),
 					  gettext_noop("Check"));
 
-	if (verbose)
+	if (verbose > 0)
 	{
 		appendPQExpBufferStr(&buf, ",\n  ");
 		printACLColumn(&buf, "t.typacl");
@@ -4440,7 +4441,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 "
@@ -4484,7 +4485,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;
@@ -4508,7 +4509,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"));
@@ -4518,7 +4519,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"
@@ -4565,7 +4566,7 @@ listConversions(const char *pattern, bool verbose, bool showSystem)
  * Describes configuration parameters.
  */
 bool
-describeConfigurationParameters(const char *pattern, bool verbose,
+describeConfigurationParameters(const char *pattern, int verbose,
 								bool showSystem)
 {
 	PQExpBufferData buf;
@@ -4634,7 +4635,7 @@ describeConfigurationParameters(const char *pattern, bool verbose,
  * Describes Event Triggers.
  */
 bool
-listEventTriggers(const char *pattern, bool verbose)
+listEventTriggers(const char *pattern, int verbose)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -4675,7 +4676,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"));
@@ -4812,7 +4813,7 @@ listExtendedStats(const char *pattern)
  * Describes casts.
  */
 bool
-listCasts(const char *pattern, bool verbose)
+listCasts(const char *pattern, int verbose)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -4853,7 +4854,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"));
@@ -4874,7 +4875,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 = "
@@ -4931,7 +4932,7 @@ error_return:
  * Describes collations.
  */
 bool
-listCollations(const char *pattern, bool verbose, bool showSystem)
+listCollations(const char *pattern, int verbose, bool showSystem)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -4991,7 +4992,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"));
@@ -5061,7 +5062,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");
@@ -5173,13 +5174,13 @@ error_return:
  * list text search parsers
  */
 bool
-listTSParsers(const char *pattern, bool verbose)
+listTSParsers(const char *pattern, int verbose)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
 	printQueryOpt myopt = pset.popt;
 
-	if (verbose)
+	if (verbose > 0)
 		return listTSParsersVerbose(pattern);
 
 	initPQExpBuffer(&buf);
@@ -5423,7 +5424,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;
@@ -5438,7 +5439,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"
@@ -5489,7 +5490,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;
@@ -5497,7 +5498,7 @@ listTSTemplates(const char *pattern, bool verbose)
 
 	initPQExpBuffer(&buf);
 
-	if (verbose)
+	if (verbose > 0)
 		printfPQExpBuffer(&buf,
 						  "SELECT\n"
 						  "  n.nspname AS \"%s\",\n"
@@ -5555,13 +5556,13 @@ 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;
 	printQueryOpt myopt = pset.popt;
 
-	if (verbose)
+	if (verbose > 0)
 		return listTSConfigsVerbose(pattern);
 
 	initPQExpBuffer(&buf);
@@ -5761,7 +5762,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;
@@ -5778,7 +5779,7 @@ listForeignDataWrappers(const char *pattern, bool verbose)
 					  gettext_noop("Handler"),
 					  gettext_noop("Validator"));
 
-	if (verbose)
+	if (verbose > 0)
 	{
 		appendPQExpBufferStr(&buf, ",\n  ");
 		printACLColumn(&buf, "fdwacl");
@@ -5796,7 +5797,7 @@ listForeignDataWrappers(const char *pattern, bool verbose)
 
 	appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_foreign_data_wrapper fdw\n");
 
-	if (verbose)
+	if (verbose > 0)
 		appendPQExpBufferStr(&buf,
 							 "LEFT JOIN pg_catalog.pg_description d\n"
 							 "       ON d.classoid = fdw.tableoid "
@@ -5833,7 +5834,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;
@@ -5848,7 +5849,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");
@@ -5873,7 +5874,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 "
@@ -5910,7 +5911,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;
@@ -5923,7 +5924,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 "
@@ -5966,7 +5967,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;
@@ -5981,7 +5982,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 "
@@ -6001,7 +6002,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 "
@@ -6565,7 +6566,7 @@ error_return:
  * 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;
@@ -6595,7 +6596,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)
@@ -6706,7 +6707,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;
@@ -6741,7 +6742,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"
@@ -6757,7 +6758,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");
@@ -6808,7 +6809,7 @@ error_return:
  */
 bool
 listOperatorFamilies(const char *access_method_pattern,
-					 const char *type_pattern, bool verbose)
+					 const char *type_pattern, int verbose)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -6833,7 +6834,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"));
@@ -6898,7 +6899,7 @@ error_return:
  */
 bool
 listOpFamilyOperators(const char *access_method_pattern,
-					  const char *family_pattern, bool verbose)
+					  const char *family_pattern, int verbose)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -6931,7 +6932,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"));
@@ -6940,7 +6941,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");
 
@@ -6997,7 +6998,7 @@ error_return:
  */
 bool
 listOpFamilyFunctions(const char *access_method_pattern,
-					  const char *family_pattern, bool verbose)
+					  const char *family_pattern, int verbose)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -7024,7 +7025,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"));
@@ -7086,7 +7087,7 @@ error_return:
  * Lists large objects
  */
 bool
-listLargeObjects(bool verbose)
+listLargeObjects(int verbose)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -7100,7 +7101,7 @@ listLargeObjects(bool verbose)
 					  gettext_noop("ID"),
 					  gettext_noop("Owner"));
 
-	if (verbose)
+	if (verbose > 0)
 	{
 		printACLColumn(&buf, "lomacl");
 		appendPQExpBufferStr(&buf, ",\n  ");
diff --git a/src/bin/psql/describe.h b/src/bin/psql/describe.h
index f11579a7bbc..8776a20a6b6 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);
@@ -50,62 +50,62 @@ 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);
 
 /* \dconfig */
-extern bool describeConfigurationParameters(const char *pattern, bool verbose,
+extern bool describeConfigurationParameters(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);
@@ -117,7 +117,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);
@@ -126,27 +126,27 @@ 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 *type_pattern,
-								bool verbose);
+								int verbose);
 
 /* \dAf */
 extern bool listOperatorFamilies(const char *access_method_pattern,
 								 const char *type_pattern,
-								 bool verbose);
+								 int verbose);
 
 /* \dAo */
 extern bool listOpFamilyOperators(const char *access_method_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);
 
 /* \dl or \lo_list */
-extern bool listLargeObjects(bool verbose);
+extern bool listLargeObjects(int verbose);
 
 #endif							/* DESCRIBE_H */
-- 
2.34.1


--X119r+cMzLJwahiZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="0004-Move-the-double-plus-Size-columns-to-the-right.patch"



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

* [PATCH 3/4] f!convert the other verbose to int, too
@ 2021-07-15 08:19  Justin Pryzby <[email protected]>
  0 siblings, 0 replies; 34+ messages in thread

From: Justin Pryzby @ 2021-07-15 08:19 UTC (permalink / raw)

---
 src/bin/psql/command.c  |  82 ++++++++++----------
 src/bin/psql/describe.c | 163 ++++++++++++++++++++--------------------
 src/bin/psql/describe.h |  58 +++++++-------
 3 files changed, 151 insertions(+), 152 deletions(-)

diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index 667beb1b16e..3039aaca699 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -76,7 +76,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,
@@ -756,8 +756,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,
@@ -766,7 +765,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])
@@ -775,10 +773,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':
 				{
@@ -794,16 +792,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;
@@ -814,7 +812,7 @@ 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);
@@ -822,15 +820,15 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd)
 			case 'c':
 				if (strncmp(cmd, "dconfig", 7) == 0)
 					success = describeConfigurationParameters(pattern,
-															  show_verbose,
+															  verbose,
 															  show_system);
 				else
 					success = listConversions(pattern,
-											  show_verbose,
+											  verbose,
 											  show_system);
 				break;
 			case 'C':
-				success = listCasts(pattern, show_verbose);
+				success = listCasts(pattern, verbose);
 				break;
 			case 'd':
 				if (strncmp(cmd, "ddp", 3) == 0)
@@ -839,7 +837,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])
@@ -853,7 +851,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;
@@ -862,23 +860,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 = listLargeObjects(show_verbose);
+				success = listLargeObjects(verbose);
 				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, show_system);
@@ -892,7 +890,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;
@@ -901,7 +899,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':
@@ -909,7 +907,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')
@@ -932,36 +930,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;
@@ -972,16 +970,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;
@@ -989,7 +987,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);
@@ -998,7 +996,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;
@@ -1019,7 +1017,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];
@@ -1042,11 +1040,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]);
@@ -2016,9 +2014,9 @@ exec_command_lo(PsqlScanState scan_state, bool active_branch, const char *cmd)
 		}
 
 		else if (strcmp(cmd + 3, "list") == 0)
-			success = listLargeObjects(false);
+			success = listLargeObjects(0);
 		else if (strcmp(cmd + 3, "list+") == 0)
-			success = listLargeObjects(true);
+			success = listLargeObjects(1);
 
 		else if (strcmp(cmd + 3, "unlink") == 0)
 		{
diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index 3be7a5b8dc8..7eff1249015 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -33,7 +33,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);
@@ -68,7 +68,7 @@ static bool validateSQLNamePattern(PQExpBuffer buf, const char *pattern,
  * 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;
@@ -169,7 +169,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"
@@ -235,7 +235,7 @@ describeTablespaces(const char *pattern, int verbose)
 					  gettext_noop("Owner"),
 					  gettext_noop("Location"));
 
-	if (verbose)
+	if (verbose > 0)
 	{
 		appendPQExpBufferStr(&buf, ",\n  ");
 		printACLColumn(&buf, "spcacl");
@@ -301,7 +301,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;
@@ -386,7 +386,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"
@@ -441,7 +441,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");
 
@@ -627,7 +627,7 @@ error_return:
  * describe types
  */
 bool
-describeTypes(const char *pattern, bool verbose, bool showSystem)
+describeTypes(const char *pattern, int verbose, bool showSystem)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -640,7 +640,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"
@@ -785,7 +785,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;
@@ -821,7 +821,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"));
@@ -1455,10 +1455,10 @@ error_return:
  * 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;
@@ -1544,7 +1544,7 @@ static bool
 describeOneTableDetails(const char *schemaname,
 						const char *relationname,
 						const char *oid,
-						bool verbose)
+						int verbose)
 {
 	bool		retval = false;
 	PQExpBufferData buf;
@@ -1917,7 +1917,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++;
@@ -2175,7 +2175,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,
@@ -2198,7 +2198,7 @@ describeOneTableDetails(const char *schemaname,
 							  strcmp(detached, "t") == 0 ? " DETACH PENDING" : "");
 			printTableAddFooter(&cont, tmpbuf.data);
 
-			if (verbose)
+			if (verbose > 0)
 			{
 				char	   *partconstraintdef = NULL;
 
@@ -3434,7 +3434,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)
@@ -3486,7 +3486,7 @@ describeOneTableDetails(const char *schemaname,
 			printTableAddFooter(&cont, buf.data);
 		}
 
-		if (verbose &&
+		if (verbose > 0 &&
 			(tableinfo.relkind == RELKIND_RELATION ||
 			 tableinfo.relkind == RELKIND_MATVIEW) &&
 
@@ -3510,7 +3510,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 */
@@ -3518,7 +3518,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);
@@ -3526,7 +3526,7 @@ describeOneTableDetails(const char *schemaname,
 	}
 
 	/* reloptions, if verbose */
-	if (verbose &&
+	if (verbose > 0 &&
 		tableinfo.reloptions && tableinfo.reloptions[0] != '\0')
 	{
 		const char *t = _("Options");
@@ -3626,7 +3626,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;
@@ -3648,11 +3648,12 @@ describeRoles(const char *pattern, bool verbose, bool showSystem)
 					  "  r.rolcreaterole, r.rolcreatedb, r.rolcanlogin,\n"
 					  "  r.rolconnlimit, r.rolvaliduntil");
 
-	if (verbose)
+	if (verbose > 0)
 	{
 		appendPQExpBufferStr(&buf, "\n, pg_catalog.shobj_description(r.oid, 'pg_authid') AS description");
 		ncols++;
 	}
+
 	appendPQExpBufferStr(&buf, "\n, r.rolreplication");
 
 	if (pset.sversion >= 90500)
@@ -3687,7 +3688,7 @@ describeRoles(const char *pattern, bool verbose, bool showSystem)
 	printTableAddHeader(&cont, gettext_noop("Role name"), true, align);
 	printTableAddHeader(&cont, gettext_noop("Attributes"), true, align);
 
-	if (verbose)
+	if (verbose > 0)
 		printTableAddHeader(&cont, gettext_noop("Description"), true, align);
 
 	for (i = 0; i < nrows; i++)
@@ -3744,7 +3745,7 @@ describeRoles(const char *pattern, bool verbose, bool showSystem)
 
 		printTableAddCell(&cont, attr[i], false, false);
 
-		if (verbose)
+		if (verbose > 0)
 			printTableAddCell(&cont, PQgetvalue(res, i, 8), false, false);
 	}
 	termPQExpBuffer(&buf);
@@ -3923,7 +3924,7 @@ describeRoleGrants(const char *pattern, bool showSystem)
  * (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;
@@ -3982,7 +3983,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.
@@ -4122,7 +4123,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;
@@ -4197,7 +4198,7 @@ listPartitionedTables(const char *reltypes, const char *pattern, bool verbose)
 						  ",\n c2.oid::pg_catalog.regclass as \"%s\"",
 						  gettext_noop("Table"));
 
-	if (verbose)
+	if (verbose > 0)
 	{
 		if (showNested)
 		{
@@ -4232,7 +4233,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)
 		{
@@ -4323,7 +4324,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;
@@ -4339,7 +4340,7 @@ listLanguages(const char *pattern, bool verbose, bool showSystem)
 					  gettext_noop("Owner"),
 					  gettext_noop("Trusted"));
 
-	if (verbose)
+	if (verbose > 0)
 	{
 		appendPQExpBuffer(&buf,
 						  ",\n       NOT l.lanispl AS \"%s\",\n"
@@ -4400,7 +4401,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;
@@ -4427,7 +4428,7 @@ listDomains(const char *pattern, bool verbose, bool showSystem)
 					  gettext_noop("Default"),
 					  gettext_noop("Check"));
 
-	if (verbose)
+	if (verbose > 0)
 	{
 		appendPQExpBufferStr(&buf, ",\n  ");
 		printACLColumn(&buf, "t.typacl");
@@ -4440,7 +4441,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 "
@@ -4484,7 +4485,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;
@@ -4508,7 +4509,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"));
@@ -4518,7 +4519,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"
@@ -4565,7 +4566,7 @@ listConversions(const char *pattern, bool verbose, bool showSystem)
  * Describes configuration parameters.
  */
 bool
-describeConfigurationParameters(const char *pattern, bool verbose,
+describeConfigurationParameters(const char *pattern, int verbose,
 								bool showSystem)
 {
 	PQExpBufferData buf;
@@ -4634,7 +4635,7 @@ describeConfigurationParameters(const char *pattern, bool verbose,
  * Describes Event Triggers.
  */
 bool
-listEventTriggers(const char *pattern, bool verbose)
+listEventTriggers(const char *pattern, int verbose)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -4675,7 +4676,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"));
@@ -4812,7 +4813,7 @@ listExtendedStats(const char *pattern)
  * Describes casts.
  */
 bool
-listCasts(const char *pattern, bool verbose)
+listCasts(const char *pattern, int verbose)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -4853,7 +4854,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"));
@@ -4874,7 +4875,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 = "
@@ -4931,7 +4932,7 @@ error_return:
  * Describes collations.
  */
 bool
-listCollations(const char *pattern, bool verbose, bool showSystem)
+listCollations(const char *pattern, int verbose, bool showSystem)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -4991,7 +4992,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"));
@@ -5061,7 +5062,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");
@@ -5173,13 +5174,13 @@ error_return:
  * list text search parsers
  */
 bool
-listTSParsers(const char *pattern, bool verbose)
+listTSParsers(const char *pattern, int verbose)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
 	printQueryOpt myopt = pset.popt;
 
-	if (verbose)
+	if (verbose > 0)
 		return listTSParsersVerbose(pattern);
 
 	initPQExpBuffer(&buf);
@@ -5423,7 +5424,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;
@@ -5438,7 +5439,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"
@@ -5489,7 +5490,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;
@@ -5497,7 +5498,7 @@ listTSTemplates(const char *pattern, bool verbose)
 
 	initPQExpBuffer(&buf);
 
-	if (verbose)
+	if (verbose > 0)
 		printfPQExpBuffer(&buf,
 						  "SELECT\n"
 						  "  n.nspname AS \"%s\",\n"
@@ -5555,13 +5556,13 @@ 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;
 	printQueryOpt myopt = pset.popt;
 
-	if (verbose)
+	if (verbose > 0)
 		return listTSConfigsVerbose(pattern);
 
 	initPQExpBuffer(&buf);
@@ -5761,7 +5762,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;
@@ -5778,7 +5779,7 @@ listForeignDataWrappers(const char *pattern, bool verbose)
 					  gettext_noop("Handler"),
 					  gettext_noop("Validator"));
 
-	if (verbose)
+	if (verbose > 0)
 	{
 		appendPQExpBufferStr(&buf, ",\n  ");
 		printACLColumn(&buf, "fdwacl");
@@ -5796,7 +5797,7 @@ listForeignDataWrappers(const char *pattern, bool verbose)
 
 	appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_foreign_data_wrapper fdw\n");
 
-	if (verbose)
+	if (verbose > 0)
 		appendPQExpBufferStr(&buf,
 							 "LEFT JOIN pg_catalog.pg_description d\n"
 							 "       ON d.classoid = fdw.tableoid "
@@ -5833,7 +5834,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;
@@ -5848,7 +5849,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");
@@ -5873,7 +5874,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 "
@@ -5910,7 +5911,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;
@@ -5923,7 +5924,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 "
@@ -5966,7 +5967,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;
@@ -5981,7 +5982,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 "
@@ -6001,7 +6002,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 "
@@ -6565,7 +6566,7 @@ error_return:
  * 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;
@@ -6595,7 +6596,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)
@@ -6706,7 +6707,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;
@@ -6741,7 +6742,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"
@@ -6757,7 +6758,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");
@@ -6808,7 +6809,7 @@ error_return:
  */
 bool
 listOperatorFamilies(const char *access_method_pattern,
-					 const char *type_pattern, bool verbose)
+					 const char *type_pattern, int verbose)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -6833,7 +6834,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"));
@@ -6898,7 +6899,7 @@ error_return:
  */
 bool
 listOpFamilyOperators(const char *access_method_pattern,
-					  const char *family_pattern, bool verbose)
+					  const char *family_pattern, int verbose)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -6931,7 +6932,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"));
@@ -6940,7 +6941,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");
 
@@ -6997,7 +6998,7 @@ error_return:
  */
 bool
 listOpFamilyFunctions(const char *access_method_pattern,
-					  const char *family_pattern, bool verbose)
+					  const char *family_pattern, int verbose)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -7024,7 +7025,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"));
@@ -7086,7 +7087,7 @@ error_return:
  * Lists large objects
  */
 bool
-listLargeObjects(bool verbose)
+listLargeObjects(int verbose)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -7100,7 +7101,7 @@ listLargeObjects(bool verbose)
 					  gettext_noop("ID"),
 					  gettext_noop("Owner"));
 
-	if (verbose)
+	if (verbose > 0)
 	{
 		printACLColumn(&buf, "lomacl");
 		appendPQExpBufferStr(&buf, ",\n  ");
diff --git a/src/bin/psql/describe.h b/src/bin/psql/describe.h
index f11579a7bbc..8776a20a6b6 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);
@@ -50,62 +50,62 @@ 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);
 
 /* \dconfig */
-extern bool describeConfigurationParameters(const char *pattern, bool verbose,
+extern bool describeConfigurationParameters(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);
@@ -117,7 +117,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);
@@ -126,27 +126,27 @@ 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 *type_pattern,
-								bool verbose);
+								int verbose);
 
 /* \dAf */
 extern bool listOperatorFamilies(const char *access_method_pattern,
 								 const char *type_pattern,
-								 bool verbose);
+								 int verbose);
 
 /* \dAo */
 extern bool listOpFamilyOperators(const char *access_method_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);
 
 /* \dl or \lo_list */
-extern bool listLargeObjects(bool verbose);
+extern bool listLargeObjects(int verbose);
 
 #endif							/* DESCRIBE_H */
-- 
2.34.1


--X119r+cMzLJwahiZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="0004-Move-the-double-plus-Size-columns-to-the-right.patch"



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

* [PATCH v7 14/15] WIP: Make UnlockReleaseBuffer() more efficient
@ 2025-11-19 20:32  Andres Freund <[email protected]>
  0 siblings, 0 replies; 34+ messages in thread

From: Andres Freund @ 2025-11-19 20:32 UTC (permalink / raw)

Now that the buffer content lock is implemented as part of BufferDesc.state,
releasing the lock and unpinning the buffer can be implemented as a single
atomic operation.

Author:
Reviewed-By:
Discussion: https://postgr.es/m/
Backpatch:
---
 src/backend/access/nbtree/nbtpage.c | 22 +++++++++++-
 src/backend/storage/buffer/bufmgr.c | 52 ++++++++++++++++++++++++++++-
 2 files changed, 72 insertions(+), 2 deletions(-)

diff --git a/src/backend/access/nbtree/nbtpage.c b/src/backend/access/nbtree/nbtpage.c
index 30b43a4dd18..2fd8141854c 100644
--- a/src/backend/access/nbtree/nbtpage.c
+++ b/src/backend/access/nbtree/nbtpage.c
@@ -1006,11 +1006,18 @@ _bt_relandgetbuf(Relation rel, Buffer obuf, BlockNumber blkno, int access)
 
 	Assert(BlockNumberIsValid(blkno));
 	if (BufferIsValid(obuf))
+	{
+		_bt_relbuf(rel, obuf);
+#if 0
+		Assert(BufferGetBlockNumber(obuf) != blkno);
 		_bt_unlockbuf(rel, obuf);
-	buf = ReleaseAndReadBuffer(obuf, rel, blkno);
+#endif
+	}
+	buf = ReadBuffer(rel, blkno);
 	_bt_lockbuf(rel, buf, access);
 
 	_bt_checkpage(rel, buf);
+
 	return buf;
 }
 
@@ -1022,8 +1029,21 @@ _bt_relandgetbuf(Relation rel, Buffer obuf, BlockNumber blkno, int access)
 void
 _bt_relbuf(Relation rel, Buffer buf)
 {
+#if 0
 	_bt_unlockbuf(rel, buf);
 	ReleaseBuffer(buf);
+#else
+	/*
+	 * Buffer is pinned and locked, which means that it is expected to be
+	 * defined and addressable.  Check that proactively.
+	 */
+	VALGRIND_CHECK_MEM_IS_DEFINED(BufferGetPage(buf), BLCKSZ);
+
+	UnlockReleaseBuffer(buf);
+
+	if (!RelationUsesLocalBuffers(rel))
+		VALGRIND_MAKE_MEM_NOACCESS(BufferGetPage(buf), BLCKSZ);
+#endif
 }
 
 /*
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index 7409c4e7e42..3437854e766 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -5494,13 +5494,63 @@ ReleaseBuffer(Buffer buffer)
 /*
  * UnlockReleaseBuffer -- release the content lock and pin on a buffer
  *
- * This is just a shorthand for a common combination.
+ * This is just a, more efficient, shorthand for a common combination.
  */
 void
 UnlockReleaseBuffer(Buffer buffer)
 {
+#if 1
+	int			mode;
+	BufferDesc *buf;
+	PrivateRefCountEntry *ref;
+	uint64		sub;
+	uint64		lockstate;
+
+	if (!BufferIsValid(buffer))
+		elog(ERROR, "bad buffer ID: %d", buffer);
+
+	if (BufferIsLocal(buffer))
+	{
+		UnpinLocalBuffer(buffer);
+		return;
+	}
+
+	ResourceOwnerForgetBuffer(CurrentResourceOwner, buffer);
+
+	buf = GetBufferDescriptor(buffer - 1);
+
+	mode = BufferLockDisownInternal(buffer, buf);
+
+	/* compute state modification for lock release */
+	sub = BufferLockReleaseSub(mode);
+
+	/* compute state modification for pin release */
+	ref = GetPrivateRefCountEntry(buffer, false);
+	Assert(ref != NULL);
+	Assert(ref->data.refcount > 0);
+	ref->data.refcount--;
+
+	if (ref->data.refcount == 0)
+	{
+		sub |= BUF_REFCOUNT_ONE;
+		ForgetPrivateRefCountEntry(ref);
+	}
+
+	/* perform the lock and pin release in one atomic op */
+	lockstate = pg_atomic_sub_fetch_u64(&buf->state, sub);
+
+	/* wake up waiters etc */
+	BufferLockProcessRelease(buf, mode, lockstate);
+
+	if (lockstate & BM_PIN_COUNT_WAITER)
+		WakePinCountWaiter(buf);
+
+	RESUME_INTERRUPTS();
+
+#else
 	LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
 	ReleaseBuffer(buffer);
+#endif
 }
 
 /*
-- 
2.48.1.76.g4e746b1a31.dirty


--kad4mm4awdo7v2ki
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v7-0015-WIP-bufmgr-Don-t-copy-pages-while-writing-out.patch"



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

* [PATCH v10 6/8] WIP: Make UnlockReleaseBuffer() more efficient
@ 2025-11-19 20:32  Andres Freund <[email protected]>
  0 siblings, 0 replies; 34+ messages in thread

From: Andres Freund @ 2025-11-19 20:32 UTC (permalink / raw)

Now that the buffer content lock is implemented as part of BufferDesc.state,
releasing the lock and unpinning the buffer can be implemented as a single
atomic operation.

Author:
Reviewed-By:
Discussion: https://postgr.es/m/
Backpatch:
---
 src/backend/access/nbtree/nbtpage.c | 22 +++++++++++-
 src/backend/storage/buffer/bufmgr.c | 52 ++++++++++++++++++++++++++++-
 2 files changed, 72 insertions(+), 2 deletions(-)

diff --git a/src/backend/access/nbtree/nbtpage.c b/src/backend/access/nbtree/nbtpage.c
index 4125c185e8b..f3e3f67e1fd 100644
--- a/src/backend/access/nbtree/nbtpage.c
+++ b/src/backend/access/nbtree/nbtpage.c
@@ -1007,11 +1007,18 @@ _bt_relandgetbuf(Relation rel, Buffer obuf, BlockNumber blkno, int access)
 
 	Assert(BlockNumberIsValid(blkno));
 	if (BufferIsValid(obuf))
+	{
+		_bt_relbuf(rel, obuf);
+#if 0
+		Assert(BufferGetBlockNumber(obuf) != blkno);
 		_bt_unlockbuf(rel, obuf);
-	buf = ReleaseAndReadBuffer(obuf, rel, blkno);
+#endif
+	}
+	buf = ReadBuffer(rel, blkno);
 	_bt_lockbuf(rel, buf, access);
 
 	_bt_checkpage(rel, buf);
+
 	return buf;
 }
 
@@ -1023,8 +1030,21 @@ _bt_relandgetbuf(Relation rel, Buffer obuf, BlockNumber blkno, int access)
 void
 _bt_relbuf(Relation rel, Buffer buf)
 {
+#if 0
 	_bt_unlockbuf(rel, buf);
 	ReleaseBuffer(buf);
+#else
+	/*
+	 * Buffer is pinned and locked, which means that it is expected to be
+	 * defined and addressable.  Check that proactively.
+	 */
+	VALGRIND_CHECK_MEM_IS_DEFINED(BufferGetPage(buf), BLCKSZ);
+
+	UnlockReleaseBuffer(buf);
+
+	if (!RelationUsesLocalBuffers(rel))
+		VALGRIND_MAKE_MEM_NOACCESS(BufferGetPage(buf), BLCKSZ);
+#endif
 }
 
 /*
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index 98f473580a4..9574baa36cb 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -5511,13 +5511,63 @@ ReleaseBuffer(Buffer buffer)
 /*
  * UnlockReleaseBuffer -- release the content lock and pin on a buffer
  *
- * This is just a shorthand for a common combination.
+ * This is just a, more efficient, shorthand for a common combination.
  */
 void
 UnlockReleaseBuffer(Buffer buffer)
 {
+#if 1
+	int			mode;
+	BufferDesc *buf;
+	PrivateRefCountEntry *ref;
+	uint64		sub;
+	uint64		lockstate;
+
+	if (!BufferIsValid(buffer))
+		elog(ERROR, "bad buffer ID: %d", buffer);
+
+	if (BufferIsLocal(buffer))
+	{
+		UnpinLocalBuffer(buffer);
+		return;
+	}
+
+	ResourceOwnerForgetBuffer(CurrentResourceOwner, buffer);
+
+	buf = GetBufferDescriptor(buffer - 1);
+
+	mode = BufferLockDisownInternal(buffer, buf);
+
+	/* compute state modification for lock release */
+	sub = BufferLockReleaseSub(mode);
+
+	/* compute state modification for pin release */
+	ref = GetPrivateRefCountEntry(buffer, false);
+	Assert(ref != NULL);
+	Assert(ref->data.refcount > 0);
+	ref->data.refcount--;
+
+	if (ref->data.refcount == 0)
+	{
+		sub |= BUF_REFCOUNT_ONE;
+		ForgetPrivateRefCountEntry(ref);
+	}
+
+	/* perform the lock and pin release in one atomic op */
+	lockstate = pg_atomic_sub_fetch_u64(&buf->state, sub);
+
+	/* wake up waiters etc */
+	BufferLockProcessRelease(buf, mode, lockstate);
+
+	if (lockstate & BM_PIN_COUNT_WAITER)
+		WakePinCountWaiter(buf);
+
+	RESUME_INTERRUPTS();
+
+#else
 	LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
 	ReleaseBuffer(buffer);
+#endif
 }
 
 /*
-- 
2.48.1.76.g4e746b1a31.dirty


--jmawlk4t5yqwiemy
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v10-0007-WIP-bufmgr-Don-t-copy-pages-while-writing-out.patch"



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

* [PATCH v8 09/10] WIP: Make UnlockReleaseBuffer() more efficient
@ 2025-11-19 20:32  Andres Freund <[email protected]>
  0 siblings, 0 replies; 34+ messages in thread

From: Andres Freund @ 2025-11-19 20:32 UTC (permalink / raw)

Now that the buffer content lock is implemented as part of BufferDesc.state,
releasing the lock and unpinning the buffer can be implemented as a single
atomic operation.

Author:
Reviewed-By:
Discussion: https://postgr.es/m/
Backpatch:
---
 src/backend/access/nbtree/nbtpage.c | 22 +++++++++++-
 src/backend/storage/buffer/bufmgr.c | 52 ++++++++++++++++++++++++++++-
 2 files changed, 72 insertions(+), 2 deletions(-)

diff --git a/src/backend/access/nbtree/nbtpage.c b/src/backend/access/nbtree/nbtpage.c
index cfb07b2bca9..9f604751dc7 100644
--- a/src/backend/access/nbtree/nbtpage.c
+++ b/src/backend/access/nbtree/nbtpage.c
@@ -1007,11 +1007,18 @@ _bt_relandgetbuf(Relation rel, Buffer obuf, BlockNumber blkno, int access)
 
 	Assert(BlockNumberIsValid(blkno));
 	if (BufferIsValid(obuf))
+	{
+		_bt_relbuf(rel, obuf);
+#if 0
+		Assert(BufferGetBlockNumber(obuf) != blkno);
 		_bt_unlockbuf(rel, obuf);
-	buf = ReleaseAndReadBuffer(obuf, rel, blkno);
+#endif
+	}
+	buf = ReadBuffer(rel, blkno);
 	_bt_lockbuf(rel, buf, access);
 
 	_bt_checkpage(rel, buf);
+
 	return buf;
 }
 
@@ -1023,8 +1030,21 @@ _bt_relandgetbuf(Relation rel, Buffer obuf, BlockNumber blkno, int access)
 void
 _bt_relbuf(Relation rel, Buffer buf)
 {
+#if 0
 	_bt_unlockbuf(rel, buf);
 	ReleaseBuffer(buf);
+#else
+	/*
+	 * Buffer is pinned and locked, which means that it is expected to be
+	 * defined and addressable.  Check that proactively.
+	 */
+	VALGRIND_CHECK_MEM_IS_DEFINED(BufferGetPage(buf), BLCKSZ);
+
+	UnlockReleaseBuffer(buf);
+
+	if (!RelationUsesLocalBuffers(rel))
+		VALGRIND_MAKE_MEM_NOACCESS(BufferGetPage(buf), BLCKSZ);
+#endif
 }
 
 /*
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index 7c90d3413ac..7d8799bd9a1 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -5499,13 +5499,63 @@ ReleaseBuffer(Buffer buffer)
 /*
  * UnlockReleaseBuffer -- release the content lock and pin on a buffer
  *
- * This is just a shorthand for a common combination.
+ * This is just a, more efficient, shorthand for a common combination.
  */
 void
 UnlockReleaseBuffer(Buffer buffer)
 {
+#if 1
+	int			mode;
+	BufferDesc *buf;
+	PrivateRefCountEntry *ref;
+	uint64		sub;
+	uint64		lockstate;
+
+	if (!BufferIsValid(buffer))
+		elog(ERROR, "bad buffer ID: %d", buffer);
+
+	if (BufferIsLocal(buffer))
+	{
+		UnpinLocalBuffer(buffer);
+		return;
+	}
+
+	ResourceOwnerForgetBuffer(CurrentResourceOwner, buffer);
+
+	buf = GetBufferDescriptor(buffer - 1);
+
+	mode = BufferLockDisownInternal(buffer, buf);
+
+	/* compute state modification for lock release */
+	sub = BufferLockReleaseSub(mode);
+
+	/* compute state modification for pin release */
+	ref = GetPrivateRefCountEntry(buffer, false);
+	Assert(ref != NULL);
+	Assert(ref->data.refcount > 0);
+	ref->data.refcount--;
+
+	if (ref->data.refcount == 0)
+	{
+		sub |= BUF_REFCOUNT_ONE;
+		ForgetPrivateRefCountEntry(ref);
+	}
+
+	/* perform the lock and pin release in one atomic op */
+	lockstate = pg_atomic_sub_fetch_u64(&buf->state, sub);
+
+	/* wake up waiters etc */
+	BufferLockProcessRelease(buf, mode, lockstate);
+
+	if (lockstate & BM_PIN_COUNT_WAITER)
+		WakePinCountWaiter(buf);
+
+	RESUME_INTERRUPTS();
+
+#else
 	LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
 	ReleaseBuffer(buffer);
+#endif
 }
 
 /*
-- 
2.48.1.76.g4e746b1a31.dirty


--lbbj3oq7cjvyhmbk
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v8-0010-WIP-bufmgr-Don-t-copy-pages-while-writing-out.patch"



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

* [PATCH v9 09/10] WIP: Make UnlockReleaseBuffer() more efficient
@ 2025-11-19 20:32  Andres Freund <[email protected]>
  0 siblings, 0 replies; 34+ messages in thread

From: Andres Freund @ 2025-11-19 20:32 UTC (permalink / raw)

Now that the buffer content lock is implemented as part of BufferDesc.state,
releasing the lock and unpinning the buffer can be implemented as a single
atomic operation.

Author:
Reviewed-By:
Discussion: https://postgr.es/m/
Backpatch:
---
 src/backend/access/nbtree/nbtpage.c | 22 +++++++++++-
 src/backend/storage/buffer/bufmgr.c | 52 ++++++++++++++++++++++++++++-
 2 files changed, 72 insertions(+), 2 deletions(-)

diff --git a/src/backend/access/nbtree/nbtpage.c b/src/backend/access/nbtree/nbtpage.c
index 2ff0085b96f..073f5a05f81 100644
--- a/src/backend/access/nbtree/nbtpage.c
+++ b/src/backend/access/nbtree/nbtpage.c
@@ -1007,11 +1007,18 @@ _bt_relandgetbuf(Relation rel, Buffer obuf, BlockNumber blkno, int access)
 
 	Assert(BlockNumberIsValid(blkno));
 	if (BufferIsValid(obuf))
+	{
+		_bt_relbuf(rel, obuf);
+#if 0
+		Assert(BufferGetBlockNumber(obuf) != blkno);
 		_bt_unlockbuf(rel, obuf);
-	buf = ReleaseAndReadBuffer(obuf, rel, blkno);
+#endif
+	}
+	buf = ReadBuffer(rel, blkno);
 	_bt_lockbuf(rel, buf, access);
 
 	_bt_checkpage(rel, buf);
+
 	return buf;
 }
 
@@ -1023,8 +1030,21 @@ _bt_relandgetbuf(Relation rel, Buffer obuf, BlockNumber blkno, int access)
 void
 _bt_relbuf(Relation rel, Buffer buf)
 {
+#if 0
 	_bt_unlockbuf(rel, buf);
 	ReleaseBuffer(buf);
+#else
+	/*
+	 * Buffer is pinned and locked, which means that it is expected to be
+	 * defined and addressable.  Check that proactively.
+	 */
+	VALGRIND_CHECK_MEM_IS_DEFINED(BufferGetPage(buf), BLCKSZ);
+
+	UnlockReleaseBuffer(buf);
+
+	if (!RelationUsesLocalBuffers(rel))
+		VALGRIND_MAKE_MEM_NOACCESS(BufferGetPage(buf), BLCKSZ);
+#endif
 }
 
 /*
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index e944c09fb33..647af7a167c 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -5511,13 +5511,63 @@ ReleaseBuffer(Buffer buffer)
 /*
  * UnlockReleaseBuffer -- release the content lock and pin on a buffer
  *
- * This is just a shorthand for a common combination.
+ * This is just a, more efficient, shorthand for a common combination.
  */
 void
 UnlockReleaseBuffer(Buffer buffer)
 {
+#if 1
+	int			mode;
+	BufferDesc *buf;
+	PrivateRefCountEntry *ref;
+	uint64		sub;
+	uint64		lockstate;
+
+	if (!BufferIsValid(buffer))
+		elog(ERROR, "bad buffer ID: %d", buffer);
+
+	if (BufferIsLocal(buffer))
+	{
+		UnpinLocalBuffer(buffer);
+		return;
+	}
+
+	ResourceOwnerForgetBuffer(CurrentResourceOwner, buffer);
+
+	buf = GetBufferDescriptor(buffer - 1);
+
+	mode = BufferLockDisownInternal(buffer, buf);
+
+	/* compute state modification for lock release */
+	sub = BufferLockReleaseSub(mode);
+
+	/* compute state modification for pin release */
+	ref = GetPrivateRefCountEntry(buffer, false);
+	Assert(ref != NULL);
+	Assert(ref->data.refcount > 0);
+	ref->data.refcount--;
+
+	if (ref->data.refcount == 0)
+	{
+		sub |= BUF_REFCOUNT_ONE;
+		ForgetPrivateRefCountEntry(ref);
+	}
+
+	/* perform the lock and pin release in one atomic op */
+	lockstate = pg_atomic_sub_fetch_u64(&buf->state, sub);
+
+	/* wake up waiters etc */
+	BufferLockProcessRelease(buf, mode, lockstate);
+
+	if (lockstate & BM_PIN_COUNT_WAITER)
+		WakePinCountWaiter(buf);
+
+	RESUME_INTERRUPTS();
+
+#else
 	LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
 	ReleaseBuffer(buffer);
+#endif
 }
 
 /*
-- 
2.48.1.76.g4e746b1a31.dirty


--rkiyqpij3ajqn7ww
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v9-0010-WIP-bufmgr-Don-t-copy-pages-while-writing-out.patch"



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

* [PATCH v9 09/10] WIP: Make UnlockReleaseBuffer() more efficient
@ 2025-11-19 20:32  Andres Freund <[email protected]>
  0 siblings, 0 replies; 34+ messages in thread

From: Andres Freund @ 2025-11-19 20:32 UTC (permalink / raw)

Now that the buffer content lock is implemented as part of BufferDesc.state,
releasing the lock and unpinning the buffer can be implemented as a single
atomic operation.

Author:
Reviewed-By:
Discussion: https://postgr.es/m/
Backpatch:
---
 src/backend/access/nbtree/nbtpage.c | 22 +++++++++++-
 src/backend/storage/buffer/bufmgr.c | 52 ++++++++++++++++++++++++++++-
 2 files changed, 72 insertions(+), 2 deletions(-)

diff --git a/src/backend/access/nbtree/nbtpage.c b/src/backend/access/nbtree/nbtpage.c
index 2ff0085b96f..073f5a05f81 100644
--- a/src/backend/access/nbtree/nbtpage.c
+++ b/src/backend/access/nbtree/nbtpage.c
@@ -1007,11 +1007,18 @@ _bt_relandgetbuf(Relation rel, Buffer obuf, BlockNumber blkno, int access)
 
 	Assert(BlockNumberIsValid(blkno));
 	if (BufferIsValid(obuf))
+	{
+		_bt_relbuf(rel, obuf);
+#if 0
+		Assert(BufferGetBlockNumber(obuf) != blkno);
 		_bt_unlockbuf(rel, obuf);
-	buf = ReleaseAndReadBuffer(obuf, rel, blkno);
+#endif
+	}
+	buf = ReadBuffer(rel, blkno);
 	_bt_lockbuf(rel, buf, access);
 
 	_bt_checkpage(rel, buf);
+
 	return buf;
 }
 
@@ -1023,8 +1030,21 @@ _bt_relandgetbuf(Relation rel, Buffer obuf, BlockNumber blkno, int access)
 void
 _bt_relbuf(Relation rel, Buffer buf)
 {
+#if 0
 	_bt_unlockbuf(rel, buf);
 	ReleaseBuffer(buf);
+#else
+	/*
+	 * Buffer is pinned and locked, which means that it is expected to be
+	 * defined and addressable.  Check that proactively.
+	 */
+	VALGRIND_CHECK_MEM_IS_DEFINED(BufferGetPage(buf), BLCKSZ);
+
+	UnlockReleaseBuffer(buf);
+
+	if (!RelationUsesLocalBuffers(rel))
+		VALGRIND_MAKE_MEM_NOACCESS(BufferGetPage(buf), BLCKSZ);
+#endif
 }
 
 /*
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index e944c09fb33..647af7a167c 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -5511,13 +5511,63 @@ ReleaseBuffer(Buffer buffer)
 /*
  * UnlockReleaseBuffer -- release the content lock and pin on a buffer
  *
- * This is just a shorthand for a common combination.
+ * This is just a, more efficient, shorthand for a common combination.
  */
 void
 UnlockReleaseBuffer(Buffer buffer)
 {
+#if 1
+	int			mode;
+	BufferDesc *buf;
+	PrivateRefCountEntry *ref;
+	uint64		sub;
+	uint64		lockstate;
+
+	if (!BufferIsValid(buffer))
+		elog(ERROR, "bad buffer ID: %d", buffer);
+
+	if (BufferIsLocal(buffer))
+	{
+		UnpinLocalBuffer(buffer);
+		return;
+	}
+
+	ResourceOwnerForgetBuffer(CurrentResourceOwner, buffer);
+
+	buf = GetBufferDescriptor(buffer - 1);
+
+	mode = BufferLockDisownInternal(buffer, buf);
+
+	/* compute state modification for lock release */
+	sub = BufferLockReleaseSub(mode);
+
+	/* compute state modification for pin release */
+	ref = GetPrivateRefCountEntry(buffer, false);
+	Assert(ref != NULL);
+	Assert(ref->data.refcount > 0);
+	ref->data.refcount--;
+
+	if (ref->data.refcount == 0)
+	{
+		sub |= BUF_REFCOUNT_ONE;
+		ForgetPrivateRefCountEntry(ref);
+	}
+
+	/* perform the lock and pin release in one atomic op */
+	lockstate = pg_atomic_sub_fetch_u64(&buf->state, sub);
+
+	/* wake up waiters etc */
+	BufferLockProcessRelease(buf, mode, lockstate);
+
+	if (lockstate & BM_PIN_COUNT_WAITER)
+		WakePinCountWaiter(buf);
+
+	RESUME_INTERRUPTS();
+
+#else
 	LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
 	ReleaseBuffer(buffer);
+#endif
 }
 
 /*
-- 
2.48.1.76.g4e746b1a31.dirty


--rkiyqpij3ajqn7ww
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v9-0010-WIP-bufmgr-Don-t-copy-pages-while-writing-out.patch"



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

* [PATCH v10 6/8] WIP: Make UnlockReleaseBuffer() more efficient
@ 2025-11-19 20:32  Andres Freund <[email protected]>
  0 siblings, 0 replies; 34+ messages in thread

From: Andres Freund @ 2025-11-19 20:32 UTC (permalink / raw)

Now that the buffer content lock is implemented as part of BufferDesc.state,
releasing the lock and unpinning the buffer can be implemented as a single
atomic operation.

Author:
Reviewed-By:
Discussion: https://postgr.es/m/
Backpatch:
---
 src/backend/access/nbtree/nbtpage.c | 22 +++++++++++-
 src/backend/storage/buffer/bufmgr.c | 52 ++++++++++++++++++++++++++++-
 2 files changed, 72 insertions(+), 2 deletions(-)

diff --git a/src/backend/access/nbtree/nbtpage.c b/src/backend/access/nbtree/nbtpage.c
index 4125c185e8b..f3e3f67e1fd 100644
--- a/src/backend/access/nbtree/nbtpage.c
+++ b/src/backend/access/nbtree/nbtpage.c
@@ -1007,11 +1007,18 @@ _bt_relandgetbuf(Relation rel, Buffer obuf, BlockNumber blkno, int access)
 
 	Assert(BlockNumberIsValid(blkno));
 	if (BufferIsValid(obuf))
+	{
+		_bt_relbuf(rel, obuf);
+#if 0
+		Assert(BufferGetBlockNumber(obuf) != blkno);
 		_bt_unlockbuf(rel, obuf);
-	buf = ReleaseAndReadBuffer(obuf, rel, blkno);
+#endif
+	}
+	buf = ReadBuffer(rel, blkno);
 	_bt_lockbuf(rel, buf, access);
 
 	_bt_checkpage(rel, buf);
+
 	return buf;
 }
 
@@ -1023,8 +1030,21 @@ _bt_relandgetbuf(Relation rel, Buffer obuf, BlockNumber blkno, int access)
 void
 _bt_relbuf(Relation rel, Buffer buf)
 {
+#if 0
 	_bt_unlockbuf(rel, buf);
 	ReleaseBuffer(buf);
+#else
+	/*
+	 * Buffer is pinned and locked, which means that it is expected to be
+	 * defined and addressable.  Check that proactively.
+	 */
+	VALGRIND_CHECK_MEM_IS_DEFINED(BufferGetPage(buf), BLCKSZ);
+
+	UnlockReleaseBuffer(buf);
+
+	if (!RelationUsesLocalBuffers(rel))
+		VALGRIND_MAKE_MEM_NOACCESS(BufferGetPage(buf), BLCKSZ);
+#endif
 }
 
 /*
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index 98f473580a4..9574baa36cb 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -5511,13 +5511,63 @@ ReleaseBuffer(Buffer buffer)
 /*
  * UnlockReleaseBuffer -- release the content lock and pin on a buffer
  *
- * This is just a shorthand for a common combination.
+ * This is just a, more efficient, shorthand for a common combination.
  */
 void
 UnlockReleaseBuffer(Buffer buffer)
 {
+#if 1
+	int			mode;
+	BufferDesc *buf;
+	PrivateRefCountEntry *ref;
+	uint64		sub;
+	uint64		lockstate;
+
+	if (!BufferIsValid(buffer))
+		elog(ERROR, "bad buffer ID: %d", buffer);
+
+	if (BufferIsLocal(buffer))
+	{
+		UnpinLocalBuffer(buffer);
+		return;
+	}
+
+	ResourceOwnerForgetBuffer(CurrentResourceOwner, buffer);
+
+	buf = GetBufferDescriptor(buffer - 1);
+
+	mode = BufferLockDisownInternal(buffer, buf);
+
+	/* compute state modification for lock release */
+	sub = BufferLockReleaseSub(mode);
+
+	/* compute state modification for pin release */
+	ref = GetPrivateRefCountEntry(buffer, false);
+	Assert(ref != NULL);
+	Assert(ref->data.refcount > 0);
+	ref->data.refcount--;
+
+	if (ref->data.refcount == 0)
+	{
+		sub |= BUF_REFCOUNT_ONE;
+		ForgetPrivateRefCountEntry(ref);
+	}
+
+	/* perform the lock and pin release in one atomic op */
+	lockstate = pg_atomic_sub_fetch_u64(&buf->state, sub);
+
+	/* wake up waiters etc */
+	BufferLockProcessRelease(buf, mode, lockstate);
+
+	if (lockstate & BM_PIN_COUNT_WAITER)
+		WakePinCountWaiter(buf);
+
+	RESUME_INTERRUPTS();
+
+#else
 	LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
 	ReleaseBuffer(buffer);
+#endif
 }
 
 /*
-- 
2.48.1.76.g4e746b1a31.dirty


--jmawlk4t5yqwiemy
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v10-0007-WIP-bufmgr-Don-t-copy-pages-while-writing-out.patch"



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

* [PATCH v6 13/14] WIP: Make UnlockReleaseBuffer() more efficient
@ 2025-11-19 20:32  Andres Freund <[email protected]>
  0 siblings, 0 replies; 34+ messages in thread

From: Andres Freund @ 2025-11-19 20:32 UTC (permalink / raw)

Now that the buffer content lock is implemented as part of BufferDesc.state,
releasing the lock and unpinning the buffer can be implemented as a single
atomic operation.

Author:
Reviewed-By:
Discussion: https://postgr.es/m/
Backpatch:
---
 src/backend/access/nbtree/nbtpage.c | 22 +++++++++++-
 src/backend/storage/buffer/bufmgr.c | 52 ++++++++++++++++++++++++++++-
 2 files changed, 72 insertions(+), 2 deletions(-)

diff --git a/src/backend/access/nbtree/nbtpage.c b/src/backend/access/nbtree/nbtpage.c
index 30b43a4dd18..2fd8141854c 100644
--- a/src/backend/access/nbtree/nbtpage.c
+++ b/src/backend/access/nbtree/nbtpage.c
@@ -1006,11 +1006,18 @@ _bt_relandgetbuf(Relation rel, Buffer obuf, BlockNumber blkno, int access)
 
 	Assert(BlockNumberIsValid(blkno));
 	if (BufferIsValid(obuf))
+	{
+		_bt_relbuf(rel, obuf);
+#if 0
+		Assert(BufferGetBlockNumber(obuf) != blkno);
 		_bt_unlockbuf(rel, obuf);
-	buf = ReleaseAndReadBuffer(obuf, rel, blkno);
+#endif
+	}
+	buf = ReadBuffer(rel, blkno);
 	_bt_lockbuf(rel, buf, access);
 
 	_bt_checkpage(rel, buf);
+
 	return buf;
 }
 
@@ -1022,8 +1029,21 @@ _bt_relandgetbuf(Relation rel, Buffer obuf, BlockNumber blkno, int access)
 void
 _bt_relbuf(Relation rel, Buffer buf)
 {
+#if 0
 	_bt_unlockbuf(rel, buf);
 	ReleaseBuffer(buf);
+#else
+	/*
+	 * Buffer is pinned and locked, which means that it is expected to be
+	 * defined and addressable.  Check that proactively.
+	 */
+	VALGRIND_CHECK_MEM_IS_DEFINED(BufferGetPage(buf), BLCKSZ);
+
+	UnlockReleaseBuffer(buf);
+
+	if (!RelationUsesLocalBuffers(rel))
+		VALGRIND_MAKE_MEM_NOACCESS(BufferGetPage(buf), BLCKSZ);
+#endif
 }
 
 /*
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index 9ed7a368d74..584c3b2ee75 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -5437,13 +5437,63 @@ ReleaseBuffer(Buffer buffer)
 /*
  * UnlockReleaseBuffer -- release the content lock and pin on a buffer
  *
- * This is just a shorthand for a common combination.
+ * This is just a, more efficient, shorthand for a common combination.
  */
 void
 UnlockReleaseBuffer(Buffer buffer)
 {
+#if 1
+	int			mode;
+	BufferDesc *buf;
+	PrivateRefCountEntry *ref;
+	uint64		sub;
+	uint64		lockstate;
+
+	if (!BufferIsValid(buffer))
+		elog(ERROR, "bad buffer ID: %d", buffer);
+
+	if (BufferIsLocal(buffer))
+	{
+		UnpinLocalBuffer(buffer);
+		return;
+	}
+
+	ResourceOwnerForgetBuffer(CurrentResourceOwner, buffer);
+
+	buf = GetBufferDescriptor(buffer - 1);
+
+	mode = BufferLockDisownInternal(buffer, buf);
+
+	/* compute state modification for lock release */
+	sub = BufferLockReleaseSub(mode);
+
+	/* compute state modification for pin release */
+	ref = GetPrivateRefCountEntry(buffer, false);
+	Assert(ref != NULL);
+	Assert(ref->data.refcount > 0);
+	ref->data.refcount--;
+
+	if (ref->data.refcount == 0)
+	{
+		sub |= BUF_REFCOUNT_ONE;
+		ForgetPrivateRefCountEntry(ref);
+	}
+
+	/* perform the lock and pin release in one atomic op */
+	lockstate = pg_atomic_sub_fetch_u64(&buf->state, sub);
+
+	/* wake up waiters etc */
+	BufferLockProcessRelease(buf, mode, lockstate);
+
+	if (lockstate & BM_PIN_COUNT_WAITER)
+		WakePinCountWaiter(buf);
+
+	RESUME_INTERRUPTS();
+
+#else
 	LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
 	ReleaseBuffer(buffer);
+#endif
 }
 
 /*
-- 
2.48.1.76.g4e746b1a31.dirty


--mhhc7c45w3dmihtp
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v6-0014-WIP-bufmgr-Don-t-copy-pages-while-writing-out.patch"



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

* [PATCH v6 13/14] WIP: Make UnlockReleaseBuffer() more efficient
@ 2025-11-19 20:32  Andres Freund <[email protected]>
  0 siblings, 0 replies; 34+ messages in thread

From: Andres Freund @ 2025-11-19 20:32 UTC (permalink / raw)

Now that the buffer content lock is implemented as part of BufferDesc.state,
releasing the lock and unpinning the buffer can be implemented as a single
atomic operation.

Author:
Reviewed-By:
Discussion: https://postgr.es/m/
Backpatch:
---
 src/backend/access/nbtree/nbtpage.c | 22 +++++++++++-
 src/backend/storage/buffer/bufmgr.c | 52 ++++++++++++++++++++++++++++-
 2 files changed, 72 insertions(+), 2 deletions(-)

diff --git a/src/backend/access/nbtree/nbtpage.c b/src/backend/access/nbtree/nbtpage.c
index 30b43a4dd18..2fd8141854c 100644
--- a/src/backend/access/nbtree/nbtpage.c
+++ b/src/backend/access/nbtree/nbtpage.c
@@ -1006,11 +1006,18 @@ _bt_relandgetbuf(Relation rel, Buffer obuf, BlockNumber blkno, int access)
 
 	Assert(BlockNumberIsValid(blkno));
 	if (BufferIsValid(obuf))
+	{
+		_bt_relbuf(rel, obuf);
+#if 0
+		Assert(BufferGetBlockNumber(obuf) != blkno);
 		_bt_unlockbuf(rel, obuf);
-	buf = ReleaseAndReadBuffer(obuf, rel, blkno);
+#endif
+	}
+	buf = ReadBuffer(rel, blkno);
 	_bt_lockbuf(rel, buf, access);
 
 	_bt_checkpage(rel, buf);
+
 	return buf;
 }
 
@@ -1022,8 +1029,21 @@ _bt_relandgetbuf(Relation rel, Buffer obuf, BlockNumber blkno, int access)
 void
 _bt_relbuf(Relation rel, Buffer buf)
 {
+#if 0
 	_bt_unlockbuf(rel, buf);
 	ReleaseBuffer(buf);
+#else
+	/*
+	 * Buffer is pinned and locked, which means that it is expected to be
+	 * defined and addressable.  Check that proactively.
+	 */
+	VALGRIND_CHECK_MEM_IS_DEFINED(BufferGetPage(buf), BLCKSZ);
+
+	UnlockReleaseBuffer(buf);
+
+	if (!RelationUsesLocalBuffers(rel))
+		VALGRIND_MAKE_MEM_NOACCESS(BufferGetPage(buf), BLCKSZ);
+#endif
 }
 
 /*
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index 9ed7a368d74..584c3b2ee75 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -5437,13 +5437,63 @@ ReleaseBuffer(Buffer buffer)
 /*
  * UnlockReleaseBuffer -- release the content lock and pin on a buffer
  *
- * This is just a shorthand for a common combination.
+ * This is just a, more efficient, shorthand for a common combination.
  */
 void
 UnlockReleaseBuffer(Buffer buffer)
 {
+#if 1
+	int			mode;
+	BufferDesc *buf;
+	PrivateRefCountEntry *ref;
+	uint64		sub;
+	uint64		lockstate;
+
+	if (!BufferIsValid(buffer))
+		elog(ERROR, "bad buffer ID: %d", buffer);
+
+	if (BufferIsLocal(buffer))
+	{
+		UnpinLocalBuffer(buffer);
+		return;
+	}
+
+	ResourceOwnerForgetBuffer(CurrentResourceOwner, buffer);
+
+	buf = GetBufferDescriptor(buffer - 1);
+
+	mode = BufferLockDisownInternal(buffer, buf);
+
+	/* compute state modification for lock release */
+	sub = BufferLockReleaseSub(mode);
+
+	/* compute state modification for pin release */
+	ref = GetPrivateRefCountEntry(buffer, false);
+	Assert(ref != NULL);
+	Assert(ref->data.refcount > 0);
+	ref->data.refcount--;
+
+	if (ref->data.refcount == 0)
+	{
+		sub |= BUF_REFCOUNT_ONE;
+		ForgetPrivateRefCountEntry(ref);
+	}
+
+	/* perform the lock and pin release in one atomic op */
+	lockstate = pg_atomic_sub_fetch_u64(&buf->state, sub);
+
+	/* wake up waiters etc */
+	BufferLockProcessRelease(buf, mode, lockstate);
+
+	if (lockstate & BM_PIN_COUNT_WAITER)
+		WakePinCountWaiter(buf);
+
+	RESUME_INTERRUPTS();
+
+#else
 	LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
 	ReleaseBuffer(buffer);
+#endif
 }
 
 /*
-- 
2.48.1.76.g4e746b1a31.dirty


--mhhc7c45w3dmihtp
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v6-0014-WIP-bufmgr-Don-t-copy-pages-while-writing-out.patch"



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

* [PATCH v12 6/6] WIP: Make UnlockReleaseBuffer() more efficient
@ 2026-01-14 01:10  Andres Freund <[email protected]>
  0 siblings, 0 replies; 34+ messages in thread

From: Andres Freund @ 2026-01-14 01:10 UTC (permalink / raw)

Now that the buffer content lock is implemented as part of BufferDesc.state,
releasing the lock and unpinning the buffer can be implemented as a single
atomic operation.

Author:
Reviewed-By:
Discussion: https://postgr.es/m/
Backpatch:
---
 src/backend/access/nbtree/nbtpage.c | 22 +++++++++++-
 src/backend/storage/buffer/bufmgr.c | 52 ++++++++++++++++++++++++++++-
 2 files changed, 72 insertions(+), 2 deletions(-)

diff --git a/src/backend/access/nbtree/nbtpage.c b/src/backend/access/nbtree/nbtpage.c
index 4125c185e8b..f3e3f67e1fd 100644
--- a/src/backend/access/nbtree/nbtpage.c
+++ b/src/backend/access/nbtree/nbtpage.c
@@ -1007,11 +1007,18 @@ _bt_relandgetbuf(Relation rel, Buffer obuf, BlockNumber blkno, int access)
 
 	Assert(BlockNumberIsValid(blkno));
 	if (BufferIsValid(obuf))
+	{
+		_bt_relbuf(rel, obuf);
+#if 0
+		Assert(BufferGetBlockNumber(obuf) != blkno);
 		_bt_unlockbuf(rel, obuf);
-	buf = ReleaseAndReadBuffer(obuf, rel, blkno);
+#endif
+	}
+	buf = ReadBuffer(rel, blkno);
 	_bt_lockbuf(rel, buf, access);
 
 	_bt_checkpage(rel, buf);
+
 	return buf;
 }
 
@@ -1023,8 +1030,21 @@ _bt_relandgetbuf(Relation rel, Buffer obuf, BlockNumber blkno, int access)
 void
 _bt_relbuf(Relation rel, Buffer buf)
 {
+#if 0
 	_bt_unlockbuf(rel, buf);
 	ReleaseBuffer(buf);
+#else
+	/*
+	 * Buffer is pinned and locked, which means that it is expected to be
+	 * defined and addressable.  Check that proactively.
+	 */
+	VALGRIND_CHECK_MEM_IS_DEFINED(BufferGetPage(buf), BLCKSZ);
+
+	UnlockReleaseBuffer(buf);
+
+	if (!RelationUsesLocalBuffers(rel))
+		VALGRIND_MAKE_MEM_NOACCESS(BufferGetPage(buf), BLCKSZ);
+#endif
 }
 
 /*
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index 4a9107cb47a..8a4fb7c30d7 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -5502,13 +5502,63 @@ ReleaseBuffer(Buffer buffer)
 /*
  * UnlockReleaseBuffer -- release the content lock and pin on a buffer
  *
- * This is just a shorthand for a common combination.
+ * This is just a, more efficient, shorthand for a common combination.
  */
 void
 UnlockReleaseBuffer(Buffer buffer)
 {
+#if 1
+	int			mode;
+	BufferDesc *buf;
+	PrivateRefCountEntry *ref;
+	uint64		sub;
+	uint64		lockstate;
+
+	if (!BufferIsValid(buffer))
+		elog(ERROR, "bad buffer ID: %d", buffer);
+
+	if (BufferIsLocal(buffer))
+	{
+		UnpinLocalBuffer(buffer);
+		return;
+	}
+
+	ResourceOwnerForgetBuffer(CurrentResourceOwner, buffer);
+
+	buf = GetBufferDescriptor(buffer - 1);
+
+	mode = BufferLockDisownInternal(buffer, buf);
+
+	/* compute state modification for lock release */
+	sub = BufferLockReleaseSub(mode);
+
+	/* compute state modification for pin release */
+	ref = GetPrivateRefCountEntry(buffer, false);
+	Assert(ref != NULL);
+	Assert(ref->data.refcount > 0);
+	ref->data.refcount--;
+
+	if (ref->data.refcount == 0)
+	{
+		sub |= BUF_REFCOUNT_ONE;
+		ForgetPrivateRefCountEntry(ref);
+	}
+
+	/* perform the lock and pin release in one atomic op */
+	lockstate = pg_atomic_sub_fetch_u64(&buf->state, sub);
+
+	/* wake up waiters etc */
+	BufferLockProcessRelease(buf, mode, lockstate);
+
+	if (lockstate & BM_PIN_COUNT_WAITER)
+		WakePinCountWaiter(buf);
+
+	RESUME_INTERRUPTS();
+
+#else
 	LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
 	ReleaseBuffer(buffer);
+#endif
 }
 
 /*
-- 
2.48.1.76.g4e746b1a31.dirty


--3wqfabfsaassock4--





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

* [PATCH v11 7/7] WIP: Make UnlockReleaseBuffer() more efficient
@ 2026-01-14 01:10  Andres Freund <[email protected]>
  0 siblings, 0 replies; 34+ messages in thread

From: Andres Freund @ 2026-01-14 01:10 UTC (permalink / raw)

Now that the buffer content lock is implemented as part of BufferDesc.state,
releasing the lock and unpinning the buffer can be implemented as a single
atomic operation.

Author:
Reviewed-By:
Discussion: https://postgr.es/m/
Backpatch:
---
 src/backend/access/nbtree/nbtpage.c | 22 +++++++++++-
 src/backend/storage/buffer/bufmgr.c | 52 ++++++++++++++++++++++++++++-
 2 files changed, 72 insertions(+), 2 deletions(-)

diff --git a/src/backend/access/nbtree/nbtpage.c b/src/backend/access/nbtree/nbtpage.c
index 4125c185e8b..f3e3f67e1fd 100644
--- a/src/backend/access/nbtree/nbtpage.c
+++ b/src/backend/access/nbtree/nbtpage.c
@@ -1007,11 +1007,18 @@ _bt_relandgetbuf(Relation rel, Buffer obuf, BlockNumber blkno, int access)
 
 	Assert(BlockNumberIsValid(blkno));
 	if (BufferIsValid(obuf))
+	{
+		_bt_relbuf(rel, obuf);
+#if 0
+		Assert(BufferGetBlockNumber(obuf) != blkno);
 		_bt_unlockbuf(rel, obuf);
-	buf = ReleaseAndReadBuffer(obuf, rel, blkno);
+#endif
+	}
+	buf = ReadBuffer(rel, blkno);
 	_bt_lockbuf(rel, buf, access);
 
 	_bt_checkpage(rel, buf);
+
 	return buf;
 }
 
@@ -1023,8 +1030,21 @@ _bt_relandgetbuf(Relation rel, Buffer obuf, BlockNumber blkno, int access)
 void
 _bt_relbuf(Relation rel, Buffer buf)
 {
+#if 0
 	_bt_unlockbuf(rel, buf);
 	ReleaseBuffer(buf);
+#else
+	/*
+	 * Buffer is pinned and locked, which means that it is expected to be
+	 * defined and addressable.  Check that proactively.
+	 */
+	VALGRIND_CHECK_MEM_IS_DEFINED(BufferGetPage(buf), BLCKSZ);
+
+	UnlockReleaseBuffer(buf);
+
+	if (!RelationUsesLocalBuffers(rel))
+		VALGRIND_MAKE_MEM_NOACCESS(BufferGetPage(buf), BLCKSZ);
+#endif
 }
 
 /*
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index 097c8fa67c5..a3a11595b5d 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -5506,13 +5506,63 @@ ReleaseBuffer(Buffer buffer)
 /*
  * UnlockReleaseBuffer -- release the content lock and pin on a buffer
  *
- * This is just a shorthand for a common combination.
+ * This is just a, more efficient, shorthand for a common combination.
  */
 void
 UnlockReleaseBuffer(Buffer buffer)
 {
+#if 1
+	int			mode;
+	BufferDesc *buf;
+	PrivateRefCountEntry *ref;
+	uint64		sub;
+	uint64		lockstate;
+
+	if (!BufferIsValid(buffer))
+		elog(ERROR, "bad buffer ID: %d", buffer);
+
+	if (BufferIsLocal(buffer))
+	{
+		UnpinLocalBuffer(buffer);
+		return;
+	}
+
+	ResourceOwnerForgetBuffer(CurrentResourceOwner, buffer);
+
+	buf = GetBufferDescriptor(buffer - 1);
+
+	mode = BufferLockDisownInternal(buffer, buf);
+
+	/* compute state modification for lock release */
+	sub = BufferLockReleaseSub(mode);
+
+	/* compute state modification for pin release */
+	ref = GetPrivateRefCountEntry(buffer, false);
+	Assert(ref != NULL);
+	Assert(ref->data.refcount > 0);
+	ref->data.refcount--;
+
+	if (ref->data.refcount == 0)
+	{
+		sub |= BUF_REFCOUNT_ONE;
+		ForgetPrivateRefCountEntry(ref);
+	}
+
+	/* perform the lock and pin release in one atomic op */
+	lockstate = pg_atomic_sub_fetch_u64(&buf->state, sub);
+
+	/* wake up waiters etc */
+	BufferLockProcessRelease(buf, mode, lockstate);
+
+	if (lockstate & BM_PIN_COUNT_WAITER)
+		WakePinCountWaiter(buf);
+
+	RESUME_INTERRUPTS();
+
+#else
 	LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
 	ReleaseBuffer(buffer);
+#endif
 }
 
 /*
-- 
2.48.1.76.g4e746b1a31.dirty


--c6wqr3sg4llxfu2u--





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

* 2026-02-26 release announcement draft
@ 2026-02-23 06:49  Jonathan S. Katz <[email protected]>
  0 siblings, 1 reply; 34+ messages in thread

From: Jonathan S. Katz @ 2026-02-23 06:49 UTC (permalink / raw)
  To: PostgreSQL Hackers <[email protected]>

Hi,

Please see the draft of the 2026-02-26 release announcement. Please 
review for inaccuracies.

For the additional steps related to the `json[b]_strip_nulls()` issue, I 
primarily borrowed from the guidance in the release notes. For users who 
already updated to PG < 18.3, I didn't think it'd be worthwhile to say 
they should `pg_upgrade` to 18.3, given the post-update steps would be 
much less disruptive. However, I'm open to other suggestions for how to 
frame the guidance.

Thanks,

Jonathan

The PostgreSQL Global Development Group has released an update to all
supported versions of PostgreSQL, including 18.3, 17.9, 16.13, 15.17, and 14.22.
This is an out-of-cycle release that fixes [several regressions reported after the last update release](https://www.postgresql.org/about/news/out-of-cycle-release-scheduled-for-february-26-2026-3241/).

For the full list of changes, please review the [release notes](https://www.postgresql.org/docs/release/).

Bug Fixes and Improvements
--------------------------

This update fixes several bugs that were reported since the previous release. The issues listed below affect PostgreSQL 18. Some of these issues may also affect other supported versions of PostgreSQL.

* Fix issue where a standby would halt and return an error `"could not access status of transaction"`.
* Fix error where the [`substring()`](https://www.postgresql.org/docs/current/functions-string.html#id-1.5.8.10.5.2.2.17.1.1.1) function would raise an error `"invalid byte sequence for encoding"` on non-ASCII text values if the source of that value is a database column. This was due to a change introduced for the fix to [`CVE-2026-2006`](https://www.postgresql.org/support/security/CVE-2026-2006/).
* Fix for the `strict_word_similarity` function in [`pg_trgm`](https://www.postgresql.org/docs/current/pgtrgm.html) that could lead to incorrect output or crashes. This was due to an oversight in the fix for [CVE-2026-2007](https://www.postgresql.org/support/security/CVE-2026-2007/).
* Fix function volatility for `json_strip_nulls()` and `jsonb_strip_nulls()` to be immutable, like previous releases, allowing for them to be used in indexes. If you previously upgraded to PostgreSQL 18.0 through 18.2, see the additional steps in the "Updating" section.
* Fix for `NOT NULL` tests in `LATERAL UNION ALL` subquery that could lead to wrong query output.
* Avoid `NOT NULL` constraints from generating name conflicts with user-written constraints.
* Fix `pg_stat_get_backend_wait_event()` and `pg_stat_get_backend_wait_event_type()` to report values for auxiliary processes, similar to `pg_stat_activity`.
* Fix casting a composite-type variable to a domain type when returning its value from a PL/pgSQL function.
* Fix the [`hstore`](https://www.postgresql.org/docs/current/hstore.html) binary input function to avoid crashes on input with duplicate keys.

Updating
--------

All PostgreSQL update releases are cumulative. As with other minor releases, users are not required to dump and reload their database or use [`pg_upgrade`](https://www.postgresql.org/docs/current/pgupgrade.html) in order to apply this update release; you may simply shutdown PostgreSQL and update its binaries.

If you previously upgraded to PostgreSQL 18.0, 18.1 or 18.2, you need to execute the following SQL as a PostgreSQL superuser in all of your databases to make the `json_strip_nulls()` and `jsonb_strip_nulls()` functions immutable:

```
UPDATE pg_catalog.pg_proc SET provolatile = 'i' WHERE oid IN ('3261','3262');
```

You should also execute this command in the `template0` and `template1` databases so future databases you create in your PostgreSQL cluster have the correct function volatility setting.

Users who have skipped one or more update releases may need to run additional post-update steps; please see the release notes from earlier versions for details.

For more details, please see the [release notes](https://www.postgresql.org/docs/release/).

Links
-----

* [Download](https://www.postgresql.org/download/)
* [Release Notes](https://www.postgresql.org/docs/release/)
* [Security](https://www.postgresql.org/support/security/)
* [Versioning Policy](https://www.postgresql.org/support/versioning/)
* [Submit a Bug](https://www.postgresql.org/account/submitbug/)
* [Donate](https://www.postgresql.org/about/donate/)

If you have corrections or suggestions for this release announcement, please send them to the [email protected]_ public [mailing list](https://www.postgresql.org/list/).

Attachments:

  [text/plain] 20260226updaterelease.md (3.9K, ../../[email protected]/2-20260226updaterelease.md)
  download | inline:
The PostgreSQL Global Development Group has released an update to all
supported versions of PostgreSQL, including 18.3, 17.9, 16.13, 15.17, and 14.22.
This is an out-of-cycle release that fixes [several regressions reported after the last update release](https://www.postgresql.org/about/news/out-of-cycle-release-scheduled-for-february-26-2026-3241/).

For the full list of changes, please review the [release notes](https://www.postgresql.org/docs/release/).

Bug Fixes and Improvements
--------------------------

This update fixes several bugs that were reported since the previous release. The issues listed below affect PostgreSQL 18. Some of these issues may also affect other supported versions of PostgreSQL.

* Fix issue where a standby would halt and return an error `"could not access status of transaction"`.
* Fix error where the [`substring()`](https://www.postgresql.org/docs/current/functions-string.html#id-1.5.8.10.5.2.2.17.1.1.1) function would raise an error `"invalid byte sequence for encoding"` on non-ASCII text values if the source of that value is a database column. This was due to a change introduced for the fix to [`CVE-2026-2006`](https://www.postgresql.org/support/security/CVE-2026-2006/).
* Fix for the `strict_word_similarity` function in [`pg_trgm`](https://www.postgresql.org/docs/current/pgtrgm.html) that could lead to incorrect output or crashes. This was due to an oversight in the fix for [CVE-2026-2007](https://www.postgresql.org/support/security/CVE-2026-2007/).
* Fix function volatility for `json_strip_nulls()` and `jsonb_strip_nulls()` to be immutable, like previous releases, allowing for them to be used in indexes. If you previously upgraded to PostgreSQL 18.0 through 18.2, see the additional steps in the "Updating" section.
* Fix for `NOT NULL` tests in `LATERAL UNION ALL` subquery that could lead to wrong query output.
* Avoid `NOT NULL` constraints from generating name conflicts with user-written constraints.
* Fix `pg_stat_get_backend_wait_event()` and `pg_stat_get_backend_wait_event_type()` to report values for auxiliary processes, similar to `pg_stat_activity`.
* Fix casting a composite-type variable to a domain type when returning its value from a PL/pgSQL function.
* Fix the [`hstore`](https://www.postgresql.org/docs/current/hstore.html) binary input function to avoid crashes on input with duplicate keys.

Updating
--------

All PostgreSQL update releases are cumulative. As with other minor releases, users are not required to dump and reload their database or use [`pg_upgrade`](https://www.postgresql.org/docs/current/pgupgrade.html) in order to apply this update release; you may simply shutdown PostgreSQL and update its binaries.

If you previously upgraded to PostgreSQL 18.0, 18.1 or 18.2, you need to execute the following SQL as a PostgreSQL superuser in all of your databases to make the `json_strip_nulls()` and `jsonb_strip_nulls()` functions immutable:

```
UPDATE pg_catalog.pg_proc SET provolatile = 'i' WHERE oid IN ('3261','3262');
```

You should also execute this command in the `template0` and `template1` databases so future databases you create in your PostgreSQL cluster have the correct function volatility setting.

Users who have skipped one or more update releases may need to run additional post-update steps; please see the release notes from earlier versions for details.

For more details, please see the [release notes](https://www.postgresql.org/docs/release/).

Links
-----

* [Download](https://www.postgresql.org/download/)
* [Release Notes](https://www.postgresql.org/docs/release/)
* [Security](https://www.postgresql.org/support/security/)
* [Versioning Policy](https://www.postgresql.org/support/versioning/)
* [Submit a Bug](https://www.postgresql.org/account/submitbug/)
* [Donate](https://www.postgresql.org/about/donate/)

If you have corrections or suggestions for this release announcement, please send them to the [email protected]_ public [mailing list](https://www.postgresql.org/list/).

  [application/pgp-signature] OpenPGP_signature.asc (840B, ../../[email protected]/3-OpenPGP_signature.asc)
  download

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

* Re: 2026-02-26 release announcement draft
@ 2026-02-23 06:58  Daniel Westermann (DWE) <[email protected]>
  parent: Jonathan S. Katz <[email protected]>
  0 siblings, 1 reply; 34+ messages in thread

From: Daniel Westermann (DWE) @ 2026-02-23 06:58 UTC (permalink / raw)
  To: Jonathan S. Katz <[email protected]>; PostgreSQL Hackers <[email protected]>

Hi,

>You should also execute this command in the `template0` and `template1` databases so future databases you create in your PostgreSQL cluster have the correct function volatility setting.

Shouldn't it be mentioned that template0 is read only and give instructions how to do this properly?

Regards
Daniel




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

* Re: 2026-02-26 release announcement draft
@ 2026-02-24 05:53  Jonathan S. Katz <[email protected]>
  parent: Daniel Westermann (DWE) <[email protected]>
  0 siblings, 1 reply; 34+ messages in thread

From: Jonathan S. Katz @ 2026-02-24 05:53 UTC (permalink / raw)
  To: Daniel Westermann (DWE) <[email protected]>; PostgreSQL Hackers <[email protected]>

On 2/23/26 1:58 AM, Daniel Westermann (DWE) wrote:
> Hi,
> 
>> You should also execute this command in the `template0` and `template1` databases so future databases you create in your PostgreSQL cluster have the correct function volatility setting.
> 
> Shouldn't it be mentioned that template0 is read only and give instructions how to do this properly?

"template0" isn't read-only; it isn't connectable by default. That said, 
this is a good recommendation given the behaviors of these databases. I 
modified the text to include a link to the documentation for more 
information on the core template databases. Please see attached.

Thanks,

Jonathan

The PostgreSQL Global Development Group has released an update to all
supported versions of PostgreSQL, including 18.3, 17.9, 16.13, 15.17, and 14.22.
This is an out-of-cycle release that fixes [several regressions reported after the last update release](https://www.postgresql.org/about/news/out-of-cycle-release-scheduled-for-february-26-2026-3241/).

For the full list of changes, please review the [release notes](https://www.postgresql.org/docs/release/).

Bug Fixes and Improvements
--------------------------

This update fixes several bugs that were reported since the previous release. The issues listed below affect PostgreSQL 18. Some of these issues may also affect other supported versions of PostgreSQL.

* Fix issue where a standby would halt and return an error `"could not access status of transaction"`.
* Fix error where the [`substring()`](https://www.postgresql.org/docs/current/functions-string.html#id-1.5.8.10.5.2.2.17.1.1.1) function would raise an error `"invalid byte sequence for encoding"` on non-ASCII text values if the source of that value is a database column. This was due to a change introduced for the fix to [`CVE-2026-2006`](https://www.postgresql.org/support/security/CVE-2026-2006/).
* Fix for the `strict_word_similarity` function in [`pg_trgm`](https://www.postgresql.org/docs/current/pgtrgm.html) that could lead to incorrect output or crashes. This was due to an oversight in the fix for [CVE-2026-2007](https://www.postgresql.org/support/security/CVE-2026-2007/).
* Fix function volatility for `json_strip_nulls()` and `jsonb_strip_nulls()` to be immutable, like previous releases, allowing for them to be used in indexes. If you previously upgraded to PostgreSQL 18.0 through 18.2, see the additional steps in the "Updating" section.
* Fix for `NOT NULL` tests in `LATERAL UNION ALL` subquery that could lead to wrong query output.
* Avoid `NOT NULL` constraints from generating name conflicts with user-written constraints.
* Fix `pg_stat_get_backend_wait_event()` and `pg_stat_get_backend_wait_event_type()` to report values for auxiliary processes, similar to `pg_stat_activity`.
* Fix casting a composite-type variable to a domain type when returning its value from a PL/pgSQL function.
* Fix the [`hstore`](https://www.postgresql.org/docs/current/hstore.html) binary input function to avoid crashes on input with duplicate keys.

Updating
--------

All PostgreSQL update releases are cumulative. As with other minor releases, users are not required to dump and reload their database or use [`pg_upgrade`](https://www.postgresql.org/docs/current/pgupgrade.html) in order to apply this update release; you may simply shutdown PostgreSQL and update its binaries.

If you previously upgraded to PostgreSQL 18.0, 18.1 or 18.2, you need to execute the following SQL as a PostgreSQL superuser in all of your databases to make the `json_strip_nulls()` and `jsonb_strip_nulls()` functions immutable:

```
UPDATE pg_catalog.pg_proc SET provolatile = 'i' WHERE oid IN ('3261','3262');
```

You should also execute this command in the `template0` and `template1` databases so future databases you create in your PostgreSQL cluster have the correct function volatility setting. Please see the documentation on [template databases](https://www.postgresql.org/docs/current/manage-ag-templatedbs.html) for more information.

Users who have skipped one or more update releases may need to run additional post-update steps; please see the release notes from earlier versions for details.

For more details, please see the [release notes](https://www.postgresql.org/docs/release/).

Links
-----

* [Download](https://www.postgresql.org/download/)
* [Release Notes](https://www.postgresql.org/docs/release/)
* [Security](https://www.postgresql.org/support/security/)
* [Versioning Policy](https://www.postgresql.org/support/versioning/)
* [Submit a Bug](https://www.postgresql.org/account/submitbug/)
* [Donate](https://www.postgresql.org/about/donate/)

If you have corrections or suggestions for this release announcement, please send them to the [email protected]_ public [mailing list](https://www.postgresql.org/list/).

Attachments:

  [text/plain] 20260226updaterelease.md (4.1K, ../../[email protected]/2-20260226updaterelease.md)
  download | inline:
The PostgreSQL Global Development Group has released an update to all
supported versions of PostgreSQL, including 18.3, 17.9, 16.13, 15.17, and 14.22.
This is an out-of-cycle release that fixes [several regressions reported after the last update release](https://www.postgresql.org/about/news/out-of-cycle-release-scheduled-for-february-26-2026-3241/).

For the full list of changes, please review the [release notes](https://www.postgresql.org/docs/release/).

Bug Fixes and Improvements
--------------------------

This update fixes several bugs that were reported since the previous release. The issues listed below affect PostgreSQL 18. Some of these issues may also affect other supported versions of PostgreSQL.

* Fix issue where a standby would halt and return an error `"could not access status of transaction"`.
* Fix error where the [`substring()`](https://www.postgresql.org/docs/current/functions-string.html#id-1.5.8.10.5.2.2.17.1.1.1) function would raise an error `"invalid byte sequence for encoding"` on non-ASCII text values if the source of that value is a database column. This was due to a change introduced for the fix to [`CVE-2026-2006`](https://www.postgresql.org/support/security/CVE-2026-2006/).
* Fix for the `strict_word_similarity` function in [`pg_trgm`](https://www.postgresql.org/docs/current/pgtrgm.html) that could lead to incorrect output or crashes. This was due to an oversight in the fix for [CVE-2026-2007](https://www.postgresql.org/support/security/CVE-2026-2007/).
* Fix function volatility for `json_strip_nulls()` and `jsonb_strip_nulls()` to be immutable, like previous releases, allowing for them to be used in indexes. If you previously upgraded to PostgreSQL 18.0 through 18.2, see the additional steps in the "Updating" section.
* Fix for `NOT NULL` tests in `LATERAL UNION ALL` subquery that could lead to wrong query output.
* Avoid `NOT NULL` constraints from generating name conflicts with user-written constraints.
* Fix `pg_stat_get_backend_wait_event()` and `pg_stat_get_backend_wait_event_type()` to report values for auxiliary processes, similar to `pg_stat_activity`.
* Fix casting a composite-type variable to a domain type when returning its value from a PL/pgSQL function.
* Fix the [`hstore`](https://www.postgresql.org/docs/current/hstore.html) binary input function to avoid crashes on input with duplicate keys.

Updating
--------

All PostgreSQL update releases are cumulative. As with other minor releases, users are not required to dump and reload their database or use [`pg_upgrade`](https://www.postgresql.org/docs/current/pgupgrade.html) in order to apply this update release; you may simply shutdown PostgreSQL and update its binaries.

If you previously upgraded to PostgreSQL 18.0, 18.1 or 18.2, you need to execute the following SQL as a PostgreSQL superuser in all of your databases to make the `json_strip_nulls()` and `jsonb_strip_nulls()` functions immutable:

```
UPDATE pg_catalog.pg_proc SET provolatile = 'i' WHERE oid IN ('3261','3262');
```

You should also execute this command in the `template0` and `template1` databases so future databases you create in your PostgreSQL cluster have the correct function volatility setting. Please see the documentation on [template databases](https://www.postgresql.org/docs/current/manage-ag-templatedbs.html) for more information.

Users who have skipped one or more update releases may need to run additional post-update steps; please see the release notes from earlier versions for details.

For more details, please see the [release notes](https://www.postgresql.org/docs/release/).

Links
-----

* [Download](https://www.postgresql.org/download/)
* [Release Notes](https://www.postgresql.org/docs/release/)
* [Security](https://www.postgresql.org/support/security/)
* [Versioning Policy](https://www.postgresql.org/support/versioning/)
* [Submit a Bug](https://www.postgresql.org/account/submitbug/)
* [Donate](https://www.postgresql.org/about/donate/)

If you have corrections or suggestions for this release announcement, please send them to the [email protected]_ public [mailing list](https://www.postgresql.org/list/).

  [application/pgp-signature] OpenPGP_signature.asc (840B, ../../[email protected]/3-OpenPGP_signature.asc)
  download

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

* Re: 2026-02-26 release announcement draft
@ 2026-02-24 06:25  Daniel Westermann (DWE) <[email protected]>
  parent: Jonathan S. Katz <[email protected]>
  0 siblings, 0 replies; 34+ messages in thread

From: Daniel Westermann (DWE) @ 2026-02-24 06:25 UTC (permalink / raw)
  To: Jonathan S. Katz <[email protected]>; PostgreSQL Hackers <[email protected]>

>>
>>> You should also execute this command in the `template0` and `template1` databases so future databases you create in your PostgreSQL cluster have >the correct function volatility setting.
>>
>> Shouldn't it be mentioned that template0 is read only and give instructions how to do this properly?

>"template0" isn't read-only; it isn't connectable by default. That said,
>this is a good recommendation given the behaviors of these databases. I
>modified the text to include a link to the documentation for more
>information on the core template databases. Please see attached.

Ah, yes, correct. Looks good, thank you.

Regards
Daniel


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

* PoC: VALGRIND_MAKE_MEM_NOACCESS for dynamic shared memory
@ 2026-05-04 08:18  Tomas Vondra <[email protected]>
  0 siblings, 1 reply; 34+ messages in thread

From: Tomas Vondra @ 2026-05-04 08:18 UTC (permalink / raw)
  To: pgsql-hackers

Hi,

A couple of days ago we got a report regarding an incorrect shmem size
calculation in btree [1], leading to a buffer overflow / memory
corruption. Which became a much less common issue in our code, thanks to
valgrind and similar tools. But it took me a while to realize valgrind
won't catch this because we only instrument private memory (palloc et
al), while shmem is left alone.

I was wondering if it's feasible to improve this. Attached is a trivial
patch that adjusts shm_toc.c to add a couple NOACCESS bytes after each
entry in the segment. It seems to do the trick - with this we get a
reasonable report (for the reproducer provided in the bug report, before
it got fixed by 748d871b7c) from valgrind, with invalid accesses. See
the attached .log for an example. It's much better than the confusing
crashes due to corrupted state.

There's an issue, though. It seems the valgrind memory markings are not
shared between processes. The leader sets the shm_toc up, marks the
ranges as NOACCESS, and then checks it while accessing the memory. But
the parallel workers don't seem to see this, and so will produce no
reports. I'm assuming this is the case, because all the reports come
from the leader, never from the workers. Maybe there's a different
explanation (e.g. maybe it's just the leader touching the memory?).

Still, it seems useful even with this limitation. If the leader
participates, it will produce a nice report (unless the worker crashes
first, because of the corrupted state). But we also have

    debug_parallel_query = regress

in which case everything should run in a single process, and work just
fine. Maybe that's good enough.

An alternative would be to do mprotect(), but unfortunately it requires
page-aligned ranges, which makes it somewhat useless for small overflows
of a couple bytes (like here). It should work cross-process, I think,

FWIW the PoC patch adds a 32-byte chunk, not just a single byte. This is
intentional, because if the state is an array, it's quite possible the
invalid access steps over a fair number of bytes. I'm actually thinking
it should be even larger.

This modifies just the dynamic shmem, but maybe we should do this even
for the "regular" shmem allocated at start. Issues in that would likely
cause crashes pretty quick (unlike the btree issue, which requires a
somewhat special reproducer), but a nice valgrind report helps.

regards


[1]
https://www.postgresql.org/message-id/CAGCUe0Lwk3C0qdkBa%2BOLpYc7yXwW%3Dpbaz8Sju4xMXEQAmyp%2B5g%40ma...

-- 
Tomas Vondra


Attachments:

  [text/x-patch] 0001-valgrind-add-NOACCESS-sentinels-for-dynamic-shmem.patch (2.4K, ../../[email protected]/2-0001-valgrind-add-NOACCESS-sentinels-for-dynamic-shmem.patch)
  download | inline diff:
From 2cbe2650f80f062928dbb0e8bc60fc5d602d24af Mon Sep 17 00:00:00 2001
From: test <test>
Date: Sat, 2 May 2026 23:09:00 +0200
Subject: [PATCH] valgrind: add NOACCESS sentinels for dynamic shmem

When build with USE_VALGRIND, add a couple NOACCESS bytes after each
entry allocated from the segment.

Unfortunately, these markings don't seem to be shared between processes,
so it applies only for the process that sets it up (i.e. the parallel
leader), and not the workers. Even with this limitation it seems useful,
as the leader may participate in the processing. We also have
debug_parallel_query=regress, running everything in a single process.
---
 src/backend/storage/ipc/shm_toc.c | 23 ++++++++++++++++++++++-
 1 file changed, 22 insertions(+), 1 deletion(-)

diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c
index 2f9fbb0a519..0c17e1adf85 100644
--- a/src/backend/storage/ipc/shm_toc.c
+++ b/src/backend/storage/ipc/shm_toc.c
@@ -16,6 +16,7 @@
 #include "port/atomics.h"
 #include "storage/shm_toc.h"
 #include "storage/spin.h"
+#include "utils/memdebug.h"
 
 typedef struct shm_toc_entry
 {
@@ -74,6 +75,13 @@ shm_toc_attach(uint64 magic, void *address)
 	return toc;
 }
 
+/* with valgrind, we want to add a couple NOACCESS bytes */
+#ifdef USE_VALGRIND
+#define NUM_NOACCESS_BYTES 32
+#else
+#define NUM_NOACCESS_BYTES 0
+#endif
+
 /*
  * Allocate shared memory from a segment managed by a table of contents.
  *
@@ -119,9 +127,19 @@ shm_toc_allocate(shm_toc *toc, Size nbytes)
 	}
 	vtoc->toc_allocated_bytes += nbytes;
 
+#ifdef USE_VALGRIND
+	vtoc->toc_allocated_bytes += NUM_NOACCESS_BYTES;
+#endif
+
 	SpinLockRelease(&toc->toc_mutex);
 
-	return ((char *) toc) + (total_bytes - allocated_bytes - nbytes);
+#ifdef USE_VALGRIND
+	/* make the bytes at the end no-access */
+	VALGRIND_MAKE_MEM_NOACCESS(((char *) toc) + (total_bytes - allocated_bytes - NUM_NOACCESS_BYTES),
+							   NUM_NOACCESS_BYTES);
+#endif
+
+	return ((char *) toc) + (total_bytes - allocated_bytes - nbytes - NUM_NOACCESS_BYTES);
 }
 
 /*
@@ -275,5 +293,8 @@ shm_toc_estimate(shm_toc_estimator *e)
 	sz = add_size(sz, mul_size(e->number_of_keys, sizeof(shm_toc_entry)));
 	sz = add_size(sz, e->space_for_chunks);
 
+	/* add space for ENOACCESS bytes, NUM_NOACCESS_BYTES per key */
+	sz = add_size(sz, mul_size(e->number_of_keys, NUM_NOACCESS_BYTES));
+
 	return BUFFERALIGN(sz);
 }
-- 
2.54.0



  [text/x-log] valgrind.log (58.2K, ../../[email protected]/3-valgrind.log)
  download | inline:
==1159420== Invalid write of size 4
==1159420==    at 0x2AB798: _bt_parallel_serialize_arrays (nbtree.c:739)
==1159420==    by 0x2AC0C6: _bt_parallel_primscan_schedule (nbtree.c:1106)
==1159420==    by 0x2A89F3: _bt_advance_array_keys (nbtreadpage.c:2831)
==1159420==    by 0x2A6D90: _bt_checkkeys (nbtreadpage.c:1261)
==1159420==    by 0x2A50A2: _bt_readpage (nbtreadpage.c:259)
==1159420==    by 0x2B01F9: _bt_readfirstpage (nbtsearch.c:1780)
==1159420==    by 0x2B102E: _bt_endpoint (nbtsearch.c:2232)
==1159420==    by 0x2AF2D9: _bt_first (nbtsearch.c:1245)
==1159420==    by 0x2AA8BA: btgettuple (nbtree.c:249)
==1159420==    by 0x28F0AB: index_getnext_tid (indexam.c:615)
==1159420==    by 0x28F2C5: index_getnext_slot (indexam.c:707)
==1159420==    by 0x55FDF7: IndexNext (nodeIndexscan.c:135)
==1159420==    by 0x532834: ExecScanFetch (execScan.h:135)
==1159420==    by 0x53289B: ExecScanExtended (execScan.h:179)
==1159420==    by 0x532A07: ExecScan (execScan.c:59)
==1159420==    by 0x5608F1: ExecIndexScan (nodeIndexscan.c:540)
==1159420==    by 0x53E507: ExecProcNodeInstr (instrument.c:187)
==1159420==    by 0x52D7C2: ExecProcNodeFirst (execProcnode.c:469)
==1159420==    by 0x5485DF: ExecProcNode (executor.h:327)
==1159420==    by 0x548D83: ExecAppend (nodeAppend.c:368)
==1159420==  Address 0x1235e500 is 24 bytes before a block of size 219 free'd
==1159420==    at 0xA60847: AllocSetReset (aset.c:618)
==1159420==    by 0xA71058: MemoryContextResetOnly (mcxt.c:439)
==1159420==    by 0xA6093C: AllocSetDelete (aset.c:661)
==1159420==    by 0xA712E0: MemoryContextDeleteOnly (mcxt.c:546)
==1159420==    by 0xA711A4: MemoryContextDelete (mcxt.c:500)
==1159420==    by 0x415BCC: do_analyze_rel (analyze.c:869)
==1159420==    by 0x41457E: analyze_rel (analyze.c:276)
==1159420==    by 0x4F8372: vacuum (vacuum.c:651)
==1159420==    by 0x4F7E99: ExecVacuum (vacuum.c:465)
==1159420==    by 0x837AA7: standard_ProcessUtility (utility.c:863)
==1159420==    by 0x8371A0: ProcessUtility (utility.c:528)
==1159420==    by 0x8359B9: PortalRunUtility (pquery.c:1149)
==1159420==    by 0x835C2F: PortalRunMulti (pquery.c:1307)
==1159420==    by 0x83511E: PortalRun (pquery.c:784)
==1159420==    by 0x82DAB8: exec_simple_query (postgres.c:1290)
==1159420==    by 0x8331A1: PostgresMain (postgres.c:4856)
==1159420==    by 0x828F23: BackendMain (backend_startup.c:124)
==1159420==    by 0x71EB2A: postmaster_child_launch (launch_backend.c:268)
==1159420==    by 0x725241: BackendStartup (postmaster.c:3627)
==1159420==    by 0x722923: ServerLoop (postmaster.c:1728)
==1159420==  Block was alloc'd at
==1159420==    at 0xA72DB2: palloc (mcxt.c:1411)
==1159420==    by 0x20940A: heap_copytuple (heaptuple.c:693)
==1159420==    by 0x535102: tts_buffer_heap_copy_heap_tuple (execTuples.c:927)
==1159420==    by 0x413DDB: ExecCopySlotHeapTuple (tuptable.h:507)
==1159420==    by 0x4168D9: acquire_sample_rows (analyze.c:1332)
==1159420==    by 0x41505F: do_analyze_rel (analyze.c:546)
==1159420==    by 0x41457E: analyze_rel (analyze.c:276)
==1159420==    by 0x4F8372: vacuum (vacuum.c:651)
==1159420==    by 0x4F7E99: ExecVacuum (vacuum.c:465)
==1159420==    by 0x837AA7: standard_ProcessUtility (utility.c:863)
==1159420==    by 0x8371A0: ProcessUtility (utility.c:528)
==1159420==    by 0x8359B9: PortalRunUtility (pquery.c:1149)
==1159420==    by 0x835C2F: PortalRunMulti (pquery.c:1307)
==1159420==    by 0x83511E: PortalRun (pquery.c:784)
==1159420==    by 0x82DAB8: exec_simple_query (postgres.c:1290)
==1159420==    by 0x8331A1: PostgresMain (postgres.c:4856)
==1159420==    by 0x828F23: BackendMain (backend_startup.c:124)
==1159420==    by 0x71EB2A: postmaster_child_launch (launch_backend.c:268)
==1159420==    by 0x725241: BackendStartup (postmaster.c:3627)
==1159420==    by 0x722923: ServerLoop (postmaster.c:1728)
==1159420== 
{
   <insert_a_suppression_name_here>
   Memcheck:Addr4
   fun:_bt_parallel_serialize_arrays
   fun:_bt_parallel_primscan_schedule
   fun:_bt_advance_array_keys
   fun:_bt_checkkeys
   fun:_bt_readpage
   fun:_bt_readfirstpage
   fun:_bt_endpoint
   fun:_bt_first
   fun:btgettuple
   fun:index_getnext_tid
   fun:index_getnext_slot
   fun:IndexNext
   fun:ExecScanFetch
   fun:ExecScanExtended
   fun:ExecScan
   fun:ExecIndexScan
   fun:ExecProcNodeInstr
   fun:ExecProcNodeFirst
   fun:ExecProcNode
   fun:ExecAppend
}
==1159420== Invalid write of size 4
==1159420==    at 0x8A311D: datumSerialize (datum.c:516)
==1159420==    by 0x2AB818: _bt_parallel_serialize_arrays (nbtree.c:749)
==1159420==    by 0x2AC0C6: _bt_parallel_primscan_schedule (nbtree.c:1106)
==1159420==    by 0x2A89F3: _bt_advance_array_keys (nbtreadpage.c:2831)
==1159420==    by 0x2A6D90: _bt_checkkeys (nbtreadpage.c:1261)
==1159420==    by 0x2A50A2: _bt_readpage (nbtreadpage.c:259)
==1159420==    by 0x2B01F9: _bt_readfirstpage (nbtsearch.c:1780)
==1159420==    by 0x2B102E: _bt_endpoint (nbtsearch.c:2232)
==1159420==    by 0x2AF2D9: _bt_first (nbtsearch.c:1245)
==1159420==    by 0x2AA8BA: btgettuple (nbtree.c:249)
==1159420==    by 0x28F0AB: index_getnext_tid (indexam.c:615)
==1159420==    by 0x28F2C5: index_getnext_slot (indexam.c:707)
==1159420==    by 0x55FDF7: IndexNext (nodeIndexscan.c:135)
==1159420==    by 0x532834: ExecScanFetch (execScan.h:135)
==1159420==    by 0x53289B: ExecScanExtended (execScan.h:179)
==1159420==    by 0x532A07: ExecScan (execScan.c:59)
==1159420==    by 0x5608F1: ExecIndexScan (nodeIndexscan.c:540)
==1159420==    by 0x53E507: ExecProcNodeInstr (instrument.c:187)
==1159420==    by 0x52D7C2: ExecProcNodeFirst (execProcnode.c:469)
==1159420==    by 0x5485DF: ExecProcNode (executor.h:327)
==1159420==  Address 0x1235e504 is 20 bytes before a block of size 219 free'd
==1159420==    at 0xA60847: AllocSetReset (aset.c:618)
==1159420==    by 0xA71058: MemoryContextResetOnly (mcxt.c:439)
==1159420==    by 0xA6093C: AllocSetDelete (aset.c:661)
==1159420==    by 0xA712E0: MemoryContextDeleteOnly (mcxt.c:546)
==1159420==    by 0xA711A4: MemoryContextDelete (mcxt.c:500)
==1159420==    by 0x415BCC: do_analyze_rel (analyze.c:869)
==1159420==    by 0x41457E: analyze_rel (analyze.c:276)
==1159420==    by 0x4F8372: vacuum (vacuum.c:651)
==1159420==    by 0x4F7E99: ExecVacuum (vacuum.c:465)
==1159420==    by 0x837AA7: standard_ProcessUtility (utility.c:863)
==1159420==    by 0x8371A0: ProcessUtility (utility.c:528)
==1159420==    by 0x8359B9: PortalRunUtility (pquery.c:1149)
==1159420==    by 0x835C2F: PortalRunMulti (pquery.c:1307)
==1159420==    by 0x83511E: PortalRun (pquery.c:784)
==1159420==    by 0x82DAB8: exec_simple_query (postgres.c:1290)
==1159420==    by 0x8331A1: PostgresMain (postgres.c:4856)
==1159420==    by 0x828F23: BackendMain (backend_startup.c:124)
==1159420==    by 0x71EB2A: postmaster_child_launch (launch_backend.c:268)
==1159420==    by 0x725241: BackendStartup (postmaster.c:3627)
==1159420==    by 0x722923: ServerLoop (postmaster.c:1728)
==1159420==  Block was alloc'd at
==1159420==    at 0xA72DB2: palloc (mcxt.c:1411)
==1159420==    by 0x20940A: heap_copytuple (heaptuple.c:693)
==1159420==    by 0x535102: tts_buffer_heap_copy_heap_tuple (execTuples.c:927)
==1159420==    by 0x413DDB: ExecCopySlotHeapTuple (tuptable.h:507)
==1159420==    by 0x4168D9: acquire_sample_rows (analyze.c:1332)
==1159420==    by 0x41505F: do_analyze_rel (analyze.c:546)
==1159420==    by 0x41457E: analyze_rel (analyze.c:276)
==1159420==    by 0x4F8372: vacuum (vacuum.c:651)
==1159420==    by 0x4F7E99: ExecVacuum (vacuum.c:465)
==1159420==    by 0x837AA7: standard_ProcessUtility (utility.c:863)
==1159420==    by 0x8371A0: ProcessUtility (utility.c:528)
==1159420==    by 0x8359B9: PortalRunUtility (pquery.c:1149)
==1159420==    by 0x835C2F: PortalRunMulti (pquery.c:1307)
==1159420==    by 0x83511E: PortalRun (pquery.c:784)
==1159420==    by 0x82DAB8: exec_simple_query (postgres.c:1290)
==1159420==    by 0x8331A1: PostgresMain (postgres.c:4856)
==1159420==    by 0x828F23: BackendMain (backend_startup.c:124)
==1159420==    by 0x71EB2A: postmaster_child_launch (launch_backend.c:268)
==1159420==    by 0x725241: BackendStartup (postmaster.c:3627)
==1159420==    by 0x722923: ServerLoop (postmaster.c:1728)
==1159420== 
{
   <insert_a_suppression_name_here>
   Memcheck:Addr4
   fun:datumSerialize
   fun:_bt_parallel_serialize_arrays
   fun:_bt_parallel_primscan_schedule
   fun:_bt_advance_array_keys
   fun:_bt_checkkeys
   fun:_bt_readpage
   fun:_bt_readfirstpage
   fun:_bt_endpoint
   fun:_bt_first
   fun:btgettuple
   fun:index_getnext_tid
   fun:index_getnext_slot
   fun:IndexNext
   fun:ExecScanFetch
   fun:ExecScanExtended
   fun:ExecScan
   fun:ExecIndexScan
   fun:ExecProcNodeInstr
   fun:ExecProcNodeFirst
   fun:ExecProcNode
}
==1159420== Invalid write of size 8
==1159420==    at 0x8A3151: datumSerialize (datum.c:524)
==1159420==    by 0x2AB818: _bt_parallel_serialize_arrays (nbtree.c:749)
==1159420==    by 0x2AC0C6: _bt_parallel_primscan_schedule (nbtree.c:1106)
==1159420==    by 0x2A89F3: _bt_advance_array_keys (nbtreadpage.c:2831)
==1159420==    by 0x2A6D90: _bt_checkkeys (nbtreadpage.c:1261)
==1159420==    by 0x2A50A2: _bt_readpage (nbtreadpage.c:259)
==1159420==    by 0x2B01F9: _bt_readfirstpage (nbtsearch.c:1780)
==1159420==    by 0x2B102E: _bt_endpoint (nbtsearch.c:2232)
==1159420==    by 0x2AF2D9: _bt_first (nbtsearch.c:1245)
==1159420==    by 0x2AA8BA: btgettuple (nbtree.c:249)
==1159420==    by 0x28F0AB: index_getnext_tid (indexam.c:615)
==1159420==    by 0x28F2C5: index_getnext_slot (indexam.c:707)
==1159420==    by 0x55FDF7: IndexNext (nodeIndexscan.c:135)
==1159420==    by 0x532834: ExecScanFetch (execScan.h:135)
==1159420==    by 0x53289B: ExecScanExtended (execScan.h:179)
==1159420==    by 0x532A07: ExecScan (execScan.c:59)
==1159420==    by 0x5608F1: ExecIndexScan (nodeIndexscan.c:540)
==1159420==    by 0x53E507: ExecProcNodeInstr (instrument.c:187)
==1159420==    by 0x52D7C2: ExecProcNodeFirst (execProcnode.c:469)
==1159420==    by 0x5485DF: ExecProcNode (executor.h:327)
==1159420==  Address 0x1235e508 is 16 bytes before a block of size 219 free'd
==1159420==    at 0xA60847: AllocSetReset (aset.c:618)
==1159420==    by 0xA71058: MemoryContextResetOnly (mcxt.c:439)
==1159420==    by 0xA6093C: AllocSetDelete (aset.c:661)
==1159420==    by 0xA712E0: MemoryContextDeleteOnly (mcxt.c:546)
==1159420==    by 0xA711A4: MemoryContextDelete (mcxt.c:500)
==1159420==    by 0x415BCC: do_analyze_rel (analyze.c:869)
==1159420==    by 0x41457E: analyze_rel (analyze.c:276)
==1159420==    by 0x4F8372: vacuum (vacuum.c:651)
==1159420==    by 0x4F7E99: ExecVacuum (vacuum.c:465)
==1159420==    by 0x837AA7: standard_ProcessUtility (utility.c:863)
==1159420==    by 0x8371A0: ProcessUtility (utility.c:528)
==1159420==    by 0x8359B9: PortalRunUtility (pquery.c:1149)
==1159420==    by 0x835C2F: PortalRunMulti (pquery.c:1307)
==1159420==    by 0x83511E: PortalRun (pquery.c:784)
==1159420==    by 0x82DAB8: exec_simple_query (postgres.c:1290)
==1159420==    by 0x8331A1: PostgresMain (postgres.c:4856)
==1159420==    by 0x828F23: BackendMain (backend_startup.c:124)
==1159420==    by 0x71EB2A: postmaster_child_launch (launch_backend.c:268)
==1159420==    by 0x725241: BackendStartup (postmaster.c:3627)
==1159420==    by 0x722923: ServerLoop (postmaster.c:1728)
==1159420==  Block was alloc'd at
==1159420==    at 0xA72DB2: palloc (mcxt.c:1411)
==1159420==    by 0x20940A: heap_copytuple (heaptuple.c:693)
==1159420==    by 0x535102: tts_buffer_heap_copy_heap_tuple (execTuples.c:927)
==1159420==    by 0x413DDB: ExecCopySlotHeapTuple (tuptable.h:507)
==1159420==    by 0x4168D9: acquire_sample_rows (analyze.c:1332)
==1159420==    by 0x41505F: do_analyze_rel (analyze.c:546)
==1159420==    by 0x41457E: analyze_rel (analyze.c:276)
==1159420==    by 0x4F8372: vacuum (vacuum.c:651)
==1159420==    by 0x4F7E99: ExecVacuum (vacuum.c:465)
==1159420==    by 0x837AA7: standard_ProcessUtility (utility.c:863)
==1159420==    by 0x8371A0: ProcessUtility (utility.c:528)
==1159420==    by 0x8359B9: PortalRunUtility (pquery.c:1149)
==1159420==    by 0x835C2F: PortalRunMulti (pquery.c:1307)
==1159420==    by 0x83511E: PortalRun (pquery.c:784)
==1159420==    by 0x82DAB8: exec_simple_query (postgres.c:1290)
==1159420==    by 0x8331A1: PostgresMain (postgres.c:4856)
==1159420==    by 0x828F23: BackendMain (backend_startup.c:124)
==1159420==    by 0x71EB2A: postmaster_child_launch (launch_backend.c:268)
==1159420==    by 0x725241: BackendStartup (postmaster.c:3627)
==1159420==    by 0x722923: ServerLoop (postmaster.c:1728)
==1159420== 
{
   <insert_a_suppression_name_here>
   Memcheck:Addr8
   fun:datumSerialize
   fun:_bt_parallel_serialize_arrays
   fun:_bt_parallel_primscan_schedule
   fun:_bt_advance_array_keys
   fun:_bt_checkkeys
   fun:_bt_readpage
   fun:_bt_readfirstpage
   fun:_bt_endpoint
   fun:_bt_first
   fun:btgettuple
   fun:index_getnext_tid
   fun:index_getnext_slot
   fun:IndexNext
   fun:ExecScanFetch
   fun:ExecScanExtended
   fun:ExecScan
   fun:ExecIndexScan
   fun:ExecProcNodeInstr
   fun:ExecProcNodeFirst
   fun:ExecProcNode
}
==1159420== Invalid read of size 4
==1159420==    at 0x2AB982: _bt_parallel_restore_arrays (nbtree.c:786)
==1159420==    by 0x2ABD09: _bt_parallel_seize (nbtree.c:942)
==1159420==    by 0x2AEBDF: _bt_first (nbtsearch.c:920)
==1159420==    by 0x2AA8BA: btgettuple (nbtree.c:249)
==1159420==    by 0x28F0AB: index_getnext_tid (indexam.c:615)
==1159420==    by 0x28F2C5: index_getnext_slot (indexam.c:707)
==1159420==    by 0x55FDF7: IndexNext (nodeIndexscan.c:135)
==1159420==    by 0x532834: ExecScanFetch (execScan.h:135)
==1159420==    by 0x53289B: ExecScanExtended (execScan.h:179)
==1159420==    by 0x532A07: ExecScan (execScan.c:59)
==1159420==    by 0x5608F1: ExecIndexScan (nodeIndexscan.c:540)
==1159420==    by 0x53E507: ExecProcNodeInstr (instrument.c:187)
==1159420==    by 0x52D7C2: ExecProcNodeFirst (execProcnode.c:469)
==1159420==    by 0x5485DF: ExecProcNode (executor.h:327)
==1159420==    by 0x548D83: ExecAppend (nodeAppend.c:368)
==1159420==    by 0x53E507: ExecProcNodeInstr (instrument.c:187)
==1159420==    by 0x52D7C2: ExecProcNodeFirst (execProcnode.c:469)
==1159420==    by 0x54F8FD: ExecProcNode (executor.h:327)
==1159420==    by 0x54FFF2: gather_getnext (nodeGather.c:295)
==1159420==    by 0x54FE86: ExecGather (nodeGather.c:230)
==1159420==  Address 0x1235e500 is 24 bytes before a block of size 219 free'd
==1159420==    at 0xA60847: AllocSetReset (aset.c:618)
==1159420==    by 0xA71058: MemoryContextResetOnly (mcxt.c:439)
==1159420==    by 0xA6093C: AllocSetDelete (aset.c:661)
==1159420==    by 0xA712E0: MemoryContextDeleteOnly (mcxt.c:546)
==1159420==    by 0xA711A4: MemoryContextDelete (mcxt.c:500)
==1159420==    by 0x415BCC: do_analyze_rel (analyze.c:869)
==1159420==    by 0x41457E: analyze_rel (analyze.c:276)
==1159420==    by 0x4F8372: vacuum (vacuum.c:651)
==1159420==    by 0x4F7E99: ExecVacuum (vacuum.c:465)
==1159420==    by 0x837AA7: standard_ProcessUtility (utility.c:863)
==1159420==    by 0x8371A0: ProcessUtility (utility.c:528)
==1159420==    by 0x8359B9: PortalRunUtility (pquery.c:1149)
==1159420==    by 0x835C2F: PortalRunMulti (pquery.c:1307)
==1159420==    by 0x83511E: PortalRun (pquery.c:784)
==1159420==    by 0x82DAB8: exec_simple_query (postgres.c:1290)
==1159420==    by 0x8331A1: PostgresMain (postgres.c:4856)
==1159420==    by 0x828F23: BackendMain (backend_startup.c:124)
==1159420==    by 0x71EB2A: postmaster_child_launch (launch_backend.c:268)
==1159420==    by 0x725241: BackendStartup (postmaster.c:3627)
==1159420==    by 0x722923: ServerLoop (postmaster.c:1728)
==1159420==  Block was alloc'd at
==1159420==    at 0xA72DB2: palloc (mcxt.c:1411)
==1159420==    by 0x20940A: heap_copytuple (heaptuple.c:693)
==1159420==    by 0x535102: tts_buffer_heap_copy_heap_tuple (execTuples.c:927)
==1159420==    by 0x413DDB: ExecCopySlotHeapTuple (tuptable.h:507)
==1159420==    by 0x4168D9: acquire_sample_rows (analyze.c:1332)
==1159420==    by 0x41505F: do_analyze_rel (analyze.c:546)
==1159420==    by 0x41457E: analyze_rel (analyze.c:276)
==1159420==    by 0x4F8372: vacuum (vacuum.c:651)
==1159420==    by 0x4F7E99: ExecVacuum (vacuum.c:465)
==1159420==    by 0x837AA7: standard_ProcessUtility (utility.c:863)
==1159420==    by 0x8371A0: ProcessUtility (utility.c:528)
==1159420==    by 0x8359B9: PortalRunUtility (pquery.c:1149)
==1159420==    by 0x835C2F: PortalRunMulti (pquery.c:1307)
==1159420==    by 0x83511E: PortalRun (pquery.c:784)
==1159420==    by 0x82DAB8: exec_simple_query (postgres.c:1290)
==1159420==    by 0x8331A1: PostgresMain (postgres.c:4856)
==1159420==    by 0x828F23: BackendMain (backend_startup.c:124)
==1159420==    by 0x71EB2A: postmaster_child_launch (launch_backend.c:268)
==1159420==    by 0x725241: BackendStartup (postmaster.c:3627)
==1159420==    by 0x722923: ServerLoop (postmaster.c:1728)
==1159420== 
{
   <insert_a_suppression_name_here>
   Memcheck:Addr4
   fun:_bt_parallel_restore_arrays
   fun:_bt_parallel_seize
   fun:_bt_first
   fun:btgettuple
   fun:index_getnext_tid
   fun:index_getnext_slot
   fun:IndexNext
   fun:ExecScanFetch
   fun:ExecScanExtended
   fun:ExecScan
   fun:ExecIndexScan
   fun:ExecProcNodeInstr
   fun:ExecProcNodeFirst
   fun:ExecProcNode
   fun:ExecAppend
   fun:ExecProcNodeInstr
   fun:ExecProcNodeFirst
   fun:ExecProcNode
   fun:gather_getnext
   fun:ExecGather
}
==1159420== Invalid read of size 4
==1159420==    at 0x8A323A: datumRestore (datum.c:565)
==1159420==    by 0x2AB9E4: _bt_parallel_restore_arrays (nbtree.c:797)
==1159420==    by 0x2ABD09: _bt_parallel_seize (nbtree.c:942)
==1159420==    by 0x2AEBDF: _bt_first (nbtsearch.c:920)
==1159420==    by 0x2AA8BA: btgettuple (nbtree.c:249)
==1159420==    by 0x28F0AB: index_getnext_tid (indexam.c:615)
==1159420==    by 0x28F2C5: index_getnext_slot (indexam.c:707)
==1159420==    by 0x55FDF7: IndexNext (nodeIndexscan.c:135)
==1159420==    by 0x532834: ExecScanFetch (execScan.h:135)
==1159420==    by 0x53289B: ExecScanExtended (execScan.h:179)
==1159420==    by 0x532A07: ExecScan (execScan.c:59)
==1159420==    by 0x5608F1: ExecIndexScan (nodeIndexscan.c:540)
==1159420==    by 0x53E507: ExecProcNodeInstr (instrument.c:187)
==1159420==    by 0x52D7C2: ExecProcNodeFirst (execProcnode.c:469)
==1159420==    by 0x5485DF: ExecProcNode (executor.h:327)
==1159420==    by 0x548D83: ExecAppend (nodeAppend.c:368)
==1159420==    by 0x53E507: ExecProcNodeInstr (instrument.c:187)
==1159420==    by 0x52D7C2: ExecProcNodeFirst (execProcnode.c:469)
==1159420==    by 0x54F8FD: ExecProcNode (executor.h:327)
==1159420==    by 0x54FFF2: gather_getnext (nodeGather.c:295)
==1159420==  Address 0x1235e504 is 20 bytes before a block of size 219 free'd
==1159420==    at 0xA60847: AllocSetReset (aset.c:618)
==1159420==    by 0xA71058: MemoryContextResetOnly (mcxt.c:439)
==1159420==    by 0xA6093C: AllocSetDelete (aset.c:661)
==1159420==    by 0xA712E0: MemoryContextDeleteOnly (mcxt.c:546)
==1159420==    by 0xA711A4: MemoryContextDelete (mcxt.c:500)
==1159420==    by 0x415BCC: do_analyze_rel (analyze.c:869)
==1159420==    by 0x41457E: analyze_rel (analyze.c:276)
==1159420==    by 0x4F8372: vacuum (vacuum.c:651)
==1159420==    by 0x4F7E99: ExecVacuum (vacuum.c:465)
==1159420==    by 0x837AA7: standard_ProcessUtility (utility.c:863)
==1159420==    by 0x8371A0: ProcessUtility (utility.c:528)
==1159420==    by 0x8359B9: PortalRunUtility (pquery.c:1149)
==1159420==    by 0x835C2F: PortalRunMulti (pquery.c:1307)
==1159420==    by 0x83511E: PortalRun (pquery.c:784)
==1159420==    by 0x82DAB8: exec_simple_query (postgres.c:1290)
==1159420==    by 0x8331A1: PostgresMain (postgres.c:4856)
==1159420==    by 0x828F23: BackendMain (backend_startup.c:124)
==1159420==    by 0x71EB2A: postmaster_child_launch (launch_backend.c:268)
==1159420==    by 0x725241: BackendStartup (postmaster.c:3627)
==1159420==    by 0x722923: ServerLoop (postmaster.c:1728)
==1159420==  Block was alloc'd at
==1159420==    at 0xA72DB2: palloc (mcxt.c:1411)
==1159420==    by 0x20940A: heap_copytuple (heaptuple.c:693)
==1159420==    by 0x535102: tts_buffer_heap_copy_heap_tuple (execTuples.c:927)
==1159420==    by 0x413DDB: ExecCopySlotHeapTuple (tuptable.h:507)
==1159420==    by 0x4168D9: acquire_sample_rows (analyze.c:1332)
==1159420==    by 0x41505F: do_analyze_rel (analyze.c:546)
==1159420==    by 0x41457E: analyze_rel (analyze.c:276)
==1159420==    by 0x4F8372: vacuum (vacuum.c:651)
==1159420==    by 0x4F7E99: ExecVacuum (vacuum.c:465)
==1159420==    by 0x837AA7: standard_ProcessUtility (utility.c:863)
==1159420==    by 0x8371A0: ProcessUtility (utility.c:528)
==1159420==    by 0x8359B9: PortalRunUtility (pquery.c:1149)
==1159420==    by 0x835C2F: PortalRunMulti (pquery.c:1307)
==1159420==    by 0x83511E: PortalRun (pquery.c:784)
==1159420==    by 0x82DAB8: exec_simple_query (postgres.c:1290)
==1159420==    by 0x8331A1: PostgresMain (postgres.c:4856)
==1159420==    by 0x828F23: BackendMain (backend_startup.c:124)
==1159420==    by 0x71EB2A: postmaster_child_launch (launch_backend.c:268)
==1159420==    by 0x725241: BackendStartup (postmaster.c:3627)
==1159420==    by 0x722923: ServerLoop (postmaster.c:1728)
==1159420== 
{
   <insert_a_suppression_name_here>
   Memcheck:Addr4
   fun:datumRestore
   fun:_bt_parallel_restore_arrays
   fun:_bt_parallel_seize
   fun:_bt_first
   fun:btgettuple
   fun:index_getnext_tid
   fun:index_getnext_slot
   fun:IndexNext
   fun:ExecScanFetch
   fun:ExecScanExtended
   fun:ExecScan
   fun:ExecIndexScan
   fun:ExecProcNodeInstr
   fun:ExecProcNodeFirst
   fun:ExecProcNode
   fun:ExecAppend
   fun:ExecProcNodeInstr
   fun:ExecProcNodeFirst
   fun:ExecProcNode
   fun:gather_getnext
}
==1159420== Invalid read of size 8
==1159420==    at 0x8A3280: datumRestore (datum.c:583)
==1159420==    by 0x2AB9E4: _bt_parallel_restore_arrays (nbtree.c:797)
==1159420==    by 0x2ABD09: _bt_parallel_seize (nbtree.c:942)
==1159420==    by 0x2AEBDF: _bt_first (nbtsearch.c:920)
==1159420==    by 0x2AA8BA: btgettuple (nbtree.c:249)
==1159420==    by 0x28F0AB: index_getnext_tid (indexam.c:615)
==1159420==    by 0x28F2C5: index_getnext_slot (indexam.c:707)
==1159420==    by 0x55FDF7: IndexNext (nodeIndexscan.c:135)
==1159420==    by 0x532834: ExecScanFetch (execScan.h:135)
==1159420==    by 0x53289B: ExecScanExtended (execScan.h:179)
==1159420==    by 0x532A07: ExecScan (execScan.c:59)
==1159420==    by 0x5608F1: ExecIndexScan (nodeIndexscan.c:540)
==1159420==    by 0x53E507: ExecProcNodeInstr (instrument.c:187)
==1159420==    by 0x52D7C2: ExecProcNodeFirst (execProcnode.c:469)
==1159420==    by 0x5485DF: ExecProcNode (executor.h:327)
==1159420==    by 0x548D83: ExecAppend (nodeAppend.c:368)
==1159420==    by 0x53E507: ExecProcNodeInstr (instrument.c:187)
==1159420==    by 0x52D7C2: ExecProcNodeFirst (execProcnode.c:469)
==1159420==    by 0x54F8FD: ExecProcNode (executor.h:327)
==1159420==    by 0x54FFF2: gather_getnext (nodeGather.c:295)
==1159420==  Address 0x1235e508 is 16 bytes before a block of size 219 free'd
==1159420==    at 0xA60847: AllocSetReset (aset.c:618)
==1159420==    by 0xA71058: MemoryContextResetOnly (mcxt.c:439)
==1159420==    by 0xA6093C: AllocSetDelete (aset.c:661)
==1159420==    by 0xA712E0: MemoryContextDeleteOnly (mcxt.c:546)
==1159420==    by 0xA711A4: MemoryContextDelete (mcxt.c:500)
==1159420==    by 0x415BCC: do_analyze_rel (analyze.c:869)
==1159420==    by 0x41457E: analyze_rel (analyze.c:276)
==1159420==    by 0x4F8372: vacuum (vacuum.c:651)
==1159420==    by 0x4F7E99: ExecVacuum (vacuum.c:465)
==1159420==    by 0x837AA7: standard_ProcessUtility (utility.c:863)
==1159420==    by 0x8371A0: ProcessUtility (utility.c:528)
==1159420==    by 0x8359B9: PortalRunUtility (pquery.c:1149)
==1159420==    by 0x835C2F: PortalRunMulti (pquery.c:1307)
==1159420==    by 0x83511E: PortalRun (pquery.c:784)
==1159420==    by 0x82DAB8: exec_simple_query (postgres.c:1290)
==1159420==    by 0x8331A1: PostgresMain (postgres.c:4856)
==1159420==    by 0x828F23: BackendMain (backend_startup.c:124)
==1159420==    by 0x71EB2A: postmaster_child_launch (launch_backend.c:268)
==1159420==    by 0x725241: BackendStartup (postmaster.c:3627)
==1159420==    by 0x722923: ServerLoop (postmaster.c:1728)
==1159420==  Block was alloc'd at
==1159420==    at 0xA72DB2: palloc (mcxt.c:1411)
==1159420==    by 0x20940A: heap_copytuple (heaptuple.c:693)
==1159420==    by 0x535102: tts_buffer_heap_copy_heap_tuple (execTuples.c:927)
==1159420==    by 0x413DDB: ExecCopySlotHeapTuple (tuptable.h:507)
==1159420==    by 0x4168D9: acquire_sample_rows (analyze.c:1332)
==1159420==    by 0x41505F: do_analyze_rel (analyze.c:546)
==1159420==    by 0x41457E: analyze_rel (analyze.c:276)
==1159420==    by 0x4F8372: vacuum (vacuum.c:651)
==1159420==    by 0x4F7E99: ExecVacuum (vacuum.c:465)
==1159420==    by 0x837AA7: standard_ProcessUtility (utility.c:863)
==1159420==    by 0x8371A0: ProcessUtility (utility.c:528)
==1159420==    by 0x8359B9: PortalRunUtility (pquery.c:1149)
==1159420==    by 0x835C2F: PortalRunMulti (pquery.c:1307)
==1159420==    by 0x83511E: PortalRun (pquery.c:784)
==1159420==    by 0x82DAB8: exec_simple_query (postgres.c:1290)
==1159420==    by 0x8331A1: PostgresMain (postgres.c:4856)
==1159420==    by 0x828F23: BackendMain (backend_startup.c:124)
==1159420==    by 0x71EB2A: postmaster_child_launch (launch_backend.c:268)
==1159420==    by 0x725241: BackendStartup (postmaster.c:3627)
==1159420==    by 0x722923: ServerLoop (postmaster.c:1728)
==1159420== 
{
   <insert_a_suppression_name_here>
   Memcheck:Addr8
   fun:datumRestore
   fun:_bt_parallel_restore_arrays
   fun:_bt_parallel_seize
   fun:_bt_first
   fun:btgettuple
   fun:index_getnext_tid
   fun:index_getnext_slot
   fun:IndexNext
   fun:ExecScanFetch
   fun:ExecScanExtended
   fun:ExecScan
   fun:ExecIndexScan
   fun:ExecProcNodeInstr
   fun:ExecProcNodeFirst
   fun:ExecProcNode
   fun:ExecAppend
   fun:ExecProcNodeInstr
   fun:ExecProcNodeFirst
   fun:ExecProcNode
   fun:gather_getnext
}
==1159420== Invalid write of size 4
==1159420==    at 0x2AB798: _bt_parallel_serialize_arrays (nbtree.c:739)
==1159420==    by 0x2AC0C6: _bt_parallel_primscan_schedule (nbtree.c:1106)
==1159420==    by 0x2A4F6E: _bt_readpage (nbtreadpage.c:218)
==1159420==    by 0x2B062B: _bt_readnextpage (nbtsearch.c:1915)
==1159420==    by 0x2B0131: _bt_steppage (nbtsearch.c:1723)
==1159420==    by 0x2B02C9: _bt_readfirstpage (nbtsearch.c:1797)
==1159420==    by 0x2AFB8C: _bt_first (nbtsearch.c:1564)
==1159420==    by 0x2AA8BA: btgettuple (nbtree.c:249)
==1159420==    by 0x28F0AB: index_getnext_tid (indexam.c:615)
==1159420==    by 0x28F2C5: index_getnext_slot (indexam.c:707)
==1159420==    by 0x55FDF7: IndexNext (nodeIndexscan.c:135)
==1159420==    by 0x532834: ExecScanFetch (execScan.h:135)
==1159420==    by 0x53289B: ExecScanExtended (execScan.h:179)
==1159420==    by 0x532A07: ExecScan (execScan.c:59)
==1159420==    by 0x5608F1: ExecIndexScan (nodeIndexscan.c:540)
==1159420==    by 0x53E507: ExecProcNodeInstr (instrument.c:187)
==1159420==    by 0x52D7C2: ExecProcNodeFirst (execProcnode.c:469)
==1159420==    by 0x5485DF: ExecProcNode (executor.h:327)
==1159420==    by 0x548D83: ExecAppend (nodeAppend.c:368)
==1159420==    by 0x53E507: ExecProcNodeInstr (instrument.c:187)
==1159420==  Address 0x1235e500 is 24 bytes before a block of size 219 free'd
==1159420==    at 0xA60847: AllocSetReset (aset.c:618)
==1159420==    by 0xA71058: MemoryContextResetOnly (mcxt.c:439)
==1159420==    by 0xA6093C: AllocSetDelete (aset.c:661)
==1159420==    by 0xA712E0: MemoryContextDeleteOnly (mcxt.c:546)
==1159420==    by 0xA711A4: MemoryContextDelete (mcxt.c:500)
==1159420==    by 0x415BCC: do_analyze_rel (analyze.c:869)
==1159420==    by 0x41457E: analyze_rel (analyze.c:276)
==1159420==    by 0x4F8372: vacuum (vacuum.c:651)
==1159420==    by 0x4F7E99: ExecVacuum (vacuum.c:465)
==1159420==    by 0x837AA7: standard_ProcessUtility (utility.c:863)
==1159420==    by 0x8371A0: ProcessUtility (utility.c:528)
==1159420==    by 0x8359B9: PortalRunUtility (pquery.c:1149)
==1159420==    by 0x835C2F: PortalRunMulti (pquery.c:1307)
==1159420==    by 0x83511E: PortalRun (pquery.c:784)
==1159420==    by 0x82DAB8: exec_simple_query (postgres.c:1290)
==1159420==    by 0x8331A1: PostgresMain (postgres.c:4856)
==1159420==    by 0x828F23: BackendMain (backend_startup.c:124)
==1159420==    by 0x71EB2A: postmaster_child_launch (launch_backend.c:268)
==1159420==    by 0x725241: BackendStartup (postmaster.c:3627)
==1159420==    by 0x722923: ServerLoop (postmaster.c:1728)
==1159420==  Block was alloc'd at
==1159420==    at 0xA72DB2: palloc (mcxt.c:1411)
==1159420==    by 0x20940A: heap_copytuple (heaptuple.c:693)
==1159420==    by 0x535102: tts_buffer_heap_copy_heap_tuple (execTuples.c:927)
==1159420==    by 0x413DDB: ExecCopySlotHeapTuple (tuptable.h:507)
==1159420==    by 0x4168D9: acquire_sample_rows (analyze.c:1332)
==1159420==    by 0x41505F: do_analyze_rel (analyze.c:546)
==1159420==    by 0x41457E: analyze_rel (analyze.c:276)
==1159420==    by 0x4F8372: vacuum (vacuum.c:651)
==1159420==    by 0x4F7E99: ExecVacuum (vacuum.c:465)
==1159420==    by 0x837AA7: standard_ProcessUtility (utility.c:863)
==1159420==    by 0x8371A0: ProcessUtility (utility.c:528)
==1159420==    by 0x8359B9: PortalRunUtility (pquery.c:1149)
==1159420==    by 0x835C2F: PortalRunMulti (pquery.c:1307)
==1159420==    by 0x83511E: PortalRun (pquery.c:784)
==1159420==    by 0x82DAB8: exec_simple_query (postgres.c:1290)
==1159420==    by 0x8331A1: PostgresMain (postgres.c:4856)
==1159420==    by 0x828F23: BackendMain (backend_startup.c:124)
==1159420==    by 0x71EB2A: postmaster_child_launch (launch_backend.c:268)
==1159420==    by 0x725241: BackendStartup (postmaster.c:3627)
==1159420==    by 0x722923: ServerLoop (postmaster.c:1728)
==1159420== 
{
   <insert_a_suppression_name_here>
   Memcheck:Addr4
   fun:_bt_parallel_serialize_arrays
   fun:_bt_parallel_primscan_schedule
   fun:_bt_readpage
   fun:_bt_readnextpage
   fun:_bt_steppage
   fun:_bt_readfirstpage
   fun:_bt_first
   fun:btgettuple
   fun:index_getnext_tid
   fun:index_getnext_slot
   fun:IndexNext
   fun:ExecScanFetch
   fun:ExecScanExtended
   fun:ExecScan
   fun:ExecIndexScan
   fun:ExecProcNodeInstr
   fun:ExecProcNodeFirst
   fun:ExecProcNode
   fun:ExecAppend
   fun:ExecProcNodeInstr
}
==1159420== Invalid write of size 4
==1159420==    at 0x8A311D: datumSerialize (datum.c:516)
==1159420==    by 0x2AB818: _bt_parallel_serialize_arrays (nbtree.c:749)
==1159420==    by 0x2AC0C6: _bt_parallel_primscan_schedule (nbtree.c:1106)
==1159420==    by 0x2A4F6E: _bt_readpage (nbtreadpage.c:218)
==1159420==    by 0x2B062B: _bt_readnextpage (nbtsearch.c:1915)
==1159420==    by 0x2B0131: _bt_steppage (nbtsearch.c:1723)
==1159420==    by 0x2B02C9: _bt_readfirstpage (nbtsearch.c:1797)
==1159420==    by 0x2AFB8C: _bt_first (nbtsearch.c:1564)
==1159420==    by 0x2AA8BA: btgettuple (nbtree.c:249)
==1159420==    by 0x28F0AB: index_getnext_tid (indexam.c:615)
==1159420==    by 0x28F2C5: index_getnext_slot (indexam.c:707)
==1159420==    by 0x55FDF7: IndexNext (nodeIndexscan.c:135)
==1159420==    by 0x532834: ExecScanFetch (execScan.h:135)
==1159420==    by 0x53289B: ExecScanExtended (execScan.h:179)
==1159420==    by 0x532A07: ExecScan (execScan.c:59)
==1159420==    by 0x5608F1: ExecIndexScan (nodeIndexscan.c:540)
==1159420==    by 0x53E507: ExecProcNodeInstr (instrument.c:187)
==1159420==    by 0x52D7C2: ExecProcNodeFirst (execProcnode.c:469)
==1159420==    by 0x5485DF: ExecProcNode (executor.h:327)
==1159420==    by 0x548D83: ExecAppend (nodeAppend.c:368)
==1159420==  Address 0x1235e504 is 20 bytes before a block of size 219 free'd
==1159420==    at 0xA60847: AllocSetReset (aset.c:618)
==1159420==    by 0xA71058: MemoryContextResetOnly (mcxt.c:439)
==1159420==    by 0xA6093C: AllocSetDelete (aset.c:661)
==1159420==    by 0xA712E0: MemoryContextDeleteOnly (mcxt.c:546)
==1159420==    by 0xA711A4: MemoryContextDelete (mcxt.c:500)
==1159420==    by 0x415BCC: do_analyze_rel (analyze.c:869)
==1159420==    by 0x41457E: analyze_rel (analyze.c:276)
==1159420==    by 0x4F8372: vacuum (vacuum.c:651)
==1159420==    by 0x4F7E99: ExecVacuum (vacuum.c:465)
==1159420==    by 0x837AA7: standard_ProcessUtility (utility.c:863)
==1159420==    by 0x8371A0: ProcessUtility (utility.c:528)
==1159420==    by 0x8359B9: PortalRunUtility (pquery.c:1149)
==1159420==    by 0x835C2F: PortalRunMulti (pquery.c:1307)
==1159420==    by 0x83511E: PortalRun (pquery.c:784)
==1159420==    by 0x82DAB8: exec_simple_query (postgres.c:1290)
==1159420==    by 0x8331A1: PostgresMain (postgres.c:4856)
==1159420==    by 0x828F23: BackendMain (backend_startup.c:124)
==1159420==    by 0x71EB2A: postmaster_child_launch (launch_backend.c:268)
==1159420==    by 0x725241: BackendStartup (postmaster.c:3627)
==1159420==    by 0x722923: ServerLoop (postmaster.c:1728)
==1159420==  Block was alloc'd at
==1159420==    at 0xA72DB2: palloc (mcxt.c:1411)
==1159420==    by 0x20940A: heap_copytuple (heaptuple.c:693)
==1159420==    by 0x535102: tts_buffer_heap_copy_heap_tuple (execTuples.c:927)
==1159420==    by 0x413DDB: ExecCopySlotHeapTuple (tuptable.h:507)
==1159420==    by 0x4168D9: acquire_sample_rows (analyze.c:1332)
==1159420==    by 0x41505F: do_analyze_rel (analyze.c:546)
==1159420==    by 0x41457E: analyze_rel (analyze.c:276)
==1159420==    by 0x4F8372: vacuum (vacuum.c:651)
==1159420==    by 0x4F7E99: ExecVacuum (vacuum.c:465)
==1159420==    by 0x837AA7: standard_ProcessUtility (utility.c:863)
==1159420==    by 0x8371A0: ProcessUtility (utility.c:528)
==1159420==    by 0x8359B9: PortalRunUtility (pquery.c:1149)
==1159420==    by 0x835C2F: PortalRunMulti (pquery.c:1307)
==1159420==    by 0x83511E: PortalRun (pquery.c:784)
==1159420==    by 0x82DAB8: exec_simple_query (postgres.c:1290)
==1159420==    by 0x8331A1: PostgresMain (postgres.c:4856)
==1159420==    by 0x828F23: BackendMain (backend_startup.c:124)
==1159420==    by 0x71EB2A: postmaster_child_launch (launch_backend.c:268)
==1159420==    by 0x725241: BackendStartup (postmaster.c:3627)
==1159420==    by 0x722923: ServerLoop (postmaster.c:1728)
==1159420== 
{
   <insert_a_suppression_name_here>
   Memcheck:Addr4
   fun:datumSerialize
   fun:_bt_parallel_serialize_arrays
   fun:_bt_parallel_primscan_schedule
   fun:_bt_readpage
   fun:_bt_readnextpage
   fun:_bt_steppage
   fun:_bt_readfirstpage
   fun:_bt_first
   fun:btgettuple
   fun:index_getnext_tid
   fun:index_getnext_slot
   fun:IndexNext
   fun:ExecScanFetch
   fun:ExecScanExtended
   fun:ExecScan
   fun:ExecIndexScan
   fun:ExecProcNodeInstr
   fun:ExecProcNodeFirst
   fun:ExecProcNode
   fun:ExecAppend
}
==1159420== Invalid write of size 8
==1159420==    at 0x8A3151: datumSerialize (datum.c:524)
==1159420==    by 0x2AB818: _bt_parallel_serialize_arrays (nbtree.c:749)
==1159420==    by 0x2AC0C6: _bt_parallel_primscan_schedule (nbtree.c:1106)
==1159420==    by 0x2A4F6E: _bt_readpage (nbtreadpage.c:218)
==1159420==    by 0x2B062B: _bt_readnextpage (nbtsearch.c:1915)
==1159420==    by 0x2B0131: _bt_steppage (nbtsearch.c:1723)
==1159420==    by 0x2B02C9: _bt_readfirstpage (nbtsearch.c:1797)
==1159420==    by 0x2AFB8C: _bt_first (nbtsearch.c:1564)
==1159420==    by 0x2AA8BA: btgettuple (nbtree.c:249)
==1159420==    by 0x28F0AB: index_getnext_tid (indexam.c:615)
==1159420==    by 0x28F2C5: index_getnext_slot (indexam.c:707)
==1159420==    by 0x55FDF7: IndexNext (nodeIndexscan.c:135)
==1159420==    by 0x532834: ExecScanFetch (execScan.h:135)
==1159420==    by 0x53289B: ExecScanExtended (execScan.h:179)
==1159420==    by 0x532A07: ExecScan (execScan.c:59)
==1159420==    by 0x5608F1: ExecIndexScan (nodeIndexscan.c:540)
==1159420==    by 0x53E507: ExecProcNodeInstr (instrument.c:187)
==1159420==    by 0x52D7C2: ExecProcNodeFirst (execProcnode.c:469)
==1159420==    by 0x5485DF: ExecProcNode (executor.h:327)
==1159420==    by 0x548D83: ExecAppend (nodeAppend.c:368)
==1159420==  Address 0x1235e508 is 16 bytes before a block of size 219 free'd
==1159420==    at 0xA60847: AllocSetReset (aset.c:618)
==1159420==    by 0xA71058: MemoryContextResetOnly (mcxt.c:439)
==1159420==    by 0xA6093C: AllocSetDelete (aset.c:661)
==1159420==    by 0xA712E0: MemoryContextDeleteOnly (mcxt.c:546)
==1159420==    by 0xA711A4: MemoryContextDelete (mcxt.c:500)
==1159420==    by 0x415BCC: do_analyze_rel (analyze.c:869)
==1159420==    by 0x41457E: analyze_rel (analyze.c:276)
==1159420==    by 0x4F8372: vacuum (vacuum.c:651)
==1159420==    by 0x4F7E99: ExecVacuum (vacuum.c:465)
==1159420==    by 0x837AA7: standard_ProcessUtility (utility.c:863)
==1159420==    by 0x8371A0: ProcessUtility (utility.c:528)
==1159420==    by 0x8359B9: PortalRunUtility (pquery.c:1149)
==1159420==    by 0x835C2F: PortalRunMulti (pquery.c:1307)
==1159420==    by 0x83511E: PortalRun (pquery.c:784)
==1159420==    by 0x82DAB8: exec_simple_query (postgres.c:1290)
==1159420==    by 0x8331A1: PostgresMain (postgres.c:4856)
==1159420==    by 0x828F23: BackendMain (backend_startup.c:124)
==1159420==    by 0x71EB2A: postmaster_child_launch (launch_backend.c:268)
==1159420==    by 0x725241: BackendStartup (postmaster.c:3627)
==1159420==    by 0x722923: ServerLoop (postmaster.c:1728)
==1159420==  Block was alloc'd at
==1159420==    at 0xA72DB2: palloc (mcxt.c:1411)
==1159420==    by 0x20940A: heap_copytuple (heaptuple.c:693)
==1159420==    by 0x535102: tts_buffer_heap_copy_heap_tuple (execTuples.c:927)
==1159420==    by 0x413DDB: ExecCopySlotHeapTuple (tuptable.h:507)
==1159420==    by 0x4168D9: acquire_sample_rows (analyze.c:1332)
==1159420==    by 0x41505F: do_analyze_rel (analyze.c:546)
==1159420==    by 0x41457E: analyze_rel (analyze.c:276)
==1159420==    by 0x4F8372: vacuum (vacuum.c:651)
==1159420==    by 0x4F7E99: ExecVacuum (vacuum.c:465)
==1159420==    by 0x837AA7: standard_ProcessUtility (utility.c:863)
==1159420==    by 0x8371A0: ProcessUtility (utility.c:528)
==1159420==    by 0x8359B9: PortalRunUtility (pquery.c:1149)
==1159420==    by 0x835C2F: PortalRunMulti (pquery.c:1307)
==1159420==    by 0x83511E: PortalRun (pquery.c:784)
==1159420==    by 0x82DAB8: exec_simple_query (postgres.c:1290)
==1159420==    by 0x8331A1: PostgresMain (postgres.c:4856)
==1159420==    by 0x828F23: BackendMain (backend_startup.c:124)
==1159420==    by 0x71EB2A: postmaster_child_launch (launch_backend.c:268)
==1159420==    by 0x725241: BackendStartup (postmaster.c:3627)
==1159420==    by 0x722923: ServerLoop (postmaster.c:1728)
==1159420== 
{
   <insert_a_suppression_name_here>
   Memcheck:Addr8
   fun:datumSerialize
   fun:_bt_parallel_serialize_arrays
   fun:_bt_parallel_primscan_schedule
   fun:_bt_readpage
   fun:_bt_readnextpage
   fun:_bt_steppage
   fun:_bt_readfirstpage
   fun:_bt_first
   fun:btgettuple
   fun:index_getnext_tid
   fun:index_getnext_slot
   fun:IndexNext
   fun:ExecScanFetch
   fun:ExecScanExtended
   fun:ExecScan
   fun:ExecIndexScan
   fun:ExecProcNodeInstr
   fun:ExecProcNodeFirst
   fun:ExecProcNode
   fun:ExecAppend
}
==1159420== Invalid read of size 8
==1159420==    at 0x4852684: memmove (vg_replace_strmem.c:1414)
==1159420==    by 0x54C675: ExecBitmapIndexScanRetrieveInstrumentation (nodeBitmapIndexscan.c:447)
==1159420==    by 0x527685: ExecParallelRetrieveInstrumentation (execParallel.c:1143)
==1159420==    by 0x5EBAB7: planstate_tree_walker_impl (nodeFuncs.c:4861)
==1159420==    by 0x527712: ExecParallelRetrieveInstrumentation (execParallel.c:1173)
==1159420==    by 0x5EBE07: planstate_walk_members (nodeFuncs.c:4953)
==1159420==    by 0x5EBB53: planstate_tree_walker_impl (nodeFuncs.c:4876)
==1159420==    by 0x527712: ExecParallelRetrieveInstrumentation (execParallel.c:1173)
==1159420==    by 0x5279AE: ExecParallelCleanup (execParallel.c:1278)
==1159420==    by 0x550361: ExecShutdownGather (nodeGather.c:426)
==1159420==    by 0x52DD0A: ExecShutdownNode_walker (execProcnode.c:784)
==1159420==    by 0x52DC59: ExecShutdownNode (execProcnode.c:755)
==1159420==    by 0x5228D3: ExecutePlan (execMain.c:1794)
==1159420==    by 0x51FE84: standard_ExecutorRun (execMain.c:377)
==1159420==    by 0x51FCE6: ExecutorRun (execMain.c:314)
==1159420==    by 0x4435D6: ExplainOnePlan (explain.c:587)
==1159420==    by 0x442F9E: standard_ExplainOneQuery (explain.c:378)
==1159420==    by 0x442CF5: ExplainOneQuery (explain.c:315)
==1159420==    by 0x442973: ExplainQuery (explain.c:228)
==1159420==    by 0x837AE3: standard_ProcessUtility (utility.c:871)
==1159420==  Address 0x1235e560 is 72 bytes inside a block of size 219 free'd
==1159420==    at 0xA60847: AllocSetReset (aset.c:618)
==1159420==    by 0xA71058: MemoryContextResetOnly (mcxt.c:439)
==1159420==    by 0xA6093C: AllocSetDelete (aset.c:661)
==1159420==    by 0xA712E0: MemoryContextDeleteOnly (mcxt.c:546)
==1159420==    by 0xA711A4: MemoryContextDelete (mcxt.c:500)
==1159420==    by 0x415BCC: do_analyze_rel (analyze.c:869)
==1159420==    by 0x41457E: analyze_rel (analyze.c:276)
==1159420==    by 0x4F8372: vacuum (vacuum.c:651)
==1159420==    by 0x4F7E99: ExecVacuum (vacuum.c:465)
==1159420==    by 0x837AA7: standard_ProcessUtility (utility.c:863)
==1159420==    by 0x8371A0: ProcessUtility (utility.c:528)
==1159420==    by 0x8359B9: PortalRunUtility (pquery.c:1149)
==1159420==    by 0x835C2F: PortalRunMulti (pquery.c:1307)
==1159420==    by 0x83511E: PortalRun (pquery.c:784)
==1159420==    by 0x82DAB8: exec_simple_query (postgres.c:1290)
==1159420==    by 0x8331A1: PostgresMain (postgres.c:4856)
==1159420==    by 0x828F23: BackendMain (backend_startup.c:124)
==1159420==    by 0x71EB2A: postmaster_child_launch (launch_backend.c:268)
==1159420==    by 0x725241: BackendStartup (postmaster.c:3627)
==1159420==    by 0x722923: ServerLoop (postmaster.c:1728)
==1159420==  Block was alloc'd at
==1159420==    at 0xA72DB2: palloc (mcxt.c:1411)
==1159420==    by 0x20940A: heap_copytuple (heaptuple.c:693)
==1159420==    by 0x535102: tts_buffer_heap_copy_heap_tuple (execTuples.c:927)
==1159420==    by 0x413DDB: ExecCopySlotHeapTuple (tuptable.h:507)
==1159420==    by 0x4168D9: acquire_sample_rows (analyze.c:1332)
==1159420==    by 0x41505F: do_analyze_rel (analyze.c:546)
==1159420==    by 0x41457E: analyze_rel (analyze.c:276)
==1159420==    by 0x4F8372: vacuum (vacuum.c:651)
==1159420==    by 0x4F7E99: ExecVacuum (vacuum.c:465)
==1159420==    by 0x837AA7: standard_ProcessUtility (utility.c:863)
==1159420==    by 0x8371A0: ProcessUtility (utility.c:528)
==1159420==    by 0x8359B9: PortalRunUtility (pquery.c:1149)
==1159420==    by 0x835C2F: PortalRunMulti (pquery.c:1307)
==1159420==    by 0x83511E: PortalRun (pquery.c:784)
==1159420==    by 0x82DAB8: exec_simple_query (postgres.c:1290)
==1159420==    by 0x8331A1: PostgresMain (postgres.c:4856)
==1159420==    by 0x828F23: BackendMain (backend_startup.c:124)
==1159420==    by 0x71EB2A: postmaster_child_launch (launch_backend.c:268)
==1159420==    by 0x725241: BackendStartup (postmaster.c:3627)
==1159420==    by 0x722923: ServerLoop (postmaster.c:1728)
==1159420== 
{
   <insert_a_suppression_name_here>
   Memcheck:Addr8
   fun:memmove
   fun:ExecBitmapIndexScanRetrieveInstrumentation
   fun:ExecParallelRetrieveInstrumentation
   fun:planstate_tree_walker_impl
   fun:ExecParallelRetrieveInstrumentation
   fun:planstate_walk_members
   fun:planstate_tree_walker_impl
   fun:ExecParallelRetrieveInstrumentation
   fun:ExecParallelCleanup
   fun:ExecShutdownGather
   fun:ExecShutdownNode_walker
   fun:ExecShutdownNode
   fun:ExecutePlan
   fun:standard_ExecutorRun
   fun:ExecutorRun
   fun:ExplainOnePlan
   fun:standard_ExplainOneQuery
   fun:ExplainOneQuery
   fun:ExplainQuery
   fun:standard_ProcessUtility
}
==1159420== Invalid read of size 8
==1159420==    at 0x485268F: memmove (vg_replace_strmem.c:1414)
==1159420==    by 0x54C675: ExecBitmapIndexScanRetrieveInstrumentation (nodeBitmapIndexscan.c:447)
==1159420==    by 0x527685: ExecParallelRetrieveInstrumentation (execParallel.c:1143)
==1159420==    by 0x5EBAB7: planstate_tree_walker_impl (nodeFuncs.c:4861)
==1159420==    by 0x527712: ExecParallelRetrieveInstrumentation (execParallel.c:1173)
==1159420==    by 0x5EBE07: planstate_walk_members (nodeFuncs.c:4953)
==1159420==    by 0x5EBB53: planstate_tree_walker_impl (nodeFuncs.c:4876)
==1159420==    by 0x527712: ExecParallelRetrieveInstrumentation (execParallel.c:1173)
==1159420==    by 0x5279AE: ExecParallelCleanup (execParallel.c:1278)
==1159420==    by 0x550361: ExecShutdownGather (nodeGather.c:426)
==1159420==    by 0x52DD0A: ExecShutdownNode_walker (execProcnode.c:784)
==1159420==    by 0x52DC59: ExecShutdownNode (execProcnode.c:755)
==1159420==    by 0x5228D3: ExecutePlan (execMain.c:1794)
==1159420==    by 0x51FE84: standard_ExecutorRun (execMain.c:377)
==1159420==    by 0x51FCE6: ExecutorRun (execMain.c:314)
==1159420==    by 0x4435D6: ExplainOnePlan (explain.c:587)
==1159420==    by 0x442F9E: standard_ExplainOneQuery (explain.c:378)
==1159420==    by 0x442CF5: ExplainOneQuery (explain.c:315)
==1159420==    by 0x442973: ExplainQuery (explain.c:228)
==1159420==    by 0x837AE3: standard_ProcessUtility (utility.c:871)
==1159420==  Address 0x1235e568 is 80 bytes inside a block of size 219 free'd
==1159420==    at 0xA60847: AllocSetReset (aset.c:618)
==1159420==    by 0xA71058: MemoryContextResetOnly (mcxt.c:439)
==1159420==    by 0xA6093C: AllocSetDelete (aset.c:661)
==1159420==    by 0xA712E0: MemoryContextDeleteOnly (mcxt.c:546)
==1159420==    by 0xA711A4: MemoryContextDelete (mcxt.c:500)
==1159420==    by 0x415BCC: do_analyze_rel (analyze.c:869)
==1159420==    by 0x41457E: analyze_rel (analyze.c:276)
==1159420==    by 0x4F8372: vacuum (vacuum.c:651)
==1159420==    by 0x4F7E99: ExecVacuum (vacuum.c:465)
==1159420==    by 0x837AA7: standard_ProcessUtility (utility.c:863)
==1159420==    by 0x8371A0: ProcessUtility (utility.c:528)
==1159420==    by 0x8359B9: PortalRunUtility (pquery.c:1149)
==1159420==    by 0x835C2F: PortalRunMulti (pquery.c:1307)
==1159420==    by 0x83511E: PortalRun (pquery.c:784)
==1159420==    by 0x82DAB8: exec_simple_query (postgres.c:1290)
==1159420==    by 0x8331A1: PostgresMain (postgres.c:4856)
==1159420==    by 0x828F23: BackendMain (backend_startup.c:124)
==1159420==    by 0x71EB2A: postmaster_child_launch (launch_backend.c:268)
==1159420==    by 0x725241: BackendStartup (postmaster.c:3627)
==1159420==    by 0x722923: ServerLoop (postmaster.c:1728)
==1159420==  Block was alloc'd at
==1159420==    at 0xA72DB2: palloc (mcxt.c:1411)
==1159420==    by 0x20940A: heap_copytuple (heaptuple.c:693)
==1159420==    by 0x535102: tts_buffer_heap_copy_heap_tuple (execTuples.c:927)
==1159420==    by 0x413DDB: ExecCopySlotHeapTuple (tuptable.h:507)
==1159420==    by 0x4168D9: acquire_sample_rows (analyze.c:1332)
==1159420==    by 0x41505F: do_analyze_rel (analyze.c:546)
==1159420==    by 0x41457E: analyze_rel (analyze.c:276)
==1159420==    by 0x4F8372: vacuum (vacuum.c:651)
==1159420==    by 0x4F7E99: ExecVacuum (vacuum.c:465)
==1159420==    by 0x837AA7: standard_ProcessUtility (utility.c:863)
==1159420==    by 0x8371A0: ProcessUtility (utility.c:528)
==1159420==    by 0x8359B9: PortalRunUtility (pquery.c:1149)
==1159420==    by 0x835C2F: PortalRunMulti (pquery.c:1307)
==1159420==    by 0x83511E: PortalRun (pquery.c:784)
==1159420==    by 0x82DAB8: exec_simple_query (postgres.c:1290)
==1159420==    by 0x8331A1: PostgresMain (postgres.c:4856)
==1159420==    by 0x828F23: BackendMain (backend_startup.c:124)
==1159420==    by 0x71EB2A: postmaster_child_launch (launch_backend.c:268)
==1159420==    by 0x725241: BackendStartup (postmaster.c:3627)
==1159420==    by 0x722923: ServerLoop (postmaster.c:1728)
==1159420== 
{
   <insert_a_suppression_name_here>
   Memcheck:Addr8
   fun:memmove
   fun:ExecBitmapIndexScanRetrieveInstrumentation
   fun:ExecParallelRetrieveInstrumentation
   fun:planstate_tree_walker_impl
   fun:ExecParallelRetrieveInstrumentation
   fun:planstate_walk_members
   fun:planstate_tree_walker_impl
   fun:ExecParallelRetrieveInstrumentation
   fun:ExecParallelCleanup
   fun:ExecShutdownGather
   fun:ExecShutdownNode_walker
   fun:ExecShutdownNode
   fun:ExecutePlan
   fun:standard_ExecutorRun
   fun:ExecutorRun
   fun:ExplainOnePlan
   fun:standard_ExplainOneQuery
   fun:ExplainOneQuery
   fun:ExplainQuery
   fun:standard_ProcessUtility
}
==1159420== Invalid read of size 8
==1159420==    at 0x4852697: memmove (vg_replace_strmem.c:1414)
==1159420==    by 0x54C675: ExecBitmapIndexScanRetrieveInstrumentation (nodeBitmapIndexscan.c:447)
==1159420==    by 0x527685: ExecParallelRetrieveInstrumentation (execParallel.c:1143)
==1159420==    by 0x5EBAB7: planstate_tree_walker_impl (nodeFuncs.c:4861)
==1159420==    by 0x527712: ExecParallelRetrieveInstrumentation (execParallel.c:1173)
==1159420==    by 0x5EBE07: planstate_walk_members (nodeFuncs.c:4953)
==1159420==    by 0x5EBB53: planstate_tree_walker_impl (nodeFuncs.c:4876)
==1159420==    by 0x527712: ExecParallelRetrieveInstrumentation (execParallel.c:1173)
==1159420==    by 0x5279AE: ExecParallelCleanup (execParallel.c:1278)
==1159420==    by 0x550361: ExecShutdownGather (nodeGather.c:426)
==1159420==    by 0x52DD0A: ExecShutdownNode_walker (execProcnode.c:784)
==1159420==    by 0x52DC59: ExecShutdownNode (execProcnode.c:755)
==1159420==    by 0x5228D3: ExecutePlan (execMain.c:1794)
==1159420==    by 0x51FE84: standard_ExecutorRun (execMain.c:377)
==1159420==    by 0x51FCE6: ExecutorRun (execMain.c:314)
==1159420==    by 0x4435D6: ExplainOnePlan (explain.c:587)
==1159420==    by 0x442F9E: standard_ExplainOneQuery (explain.c:378)
==1159420==    by 0x442CF5: ExplainOneQuery (explain.c:315)
==1159420==    by 0x442973: ExplainQuery (explain.c:228)
==1159420==    by 0x837AE3: standard_ProcessUtility (utility.c:871)
==1159420==  Address 0x1235e570 is 88 bytes inside a block of size 219 free'd
==1159420==    at 0xA60847: AllocSetReset (aset.c:618)
==1159420==    by 0xA71058: MemoryContextResetOnly (mcxt.c:439)
==1159420==    by 0xA6093C: AllocSetDelete (aset.c:661)
==1159420==    by 0xA712E0: MemoryContextDeleteOnly (mcxt.c:546)
==1159420==    by 0xA711A4: MemoryContextDelete (mcxt.c:500)
==1159420==    by 0x415BCC: do_analyze_rel (analyze.c:869)
==1159420==    by 0x41457E: analyze_rel (analyze.c:276)
==1159420==    by 0x4F8372: vacuum (vacuum.c:651)
==1159420==    by 0x4F7E99: ExecVacuum (vacuum.c:465)
==1159420==    by 0x837AA7: standard_ProcessUtility (utility.c:863)
==1159420==    by 0x8371A0: ProcessUtility (utility.c:528)
==1159420==    by 0x8359B9: PortalRunUtility (pquery.c:1149)
==1159420==    by 0x835C2F: PortalRunMulti (pquery.c:1307)
==1159420==    by 0x83511E: PortalRun (pquery.c:784)
==1159420==    by 0x82DAB8: exec_simple_query (postgres.c:1290)
==1159420==    by 0x8331A1: PostgresMain (postgres.c:4856)
==1159420==    by 0x828F23: BackendMain (backend_startup.c:124)
==1159420==    by 0x71EB2A: postmaster_child_launch (launch_backend.c:268)
==1159420==    by 0x725241: BackendStartup (postmaster.c:3627)
==1159420==    by 0x722923: ServerLoop (postmaster.c:1728)
==1159420==  Block was alloc'd at
==1159420==    at 0xA72DB2: palloc (mcxt.c:1411)
==1159420==    by 0x20940A: heap_copytuple (heaptuple.c:693)
==1159420==    by 0x535102: tts_buffer_heap_copy_heap_tuple (execTuples.c:927)
==1159420==    by 0x413DDB: ExecCopySlotHeapTuple (tuptable.h:507)
==1159420==    by 0x4168D9: acquire_sample_rows (analyze.c:1332)
==1159420==    by 0x41505F: do_analyze_rel (analyze.c:546)
==1159420==    by 0x41457E: analyze_rel (analyze.c:276)
==1159420==    by 0x4F8372: vacuum (vacuum.c:651)
==1159420==    by 0x4F7E99: ExecVacuum (vacuum.c:465)
==1159420==    by 0x837AA7: standard_ProcessUtility (utility.c:863)
==1159420==    by 0x8371A0: ProcessUtility (utility.c:528)
==1159420==    by 0x8359B9: PortalRunUtility (pquery.c:1149)
==1159420==    by 0x835C2F: PortalRunMulti (pquery.c:1307)
==1159420==    by 0x83511E: PortalRun (pquery.c:784)
==1159420==    by 0x82DAB8: exec_simple_query (postgres.c:1290)
==1159420==    by 0x8331A1: PostgresMain (postgres.c:4856)
==1159420==    by 0x828F23: BackendMain (backend_startup.c:124)
==1159420==    by 0x71EB2A: postmaster_child_launch (launch_backend.c:268)
==1159420==    by 0x725241: BackendStartup (postmaster.c:3627)
==1159420==    by 0x722923: ServerLoop (postmaster.c:1728)
==1159420== 
{
   <insert_a_suppression_name_here>
   Memcheck:Addr8
   fun:memmove
   fun:ExecBitmapIndexScanRetrieveInstrumentation
   fun:ExecParallelRetrieveInstrumentation
   fun:planstate_tree_walker_impl
   fun:ExecParallelRetrieveInstrumentation
   fun:planstate_walk_members
   fun:planstate_tree_walker_impl
   fun:ExecParallelRetrieveInstrumentation
   fun:ExecParallelCleanup
   fun:ExecShutdownGather
   fun:ExecShutdownNode_walker
   fun:ExecShutdownNode
   fun:ExecutePlan
   fun:standard_ExecutorRun
   fun:ExecutorRun
   fun:ExplainOnePlan
   fun:standard_ExplainOneQuery
   fun:ExplainOneQuery
   fun:ExplainQuery
   fun:standard_ProcessUtility
}
==1159420== Invalid read of size 8
==1159420==    at 0x485269F: memmove (vg_replace_strmem.c:1414)
==1159420==    by 0x54C675: ExecBitmapIndexScanRetrieveInstrumentation (nodeBitmapIndexscan.c:447)
==1159420==    by 0x527685: ExecParallelRetrieveInstrumentation (execParallel.c:1143)
==1159420==    by 0x5EBAB7: planstate_tree_walker_impl (nodeFuncs.c:4861)
==1159420==    by 0x527712: ExecParallelRetrieveInstrumentation (execParallel.c:1173)
==1159420==    by 0x5EBE07: planstate_walk_members (nodeFuncs.c:4953)
==1159420==    by 0x5EBB53: planstate_tree_walker_impl (nodeFuncs.c:4876)
==1159420==    by 0x527712: ExecParallelRetrieveInstrumentation (execParallel.c:1173)
==1159420==    by 0x5279AE: ExecParallelCleanup (execParallel.c:1278)
==1159420==    by 0x550361: ExecShutdownGather (nodeGather.c:426)
==1159420==    by 0x52DD0A: ExecShutdownNode_walker (execProcnode.c:784)
==1159420==    by 0x52DC59: ExecShutdownNode (execProcnode.c:755)
==1159420==    by 0x5228D3: ExecutePlan (execMain.c:1794)
==1159420==    by 0x51FE84: standard_ExecutorRun (execMain.c:377)
==1159420==    by 0x51FCE6: ExecutorRun (execMain.c:314)
==1159420==    by 0x4435D6: ExplainOnePlan (explain.c:587)
==1159420==    by 0x442F9E: standard_ExplainOneQuery (explain.c:378)
==1159420==    by 0x442CF5: ExplainOneQuery (explain.c:315)
==1159420==    by 0x442973: ExplainQuery (explain.c:228)
==1159420==    by 0x837AE3: standard_ProcessUtility (utility.c:871)
==1159420==  Address 0x1235e578 is 96 bytes inside a block of size 219 free'd
==1159420==    at 0xA60847: AllocSetReset (aset.c:618)
==1159420==    by 0xA71058: MemoryContextResetOnly (mcxt.c:439)
==1159420==    by 0xA6093C: AllocSetDelete (aset.c:661)
==1159420==    by 0xA712E0: MemoryContextDeleteOnly (mcxt.c:546)
==1159420==    by 0xA711A4: MemoryContextDelete (mcxt.c:500)
==1159420==    by 0x415BCC: do_analyze_rel (analyze.c:869)
==1159420==    by 0x41457E: analyze_rel (analyze.c:276)
==1159420==    by 0x4F8372: vacuum (vacuum.c:651)
==1159420==    by 0x4F7E99: ExecVacuum (vacuum.c:465)
==1159420==    by 0x837AA7: standard_ProcessUtility (utility.c:863)
==1159420==    by 0x8371A0: ProcessUtility (utility.c:528)
==1159420==    by 0x8359B9: PortalRunUtility (pquery.c:1149)
==1159420==    by 0x835C2F: PortalRunMulti (pquery.c:1307)
==1159420==    by 0x83511E: PortalRun (pquery.c:784)
==1159420==    by 0x82DAB8: exec_simple_query (postgres.c:1290)
==1159420==    by 0x8331A1: PostgresMain (postgres.c:4856)
==1159420==    by 0x828F23: BackendMain (backend_startup.c:124)
==1159420==    by 0x71EB2A: postmaster_child_launch (launch_backend.c:268)
==1159420==    by 0x725241: BackendStartup (postmaster.c:3627)
==1159420==    by 0x722923: ServerLoop (postmaster.c:1728)
==1159420==  Block was alloc'd at
==1159420==    at 0xA72DB2: palloc (mcxt.c:1411)
==1159420==    by 0x20940A: heap_copytuple (heaptuple.c:693)
==1159420==    by 0x535102: tts_buffer_heap_copy_heap_tuple (execTuples.c:927)
==1159420==    by 0x413DDB: ExecCopySlotHeapTuple (tuptable.h:507)
==1159420==    by 0x4168D9: acquire_sample_rows (analyze.c:1332)
==1159420==    by 0x41505F: do_analyze_rel (analyze.c:546)
==1159420==    by 0x41457E: analyze_rel (analyze.c:276)
==1159420==    by 0x4F8372: vacuum (vacuum.c:651)
==1159420==    by 0x4F7E99: ExecVacuum (vacuum.c:465)
==1159420==    by 0x837AA7: standard_ProcessUtility (utility.c:863)
==1159420==    by 0x8371A0: ProcessUtility (utility.c:528)
==1159420==    by 0x8359B9: PortalRunUtility (pquery.c:1149)
==1159420==    by 0x835C2F: PortalRunMulti (pquery.c:1307)
==1159420==    by 0x83511E: PortalRun (pquery.c:784)
==1159420==    by 0x82DAB8: exec_simple_query (postgres.c:1290)
==1159420==    by 0x8331A1: PostgresMain (postgres.c:4856)
==1159420==    by 0x828F23: BackendMain (backend_startup.c:124)
==1159420==    by 0x71EB2A: postmaster_child_launch (launch_backend.c:268)
==1159420==    by 0x725241: BackendStartup (postmaster.c:3627)
==1159420==    by 0x722923: ServerLoop (postmaster.c:1728)
==1159420== 
{
   <insert_a_suppression_name_here>
   Memcheck:Addr8
   fun:memmove
   fun:ExecBitmapIndexScanRetrieveInstrumentation
   fun:ExecParallelRetrieveInstrumentation
   fun:planstate_tree_walker_impl
   fun:ExecParallelRetrieveInstrumentation
   fun:planstate_walk_members
   fun:planstate_tree_walker_impl
   fun:ExecParallelRetrieveInstrumentation
   fun:ExecParallelCleanup
   fun:ExecShutdownGather
   fun:ExecShutdownNode_walker
   fun:ExecShutdownNode
   fun:ExecutePlan
   fun:standard_ExecutorRun
   fun:ExecutorRun
   fun:ExplainOnePlan
   fun:standard_ExplainOneQuery
   fun:ExplainOneQuery
   fun:ExplainQuery
   fun:standard_ProcessUtility
}
==1159420== 
==1159420== Process terminating with default action of signal 11 (SIGSEGV): dumping core
==1159420==  Access not within mapped region at address 0x124BC000
==1159420==    at 0x4852684: memmove (vg_replace_strmem.c:1414)
==1159420==    by 0x54C675: ExecBitmapIndexScanRetrieveInstrumentation (nodeBitmapIndexscan.c:447)
==1159420==    by 0x527685: ExecParallelRetrieveInstrumentation (execParallel.c:1143)
==1159420==    by 0x5EBAB7: planstate_tree_walker_impl (nodeFuncs.c:4861)
==1159420==    by 0x527712: ExecParallelRetrieveInstrumentation (execParallel.c:1173)
==1159420==    by 0x5EBE07: planstate_walk_members (nodeFuncs.c:4953)
==1159420==    by 0x5EBB53: planstate_tree_walker_impl (nodeFuncs.c:4876)
==1159420==    by 0x527712: ExecParallelRetrieveInstrumentation (execParallel.c:1173)
==1159420==    by 0x5279AE: ExecParallelCleanup (execParallel.c:1278)
==1159420==    by 0x550361: ExecShutdownGather (nodeGather.c:426)
==1159420==    by 0x52DD0A: ExecShutdownNode_walker (execProcnode.c:784)
==1159420==    by 0x52DC59: ExecShutdownNode (execProcnode.c:755)
==1159420==    by 0x5228D3: ExecutePlan (execMain.c:1794)
==1159420==    by 0x51FE84: standard_ExecutorRun (execMain.c:377)
==1159420==    by 0x51FCE6: ExecutorRun (execMain.c:314)
==1159420==    by 0x4435D6: ExplainOnePlan (explain.c:587)
==1159420==    by 0x442F9E: standard_ExplainOneQuery (explain.c:378)
==1159420==    by 0x442CF5: ExplainOneQuery (explain.c:315)
==1159420==    by 0x442973: ExplainQuery (explain.c:228)
==1159420==    by 0x837AE3: standard_ProcessUtility (utility.c:871)
==1159420==  If you believe this happened as a result of a stack
==1159420==  overflow in your program's main thread (unlikely but
==1159420==  possible), you can try to increase the size of the
==1159420==  main thread stack using the --main-stacksize= flag.
==1159420==  The main thread stack size used in this run was 8388608.

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

* Re: PoC: VALGRIND_MAKE_MEM_NOACCESS for dynamic shared memory
@ 2026-05-04 13:56  Andres Freund <[email protected]>
  parent: Tomas Vondra <[email protected]>
  0 siblings, 1 reply; 34+ messages in thread

From: Andres Freund @ 2026-05-04 13:56 UTC (permalink / raw)
  To: Tomas Vondra <[email protected]>; +Cc: pgsql-hackers

Hi,

On 2026-05-04 10:18:31 +0200, Tomas Vondra wrote:
> A couple of days ago we got a report regarding an incorrect shmem size
> calculation in btree [1], leading to a buffer overflow / memory
> corruption. Which became a much less common issue in our code, thanks to
> valgrind and similar tools. But it took me a while to realize valgrind
> won't catch this because we only instrument private memory (palloc et
> al), while shmem is left alone.
> 
> I was wondering if it's feasible to improve this. Attached is a trivial
> patch that adjusts shm_toc.c to add a couple NOACCESS bytes after each
> entry in the segment. It seems to do the trick - with this we get a
> reasonable report (for the reproducer provided in the bug report, before
> it got fixed by 748d871b7c) from valgrind, with invalid accesses. See
> the attached .log for an example. It's much better than the confusing
> crashes due to corrupted state.
> 
> There's an issue, though. It seems the valgrind memory markings are not
> shared between processes. The leader sets the shm_toc up, marks the
> ranges as NOACCESS, and then checks it while accessing the memory. But
> the parallel workers don't seem to see this, and so will produce no
> reports. I'm assuming this is the case, because all the reports come
> from the leader, never from the workers. Maybe there's a different
> explanation (e.g. maybe it's just the leader touching the memory?).

I assume the issue is just that the workers don't have the NOACCESS markers? I
think you'd need to do them in every process using the shm_toc.  Either by
doing it in shm_toc_attach() or in shm_toc().



> An alternative would be to do mprotect(), but unfortunately it requires
> page-aligned ranges, which makes it somewhat useless for small overflows
> of a couple bytes (like here). It should work cross-process, I think,

It doesn't work across processes. Every process has their own mprotect "view".


> FWIW the PoC patch adds a 32-byte chunk, not just a single byte. This is
> intentional, because if the state is an array, it's quite possible the
> invalid access steps over a fair number of bytes. I'm actually thinking
> it should be even larger.
> 
> This modifies just the dynamic shmem, but maybe we should do this even
> for the "regular" shmem allocated at start. Issues in that would likely
> cause crashes pretty quick (unlike the btree issue, which requires a
> somewhat special reproducer), but a nice valgrind report helps.

I can tell you from experience that no, it's not necessarily quickly caught.
So yes, I think we should definitely do that.



>  /*
>   * Allocate shared memory from a segment managed by a table of contents.
>   *
> @@ -119,9 +127,19 @@ shm_toc_allocate(shm_toc *toc, Size nbytes)
>  	}
>  	vtoc->toc_allocated_bytes += nbytes;
>  
> +#ifdef USE_VALGRIND
> +	vtoc->toc_allocated_bytes += NUM_NOACCESS_BYTES;
> +#endif
> +
>  	SpinLockRelease(&toc->toc_mutex);
>  
> -	return ((char *) toc) + (total_bytes - allocated_bytes - nbytes);
> +#ifdef USE_VALGRIND
> +	/* make the bytes at the end no-access */
> +	VALGRIND_MAKE_MEM_NOACCESS(((char *) toc) + (total_bytes - allocated_bytes - NUM_NOACCESS_BYTES),
> +							   NUM_NOACCESS_BYTES);
> +#endif
> +
> +	return ((char *) toc) + (total_bytes - allocated_bytes - nbytes - NUM_NOACCESS_BYTES);
>  }

The size is already rounded up by that point:

	/*
	 * Make sure request is well-aligned.  XXX: MAXALIGN is not enough,
	 * because atomic ops might need a wider alignment.  We don't have a
	 * proper definition for the minimum to make atomic ops safe, but
	 * BUFFERALIGN ought to be enough.
	 */
	nbytes = BUFFERALIGN(nbytes);

Which means that you'll often have a up to 32byte pad at the end of the
(ALIGNOF_BUFFER=32) allocation already. I don't care about the waste, but the
ALIGNOF_BUFFER padding will often prevent detecting smaller out-of-bounds
accesses.

Greetings,

Andres Freund





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

* Re: PoC: VALGRIND_MAKE_MEM_NOACCESS for dynamic shared memory
@ 2026-05-04 14:21  Tomas Vondra <[email protected]>
  parent: Andres Freund <[email protected]>
  0 siblings, 0 replies; 34+ messages in thread

From: Tomas Vondra @ 2026-05-04 14:21 UTC (permalink / raw)
  To: Andres Freund <[email protected]>; +Cc: pgsql-hackers



On 5/4/26 15:56, Andres Freund wrote:
> Hi,
> 
> On 2026-05-04 10:18:31 +0200, Tomas Vondra wrote:
>> A couple of days ago we got a report regarding an incorrect shmem size
>> calculation in btree [1], leading to a buffer overflow / memory
>> corruption. Which became a much less common issue in our code, thanks to
>> valgrind and similar tools. But it took me a while to realize valgrind
>> won't catch this because we only instrument private memory (palloc et
>> al), while shmem is left alone.
>>
>> I was wondering if it's feasible to improve this. Attached is a trivial
>> patch that adjusts shm_toc.c to add a couple NOACCESS bytes after each
>> entry in the segment. It seems to do the trick - with this we get a
>> reasonable report (for the reproducer provided in the bug report, before
>> it got fixed by 748d871b7c) from valgrind, with invalid accesses. See
>> the attached .log for an example. It's much better than the confusing
>> crashes due to corrupted state.
>>
>> There's an issue, though. It seems the valgrind memory markings are not
>> shared between processes. The leader sets the shm_toc up, marks the
>> ranges as NOACCESS, and then checks it while accessing the memory. But
>> the parallel workers don't seem to see this, and so will produce no
>> reports. I'm assuming this is the case, because all the reports come
>> from the leader, never from the workers. Maybe there's a different
>> explanation (e.g. maybe it's just the leader touching the memory?).
> 
> I assume the issue is just that the workers don't have the NOACCESS markers? I
> think you'd need to do them in every process using the shm_toc.  Either by
> doing it in shm_toc_attach() or in shm_toc().
> 

Right, but it'd also need to know how long the entry is. Which AFAIK it
does not. We don't want to redo the calculation in every worker, but we
might add a "len" field to the toc entry.

> 
> 
>> An alternative would be to do mprotect(), but unfortunately it requires
>> page-aligned ranges, which makes it somewhat useless for small overflows
>> of a couple bytes (like here). It should work cross-process, I think,
> 
> It doesn't work across processes. Every process has their own mprotect "view".
> 

Ah, OK. So I guessed wrong, and it has the same issue as NOACCESS.

> 
>> FWIW the PoC patch adds a 32-byte chunk, not just a single byte. This is
>> intentional, because if the state is an array, it's quite possible the
>> invalid access steps over a fair number of bytes. I'm actually thinking
>> it should be even larger.
>>
>> This modifies just the dynamic shmem, but maybe we should do this even
>> for the "regular" shmem allocated at start. Issues in that would likely
>> cause crashes pretty quick (unlike the btree issue, which requires a
>> somewhat special reproducer), but a nice valgrind report helps.
> 
> I can tell you from experience that no, it's not necessarily quickly caught.
> So yes, I think we should definitely do that.
> 

Understood.

> 
> 
>>  /*
>>   * Allocate shared memory from a segment managed by a table of contents.
>>   *
>> @@ -119,9 +127,19 @@ shm_toc_allocate(shm_toc *toc, Size nbytes)
>>  	}
>>  	vtoc->toc_allocated_bytes += nbytes;
>>  
>> +#ifdef USE_VALGRIND
>> +	vtoc->toc_allocated_bytes += NUM_NOACCESS_BYTES;
>> +#endif
>> +
>>  	SpinLockRelease(&toc->toc_mutex);
>>  
>> -	return ((char *) toc) + (total_bytes - allocated_bytes - nbytes);
>> +#ifdef USE_VALGRIND
>> +	/* make the bytes at the end no-access */
>> +	VALGRIND_MAKE_MEM_NOACCESS(((char *) toc) + (total_bytes - allocated_bytes - NUM_NOACCESS_BYTES),
>> +							   NUM_NOACCESS_BYTES);
>> +#endif
>> +
>> +	return ((char *) toc) + (total_bytes - allocated_bytes - nbytes - NUM_NOACCESS_BYTES);
>>  }
> 
> The size is already rounded up by that point:
> 
> 	/*
> 	 * Make sure request is well-aligned.  XXX: MAXALIGN is not enough,
> 	 * because atomic ops might need a wider alignment.  We don't have a
> 	 * proper definition for the minimum to make atomic ops safe, but
> 	 * BUFFERALIGN ought to be enough.
> 	 */
> 	nbytes = BUFFERALIGN(nbytes);
> 
> Which means that you'll often have a up to 32byte pad at the end of the
> (ALIGNOF_BUFFER=32) allocation already. I don't care about the waste, but the
> ALIGNOF_BUFFER padding will often prevent detecting smaller out-of-bounds
> accesses.
> 

Good point. I forgot about this alignment rounding. I don't care about
the waste either (it'd be a bit silly in a valgrind build anyway), but
not catching smaller mistakes would not be great.


regards

-- 
Tomas Vondra






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


end of thread, other threads:[~2026-05-04 14:21 UTC | newest]

Thread overview: 34+ messages (download: mbox mbox.gz follow: Atom feed)
-- links below jump to the message on this page --
2019-05-01 00:05 [PATCH v3] print table associated with given TOAST table Justin Pryzby <[email protected]>
2019-05-01 00:05 [PATCH v5] print table associated with given TOAST table Justin Pryzby <[email protected]>
2019-05-01 00:05 [PATCH v7] print table associated with given TOAST table Justin Pryzby <[email protected]>
2019-05-01 00:05 [PATCH v5] print table associated with given TOAST table Justin Pryzby <[email protected]>
2019-05-01 00:05 [PATCH v2 2/2] print table associated with given TOAST table Justin Pryzby <[email protected]>
2019-05-01 00:05 [PATCH v3] print table associated with given TOAST table Justin Pryzby <[email protected]>
2021-07-15 08:19 [PATCH 3/4] f!convert the other verbose to int, too Justin Pryzby <[email protected]>
2021-07-15 08:19 [PATCH v3 3/4] f!convert the other verbose to int, too Justin Pryzby <[email protected]>
2021-07-15 08:19 [PATCH v8 3/4] f!convert the other verbose to int, too Justin Pryzby <[email protected]>
2021-07-15 08:19 [PATCH 3/4] f!convert the other verbose to int, too Justin Pryzby <[email protected]>
2021-07-15 08:19 [PATCH 3/4] f!convert the other verbose to int, too Justin Pryzby <[email protected]>
2021-07-15 08:19 [PATCH v2 3/5] f!convert the other verbose to int, too Justin Pryzby <[email protected]>
2021-07-15 08:19 [PATCH 3/4] f!convert the other verbose to int, too Justin Pryzby <[email protected]>
2021-07-15 08:19 [PATCH 3/4] f!convert the other verbose to int, too Justin Pryzby <[email protected]>
2021-07-15 08:19 [PATCH 3/4] f!convert the other verbose to int, too Justin Pryzby <[email protected]>
2021-07-15 08:19 [PATCH 3/4] f!convert the other verbose to int, too Justin Pryzby <[email protected]>
2021-07-15 08:19 [PATCH v4 3/4] f!convert the other verbose to int, too Justin Pryzby <[email protected]>
2025-11-19 20:32 [PATCH v9 09/10] WIP: Make UnlockReleaseBuffer() more efficient Andres Freund <[email protected]>
2025-11-19 20:32 [PATCH v9 09/10] WIP: Make UnlockReleaseBuffer() more efficient Andres Freund <[email protected]>
2025-11-19 20:32 [PATCH v8 09/10] WIP: Make UnlockReleaseBuffer() more efficient Andres Freund <[email protected]>
2025-11-19 20:32 [PATCH v10 6/8] WIP: Make UnlockReleaseBuffer() more efficient Andres Freund <[email protected]>
2025-11-19 20:32 [PATCH v10 6/8] WIP: Make UnlockReleaseBuffer() more efficient Andres Freund <[email protected]>
2025-11-19 20:32 [PATCH v6 13/14] WIP: Make UnlockReleaseBuffer() more efficient Andres Freund <[email protected]>
2025-11-19 20:32 [PATCH v7 14/15] WIP: Make UnlockReleaseBuffer() more efficient Andres Freund <[email protected]>
2025-11-19 20:32 [PATCH v6 13/14] WIP: Make UnlockReleaseBuffer() more efficient Andres Freund <[email protected]>
2026-01-14 01:10 [PATCH v12 6/6] WIP: Make UnlockReleaseBuffer() more efficient Andres Freund <[email protected]>
2026-01-14 01:10 [PATCH v11 7/7] WIP: Make UnlockReleaseBuffer() more efficient Andres Freund <[email protected]>
2026-02-23 06:49 2026-02-26 release announcement draft Jonathan S. Katz <[email protected]>
2026-02-23 06:58 ` Re: 2026-02-26 release announcement draft Daniel Westermann (DWE) <[email protected]>
2026-02-24 05:53   ` Re: 2026-02-26 release announcement draft Jonathan S. Katz <[email protected]>
2026-02-24 06:25     ` Re: 2026-02-26 release announcement draft Daniel Westermann (DWE) <[email protected]>
2026-05-04 08:18 PoC: VALGRIND_MAKE_MEM_NOACCESS for dynamic shared memory Tomas Vondra <[email protected]>
2026-05-04 13:56 ` Re: PoC: VALGRIND_MAKE_MEM_NOACCESS for dynamic shared memory Andres Freund <[email protected]>
2026-05-04 14:21   ` Re: PoC: VALGRIND_MAKE_MEM_NOACCESS for dynamic shared memory Tomas Vondra <[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