pg.ddx.io  pgsql-hackers@postgresql.org mailing list archive  
help / color / mirror / Atom feed
Re: [PATCH] psql: \dn+ to show size of each schema (and \dA+ for AMs)
22+ messages / 7 participants
[nested] [flat]

* Re: [PATCH] psql: \dn+ to show size of each schema (and \dA+ for AMs)
@ 2021-07-16 01:16  Justin Pryzby <pryzby@telsasoft.com>
  0 siblings, 2 replies; 22+ messages in thread

From: Justin Pryzby @ 2021-07-16 01:16 UTC (permalink / raw)
  To: Laurenz Albe <laurenz.albe@cybertec.at>; +Cc: Ian Lawrence Barwick <barwick@gmail.com>; pgsql-hackers; gilles@darold.net

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

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

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

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

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

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

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

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

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

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

-- 
Justin

Attachments: download all (4 files, .tar.gz)

v3-0001-psql-show-size-of-schemas-and-AMs-in-dn-and-dA.patch (text/x-diff, 7.3K) download From d7f5446c0aa1a12a512482d2ed121eb44f6e2f59 Mon Sep 17 00:00:00 2001 From: Justin Pryzby <pryzbyj@telsasoft.com> Date: Tue, 13 Jul 2021 21:25:48 -0500 Subject: [PATCH v3 1/4] psql: show size of schemas and AMs in \dn+ and \dA+.. See also: 358a897fa, 528ac10c7 Add pg_am_size() and psql \dA++ --- src/backend/utils/adt/dbsize.c | 138 ++++++++++++++++++++++++++++++++ src/bin/psql/describe.c | 12 ++- src/include/catalog/pg_proc.dat | 19 +++++ 3 files changed, 168 insertions(+), 1 deletion(-) diff --git a/src/backend/utils/adt/dbsize.c b/src/backend/utils/adt/dbsize.c index d5a7fb13f3..62273d4f15 100644 --- a/src/backend/utils/adt/dbsize.c +++ b/src/backend/utils/adt/dbsize.c @@ -13,18 +13,23 @@ #include <sys/stat.h> +#include "access/genam.h" #include "access/htup_details.h" #include "access/relation.h" +#include "access/table.h" #include "catalog/catalog.h" #include "catalog/namespace.h" #include "catalog/pg_authid.h" #include "catalog/pg_tablespace.h" #include "commands/dbcommands.h" +#include "commands/defrem.h" #include "commands/tablespace.h" #include "miscadmin.h" #include "storage/fd.h" #include "utils/acl.h" #include "utils/builtins.h" +#include "utils/fmgroids.h" +#include "utils/lsyscache.h" #include "utils/numeric.h" #include "utils/rel.h" #include "utils/relfilenodemap.h" @@ -832,6 +837,139 @@ pg_size_bytes(PG_FUNCTION_ARGS) PG_RETURN_INT64(result); } +/* Return the sum of size of relations for which the given attribute has the specified OID */ +static int64 +calculate_size_attvalue(int attnum, Oid attval) +{ + int64 totalsize = 0; + ScanKeyData skey; + Relation pg_class; + SysScanDesc scan; + HeapTuple tuple; + + ScanKeyInit(&skey, attnum, + BTEqualStrategyNumber, F_OIDEQ, attval); + + pg_class = table_open(RelationRelationId, AccessShareLock); + scan = systable_beginscan(pg_class, InvalidOid, false, NULL, 1, &skey); + while (HeapTupleIsValid(tuple = systable_getnext(scan))) + { + Relation rel; + Form_pg_class classtuple = (Form_pg_class) GETSTRUCT(tuple); + + rel = try_relation_open(classtuple->oid, AccessShareLock); + if (!rel) + continue; + + for (int forkNum = 0; forkNum <= MAX_FORKNUM; forkNum++) + totalsize += calculate_relation_size(&rel->rd_node, rel->rd_backend, forkNum); + + relation_close(rel, AccessShareLock); + } + + systable_endscan(scan); + table_close(pg_class, AccessShareLock); + return totalsize; +} + +/* Compute the size of relations in a schema (namespace) */ +static int64 +calculate_namespace_size(Oid nspOid) +{ + /* + * User must be a member of pg_read_all_stats or have CREATE privilege for + * target namespace. + */ + if (!is_member_of_role(GetUserId(), ROLE_PG_READ_ALL_STATS)) + { + AclResult aclresult; + aclresult = pg_namespace_aclcheck(nspOid, GetUserId(), ACL_CREATE); + if (aclresult != ACLCHECK_OK) + aclcheck_error(aclresult, OBJECT_SCHEMA, + get_namespace_name(nspOid)); + } + + return calculate_size_attvalue(Anum_pg_class_relnamespace, nspOid); +} + +Datum +pg_namespace_size_oid(PG_FUNCTION_ARGS) +{ + int64 size; + Oid nspOid = PG_GETARG_OID(0); + + size = calculate_namespace_size(nspOid); + + if (size < 0) + PG_RETURN_NULL(); + + PG_RETURN_INT64(size); +} + +Datum +pg_namespace_size_name(PG_FUNCTION_ARGS) +{ + int64 size; + Name nspName = PG_GETARG_NAME(0); + Oid nspOid = get_namespace_oid(NameStr(*nspName), false); + + size = calculate_namespace_size(nspOid); + + if (size < 0) + PG_RETURN_NULL(); + + PG_RETURN_INT64(size); +} + +/* Compute the size of relations using an access method */ +static int64 +calculate_am_size(Oid amOid) +{ + /* + * User must be a member of pg_read_all_stats or have CREATE privilege for + * target namespace. + */ + if (!is_member_of_role(GetUserId(), ROLE_PG_READ_ALL_STATS)) + { + AclResult aclresult; + aclresult = pg_namespace_aclcheck(amOid, GetUserId(), ACL_CREATE); + if (aclresult != ACLCHECK_OK) + aclcheck_error(aclresult, OBJECT_SCHEMA, + get_am_name(amOid)); + } + + return calculate_size_attvalue(Anum_pg_class_relam, amOid); +} + +Datum +pg_am_size_oid(PG_FUNCTION_ARGS) +{ + int64 size; + Oid amOid = PG_GETARG_OID(0); + + size = calculate_am_size(amOid); + + if (size < 0) + PG_RETURN_NULL(); + + PG_RETURN_INT64(size); +} + +Datum +pg_am_size_name(PG_FUNCTION_ARGS) +{ + int64 size; + Name amName = PG_GETARG_NAME(0); + Oid amOid = get_am_oid(NameStr(*amName), false); + + size = calculate_am_size(amOid); + + if (size < 0) + PG_RETURN_NULL(); + + PG_RETURN_INT64(size); +} + /* * Get the filenode of a relation * diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c index ba658f731b..fe5d88a2b7 100644 --- a/src/bin/psql/describe.c +++ b/src/bin/psql/describe.c @@ -152,7 +152,7 @@ describeAccessMethods(const char *pattern, bool verbose) PQExpBufferData buf; PGresult *res; printQueryOpt myopt = pset.popt; - static const bool translate_columns[] = {false, true, false, false}; + static const bool translate_columns[] = {false, true, false, false, false}; if (pset.sversion < 90600) { @@ -184,6 +184,11 @@ describeAccessMethods(const char *pattern, bool verbose) " pg_catalog.obj_description(oid, 'pg_am') AS \"%s\"", gettext_noop("Handler"), gettext_noop("Description")); + + if (pset.sversion >= 150000) + appendPQExpBuffer(&buf, + ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_am_size(oid)) AS \"%s\"", + gettext_noop("Size")); } appendPQExpBufferStr(&buf, @@ -5036,6 +5041,11 @@ listSchemas(const char *pattern, bool verbose, bool showSystem) appendPQExpBuffer(&buf, ",\n pg_catalog.obj_description(n.oid, 'pg_namespace') AS \"%s\"", gettext_noop("Description")); + + if (verbose && pset.sversion >= 150000) + appendPQExpBuffer(&buf, + ",\n pg_catalog.pg_size_pretty(pg_namespace_size(n.oid)) AS \"%s\"", + gettext_noop("Size")); } appendPQExpBufferStr(&buf, diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat index fde251fa4f..4518aad200 100644 --- a/src/include/catalog/pg_proc.dat +++ b/src/include/catalog/pg_proc.dat @@ -7158,6 +7158,25 @@ descr => 'total disk space usage for the specified tablespace', proname => 'pg_tablespace_size', provolatile => 'v', prorettype => 'int8', proargtypes => 'name', prosrc => 'pg_tablespace_size_name' }, + +{ oid => '9410', + descr => 'total disk space usage for the specified namespace', + proname => 'pg_namespace_size', provolatile => 'v', prorettype => 'int8', + proargtypes => 'oid', prosrc => 'pg_namespace_size_oid' }, +{ oid => '9411', + descr => 'total disk space usage for the specified namespace', + proname => 'pg_namespace_size', provolatile => 'v', prorettype => 'int8', + proargtypes => 'name', prosrc => 'pg_namespace_size_name' }, + +{ oid => '9412', + descr => 'total disk space usage for the specified access method', + proname => 'pg_am_size', provolatile => 'v', prorettype => 'int8', + proargtypes => 'oid', prosrc => 'pg_am_size_oid' }, +{ oid => '9413', + descr => 'total disk space usage for the specified access method', + proname => 'pg_am_size', provolatile => 'v', prorettype => 'int8', + proargtypes => 'name', prosrc => 'pg_am_size_name' }, + { oid => '2324', descr => 'total disk space usage for the specified database', proname => 'pg_database_size', provolatile => 'v', prorettype => 'int8', proargtypes => 'oid', prosrc => 'pg_database_size_oid' }, -- 2.17.0
v3-0002-psql-dn-dA-db-and-l-to-show-the-size-only-with.patch (text/x-diff, 7.9K) download From 351de9f97334467b5513b2245e62ea3edad3d1f5 Mon Sep 17 00:00:00 2001 From: Justin Pryzby <pryzbyj@telsasoft.com> Date: Thu, 15 Jul 2021 03:14:20 -0500 Subject: [PATCH v3 2/4] psql \dn, \dA, \db and \l to show the size only with ++.. \dt+ and \dP+ are not changed, since showing the table sizes is their primary purpose. --- src/bin/psql/command.c | 22 ++++++++++++++-------- src/bin/psql/describe.c | 16 ++++++++-------- src/bin/psql/describe.h | 8 ++++---- 3 files changed, 26 insertions(+), 20 deletions(-) diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c index 49d4c0e3ce..bfb10d91e4 100644 --- a/src/bin/psql/command.c +++ b/src/bin/psql/command.c @@ -362,7 +362,8 @@ exec_command(const char *cmd, else if (strcmp(cmd, "if") == 0) status = exec_command_if(scan_state, cstack, query_buf); else if (strcmp(cmd, "l") == 0 || strcmp(cmd, "list") == 0 || - strcmp(cmd, "l+") == 0 || strcmp(cmd, "list+") == 0) + strcmp(cmd, "l+") == 0 || strcmp(cmd, "l++") == 0 || + strcmp(cmd, "list+") == 0 || strcmp(cmd, "list++") == 0) status = exec_command_list(scan_state, active_branch, cmd); else if (strncmp(cmd, "lo_", 3) == 0) status = exec_command_lo(scan_state, active_branch, cmd); @@ -707,6 +708,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) if (active_branch) { char *pattern; + int verbose = 0; bool show_verbose, show_system; @@ -714,7 +716,10 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) pattern = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, true); - show_verbose = strchr(cmd, '+') ? true : false; + for (const char *t = cmd; *t != '\0'; ++t) + verbose += *t == '+' ? 1 : 0; + + show_verbose = (bool) (verbose != 0); show_system = strchr(cmd, 'S') ? true : false; switch (cmd[1]) @@ -739,7 +744,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) { case '\0': case '+': - success = describeAccessMethods(pattern, show_verbose); + success = describeAccessMethods(pattern, verbose); break; case 'c': success = listOperatorClasses(pattern, pattern2, show_verbose); @@ -766,7 +771,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) success = describeAggregates(pattern, show_verbose, show_system); break; case 'b': - success = describeTablespaces(pattern, show_verbose); + success = describeTablespaces(pattern, verbose); break; case 'c': success = listConversions(pattern, show_verbose, show_system); @@ -813,7 +818,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) success = listLanguages(pattern, show_verbose, show_system); break; case 'n': - success = listSchemas(pattern, show_verbose, show_system); + success = listSchemas(pattern, verbose, show_system); break; case 'o': success = exec_command_dfo(scan_state, cmd, pattern, @@ -1870,14 +1875,15 @@ exec_command_list(PsqlScanState scan_state, bool active_branch, const char *cmd) if (active_branch) { char *pattern; - bool show_verbose; + int verbose = 0; pattern = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, true); - show_verbose = strchr(cmd, '+') ? true : false; + for (const char *t = cmd; *t != '\0'; ++t) + verbose += *t == '+' ? 1 : 0; - success = listAllDbs(pattern, show_verbose); + success = listAllDbs(pattern, verbose); if (pattern) free(pattern); diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c index fe5d88a2b7..ce04dbb9ce 100644 --- a/src/bin/psql/describe.c +++ b/src/bin/psql/describe.c @@ -147,7 +147,7 @@ describeAggregates(const char *pattern, bool verbose, bool showSystem) * Takes an optional regexp to select particular access methods */ bool -describeAccessMethods(const char *pattern, bool verbose) +describeAccessMethods(const char *pattern, int verbose) { PQExpBufferData buf; PGresult *res; @@ -185,7 +185,7 @@ describeAccessMethods(const char *pattern, bool verbose) gettext_noop("Handler"), gettext_noop("Description")); - if (pset.sversion >= 150000) + if (verbose > 1 && pset.sversion >= 150000) appendPQExpBuffer(&buf, ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_am_size(oid)) AS \"%s\"", gettext_noop("Size")); @@ -222,7 +222,7 @@ describeAccessMethods(const char *pattern, bool verbose) * Takes an optional regexp to select particular tablespaces */ bool -describeTablespaces(const char *pattern, bool verbose) +describeTablespaces(const char *pattern, int verbose) { PQExpBufferData buf; PGresult *res; @@ -268,7 +268,7 @@ describeTablespaces(const char *pattern, bool verbose) ",\n spcoptions AS \"%s\"", gettext_noop("Options")); - if (verbose && pset.sversion >= 90200) + if (verbose > 1 && pset.sversion >= 90200) appendPQExpBuffer(&buf, ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_tablespace_size(oid)) AS \"%s\"", gettext_noop("Size")); @@ -1028,7 +1028,7 @@ describeOperators(const char *oper_pattern, * for \l, \list, and -l switch */ bool -listAllDbs(const char *pattern, bool verbose) +listAllDbs(const char *pattern, int verbose) { PGresult *res; PQExpBufferData buf; @@ -1051,7 +1051,7 @@ listAllDbs(const char *pattern, bool verbose) gettext_noop("Ctype")); appendPQExpBufferStr(&buf, " "); printACLColumn(&buf, "d.datacl"); - if (verbose && pset.sversion >= 80200) + if (verbose > 1 && pset.sversion >= 80200) appendPQExpBuffer(&buf, ",\n CASE WHEN pg_catalog.has_database_privilege(d.datname, 'CONNECT')\n" " THEN pg_catalog.pg_size_pretty(pg_catalog.pg_database_size(d.datname))\n" @@ -5021,7 +5021,7 @@ listCollations(const char *pattern, bool verbose, bool showSystem) * Describes schemas (namespaces) */ bool -listSchemas(const char *pattern, bool verbose, bool showSystem) +listSchemas(const char *pattern, int verbose, bool showSystem) { PQExpBufferData buf; PGresult *res; @@ -5042,7 +5042,7 @@ listSchemas(const char *pattern, bool verbose, bool showSystem) ",\n pg_catalog.obj_description(n.oid, 'pg_namespace') AS \"%s\"", gettext_noop("Description")); - if (verbose && pset.sversion >= 150000) + if (verbose > 1 && pset.sversion >= 150000) appendPQExpBuffer(&buf, ",\n pg_catalog.pg_size_pretty(pg_namespace_size(n.oid)) AS \"%s\"", gettext_noop("Size")); diff --git a/src/bin/psql/describe.h b/src/bin/psql/describe.h index 71b320f1fc..edeea38580 100644 --- a/src/bin/psql/describe.h +++ b/src/bin/psql/describe.h @@ -13,10 +13,10 @@ extern bool describeAggregates(const char *pattern, bool verbose, bool showSystem); /* \dA */ -extern bool describeAccessMethods(const char *pattern, bool verbose); +extern bool describeAccessMethods(const char *pattern, int verbose); /* \db */ -extern bool describeTablespaces(const char *pattern, bool verbose); +extern bool describeTablespaces(const char *pattern, int verbose); /* \df, \dfa, \dfn, \dft, \dfw, etc. */ extern bool describeFunctions(const char *functypes, const char *func_pattern, @@ -62,7 +62,7 @@ extern bool listTSDictionaries(const char *pattern, bool verbose); extern bool listTSTemplates(const char *pattern, bool verbose); /* \l */ -extern bool listAllDbs(const char *pattern, bool verbose); +extern bool listAllDbs(const char *pattern, int verbose); /* \dt, \di, \ds, \dS, etc. */ extern bool listTables(const char *tabtypes, const char *pattern, bool verbose, bool showSystem); @@ -83,7 +83,7 @@ extern bool listCasts(const char *pattern, bool verbose); extern bool listCollations(const char *pattern, bool verbose, bool showSystem); /* \dn */ -extern bool listSchemas(const char *pattern, bool verbose, bool showSystem); +extern bool listSchemas(const char *pattern, int verbose, bool showSystem); /* \dew */ extern bool listForeignDataWrappers(const char *pattern, bool verbose); -- 2.17.0
v3-0003-f-convert-the-other-verbose-to-int-too.patch (text/x-diff, 41.5K) download From 79b02af25ba0253b6025cef6b3e94abb2ddfe2eb Mon Sep 17 00:00:00 2001 From: Justin Pryzby <pryzbyj@telsasoft.com> Date: Thu, 15 Jul 2021 03:19:58 -0500 Subject: [PATCH v3 3/4] f!convert the other verbose to int, too --- src/bin/psql/command.c | 74 +++++++++-------- src/bin/psql/describe.c | 172 ++++++++++++++++++++-------------------- src/bin/psql/describe.h | 54 ++++++------- 3 files changed, 149 insertions(+), 151 deletions(-) diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c index bfb10d91e4..c3738a106f 100644 --- a/src/bin/psql/command.c +++ b/src/bin/psql/command.c @@ -75,7 +75,7 @@ static backslashResult exec_command_d(PsqlScanState scan_state, bool active_bran const char *cmd); static bool exec_command_dfo(PsqlScanState scan_state, const char *cmd, const char *pattern, - bool show_verbose, bool show_system); + int verbose, bool show_system); static backslashResult exec_command_edit(PsqlScanState scan_state, bool active_branch, PQExpBuffer query_buf, PQExpBuffer previous_buf); static backslashResult exec_command_ef_ev(PsqlScanState scan_state, bool active_branch, @@ -709,8 +709,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) { char *pattern; int verbose = 0; - bool show_verbose, - show_system; + bool show_system; /* We don't do SQLID reduction on the pattern yet */ pattern = psql_scan_slash_option(scan_state, @@ -719,7 +718,6 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) for (const char *t = cmd; *t != '\0'; ++t) verbose += *t == '+' ? 1 : 0; - show_verbose = (bool) (verbose != 0); show_system = strchr(cmd, 'S') ? true : false; switch (cmd[1]) @@ -728,10 +726,10 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) case '+': case 'S': if (pattern) - success = describeTableDetails(pattern, show_verbose, show_system); + success = describeTableDetails(pattern, verbose, show_system); else /* standard listing of interesting things */ - success = listTables("tvmsE", NULL, show_verbose, show_system); + success = listTables("tvmsE", NULL, verbose, show_system); break; case 'A': { @@ -747,16 +745,16 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) success = describeAccessMethods(pattern, verbose); break; case 'c': - success = listOperatorClasses(pattern, pattern2, show_verbose); + success = listOperatorClasses(pattern, pattern2, verbose); break; case 'f': - success = listOperatorFamilies(pattern, pattern2, show_verbose); + success = listOperatorFamilies(pattern, pattern2, verbose); break; case 'o': - success = listOpFamilyOperators(pattern, pattern2, show_verbose); + success = listOpFamilyOperators(pattern, pattern2, verbose); break; case 'p': - success = listOpFamilyFunctions(pattern, pattern2, show_verbose); + success = listOpFamilyFunctions(pattern, pattern2, verbose); break; default: status = PSQL_CMD_UNKNOWN; @@ -768,16 +766,16 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) } break; case 'a': - success = describeAggregates(pattern, show_verbose, show_system); + success = describeAggregates(pattern, verbose, show_system); break; case 'b': success = describeTablespaces(pattern, verbose); break; case 'c': - success = listConversions(pattern, show_verbose, show_system); + success = listConversions(pattern, verbose, show_system); break; case 'C': - success = listCasts(pattern, show_verbose); + success = listCasts(pattern, verbose); break; case 'd': if (strncmp(cmd, "ddp", 3) == 0) @@ -786,7 +784,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) success = objectDescription(pattern, show_system); break; case 'D': - success = listDomains(pattern, show_verbose, show_system); + success = listDomains(pattern, verbose, show_system); break; case 'f': /* function subsystem */ switch (cmd[2]) @@ -800,7 +798,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) case 't': case 'w': success = exec_command_dfo(scan_state, cmd, pattern, - show_verbose, show_system); + verbose, show_system); break; default: status = PSQL_CMD_UNKNOWN; @@ -809,23 +807,23 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) break; case 'g': /* no longer distinct from \du */ - success = describeRoles(pattern, show_verbose, show_system); + success = describeRoles(pattern, verbose, show_system); break; case 'l': success = do_lo_list(); break; case 'L': - success = listLanguages(pattern, show_verbose, show_system); + success = listLanguages(pattern, verbose, show_system); break; case 'n': success = listSchemas(pattern, verbose, show_system); break; case 'o': success = exec_command_dfo(scan_state, cmd, pattern, - show_verbose, show_system); + verbose, show_system); break; case 'O': - success = listCollations(pattern, show_verbose, show_system); + success = listCollations(pattern, verbose, show_system); break; case 'p': success = permissionsList(pattern); @@ -839,7 +837,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) case 't': case 'i': case 'n': - success = listPartitionedTables(&cmd[2], pattern, show_verbose); + success = listPartitionedTables(&cmd[2], pattern, verbose); break; default: status = PSQL_CMD_UNKNOWN; @@ -848,7 +846,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) } break; case 'T': - success = describeTypes(pattern, show_verbose, show_system); + success = describeTypes(pattern, verbose, show_system); break; case 't': case 'v': @@ -856,7 +854,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) case 'i': case 's': case 'E': - success = listTables(&cmd[1], pattern, show_verbose, show_system); + success = listTables(&cmd[1], pattern, verbose, show_system); break; case 'r': if (cmd[2] == 'd' && cmd[3] == 's') @@ -878,36 +876,36 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) switch (cmd[2]) { case 'p': - if (show_verbose) + if (verbose > 0) success = describePublications(pattern); else success = listPublications(pattern); break; case 's': - success = describeSubscriptions(pattern, show_verbose); + success = describeSubscriptions(pattern, verbose); break; default: status = PSQL_CMD_UNKNOWN; } break; case 'u': - success = describeRoles(pattern, show_verbose, show_system); + success = describeRoles(pattern, verbose, show_system); break; case 'F': /* text search subsystem */ switch (cmd[2]) { case '\0': case '+': - success = listTSConfigs(pattern, show_verbose); + success = listTSConfigs(pattern, verbose); break; case 'p': - success = listTSParsers(pattern, show_verbose); + success = listTSParsers(pattern, verbose); break; case 'd': - success = listTSDictionaries(pattern, show_verbose); + success = listTSDictionaries(pattern, verbose); break; case 't': - success = listTSTemplates(pattern, show_verbose); + success = listTSTemplates(pattern, verbose); break; default: status = PSQL_CMD_UNKNOWN; @@ -918,16 +916,16 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) switch (cmd[2]) { case 's': - success = listForeignServers(pattern, show_verbose); + success = listForeignServers(pattern, verbose); break; case 'u': - success = listUserMappings(pattern, show_verbose); + success = listUserMappings(pattern, verbose); break; case 'w': - success = listForeignDataWrappers(pattern, show_verbose); + success = listForeignDataWrappers(pattern, verbose); break; case 't': - success = listForeignTables(pattern, show_verbose); + success = listForeignTables(pattern, verbose); break; default: status = PSQL_CMD_UNKNOWN; @@ -935,7 +933,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) } break; case 'x': /* Extensions */ - if (show_verbose) + if (verbose > 0) success = listExtensionContents(pattern); else success = listExtensions(pattern); @@ -944,7 +942,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) success = listExtendedStats(pattern); break; case 'y': /* Event Triggers */ - success = listEventTriggers(pattern, show_verbose); + success = listEventTriggers(pattern, verbose); break; default: status = PSQL_CMD_UNKNOWN; @@ -966,7 +964,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) static bool exec_command_dfo(PsqlScanState scan_state, const char *cmd, const char *pattern, - bool show_verbose, bool show_system) + int verbose, bool show_system) { bool success; char *arg_patterns[FUNC_MAX_ARGS]; @@ -989,11 +987,11 @@ exec_command_dfo(PsqlScanState scan_state, const char *cmd, if (cmd[1] == 'f') success = describeFunctions(&cmd[2], pattern, arg_patterns, num_arg_patterns, - show_verbose, show_system); + verbose, show_system); else success = describeOperators(pattern, arg_patterns, num_arg_patterns, - show_verbose, show_system); + verbose, show_system); while (--num_arg_patterns >= 0) free(arg_patterns[num_arg_patterns]); diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c index ce04dbb9ce..d6e3fee154 100644 --- a/src/bin/psql/describe.c +++ b/src/bin/psql/describe.c @@ -32,7 +32,7 @@ static const char *map_typename_pattern(const char *pattern); static bool describeOneTableDetails(const char *schemaname, const char *relationname, const char *oid, - bool verbose); + int verbose); static void add_tablespace_footer(printTableContent *const cont, char relkind, Oid tablespace, const bool newline); static void add_role_attribute(PQExpBuffer buf, const char *const str); @@ -61,7 +61,7 @@ static bool listOneExtensionContents(const char *extname, const char *oid); * Takes an optional regexp to select particular aggregates */ bool -describeAggregates(const char *pattern, bool verbose, bool showSystem) +describeAggregates(const char *pattern, int verbose, bool showSystem) { PQExpBufferData buf; PGresult *res; @@ -177,7 +177,7 @@ describeAccessMethods(const char *pattern, int verbose) gettext_noop("Table"), gettext_noop("Type")); - if (verbose) + if (verbose > 0) { appendPQExpBuffer(&buf, ",\n amhandler AS \"%s\",\n" @@ -257,13 +257,13 @@ describeTablespaces(const char *pattern, int verbose) gettext_noop("Owner"), gettext_noop("Location")); - if (verbose) + if (verbose > 0) { appendPQExpBufferStr(&buf, ",\n "); printACLColumn(&buf, "spcacl"); } - if (verbose && pset.sversion >= 90000) + if (verbose > 0 && pset.sversion >= 90000) appendPQExpBuffer(&buf, ",\n spcoptions AS \"%s\"", gettext_noop("Options")); @@ -273,7 +273,7 @@ describeTablespaces(const char *pattern, int verbose) ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_tablespace_size(oid)) AS \"%s\"", gettext_noop("Size")); - if (verbose && pset.sversion >= 80200) + if (verbose > 0 && pset.sversion >= 80200) appendPQExpBuffer(&buf, ",\n pg_catalog.shobj_description(oid, 'pg_tablespace') AS \"%s\"", gettext_noop("Description")); @@ -320,7 +320,7 @@ describeTablespaces(const char *pattern, int verbose) bool describeFunctions(const char *functypes, const char *func_pattern, char **arg_patterns, int num_arg_patterns, - bool verbose, bool showSystem) + int verbose, bool showSystem) { bool showAggregate = strchr(functypes, 'a') != NULL; bool showNormal = strchr(functypes, 'n') != NULL; @@ -480,7 +480,7 @@ describeFunctions(const char *functypes, const char *func_pattern, gettext_noop("func"), gettext_noop("Type")); - if (verbose) + if (verbose > 0) { appendPQExpBuffer(&buf, ",\n CASE\n" @@ -540,7 +540,7 @@ describeFunctions(const char *functypes, const char *func_pattern, i, i, i, i, i, i); } - if (verbose) + if (verbose > 0) appendPQExpBufferStr(&buf, " LEFT JOIN pg_catalog.pg_language l ON l.oid = p.prolang\n"); @@ -719,7 +719,7 @@ describeFunctions(const char *functypes, const char *func_pattern, * describe types */ bool -describeTypes(const char *pattern, bool verbose, bool showSystem) +describeTypes(const char *pattern, int verbose, bool showSystem) { PQExpBufferData buf; PGresult *res; @@ -732,7 +732,7 @@ describeTypes(const char *pattern, bool verbose, bool showSystem) " pg_catalog.format_type(t.oid, NULL) AS \"%s\",\n", gettext_noop("Schema"), gettext_noop("Name")); - if (verbose) + if (verbose > 0) appendPQExpBuffer(&buf, " t.typname AS \"%s\",\n" " CASE WHEN t.typrelid != 0\n" @@ -743,7 +743,7 @@ describeTypes(const char *pattern, bool verbose, bool showSystem) " END AS \"%s\",\n", gettext_noop("Internal name"), gettext_noop("Size")); - if (verbose && pset.sversion >= 80300) + if (verbose > 0 && pset.sversion >= 80300) { appendPQExpBufferStr(&buf, " pg_catalog.array_to_string(\n" @@ -765,13 +765,13 @@ describeTypes(const char *pattern, bool verbose, bool showSystem) " ) AS \"%s\",\n", gettext_noop("Elements")); } - if (verbose) + if (verbose > 0) { appendPQExpBuffer(&buf, " pg_catalog.pg_get_userbyid(t.typowner) AS \"%s\",\n", gettext_noop("Owner")); } - if (verbose && pset.sversion >= 90200) + if (verbose > 0 && pset.sversion >= 90200) { printACLColumn(&buf, "t.typacl"); appendPQExpBufferStr(&buf, ",\n "); @@ -895,7 +895,7 @@ map_typename_pattern(const char *pattern) bool describeOperators(const char *oper_pattern, char **arg_patterns, int num_arg_patterns, - bool verbose, bool showSystem) + int verbose, bool showSystem) { PQExpBufferData buf; PGresult *res; @@ -932,7 +932,7 @@ describeOperators(const char *oper_pattern, gettext_noop("Right arg type"), gettext_noop("Result type")); - if (verbose) + if (verbose > 0) appendPQExpBuffer(&buf, " o.oprcode AS \"%s\",\n", gettext_noop("Function")); @@ -1058,17 +1058,17 @@ listAllDbs(const char *pattern, int verbose) " ELSE 'No Access'\n" " END as \"%s\"", gettext_noop("Size")); - if (verbose && pset.sversion >= 80000) + if (verbose > 0 && pset.sversion >= 80000) appendPQExpBuffer(&buf, ",\n t.spcname as \"%s\"", gettext_noop("Tablespace")); - if (verbose && pset.sversion >= 80200) + if (verbose > 0 && pset.sversion >= 80200) appendPQExpBuffer(&buf, ",\n pg_catalog.shobj_description(d.oid, 'pg_database') as \"%s\"", gettext_noop("Description")); appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_database d\n"); - if (verbose && pset.sversion >= 80000) + if (verbose > 0 && pset.sversion >= 80000) appendPQExpBufferStr(&buf, " JOIN pg_catalog.pg_tablespace t on d.dattablespace = t.oid\n"); @@ -1532,10 +1532,10 @@ objectDescription(const char *pattern, bool showSystem) * This routine finds the tables to be displayed, and calls * describeOneTableDetails for each one. * - * verbose: if true, this is \d+ + * verbose: this is \d+ (or \d++) */ bool -describeTableDetails(const char *pattern, bool verbose, bool showSystem) +describeTableDetails(const char *pattern, int verbose, bool showSystem) { PQExpBufferData buf; PGresult *res; @@ -1616,7 +1616,7 @@ static bool describeOneTableDetails(const char *schemaname, const char *relationname, const char *oid, - bool verbose) + int verbose) { bool retval = false; PQExpBufferData buf; @@ -2055,7 +2055,7 @@ describeOneTableDetails(const char *schemaname, " pg_catalog.pg_options_to_table(attfdwoptions)), ', ') || ')' END AS attfdwoptions"); fdwopts_col = cols++; } - if (verbose) + if (verbose > 0) { appendPQExpBufferStr(&buf, ",\n a.attstorage"); attstorage_col = cols++; @@ -2318,7 +2318,7 @@ describeOneTableDetails(const char *schemaname, "false as inhdetachpending"); /* If verbose, also request the partition constraint definition */ - if (verbose) + if (verbose > 0) appendPQExpBufferStr(&buf, ",\n pg_catalog.pg_get_partition_constraintdef(c.oid)"); appendPQExpBuffer(&buf, @@ -2341,7 +2341,7 @@ describeOneTableDetails(const char *schemaname, strcmp(detached, "t") == 0 ? " DETACH PENDING" : ""); printTableAddFooter(&cont, tmpbuf.data); - if (verbose) + if (verbose > 0) { char *partconstraintdef = NULL; @@ -3548,7 +3548,7 @@ describeOneTableDetails(const char *schemaname, printfPQExpBuffer(&buf, _("Number of partitions: %d"), tuples); printTableAddFooter(&cont, buf.data); } - else if (!verbose) + else if (verbose == 0) { /* print the number of child tables, if any */ if (tuples > 0) @@ -3598,7 +3598,7 @@ describeOneTableDetails(const char *schemaname, printTableAddFooter(&cont, buf.data); } - if (verbose && + if (verbose > 0 && (tableinfo.relkind == RELKIND_RELATION || tableinfo.relkind == RELKIND_MATVIEW) && @@ -3622,7 +3622,7 @@ describeOneTableDetails(const char *schemaname, } /* OIDs, if verbose and not a materialized view */ - if (verbose && tableinfo.relkind != RELKIND_MATVIEW && tableinfo.hasoids) + if (verbose > 0 && tableinfo.relkind != RELKIND_MATVIEW && tableinfo.hasoids) printTableAddFooter(&cont, _("Has OIDs: yes")); /* Tablespace info */ @@ -3630,7 +3630,7 @@ describeOneTableDetails(const char *schemaname, true); /* Access method info */ - if (verbose && tableinfo.relam != NULL && !pset.hide_tableam) + if (verbose > 0 && tableinfo.relam != NULL && !pset.hide_tableam) { printfPQExpBuffer(&buf, _("Access method: %s"), tableinfo.relam); printTableAddFooter(&cont, buf.data); @@ -3638,7 +3638,7 @@ describeOneTableDetails(const char *schemaname, } /* reloptions, if verbose */ - if (verbose && + if (verbose > 0 && tableinfo.reloptions && tableinfo.reloptions[0] != '\0') { const char *t = _("Options"); @@ -3741,7 +3741,7 @@ add_tablespace_footer(printTableContent *const cont, char relkind, * Describes roles. Any schema portion of the pattern is ignored. */ bool -describeRoles(const char *pattern, bool verbose, bool showSystem) +describeRoles(const char *pattern, int verbose, bool showSystem) { PQExpBufferData buf; PGresult *res; @@ -3769,7 +3769,7 @@ describeRoles(const char *pattern, bool verbose, bool showSystem) " JOIN pg_catalog.pg_roles b ON (m.roleid = b.oid)\n" " WHERE m.member = r.oid) as memberof"); - if (verbose && pset.sversion >= 80200) + if (verbose > 0 && pset.sversion >= 80200) { appendPQExpBufferStr(&buf, "\n, pg_catalog.shobj_description(r.oid, 'pg_authid') AS description"); ncols++; @@ -3824,7 +3824,7 @@ describeRoles(const char *pattern, bool verbose, bool showSystem) /* ignores implicit memberships from superuser & pg_database_owner */ printTableAddHeader(&cont, gettext_noop("Member of"), true, align); - if (verbose && pset.sversion >= 80200) + if (verbose > 0 && pset.sversion >= 80200) printTableAddHeader(&cont, gettext_noop("Description"), true, align); for (i = 0; i < nrows; i++) @@ -3884,7 +3884,7 @@ describeRoles(const char *pattern, bool verbose, bool showSystem) printTableAddCell(&cont, PQgetvalue(res, i, 8), false, false); - if (verbose && pset.sversion >= 80200) + if (verbose > 0 && pset.sversion >= 80200) printTableAddCell(&cont, PQgetvalue(res, i, 9), false, false); } termPQExpBuffer(&buf); @@ -3997,7 +3997,7 @@ listDbRoleSettings(const char *pattern, const char *pattern2) * (any order of the above is fine) */ bool -listTables(const char *tabtypes, const char *pattern, bool verbose, bool showSystem) +listTables(const char *tabtypes, const char *pattern, int verbose, bool showSystem) { bool showTables = strchr(tabtypes, 't') != NULL; bool showIndexes = strchr(tabtypes, 'i') != NULL; @@ -4062,7 +4062,7 @@ listTables(const char *tabtypes, const char *pattern, bool verbose, bool showSys cols_so_far++; } - if (verbose) + if (verbose > 0) { /* * Show whether a relation is permanent, temporary, or unlogged. Like @@ -4213,7 +4213,7 @@ listTables(const char *tabtypes, const char *pattern, bool verbose, bool showSys * and you can mix and match these in any order. */ bool -listPartitionedTables(const char *reltypes, const char *pattern, bool verbose) +listPartitionedTables(const char *reltypes, const char *pattern, int verbose) { bool showTables = strchr(reltypes, 't') != NULL; bool showIndexes = strchr(reltypes, 'i') != NULL; @@ -4288,7 +4288,7 @@ listPartitionedTables(const char *reltypes, const char *pattern, bool verbose) ",\n c2.oid::regclass as \"%s\"", gettext_noop("Table")); - if (verbose) + if (verbose > 0) { if (showNested) { @@ -4323,7 +4323,7 @@ listPartitionedTables(const char *reltypes, const char *pattern, bool verbose) appendPQExpBufferStr(&buf, "\n LEFT JOIN pg_catalog.pg_inherits inh ON c.oid = inh.inhrelid"); - if (verbose) + if (verbose > 0) { if (pset.sversion < 120000) { @@ -4409,7 +4409,7 @@ listPartitionedTables(const char *reltypes, const char *pattern, bool verbose) * Describes languages. */ bool -listLanguages(const char *pattern, bool verbose, bool showSystem) +listLanguages(const char *pattern, int verbose, bool showSystem) { PQExpBufferData buf; PGresult *res; @@ -4429,7 +4429,7 @@ listLanguages(const char *pattern, bool verbose, bool showSystem) " l.lanpltrusted AS \"%s\"", gettext_noop("Trusted")); - if (verbose) + if (verbose > 0) { appendPQExpBuffer(&buf, ",\n NOT l.lanispl AS \"%s\",\n" @@ -4484,7 +4484,7 @@ listLanguages(const char *pattern, bool verbose, bool showSystem) * Describes domains. */ bool -listDomains(const char *pattern, bool verbose, bool showSystem) +listDomains(const char *pattern, int verbose, bool showSystem) { PQExpBufferData buf; PGresult *res; @@ -4515,7 +4515,7 @@ listDomains(const char *pattern, bool verbose, bool showSystem) gettext_noop("Default"), gettext_noop("Check")); - if (verbose) + if (verbose > 0) { if (pset.sversion >= 90200) { @@ -4531,7 +4531,7 @@ listDomains(const char *pattern, bool verbose, bool showSystem) "\nFROM pg_catalog.pg_type t\n" " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace\n"); - if (verbose) + if (verbose > 0) appendPQExpBufferStr(&buf, " LEFT JOIN pg_catalog.pg_description d " "ON d.classoid = t.tableoid AND d.objoid = t.oid " @@ -4570,7 +4570,7 @@ listDomains(const char *pattern, bool verbose, bool showSystem) * Describes conversions. */ bool -listConversions(const char *pattern, bool verbose, bool showSystem) +listConversions(const char *pattern, int verbose, bool showSystem) { PQExpBufferData buf; PGresult *res; @@ -4594,7 +4594,7 @@ listConversions(const char *pattern, bool verbose, bool showSystem) gettext_noop("yes"), gettext_noop("no"), gettext_noop("Default?")); - if (verbose) + if (verbose > 0) appendPQExpBuffer(&buf, ",\n d.description AS \"%s\"", gettext_noop("Description")); @@ -4604,7 +4604,7 @@ listConversions(const char *pattern, bool verbose, bool showSystem) " JOIN pg_catalog.pg_namespace n " "ON n.oid = c.connamespace\n"); - if (verbose) + if (verbose > 0) appendPQExpBufferStr(&buf, "LEFT JOIN pg_catalog.pg_description d " "ON d.classoid = c.tableoid\n" @@ -4646,7 +4646,7 @@ listConversions(const char *pattern, bool verbose, bool showSystem) * Describes Event Triggers. */ bool -listEventTriggers(const char *pattern, bool verbose) +listEventTriggers(const char *pattern, int verbose) { PQExpBufferData buf; PGresult *res; @@ -4677,7 +4677,7 @@ listEventTriggers(const char *pattern, bool verbose) gettext_noop("Enabled"), gettext_noop("Function"), gettext_noop("Tags")); - if (verbose) + if (verbose > 0) appendPQExpBuffer(&buf, ",\npg_catalog.obj_description(e.oid, 'pg_event_trigger') as \"%s\"", gettext_noop("Description")); @@ -4804,7 +4804,7 @@ listExtendedStats(const char *pattern) * Describes casts. */ bool -listCasts(const char *pattern, bool verbose) +listCasts(const char *pattern, int verbose) { PQExpBufferData buf; PGresult *res; @@ -4852,7 +4852,7 @@ listCasts(const char *pattern, bool verbose) gettext_noop("yes"), gettext_noop("Implicit?")); - if (verbose) + if (verbose > 0) appendPQExpBuffer(&buf, ",\n d.description AS \"%s\"", gettext_noop("Description")); @@ -4873,7 +4873,7 @@ listCasts(const char *pattern, bool verbose) " LEFT JOIN pg_catalog.pg_namespace nt\n" " ON nt.oid = tt.typnamespace\n"); - if (verbose) + if (verbose > 0) appendPQExpBufferStr(&buf, " LEFT JOIN pg_catalog.pg_description d\n" " ON d.classoid = c.tableoid AND d.objoid = " @@ -4922,7 +4922,7 @@ listCasts(const char *pattern, bool verbose) * Describes collations. */ bool -listCollations(const char *pattern, bool verbose, bool showSystem) +listCollations(const char *pattern, int verbose, bool showSystem) { PQExpBufferData buf; PGresult *res; @@ -4971,7 +4971,7 @@ listCollations(const char *pattern, bool verbose, bool showSystem) gettext_noop("yes"), gettext_noop("Deterministic?")); - if (verbose) + if (verbose > 0) appendPQExpBuffer(&buf, ",\n pg_catalog.obj_description(c.oid, 'pg_collation') AS \"%s\"", gettext_noop("Description")); @@ -5034,7 +5034,7 @@ listSchemas(const char *pattern, int verbose, bool showSystem) gettext_noop("Name"), gettext_noop("Owner")); - if (verbose) + if (verbose > 0) { appendPQExpBufferStr(&buf, ",\n "); printACLColumn(&buf, "n.nspacl"); @@ -5083,7 +5083,7 @@ listSchemas(const char *pattern, int verbose, bool showSystem) * list text search parsers */ bool -listTSParsers(const char *pattern, bool verbose) +listTSParsers(const char *pattern, int verbose) { PQExpBufferData buf; PGresult *res; @@ -5099,7 +5099,7 @@ listTSParsers(const char *pattern, bool verbose) return true; } - if (verbose) + if (verbose > 0) return listTSParsersVerbose(pattern); initPQExpBuffer(&buf); @@ -5330,7 +5330,7 @@ describeOneTSParser(const char *oid, const char *nspname, const char *prsname) * list text search dictionaries */ bool -listTSDictionaries(const char *pattern, bool verbose) +listTSDictionaries(const char *pattern, int verbose) { PQExpBufferData buf; PGresult *res; @@ -5355,7 +5355,7 @@ listTSDictionaries(const char *pattern, bool verbose) gettext_noop("Schema"), gettext_noop("Name")); - if (verbose) + if (verbose > 0) { appendPQExpBuffer(&buf, " ( SELECT COALESCE(nt.nspname, '(null)')::pg_catalog.text || '.' || t.tmplname FROM\n" @@ -5401,7 +5401,7 @@ listTSDictionaries(const char *pattern, bool verbose) * list text search templates */ bool -listTSTemplates(const char *pattern, bool verbose) +listTSTemplates(const char *pattern, int verbose) { PQExpBufferData buf; PGresult *res; @@ -5419,7 +5419,7 @@ listTSTemplates(const char *pattern, bool verbose) initPQExpBuffer(&buf); - if (verbose) + if (verbose > 0) printfPQExpBuffer(&buf, "SELECT\n" " n.nspname AS \"%s\",\n" @@ -5472,7 +5472,7 @@ listTSTemplates(const char *pattern, bool verbose) * list text search configurations */ bool -listTSConfigs(const char *pattern, bool verbose) +listTSConfigs(const char *pattern, int verbose) { PQExpBufferData buf; PGresult *res; @@ -5488,7 +5488,7 @@ listTSConfigs(const char *pattern, bool verbose) return true; } - if (verbose) + if (verbose > 0) return listTSConfigsVerbose(pattern); initPQExpBuffer(&buf); @@ -5678,7 +5678,7 @@ describeOneTSConfig(const char *oid, const char *nspname, const char *cfgname, * Describes foreign-data wrappers */ bool -listForeignDataWrappers(const char *pattern, bool verbose) +listForeignDataWrappers(const char *pattern, int verbose) { PQExpBufferData buf; PGresult *res; @@ -5708,7 +5708,7 @@ listForeignDataWrappers(const char *pattern, bool verbose) " fdw.fdwvalidator::pg_catalog.regproc AS \"%s\"", gettext_noop("Validator")); - if (verbose) + if (verbose > 0) { appendPQExpBufferStr(&buf, ",\n "); printACLColumn(&buf, "fdwacl"); @@ -5729,7 +5729,7 @@ listForeignDataWrappers(const char *pattern, bool verbose) appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_foreign_data_wrapper fdw\n"); - if (verbose && pset.sversion >= 90100) + if (verbose > 0 && pset.sversion >= 90100) appendPQExpBufferStr(&buf, "LEFT JOIN pg_catalog.pg_description d\n" " ON d.classoid = fdw.tableoid " @@ -5761,7 +5761,7 @@ listForeignDataWrappers(const char *pattern, bool verbose) * Describes foreign servers. */ bool -listForeignServers(const char *pattern, bool verbose) +listForeignServers(const char *pattern, int verbose) { PQExpBufferData buf; PGresult *res; @@ -5786,7 +5786,7 @@ listForeignServers(const char *pattern, bool verbose) gettext_noop("Owner"), gettext_noop("Foreign-data wrapper")); - if (verbose) + if (verbose > 0) { appendPQExpBufferStr(&buf, ",\n "); printACLColumn(&buf, "s.srvacl"); @@ -5811,7 +5811,7 @@ listForeignServers(const char *pattern, bool verbose) "\nFROM pg_catalog.pg_foreign_server s\n" " JOIN pg_catalog.pg_foreign_data_wrapper f ON f.oid=s.srvfdw\n"); - if (verbose) + if (verbose > 0) appendPQExpBufferStr(&buf, "LEFT JOIN pg_catalog.pg_description d\n " "ON d.classoid = s.tableoid AND d.objoid = s.oid " @@ -5843,7 +5843,7 @@ listForeignServers(const char *pattern, bool verbose) * Describes user mappings. */ bool -listUserMappings(const char *pattern, bool verbose) +listUserMappings(const char *pattern, int verbose) { PQExpBufferData buf; PGresult *res; @@ -5866,7 +5866,7 @@ listUserMappings(const char *pattern, bool verbose) gettext_noop("Server"), gettext_noop("User name")); - if (verbose) + if (verbose > 0) appendPQExpBuffer(&buf, ",\n CASE WHEN umoptions IS NULL THEN '' ELSE " " '(' || pg_catalog.array_to_string(ARRAY(SELECT " @@ -5904,7 +5904,7 @@ listUserMappings(const char *pattern, bool verbose) * Describes foreign tables. */ bool -listForeignTables(const char *pattern, bool verbose) +listForeignTables(const char *pattern, int verbose) { PQExpBufferData buf; PGresult *res; @@ -5929,7 +5929,7 @@ listForeignTables(const char *pattern, bool verbose) gettext_noop("Table"), gettext_noop("Server")); - if (verbose) + if (verbose > 0) appendPQExpBuffer(&buf, ",\n CASE WHEN ftoptions IS NULL THEN '' ELSE " " '(' || pg_catalog.array_to_string(ARRAY(SELECT " @@ -5949,7 +5949,7 @@ listForeignTables(const char *pattern, bool verbose) " ON n.oid = c.relnamespace\n" " INNER JOIN pg_catalog.pg_foreign_server s" " ON s.oid = ft.ftserver\n"); - if (verbose) + if (verbose > 0) appendPQExpBufferStr(&buf, " LEFT JOIN pg_catalog.pg_description d\n" " ON d.classoid = c.tableoid AND " @@ -6393,7 +6393,7 @@ describePublications(const char *pattern) * Takes an optional regexp to select particular subscriptions */ bool -describeSubscriptions(const char *pattern, bool verbose) +describeSubscriptions(const char *pattern, int verbose) { PQExpBufferData buf; PGresult *res; @@ -6423,7 +6423,7 @@ describeSubscriptions(const char *pattern, bool verbose) gettext_noop("Enabled"), gettext_noop("Publication")); - if (verbose) + if (verbose > 0) { /* Binary mode and streaming are only supported in v14 and higher */ if (pset.sversion >= 140000) @@ -6504,7 +6504,7 @@ printACLColumn(PQExpBuffer buf, const char *colname) */ bool listOperatorClasses(const char *access_method_pattern, - const char *type_pattern, bool verbose) + const char *type_pattern, int verbose) { PQExpBufferData buf; PGresult *res; @@ -6539,7 +6539,7 @@ listOperatorClasses(const char *access_method_pattern, gettext_noop("yes"), gettext_noop("no"), gettext_noop("Default?")); - if (verbose) + if (verbose > 0) appendPQExpBuffer(&buf, ",\n CASE\n" " WHEN pg_catalog.pg_opfamily_is_visible(of.oid)\n" @@ -6555,7 +6555,7 @@ listOperatorClasses(const char *access_method_pattern, " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.opcnamespace\n" " LEFT JOIN pg_catalog.pg_type t ON t.oid = c.opcintype\n" " LEFT JOIN pg_catalog.pg_namespace tn ON tn.oid = t.typnamespace\n"); - if (verbose) + if (verbose > 0) appendPQExpBufferStr(&buf, " LEFT JOIN pg_catalog.pg_opfamily of ON of.oid = c.opcfamily\n" " LEFT JOIN pg_catalog.pg_namespace ofn ON ofn.oid = of.opfnamespace\n"); @@ -6598,7 +6598,7 @@ listOperatorClasses(const char *access_method_pattern, */ bool listOperatorFamilies(const char *access_method_pattern, - const char *type_pattern, bool verbose) + const char *type_pattern, int verbose) { PQExpBufferData buf; PGresult *res; @@ -6623,7 +6623,7 @@ listOperatorFamilies(const char *access_method_pattern, gettext_noop("AM"), gettext_noop("Operator family"), gettext_noop("Applicable types")); - if (verbose) + if (verbose > 0) appendPQExpBuffer(&buf, ",\n pg_catalog.pg_get_userbyid(f.opfowner) AS \"%s\"\n", gettext_noop("Owner")); @@ -6680,7 +6680,7 @@ listOperatorFamilies(const char *access_method_pattern, */ bool listOpFamilyOperators(const char *access_method_pattern, - const char *family_pattern, bool verbose) + const char *family_pattern, int verbose) { PQExpBufferData buf; PGresult *res; @@ -6713,7 +6713,7 @@ listOpFamilyOperators(const char *access_method_pattern, gettext_noop("search"), gettext_noop("Purpose")); - if (verbose) + if (verbose > 0) appendPQExpBuffer(&buf, ", ofs.opfname AS \"%s\"\n", gettext_noop("Sort opfamily")); @@ -6722,7 +6722,7 @@ listOpFamilyOperators(const char *access_method_pattern, " LEFT JOIN pg_catalog.pg_opfamily of ON of.oid = o.amopfamily\n" " LEFT JOIN pg_catalog.pg_am am ON am.oid = of.opfmethod AND am.oid = o.amopmethod\n" " LEFT JOIN pg_catalog.pg_namespace nsf ON of.opfnamespace = nsf.oid\n"); - if (verbose) + if (verbose > 0) appendPQExpBufferStr(&buf, " LEFT JOIN pg_catalog.pg_opfamily ofs ON ofs.oid = o.amopsortfamily\n"); @@ -6767,7 +6767,7 @@ listOpFamilyOperators(const char *access_method_pattern, */ bool listOpFamilyFunctions(const char *access_method_pattern, - const char *family_pattern, bool verbose) + const char *family_pattern, int verbose) { PQExpBufferData buf; PGresult *res; @@ -6794,7 +6794,7 @@ listOpFamilyFunctions(const char *access_method_pattern, gettext_noop("Registered right type"), gettext_noop("Number")); - if (!verbose) + if (verbose == 0) appendPQExpBuffer(&buf, ", p.proname AS \"%s\"\n", gettext_noop("Function")); diff --git a/src/bin/psql/describe.h b/src/bin/psql/describe.h index edeea38580..cdf286242b 100644 --- a/src/bin/psql/describe.h +++ b/src/bin/psql/describe.h @@ -10,7 +10,7 @@ /* \da */ -extern bool describeAggregates(const char *pattern, bool verbose, bool showSystem); +extern bool describeAggregates(const char *pattern, int verbose, bool showSystem); /* \dA */ extern bool describeAccessMethods(const char *pattern, int verbose); @@ -21,18 +21,18 @@ extern bool describeTablespaces(const char *pattern, int verbose); /* \df, \dfa, \dfn, \dft, \dfw, etc. */ extern bool describeFunctions(const char *functypes, const char *func_pattern, char **arg_patterns, int num_arg_patterns, - bool verbose, bool showSystem); + int verbose, bool showSystem); /* \dT */ -extern bool describeTypes(const char *pattern, bool verbose, bool showSystem); +extern bool describeTypes(const char *pattern, int verbose, bool showSystem); /* \do */ extern bool describeOperators(const char *oper_pattern, char **arg_patterns, int num_arg_patterns, - bool verbose, bool showSystem); + int verbose, bool showSystem); /* \du, \dg */ -extern bool describeRoles(const char *pattern, bool verbose, bool showSystem); +extern bool describeRoles(const char *pattern, int verbose, bool showSystem); /* \drds */ extern bool listDbRoleSettings(const char *pattern, const char *pattern2); @@ -47,58 +47,58 @@ extern bool listDefaultACLs(const char *pattern); extern bool objectDescription(const char *pattern, bool showSystem); /* \d foo */ -extern bool describeTableDetails(const char *pattern, bool verbose, bool showSystem); +extern bool describeTableDetails(const char *pattern, int verbose, bool showSystem); /* \dF */ -extern bool listTSConfigs(const char *pattern, bool verbose); +extern bool listTSConfigs(const char *pattern, int verbose); /* \dFp */ -extern bool listTSParsers(const char *pattern, bool verbose); +extern bool listTSParsers(const char *pattern, int verbose); /* \dFd */ -extern bool listTSDictionaries(const char *pattern, bool verbose); +extern bool listTSDictionaries(const char *pattern, int verbose); /* \dFt */ -extern bool listTSTemplates(const char *pattern, bool verbose); +extern bool listTSTemplates(const char *pattern, int verbose); /* \l */ extern bool listAllDbs(const char *pattern, int verbose); /* \dt, \di, \ds, \dS, etc. */ -extern bool listTables(const char *tabtypes, const char *pattern, bool verbose, bool showSystem); +extern bool listTables(const char *tabtypes, const char *pattern, int verbose, bool showSystem); /* \dP */ -extern bool listPartitionedTables(const char *reltypes, const char *pattern, bool verbose); +extern bool listPartitionedTables(const char *reltypes, const char *pattern, int verbose); /* \dD */ -extern bool listDomains(const char *pattern, bool verbose, bool showSystem); +extern bool listDomains(const char *pattern, int verbose, bool showSystem); /* \dc */ -extern bool listConversions(const char *pattern, bool verbose, bool showSystem); +extern bool listConversions(const char *pattern, int verbose, bool showSystem); /* \dC */ -extern bool listCasts(const char *pattern, bool verbose); +extern bool listCasts(const char *pattern, int verbose); /* \dO */ -extern bool listCollations(const char *pattern, bool verbose, bool showSystem); +extern bool listCollations(const char *pattern, int verbose, bool showSystem); /* \dn */ extern bool listSchemas(const char *pattern, int verbose, bool showSystem); /* \dew */ -extern bool listForeignDataWrappers(const char *pattern, bool verbose); +extern bool listForeignDataWrappers(const char *pattern, int verbose); /* \des */ -extern bool listForeignServers(const char *pattern, bool verbose); +extern bool listForeignServers(const char *pattern, int verbose); /* \deu */ -extern bool listUserMappings(const char *pattern, bool verbose); +extern bool listUserMappings(const char *pattern, int verbose); /* \det */ -extern bool listForeignTables(const char *pattern, bool verbose); +extern bool listForeignTables(const char *pattern, int verbose); /* \dL */ -extern bool listLanguages(const char *pattern, bool verbose, bool showSystem); +extern bool listLanguages(const char *pattern, int verbose, bool showSystem); /* \dx */ extern bool listExtensions(const char *pattern); @@ -110,7 +110,7 @@ extern bool listExtensionContents(const char *pattern); extern bool listExtendedStats(const char *pattern); /* \dy */ -extern bool listEventTriggers(const char *pattern, bool verbose); +extern bool listEventTriggers(const char *pattern, int verbose); /* \dRp */ bool listPublications(const char *pattern); @@ -119,25 +119,25 @@ bool listPublications(const char *pattern); bool describePublications(const char *pattern); /* \dRs */ -bool describeSubscriptions(const char *pattern, bool verbose); +bool describeSubscriptions(const char *pattern, int verbose); /* \dAc */ extern bool listOperatorClasses(const char *access_method_pattern, const char *opclass_pattern, - bool verbose); + int verbose); /* \dAf */ extern bool listOperatorFamilies(const char *access_method_pattern, const char *opclass_pattern, - bool verbose); + int verbose); /* \dAo */ extern bool listOpFamilyOperators(const char *accessMethod_pattern, - const char *family_pattern, bool verbose); + const char *family_pattern, int verbose); /* \dAp */ extern bool listOpFamilyFunctions(const char *access_method_pattern, - const char *family_pattern, bool verbose); + const char *family_pattern, int verbose); #endif /* DESCRIBE_H */ -- 2.17.0
v3-0004-Move-the-double-plus-verbose-options-to-the-right.patch (text/x-diff, 2.6K) download From 4dd48f8ce389d176bf153dcfce601558b9e823fb Mon Sep 17 00:00:00 2001 From: Justin Pryzby <pryzbyj@telsasoft.com> Date: Thu, 15 Jul 2021 13:35:26 -0500 Subject: [PATCH v3 4/4] Move the double-plus verbose options to the right-most column --- src/bin/psql/describe.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c index d6e3fee154..2829d3c0f1 100644 --- a/src/bin/psql/describe.c +++ b/src/bin/psql/describe.c @@ -268,16 +268,16 @@ describeTablespaces(const char *pattern, int verbose) ",\n spcoptions AS \"%s\"", gettext_noop("Options")); - if (verbose > 1 && pset.sversion >= 90200) - appendPQExpBuffer(&buf, - ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_tablespace_size(oid)) AS \"%s\"", - gettext_noop("Size")); - if (verbose > 0 && pset.sversion >= 80200) appendPQExpBuffer(&buf, ",\n pg_catalog.shobj_description(oid, 'pg_tablespace') AS \"%s\"", gettext_noop("Description")); + if (verbose > 1 && pset.sversion >= 90200) + appendPQExpBuffer(&buf, + ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_tablespace_size(oid)) AS \"%s\"", + gettext_noop("Size")); + appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_tablespace\n"); @@ -1051,13 +1051,7 @@ listAllDbs(const char *pattern, int verbose) gettext_noop("Ctype")); appendPQExpBufferStr(&buf, " "); printACLColumn(&buf, "d.datacl"); - if (verbose > 1 && pset.sversion >= 80200) - appendPQExpBuffer(&buf, - ",\n CASE WHEN pg_catalog.has_database_privilege(d.datname, 'CONNECT')\n" - " THEN pg_catalog.pg_size_pretty(pg_catalog.pg_database_size(d.datname))\n" - " ELSE 'No Access'\n" - " END as \"%s\"", - gettext_noop("Size")); + if (verbose > 0 && pset.sversion >= 80000) appendPQExpBuffer(&buf, ",\n t.spcname as \"%s\"", @@ -1066,6 +1060,15 @@ listAllDbs(const char *pattern, int verbose) appendPQExpBuffer(&buf, ",\n pg_catalog.shobj_description(d.oid, 'pg_database') as \"%s\"", gettext_noop("Description")); + + if (verbose > 1 && pset.sversion >= 80200) + appendPQExpBuffer(&buf, + ",\n CASE WHEN pg_catalog.has_database_privilege(d.datname, 'CONNECT')\n" + " THEN pg_catalog.pg_size_pretty(pg_catalog.pg_database_size(d.datname))\n" + " ELSE 'No Access'\n" + " END as \"%s\"", + gettext_noop("Size")); + appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_database d\n"); if (verbose > 0 && pset.sversion >= 80000) -- 2.17.0
^ permalink raw reply [nested|flat] 22+ messages in thread

* Re: [PATCH] psql: \dn+ to show size of each schema (and \dA+ for AMs)
@ 2021-07-16 09:10  Laurenz Albe <laurenz.albe@cybertec.at>
  parent: Justin Pryzby <pryzby@telsasoft.com>
  1 sibling, 0 replies; 22+ messages in thread

From: Laurenz Albe @ 2021-07-16 09:10 UTC (permalink / raw)
  To: Justin Pryzby <pryzby@telsasoft.com>; +Cc: Ian Lawrence Barwick <barwick@gmail.com>; pgsql-hackers; gilles@darold.net

On Thu, 2021-07-15 at 20:16 -0500, Justin Pryzby wrote:
> On Wed, Jul 14, 2021 at 07:42:33AM +0200, Laurenz Albe wrote:
> > Besides, schemas are not physical, but logical containers.  So I see a point in
> > measuring the storage used in a certain tablespace, but not so much by all objects
> > in a certain schema.  It might be useful for accounting purposes, though.
> >
> > But I don't expect it to be in frequent enough demand to add a psql command.
> 
> But for "physical" storage it's also possible to get the size from the OS, much
> more efficiently, using /bin/df or zfs list (assuming nothing else is using
> those filesystems).  The pg_*_size functions are inefficient, but psql \db+ and
> \l+ already call them anyway.

Hm, yes, the fact that \l+ does something similar detracts from my argument.
It seems somewhat inconsistent to have the size in \l+, but not in \dn+.

Still, there is a difference: I never need \l+, because \l already shows
the permissions on the database, but I often need \dn+ to see the permissions
on schemas.  And I don't want to measure the size when I do that.

The problem is that our backslash commands are not totally consistent in
that respect, and we can hardly fix that.

Yours,
Laurenz Albe






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

* Re: [PATCH] psql: \dn+ to show size of each schema (and \dA+ for AMs)
@ 2021-09-17 10:05  Pavel Stehule <pavel.stehule@gmail.com>
  parent: Justin Pryzby <pryzby@telsasoft.com>
  1 sibling, 1 reply; 22+ messages in thread

From: Pavel Stehule @ 2021-09-17 10:05 UTC (permalink / raw)
  To: Justin Pryzby <pryzby@telsasoft.com>; +Cc: Laurenz Albe <laurenz.albe@cybertec.at>; Ian Lawrence Barwick <barwick@gmail.com>; pgsql-hackers; Gilles Darold <gilles@darold.net>

pá 17. 9. 2021 v 11:10 odesílatel Justin Pryzby <pryzby@telsasoft.com>
napsal:

> On Wed, Jul 14, 2021 at 07:42:33AM +0200, Laurenz Albe wrote:
> > Besides, schemas are not physical, but logical containers.  So I see a
> point in
> > measuring the storage used in a certain tablespace, but not so much by
> all objects
> > in a certain schema.  It might be useful for accounting purposes, though.
>
> We use only a few schemas, 1) to hide child tables; 2) to exclude some
> extended
> stats from backups, and 1-2 other things.  But it's useful to be able to
> see
> how storage is used by schema, and better to do it conveniently.
>
> I think it'd be even more useful for people who use schemas more widely
> than we
> do:
>     "Who's using all our space?"
>     \dn++
>     "Oh, it's that one - let me clean that up..."
>
> Or, "what's the pg_toast stuff, and do I need to do something about it?"
>
> > But I don't expect it to be in frequent enough demand to add a psql
> command.
> >
> > What about inventing a function pg_schema_size(regnamespace)?
>
> But for "physical" storage it's also possible to get the size from the OS,
> much
> more efficiently, using /bin/df or zfs list (assuming nothing else is using
> those filesystems).  The pg_*_size functions are inefficient, but psql
> \db+ and
> \l+ already call them anyway.
>
> For schemas, there's no way to get the size from the OS, so it's nice to
> make
> the size available from psql, conveniently.
>
> v3 patch:
>  - fixes an off by one in forkNum loop;
>  - removes an unnecessary subquery in describe.c;
>  - returns 0 rather than NULL if the schema is empty;
>  - adds pg_am_size;
>
> regression=# \dA++
>                                   List of access methods
>   Name  | Type  |       Handler        |              Description
>      |  Size
>
> --------+-------+----------------------+----------------------------------------+---------
>  brin   | Index | brinhandler          | block range index (BRIN) access
> method | 744 kB
>  btree  | Index | bthandler            | b-tree index access method
>      | 21 MB
>  gin    | Index | ginhandler           | GIN index access method
>       | 2672 kB
>  gist   | Index | gisthandler          | GiST index access method
>      | 2800 kB
>  hash   | Index | hashhandler          | hash index access method
>      | 2112 kB
>  heap   | Table | heap_tableam_handler | heap table access method
>      | 60 MB
>  heap2  | Table | heap_tableam_handler |
>       | 120 kB
>  spgist | Index | spghandler           | SP-GiST index access method
>       | 5840 kB
> (8 rows)
>
> regression=# \dn++
>                                    List of schemas
>         Name        |  Owner  | Access privileges  |      Description
>  |  Size
>
> --------------------+---------+--------------------+------------------------+---------
>  fkpart3            | pryzbyj |                    |
>   | 168 kB
>  fkpart4            | pryzbyj |                    |
>   | 104 kB
>  fkpart5            | pryzbyj |                    |
>   | 40 kB
>  fkpart6            | pryzbyj |                    |
>   | 48 kB
>  mvtest_mvschema    | pryzbyj |                    |
>   | 16 kB
>  public             | pryzbyj | pryzbyj=UC/pryzbyj+| standard public
> schema | 69 MB
>                     |         | =UC/pryzbyj        |
>   |
>  regress_indexing   | pryzbyj |                    |
>   | 48 kB
>  regress_rls_schema | pryzbyj |                    |
>   | 0 bytes
>  regress_schema_2   | pryzbyj |                    |
>   | 0 bytes
>  testxmlschema      | pryzbyj |                    |
>   | 24 kB
> (10 rows)
>
>
I tested this patch. It looks well. The performance is good enough. I got
the result for a schema with 100K tables in 3 seconds.

I am not sure if using \dt+ and \dP+ without change is a good idea. I can
imagine \dt+ and \dt++. \dP can exist just only in ++ form or we can ignore
it (like now, and support \dP+ and \dP++) with same result

I can live with the proposed patch, and I understand why  ++ was
introduced. But I am still not sure it is really user friendly. I prefer to
extend \dA and \dn with some columns (\dA has only two columns and \dn has
two columns too), and then we don't need special ++ variants for sizes.
Using three levels of detail looks not too practical (more when the basic
reports \dA and \dn) are really very simple).

Regards

Pavel



-- 
> Justin
>

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

* Re: [PATCH] psql: \dn+ to show size of each schema (and \dA+ for AMs)
@ 2021-09-28 02:46  Justin Pryzby <pryzby@telsasoft.com>
  parent: Pavel Stehule <pavel.stehule@gmail.com>
  0 siblings, 2 replies; 22+ messages in thread

From: Justin Pryzby @ 2021-09-28 02:46 UTC (permalink / raw)
  To: Pavel Stehule <pavel.stehule@gmail.com>; +Cc: Laurenz Albe <laurenz.albe@cybertec.at>; Ian Lawrence Barwick <barwick@gmail.com>; pgsql-hackers@postgresql.org, Gilles Darold <gilles@darold.net>

On Fri, Sep 17, 2021 at 12:05:04PM +0200, Pavel Stehule wrote:
> I can live with the proposed patch, and I understand why  ++ was
> introduced. But I am still not sure it is really user friendly. I prefer to
> extend \dA and \dn with some columns (\dA has only two columns and \dn has
> two columns too), and then we don't need special ++ variants for sizes.
> Using three levels of detail looks not too practical (more when the basic
> reports \dA and \dn) are really very simple).

You're suggesting to include the ACL+description in \dn and handler+description
and \dA.

Another option is to add pg_schema_size() and pg_am_size() without shortcuts in
psql.  That would avoid showing a potentially huge ACL when all one wants is
the schema size, and would serve my purposes well enough to write
| SELECT pg_namespace_size(oid), nspname FROM pg_namespace ORDER BY 1 DESC LIMIT 9;

-- 
Justin





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

* Re: [PATCH] psql: \dn+ to show size of each schema (and \dA+ for AMs)
@ 2021-09-28 04:33  Pavel Stehule <pavel.stehule@gmail.com>
  parent: Justin Pryzby <pryzby@telsasoft.com>
  1 sibling, 0 replies; 22+ messages in thread

From: Pavel Stehule @ 2021-09-28 04:33 UTC (permalink / raw)
  To: Justin Pryzby <pryzby@telsasoft.com>; +Cc: Laurenz Albe <laurenz.albe@cybertec.at>; Ian Lawrence Barwick <barwick@gmail.com>; pgsql-hackers; Gilles Darold <gilles@darold.net>

út 28. 9. 2021 v 4:46 odesílatel Justin Pryzby <pryzby@telsasoft.com>
napsal:

> On Fri, Sep 17, 2021 at 12:05:04PM +0200, Pavel Stehule wrote:
> > I can live with the proposed patch, and I understand why  ++ was
> > introduced. But I am still not sure it is really user friendly. I prefer
> to
> > extend \dA and \dn with some columns (\dA has only two columns and \dn
> has
> > two columns too), and then we don't need special ++ variants for sizes.
> > Using three levels of detail looks not too practical (more when the basic
> > reports \dA and \dn) are really very simple).
>
> You're suggesting to include the ACL+description in \dn and
> handler+description
> and \dA.
>

yes


> Another option is to add pg_schema_size() and pg_am_size() without
> shortcuts in
> psql.  That would avoid showing a potentially huge ACL when all one wants
> is
> the schema size, and would serve my purposes well enough to write
> | SELECT pg_namespace_size(oid), nspname FROM pg_namespace ORDER BY 1 DESC
> LIMIT 9;
>

It can work too.

I think the long ACL is a customer design issue, but can be. But the same
problem is in \dt+, and I don't see an objection against this design.

Maybe I am too subjective, because 4 years I use pspg, and wide reports are
not a problem for me. When the size is on the end, then it is easy to see
it in pspg.

I like to see size in \dn+ report, and I like to use pg_namespace_size
separately too. Both can be very practical functionality.

I think so \dt+ and \l+ is working very well now, and I am not too happy to
break it (partially break it).  Although the proposed change is very
minimalistic.

But your example "SELECT pg_namespace_size(oid), nspname FROM pg_namespace
ORDER BY 1 DESC LIMIT 9" navigates me to the second idea (that just
enhances the previous). Can be nice if you can have prepared views on the
server side that are +/- equivalent to psql reports, and anybody can simply
write their own custom reports.

some like

SELECT schema, tablename, owner, pg_size_pretty(size) FROM
pg_description.tables ORDER BY size DESC LIMIT 10
SELECT schema, owner, pg_size_pretty(size) FROM pg_description.schemas
ORDER BY size DESC LIMIT 10

In the future, it can simplify psql code, and it allows pretty nice
customization in any client for a lot of purposes.

Regards

Pavel





> --
> Justin
>

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

* Re: [PATCH] psql: \dn+ to show size of each schema (and \dA+ for AMs)
@ 2021-12-18 22:10  Justin Pryzby <pryzby@telsasoft.com>
  parent: Justin Pryzby <pryzby@telsasoft.com>
  1 sibling, 1 reply; 22+ messages in thread

From: Justin Pryzby @ 2021-12-18 22:10 UTC (permalink / raw)
  To: Pavel Stehule <pavel.stehule@gmail.com>; +Cc: Laurenz Albe <laurenz.albe@cybertec.at>; Ian Lawrence Barwick <barwick@gmail.com>; pgsql-hackers@postgresql.org, Gilles Darold <gilles@darold.net>

Remove bogus ACL check for AMs.
Rebased on cf0cab868.
Use ForkNumber rather than int.
Update comments and commit message.
Also move the Size column of \l and \dt

Attachments: download all (4 files, .tar.gz)

v4-0001-Add-pg_am_size-pg_namespace_size.patch (text/x-diff, 5.6K) download From a1d33780e4c61a7bdb64ee6ab5c248e1175a3efd Mon Sep 17 00:00:00 2001 From: Justin Pryzby <pryzbyj@telsasoft.com> Date: Tue, 13 Jul 2021 21:25:48 -0500 Subject: [PATCH v4 1/4] Add pg_am_size(), pg_namespace_size() .. See also: 358a897fa, 528ac10c7 --- src/backend/utils/adt/dbsize.c | 130 ++++++++++++++++++++++++++++++++ src/include/catalog/pg_proc.dat | 19 +++++ 2 files changed, 149 insertions(+) diff --git a/src/backend/utils/adt/dbsize.c b/src/backend/utils/adt/dbsize.c index d5a7fb13f3..908432ba28 100644 --- a/src/backend/utils/adt/dbsize.c +++ b/src/backend/utils/adt/dbsize.c @@ -13,18 +13,23 @@ #include <sys/stat.h> +#include "access/genam.h" #include "access/htup_details.h" #include "access/relation.h" +#include "access/table.h" #include "catalog/catalog.h" #include "catalog/namespace.h" #include "catalog/pg_authid.h" #include "catalog/pg_tablespace.h" #include "commands/dbcommands.h" +#include "commands/defrem.h" #include "commands/tablespace.h" #include "miscadmin.h" #include "storage/fd.h" #include "utils/acl.h" #include "utils/builtins.h" +#include "utils/fmgroids.h" +#include "utils/lsyscache.h" #include "utils/numeric.h" #include "utils/rel.h" #include "utils/relfilenodemap.h" @@ -832,6 +837,131 @@ pg_size_bytes(PG_FUNCTION_ARGS) PG_RETURN_INT64(result); } +/* + * Return the sum of size of relations for which the given attribute of + * pg_class matches the specified OID value. + */ +static int64 +calculate_size_attvalue(int attnum, Oid attval) +{ + int64 totalsize = 0; + ScanKeyData skey; + Relation pg_class; + SysScanDesc scan; + HeapTuple tuple; + + ScanKeyInit(&skey, attnum, + BTEqualStrategyNumber, F_OIDEQ, attval); + + pg_class = table_open(RelationRelationId, AccessShareLock); + scan = systable_beginscan(pg_class, InvalidOid, false, NULL, 1, &skey); + while (HeapTupleIsValid(tuple = systable_getnext(scan))) + { + Relation rel; + Form_pg_class classtuple = (Form_pg_class) GETSTRUCT(tuple); + + rel = try_relation_open(classtuple->oid, AccessShareLock); + if (!rel) + continue; + + for (ForkNumber forkNum = 0; forkNum <= MAX_FORKNUM; forkNum++) + totalsize += calculate_relation_size(&rel->rd_node, rel->rd_backend, forkNum); + + relation_close(rel, AccessShareLock); + } + + systable_endscan(scan); + table_close(pg_class, AccessShareLock); + return totalsize; +} + +/* Compute the size of relations in a schema (namespace) */ +static int64 +calculate_namespace_size(Oid nspOid) +{ + /* + * User must be a member of pg_read_all_stats or have CREATE privilege for + * target namespace. + */ + if (!is_member_of_role(GetUserId(), ROLE_PG_READ_ALL_STATS)) + { + AclResult aclresult; + aclresult = pg_namespace_aclcheck(nspOid, GetUserId(), ACL_CREATE); + if (aclresult != ACLCHECK_OK) + aclcheck_error(aclresult, OBJECT_SCHEMA, + get_namespace_name(nspOid)); + } + + return calculate_size_attvalue(Anum_pg_class_relnamespace, nspOid); +} + +Datum +pg_namespace_size_oid(PG_FUNCTION_ARGS) +{ + int64 size; + Oid nspOid = PG_GETARG_OID(0); + + size = calculate_namespace_size(nspOid); + + if (size < 0) + PG_RETURN_NULL(); + + PG_RETURN_INT64(size); +} + +Datum +pg_namespace_size_name(PG_FUNCTION_ARGS) +{ + int64 size; + Name nspName = PG_GETARG_NAME(0); + Oid nspOid = get_namespace_oid(NameStr(*nspName), false); + + size = calculate_namespace_size(nspOid); + + if (size < 0) + PG_RETURN_NULL(); + + PG_RETURN_INT64(size); +} + +/* Compute the size of relations using the given access method */ +static int64 +calculate_am_size(Oid amOid) +{ + /* XXX acl_check? */ + + return calculate_size_attvalue(Anum_pg_class_relam, amOid); +} + +Datum +pg_am_size_oid(PG_FUNCTION_ARGS) +{ + int64 size; + Oid amOid = PG_GETARG_OID(0); + + size = calculate_am_size(amOid); + + if (size < 0) + PG_RETURN_NULL(); + + PG_RETURN_INT64(size); +} + +Datum +pg_am_size_name(PG_FUNCTION_ARGS) +{ + int64 size; + Name amName = PG_GETARG_NAME(0); + Oid amOid = get_am_oid(NameStr(*amName), false); + + size = calculate_am_size(amOid); + + if (size < 0) + PG_RETURN_NULL(); + + PG_RETURN_INT64(size); +} + /* * Get the filenode of a relation * diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat index 4d992dc224..ff08b2ac01 100644 --- a/src/include/catalog/pg_proc.dat +++ b/src/include/catalog/pg_proc.dat @@ -7230,6 +7230,25 @@ descr => 'total disk space usage for the specified tablespace', proname => 'pg_tablespace_size', provolatile => 'v', prorettype => 'int8', proargtypes => 'name', prosrc => 'pg_tablespace_size_name' }, + +{ oid => '9410', + descr => 'total disk space usage for the specified namespace', + proname => 'pg_namespace_size', provolatile => 'v', prorettype => 'int8', + proargtypes => 'oid', prosrc => 'pg_namespace_size_oid' }, +{ oid => '9411', + descr => 'total disk space usage for the specified namespace', + proname => 'pg_namespace_size', provolatile => 'v', prorettype => 'int8', + proargtypes => 'name', prosrc => 'pg_namespace_size_name' }, + +{ oid => '9412', + descr => 'total disk space usage for the specified access method', + proname => 'pg_am_size', provolatile => 'v', prorettype => 'int8', + proargtypes => 'oid', prosrc => 'pg_am_size_oid' }, +{ oid => '9413', + descr => 'total disk space usage for the specified access method', + proname => 'pg_am_size', provolatile => 'v', prorettype => 'int8', + proargtypes => 'name', prosrc => 'pg_am_size_name' }, + { oid => '2324', descr => 'total disk space usage for the specified database', proname => 'pg_database_size', provolatile => 'v', prorettype => 'int8', proargtypes => 'oid', prosrc => 'pg_database_size_oid' }, -- 2.17.0
v4-0002-psql-add-convenience-commands-dA-and-dn.patch (text/x-diff, 8.5K) download From d736a7ba55eeebe797f6811413bfc47545fb61e4 Mon Sep 17 00:00:00 2001 From: Justin Pryzby <pryzbyj@telsasoft.com> Date: Sat, 18 Dec 2021 14:58:06 -0600 Subject: [PATCH v4 2/4] psql: add convenience commands: \dA+ and \dn+ show the size only with ++ in \dn, \dA, \db and (for consistency) \l \dt+ and \dP+ are not changed, since showing the table sizes seems to be their primary purpose. --- src/bin/psql/command.c | 22 ++++++++++++++-------- src/bin/psql/describe.c | 30 ++++++++++++++++++++++-------- src/bin/psql/describe.h | 8 ++++---- 3 files changed, 40 insertions(+), 20 deletions(-) diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c index ccd7b48108..c9b0a01f9d 100644 --- a/src/bin/psql/command.c +++ b/src/bin/psql/command.c @@ -362,7 +362,8 @@ exec_command(const char *cmd, else if (strcmp(cmd, "if") == 0) status = exec_command_if(scan_state, cstack, query_buf); else if (strcmp(cmd, "l") == 0 || strcmp(cmd, "list") == 0 || - strcmp(cmd, "l+") == 0 || strcmp(cmd, "list+") == 0) + strcmp(cmd, "l+") == 0 || strcmp(cmd, "l++") == 0 || + strcmp(cmd, "list+") == 0 || strcmp(cmd, "list++") == 0) status = exec_command_list(scan_state, active_branch, cmd); else if (strncmp(cmd, "lo_", 3) == 0) status = exec_command_lo(scan_state, active_branch, cmd); @@ -707,6 +708,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) if (active_branch) { char *pattern; + int verbose = 0; bool show_verbose, show_system; @@ -714,7 +716,10 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) pattern = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, true); - show_verbose = strchr(cmd, '+') ? true : false; + for (const char *t = cmd; *t != '\0'; ++t) + verbose += *t == '+' ? 1 : 0; + + show_verbose = (bool) (verbose != 0); show_system = strchr(cmd, 'S') ? true : false; switch (cmd[1]) @@ -739,7 +744,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) { case '\0': case '+': - success = describeAccessMethods(pattern, show_verbose); + success = describeAccessMethods(pattern, verbose); break; case 'c': success = listOperatorClasses(pattern, pattern2, show_verbose); @@ -766,7 +771,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) success = describeAggregates(pattern, show_verbose, show_system); break; case 'b': - success = describeTablespaces(pattern, show_verbose); + success = describeTablespaces(pattern, verbose); break; case 'c': success = listConversions(pattern, show_verbose, show_system); @@ -813,7 +818,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) success = listLanguages(pattern, show_verbose, show_system); break; case 'n': - success = listSchemas(pattern, show_verbose, show_system); + success = listSchemas(pattern, verbose, show_system); break; case 'o': success = exec_command_dfo(scan_state, cmd, pattern, @@ -1856,14 +1861,15 @@ exec_command_list(PsqlScanState scan_state, bool active_branch, const char *cmd) if (active_branch) { char *pattern; - bool show_verbose; + int verbose = 0; pattern = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, true); - show_verbose = strchr(cmd, '+') ? true : false; + for (const char *t = cmd; *t != '\0'; ++t) + verbose += *t == '+' ? 1 : 0; - success = listAllDbs(pattern, show_verbose); + success = listAllDbs(pattern, verbose); if (pattern) free(pattern); diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c index c28788e84f..c818e657da 100644 --- a/src/bin/psql/describe.c +++ b/src/bin/psql/describe.c @@ -128,12 +128,12 @@ 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; printQueryOpt myopt = pset.popt; - static const bool translate_columns[] = {false, true, false, false}; + static const bool translate_columns[] = {false, true, false, false, false}; if (pset.sversion < 90600) { @@ -165,6 +165,11 @@ describeAccessMethods(const char *pattern, bool verbose) " pg_catalog.obj_description(oid, 'pg_am') AS \"%s\"", gettext_noop("Handler"), gettext_noop("Description")); + + if (verbose > 1 && pset.sversion >= 150000) + appendPQExpBuffer(&buf, + ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_am_size(oid)) AS \"%s\"", + gettext_noop("Size")); } appendPQExpBufferStr(&buf, @@ -198,7 +203,7 @@ describeAccessMethods(const char *pattern, bool verbose) * Takes an optional regexp to select particular tablespaces */ bool -describeTablespaces(const char *pattern, bool verbose) +describeTablespaces(const char *pattern, int verbose) { PQExpBufferData buf; PGresult *res; @@ -218,12 +223,16 @@ describeTablespaces(const char *pattern, bool verbose) { appendPQExpBufferStr(&buf, ",\n "); printACLColumn(&buf, "spcacl"); + + if (verbose > 1) + appendPQExpBuffer(&buf, + ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_tablespace_size(oid)) AS \"%s\"", + gettext_noop("Size")); + appendPQExpBuffer(&buf, ",\n spcoptions AS \"%s\"" - ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_tablespace_size(oid)) AS \"%s\"" ",\n pg_catalog.shobj_description(oid, 'pg_tablespace') AS \"%s\"", gettext_noop("Options"), - gettext_noop("Size"), gettext_noop("Description")); } @@ -877,7 +886,7 @@ describeOperators(const char *oper_pattern, * for \l, \list, and -l switch */ bool -listAllDbs(const char *pattern, bool verbose) +listAllDbs(const char *pattern, int verbose) { PGresult *res; PQExpBufferData buf; @@ -898,7 +907,7 @@ listAllDbs(const char *pattern, bool verbose) gettext_noop("Ctype")); appendPQExpBufferStr(&buf, " "); printACLColumn(&buf, "d.datacl"); - if (verbose) + if (verbose > 1) appendPQExpBuffer(&buf, ",\n CASE WHEN pg_catalog.has_database_privilege(d.datname, 'CONNECT')\n" " THEN pg_catalog.pg_size_pretty(pg_catalog.pg_database_size(d.datname))\n" @@ -4657,7 +4666,7 @@ listCollations(const char *pattern, bool verbose, bool showSystem) * Describes schemas (namespaces) */ bool -listSchemas(const char *pattern, bool verbose, bool showSystem) +listSchemas(const char *pattern, int verbose, bool showSystem) { PQExpBufferData buf; PGresult *res; @@ -4679,6 +4688,11 @@ listSchemas(const char *pattern, bool verbose, bool showSystem) appendPQExpBuffer(&buf, ",\n pg_catalog.obj_description(n.oid, 'pg_namespace') AS \"%s\"", gettext_noop("Description")); + + if (verbose > 1 && pset.sversion >= 150000) + appendPQExpBuffer(&buf, + ",\n pg_catalog.pg_size_pretty(pg_namespace_size(n.oid)) AS \"%s\"", + gettext_noop("Size")); } appendPQExpBufferStr(&buf, diff --git a/src/bin/psql/describe.h b/src/bin/psql/describe.h index 71b320f1fc..edeea38580 100644 --- a/src/bin/psql/describe.h +++ b/src/bin/psql/describe.h @@ -13,10 +13,10 @@ extern bool describeAggregates(const char *pattern, bool verbose, bool showSystem); /* \dA */ -extern bool describeAccessMethods(const char *pattern, bool verbose); +extern bool describeAccessMethods(const char *pattern, int verbose); /* \db */ -extern bool describeTablespaces(const char *pattern, bool verbose); +extern bool describeTablespaces(const char *pattern, int verbose); /* \df, \dfa, \dfn, \dft, \dfw, etc. */ extern bool describeFunctions(const char *functypes, const char *func_pattern, @@ -62,7 +62,7 @@ extern bool listTSDictionaries(const char *pattern, bool verbose); extern bool listTSTemplates(const char *pattern, bool verbose); /* \l */ -extern bool listAllDbs(const char *pattern, bool verbose); +extern bool listAllDbs(const char *pattern, int verbose); /* \dt, \di, \ds, \dS, etc. */ extern bool listTables(const char *tabtypes, const char *pattern, bool verbose, bool showSystem); @@ -83,7 +83,7 @@ extern bool listCasts(const char *pattern, bool verbose); extern bool listCollations(const char *pattern, bool verbose, bool showSystem); /* \dn */ -extern bool listSchemas(const char *pattern, bool verbose, bool showSystem); +extern bool listSchemas(const char *pattern, int verbose, bool showSystem); /* \dew */ extern bool listForeignDataWrappers(const char *pattern, bool verbose); -- 2.17.0
v4-0003-f-convert-the-other-verbose-to-int-too.patch (text/x-diff, 39.3K) download From ec7b0104a4d32e231e1fe6be24b6d53c32247337 Mon Sep 17 00:00:00 2001 From: Justin Pryzby <pryzbyj@telsasoft.com> Date: Thu, 15 Jul 2021 03:19:58 -0500 Subject: [PATCH v4 3/4] f!convert the other verbose to int, too --- 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
v4-0004-Move-the-double-plus-Size-columns-to-the-right.patch (text/x-diff, 10.0K) download From 9fad0b322f7e6e60b8b0dbad68d8bc34a470da01 Mon Sep 17 00:00:00 2001 From: Justin Pryzby <pryzbyj@telsasoft.com> Date: Fri, 17 Dec 2021 09:35:46 -0600 Subject: [PATCH v4 4/4] Move the double-plus "Size" columns to the right \dn, \dA, \db, \l, \d and \dP+ It doesn't make much sense that one cannot show a database's default tablespace without also showing its size, and stat()ing every segment of every relation in the DB. --- src/bin/psql/describe.c | 42 ++++++++++++++--------- src/test/regress/expected/psql.out | 54 +++++++++++++++--------------- 2 files changed, 53 insertions(+), 43 deletions(-) diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c index 710bf8ef91..42bad9281e 100644 --- a/src/bin/psql/describe.c +++ b/src/bin/psql/describe.c @@ -224,11 +224,6 @@ describeTablespaces(const char *pattern, int verbose) appendPQExpBufferStr(&buf, ",\n "); printACLColumn(&buf, "spcacl"); - if (verbose > 1) - appendPQExpBuffer(&buf, - ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_tablespace_size(oid)) AS \"%s\"", - gettext_noop("Size")); - appendPQExpBuffer(&buf, ",\n spcoptions AS \"%s\"" ",\n pg_catalog.shobj_description(oid, 'pg_tablespace') AS \"%s\"", @@ -236,6 +231,11 @@ describeTablespaces(const char *pattern, int verbose) gettext_noop("Description")); } + if (verbose > 1) + appendPQExpBuffer(&buf, + ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_tablespace_size(oid)) AS \"%s\"", + gettext_noop("Size")); + appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_tablespace\n"); @@ -907,17 +907,22 @@ listAllDbs(const char *pattern, int verbose) gettext_noop("Ctype")); appendPQExpBufferStr(&buf, " "); printACLColumn(&buf, "d.datacl"); - if (verbose > 1) + + if (verbose > 0) appendPQExpBuffer(&buf, - ",\n CASE WHEN pg_catalog.has_database_privilege(d.datname, 'CONNECT')\n" - " THEN pg_catalog.pg_size_pretty(pg_catalog.pg_database_size(d.datname))\n" - " ELSE 'No Access'\n" - " END as \"%s\"" ",\n t.spcname as \"%s\"" ",\n pg_catalog.shobj_description(d.oid, 'pg_database') as \"%s\"", - gettext_noop("Size"), gettext_noop("Tablespace"), gettext_noop("Description")); + + if (verbose > 1) + appendPQExpBuffer(&buf, + ",\n CASE WHEN pg_catalog.has_database_privilege(d.datname, 'CONNECT')\n" + " THEN pg_catalog.pg_size_pretty(pg_catalog.pg_database_size(d.datname))\n" + " ELSE 'No Access'\n" + " END as \"%s\"", + gettext_noop("Size")); + appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_database d\n"); if (verbose > 0) @@ -3772,10 +3777,13 @@ listTables(const char *tabtypes, const char *pattern, int verbose, bool showSyst gettext_noop("Access method")); appendPQExpBuffer(&buf, - ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_table_size(c.oid)) as \"%s\"" ",\n pg_catalog.obj_description(c.oid, 'pg_class') as \"%s\"", - gettext_noop("Size"), gettext_noop("Description")); + + if (verbose > 1) + appendPQExpBuffer(&buf, + ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_table_size(c.oid)) as \"%s\"", + gettext_noop("Size")); } appendPQExpBufferStr(&buf, @@ -3954,6 +3962,11 @@ listPartitionedTables(const char *reltypes, const char *pattern, int verbose) gettext_noop("Table")); if (verbose > 0) + appendPQExpBuffer(&buf, + ",\n pg_catalog.obj_description(c.oid, 'pg_class') as \"%s\"", + gettext_noop("Description")); + + if (verbose > 1) { if (showNested) { @@ -3970,9 +3983,6 @@ listPartitionedTables(const char *reltypes, const char *pattern, int verbose) ",\n s.tps as \"%s\"", gettext_noop("Total size")); - appendPQExpBuffer(&buf, - ",\n pg_catalog.obj_description(c.oid, 'pg_class') as \"%s\"", - gettext_noop("Description")); } appendPQExpBufferStr(&buf, diff --git a/src/test/regress/expected/psql.out b/src/test/regress/expected/psql.out index 930ce8597a..9a521a80b3 100644 --- a/src/test/regress/expected/psql.out +++ b/src/test/regress/expected/psql.out @@ -2845,47 +2845,47 @@ Access method: heap -- AM is displayed for tables, indexes and materialized views. \d+ - List of relations - Schema | Name | Type | Owner | Persistence | Access method | Size | Description ------------------+--------------------+-------------------+----------------------+-------------+---------------+---------+------------- - tableam_display | mat_view_heap_psql | materialized view | regress_display_role | permanent | heap_psql | 0 bytes | - tableam_display | tbl_heap | table | regress_display_role | permanent | heap | 0 bytes | - tableam_display | tbl_heap_psql | table | regress_display_role | permanent | heap_psql | 0 bytes | - tableam_display | view_heap_psql | view | regress_display_role | permanent | | 0 bytes | + List of relations + Schema | Name | Type | Owner | Persistence | Access method | Description +-----------------+--------------------+-------------------+----------------------+-------------+---------------+------------- + tableam_display | mat_view_heap_psql | materialized view | regress_display_role | permanent | heap_psql | + tableam_display | tbl_heap | table | regress_display_role | permanent | heap | + tableam_display | tbl_heap_psql | table | regress_display_role | permanent | heap_psql | + tableam_display | view_heap_psql | view | regress_display_role | permanent | | (4 rows) \dt+ - List of relations - Schema | Name | Type | Owner | Persistence | Access method | Size | Description ------------------+---------------+-------+----------------------+-------------+---------------+---------+------------- - tableam_display | tbl_heap | table | regress_display_role | permanent | heap | 0 bytes | - tableam_display | tbl_heap_psql | table | regress_display_role | permanent | heap_psql | 0 bytes | + List of relations + Schema | Name | Type | Owner | Persistence | Access method | Description +-----------------+---------------+-------+----------------------+-------------+---------------+------------- + tableam_display | tbl_heap | table | regress_display_role | permanent | heap | + tableam_display | tbl_heap_psql | table | regress_display_role | permanent | heap_psql | (2 rows) \dm+ - List of relations - Schema | Name | Type | Owner | Persistence | Access method | Size | Description ------------------+--------------------+-------------------+----------------------+-------------+---------------+---------+------------- - tableam_display | mat_view_heap_psql | materialized view | regress_display_role | permanent | heap_psql | 0 bytes | + List of relations + Schema | Name | Type | Owner | Persistence | Access method | Description +-----------------+--------------------+-------------------+----------------------+-------------+---------------+------------- + tableam_display | mat_view_heap_psql | materialized view | regress_display_role | permanent | heap_psql | (1 row) -- But not for views and sequences. \dv+ - List of relations - Schema | Name | Type | Owner | Persistence | Size | Description ------------------+----------------+------+----------------------+-------------+---------+------------- - tableam_display | view_heap_psql | view | regress_display_role | permanent | 0 bytes | + List of relations + Schema | Name | Type | Owner | Persistence | Description +-----------------+----------------+------+----------------------+-------------+------------- + tableam_display | view_heap_psql | view | regress_display_role | permanent | (1 row) \set HIDE_TABLEAM on \d+ - List of relations - Schema | Name | Type | Owner | Persistence | Size | Description ------------------+--------------------+-------------------+----------------------+-------------+---------+------------- - tableam_display | mat_view_heap_psql | materialized view | regress_display_role | permanent | 0 bytes | - tableam_display | tbl_heap | table | regress_display_role | permanent | 0 bytes | - tableam_display | tbl_heap_psql | table | regress_display_role | permanent | 0 bytes | - tableam_display | view_heap_psql | view | regress_display_role | permanent | 0 bytes | + List of relations + Schema | Name | Type | Owner | Persistence | Description +-----------------+--------------------+-------------------+----------------------+-------------+------------- + tableam_display | mat_view_heap_psql | materialized view | regress_display_role | permanent | + tableam_display | tbl_heap | table | regress_display_role | permanent | + tableam_display | tbl_heap_psql | table | regress_display_role | permanent | + tableam_display | view_heap_psql | view | regress_display_role | permanent | (4 rows) RESET ROLE; -- 2.17.0
^ permalink raw reply [nested|flat] 22+ messages in thread

* Re: [PATCH] psql: \dn+ to show size of each schema (and \dA+ for AMs)
@ 2022-01-14 16:35  Justin Pryzby <pryzby@telsasoft.com>
  parent: Justin Pryzby <pryzby@telsasoft.com>
  0 siblings, 2 replies; 22+ messages in thread

From: Justin Pryzby @ 2022-01-14 16:35 UTC (permalink / raw)
  To: Pavel Stehule <pavel.stehule@gmail.com>; +Cc: Laurenz Albe <laurenz.albe@cybertec.at>; Ian Lawrence Barwick <barwick@gmail.com>; pgsql-hackers@postgresql.org, Gilles Darold <gilles@darold.net>

Rebased before Julian asks.

Attachments: download all (4 files, .tar.gz)

0001-Add-pg_am_size-pg_namespace_size.patch (text/x-diff, 5.6K) download From cf57143c85a2a6088fe6038e6d41771fd60aae34 Mon Sep 17 00:00:00 2001 From: Justin Pryzby <pryzbyj@telsasoft.com> Date: Tue, 13 Jul 2021 21:25:48 -0500 Subject: [PATCH 1/4] Add pg_am_size(), pg_namespace_size() .. See also: 358a897fa, 528ac10c7 --- src/backend/utils/adt/dbsize.c | 130 ++++++++++++++++++++++++++++++++ src/include/catalog/pg_proc.dat | 19 +++++ 2 files changed, 149 insertions(+) diff --git a/src/backend/utils/adt/dbsize.c b/src/backend/utils/adt/dbsize.c index 3a2f2e1f99d..6cde01f0587 100644 --- a/src/backend/utils/adt/dbsize.c +++ b/src/backend/utils/adt/dbsize.c @@ -13,18 +13,23 @@ #include <sys/stat.h> +#include "access/genam.h" #include "access/htup_details.h" #include "access/relation.h" +#include "access/table.h" #include "catalog/catalog.h" #include "catalog/namespace.h" #include "catalog/pg_authid.h" #include "catalog/pg_tablespace.h" #include "commands/dbcommands.h" +#include "commands/defrem.h" #include "commands/tablespace.h" #include "miscadmin.h" #include "storage/fd.h" #include "utils/acl.h" #include "utils/builtins.h" +#include "utils/fmgroids.h" +#include "utils/lsyscache.h" #include "utils/numeric.h" #include "utils/rel.h" #include "utils/relfilenodemap.h" @@ -832,6 +837,131 @@ pg_size_bytes(PG_FUNCTION_ARGS) PG_RETURN_INT64(result); } +/* + * Return the sum of size of relations for which the given attribute of + * pg_class matches the specified OID value. + */ +static int64 +calculate_size_attvalue(int attnum, Oid attval) +{ + int64 totalsize = 0; + ScanKeyData skey; + Relation pg_class; + SysScanDesc scan; + HeapTuple tuple; + + ScanKeyInit(&skey, attnum, + BTEqualStrategyNumber, F_OIDEQ, attval); + + pg_class = table_open(RelationRelationId, AccessShareLock); + scan = systable_beginscan(pg_class, InvalidOid, false, NULL, 1, &skey); + while (HeapTupleIsValid(tuple = systable_getnext(scan))) + { + Relation rel; + Form_pg_class classtuple = (Form_pg_class) GETSTRUCT(tuple); + + rel = try_relation_open(classtuple->oid, AccessShareLock); + if (!rel) + continue; + + for (ForkNumber forkNum = 0; forkNum <= MAX_FORKNUM; forkNum++) + totalsize += calculate_relation_size(&rel->rd_node, rel->rd_backend, forkNum); + + relation_close(rel, AccessShareLock); + } + + systable_endscan(scan); + table_close(pg_class, AccessShareLock); + return totalsize; +} + +/* Compute the size of relations in a schema (namespace) */ +static int64 +calculate_namespace_size(Oid nspOid) +{ + /* + * User must be a member of pg_read_all_stats or have CREATE privilege for + * target namespace. + */ + if (!is_member_of_role(GetUserId(), ROLE_PG_READ_ALL_STATS)) + { + AclResult aclresult; + aclresult = pg_namespace_aclcheck(nspOid, GetUserId(), ACL_CREATE); + if (aclresult != ACLCHECK_OK) + aclcheck_error(aclresult, OBJECT_SCHEMA, + get_namespace_name(nspOid)); + } + + return calculate_size_attvalue(Anum_pg_class_relnamespace, nspOid); +} + +Datum +pg_namespace_size_oid(PG_FUNCTION_ARGS) +{ + int64 size; + Oid nspOid = PG_GETARG_OID(0); + + size = calculate_namespace_size(nspOid); + + if (size < 0) + PG_RETURN_NULL(); + + PG_RETURN_INT64(size); +} + +Datum +pg_namespace_size_name(PG_FUNCTION_ARGS) +{ + int64 size; + Name nspName = PG_GETARG_NAME(0); + Oid nspOid = get_namespace_oid(NameStr(*nspName), false); + + size = calculate_namespace_size(nspOid); + + if (size < 0) + PG_RETURN_NULL(); + + PG_RETURN_INT64(size); +} + +/* Compute the size of relations using the given access method */ +static int64 +calculate_am_size(Oid amOid) +{ + /* XXX acl_check? */ + + return calculate_size_attvalue(Anum_pg_class_relam, amOid); +} + +Datum +pg_am_size_oid(PG_FUNCTION_ARGS) +{ + int64 size; + Oid amOid = PG_GETARG_OID(0); + + size = calculate_am_size(amOid); + + if (size < 0) + PG_RETURN_NULL(); + + PG_RETURN_INT64(size); +} + +Datum +pg_am_size_name(PG_FUNCTION_ARGS) +{ + int64 size; + Name amName = PG_GETARG_NAME(0); + Oid amOid = get_am_oid(NameStr(*amName), false); + + size = calculate_am_size(amOid); + + if (size < 0) + PG_RETURN_NULL(); + + PG_RETURN_INT64(size); +} + /* * Get the filenode of a relation * diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat index d6bf1f3274b..18248799e73 100644 --- a/src/include/catalog/pg_proc.dat +++ b/src/include/catalog/pg_proc.dat @@ -7230,6 +7230,25 @@ descr => 'total disk space usage for the specified tablespace', proname => 'pg_tablespace_size', provolatile => 'v', prorettype => 'int8', proargtypes => 'name', prosrc => 'pg_tablespace_size_name' }, + +{ oid => '9410', + descr => 'total disk space usage for the specified namespace', + proname => 'pg_namespace_size', provolatile => 'v', prorettype => 'int8', + proargtypes => 'oid', prosrc => 'pg_namespace_size_oid' }, +{ oid => '9411', + descr => 'total disk space usage for the specified namespace', + proname => 'pg_namespace_size', provolatile => 'v', prorettype => 'int8', + proargtypes => 'name', prosrc => 'pg_namespace_size_name' }, + +{ oid => '9412', + descr => 'total disk space usage for the specified access method', + proname => 'pg_am_size', provolatile => 'v', prorettype => 'int8', + proargtypes => 'oid', prosrc => 'pg_am_size_oid' }, +{ oid => '9413', + descr => 'total disk space usage for the specified access method', + proname => 'pg_am_size', provolatile => 'v', prorettype => 'int8', + proargtypes => 'name', prosrc => 'pg_am_size_name' }, + { oid => '2324', descr => 'total disk space usage for the specified database', proname => 'pg_database_size', provolatile => 'v', prorettype => 'int8', proargtypes => 'oid', prosrc => 'pg_database_size_oid' }, -- 2.17.1
0002-psql-add-convenience-commands-dA-and-dn.patch (text/x-diff, 8.5K) download From 771086b0b1d6116309a831e1e122cdce05d7dd6b Mon Sep 17 00:00:00 2001 From: Justin Pryzby <pryzbyj@telsasoft.com> Date: Sat, 18 Dec 2021 14:58:06 -0600 Subject: [PATCH 2/4] psql: add convenience commands: \dA+ and \dn+ show the size only with ++ in \dn, \dA, \db and (for consistency) \l \dt+ and \dP+ are not changed, since showing the table sizes seems to be their primary purpose. --- src/bin/psql/command.c | 22 ++++++++++++++-------- src/bin/psql/describe.c | 30 ++++++++++++++++++++++-------- src/bin/psql/describe.h | 8 ++++---- 3 files changed, 40 insertions(+), 20 deletions(-) diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c index f5904748553..cfae8fd6d12 100644 --- a/src/bin/psql/command.c +++ b/src/bin/psql/command.c @@ -366,7 +366,8 @@ exec_command(const char *cmd, else if (strcmp(cmd, "if") == 0) status = exec_command_if(scan_state, cstack, query_buf); else if (strcmp(cmd, "l") == 0 || strcmp(cmd, "list") == 0 || - strcmp(cmd, "l+") == 0 || strcmp(cmd, "list+") == 0) + strcmp(cmd, "l+") == 0 || strcmp(cmd, "l++") == 0 || + strcmp(cmd, "list+") == 0 || strcmp(cmd, "list++") == 0) status = exec_command_list(scan_state, active_branch, cmd); else if (strncmp(cmd, "lo_", 3) == 0) status = exec_command_lo(scan_state, active_branch, cmd); @@ -718,6 +719,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) if (active_branch) { char *pattern; + int verbose = 0; bool show_verbose, show_system; @@ -725,7 +727,10 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) pattern = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, true); - show_verbose = strchr(cmd, '+') ? true : false; + for (const char *t = cmd; *t != '\0'; ++t) + verbose += *t == '+' ? 1 : 0; + + show_verbose = (bool) (verbose != 0); show_system = strchr(cmd, 'S') ? true : false; switch (cmd[1]) @@ -750,7 +755,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) { case '\0': case '+': - success = describeAccessMethods(pattern, show_verbose); + success = describeAccessMethods(pattern, verbose); break; case 'c': success = listOperatorClasses(pattern, pattern2, show_verbose); @@ -777,7 +782,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) success = describeAggregates(pattern, show_verbose, show_system); break; case 'b': - success = describeTablespaces(pattern, show_verbose); + success = describeTablespaces(pattern, verbose); break; case 'c': success = listConversions(pattern, show_verbose, show_system); @@ -824,7 +829,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) success = listLanguages(pattern, show_verbose, show_system); break; case 'n': - success = listSchemas(pattern, show_verbose, show_system); + success = listSchemas(pattern, verbose, show_system); break; case 'o': success = exec_command_dfo(scan_state, cmd, pattern, @@ -1904,14 +1909,15 @@ exec_command_list(PsqlScanState scan_state, bool active_branch, const char *cmd) if (active_branch) { char *pattern; - bool show_verbose; + int verbose = 0; pattern = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, true); - show_verbose = strchr(cmd, '+') ? true : false; + for (const char *t = cmd; *t != '\0'; ++t) + verbose += *t == '+' ? 1 : 0; - success = listAllDbs(pattern, show_verbose); + success = listAllDbs(pattern, verbose); if (pattern) free(pattern); diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c index 8587b19160d..de62822674e 100644 --- a/src/bin/psql/describe.c +++ b/src/bin/psql/describe.c @@ -128,12 +128,12 @@ 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; printQueryOpt myopt = pset.popt; - static const bool translate_columns[] = {false, true, false, false}; + static const bool translate_columns[] = {false, true, false, false, false}; if (pset.sversion < 90600) { @@ -165,6 +165,11 @@ describeAccessMethods(const char *pattern, bool verbose) " pg_catalog.obj_description(oid, 'pg_am') AS \"%s\"", gettext_noop("Handler"), gettext_noop("Description")); + + if (verbose > 1 && pset.sversion >= 150000) + appendPQExpBuffer(&buf, + ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_am_size(oid)) AS \"%s\"", + gettext_noop("Size")); } appendPQExpBufferStr(&buf, @@ -198,7 +203,7 @@ describeAccessMethods(const char *pattern, bool verbose) * Takes an optional regexp to select particular tablespaces */ bool -describeTablespaces(const char *pattern, bool verbose) +describeTablespaces(const char *pattern, int verbose) { PQExpBufferData buf; PGresult *res; @@ -218,12 +223,16 @@ describeTablespaces(const char *pattern, bool verbose) { appendPQExpBufferStr(&buf, ",\n "); printACLColumn(&buf, "spcacl"); + + if (verbose > 1) + appendPQExpBuffer(&buf, + ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_tablespace_size(oid)) AS \"%s\"", + gettext_noop("Size")); + appendPQExpBuffer(&buf, ",\n spcoptions AS \"%s\"" - ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_tablespace_size(oid)) AS \"%s\"" ",\n pg_catalog.shobj_description(oid, 'pg_tablespace') AS \"%s\"", gettext_noop("Options"), - gettext_noop("Size"), gettext_noop("Description")); } @@ -877,7 +886,7 @@ describeOperators(const char *oper_pattern, * for \l, \list, and -l switch */ bool -listAllDbs(const char *pattern, bool verbose) +listAllDbs(const char *pattern, int verbose) { PGresult *res; PQExpBufferData buf; @@ -898,7 +907,7 @@ listAllDbs(const char *pattern, bool verbose) gettext_noop("Ctype")); appendPQExpBufferStr(&buf, " "); printACLColumn(&buf, "d.datacl"); - if (verbose) + if (verbose > 1) appendPQExpBuffer(&buf, ",\n CASE WHEN pg_catalog.has_database_privilege(d.datname, 'CONNECT')\n" " THEN pg_catalog.pg_size_pretty(pg_catalog.pg_database_size(d.datname))\n" @@ -4665,7 +4674,7 @@ listCollations(const char *pattern, bool verbose, bool showSystem) * Describes schemas (namespaces) */ bool -listSchemas(const char *pattern, bool verbose, bool showSystem) +listSchemas(const char *pattern, int verbose, bool showSystem) { PQExpBufferData buf; PGresult *res; @@ -4687,6 +4696,11 @@ listSchemas(const char *pattern, bool verbose, bool showSystem) appendPQExpBuffer(&buf, ",\n pg_catalog.obj_description(n.oid, 'pg_namespace') AS \"%s\"", gettext_noop("Description")); + + if (verbose > 1 && pset.sversion >= 150000) + appendPQExpBuffer(&buf, + ",\n pg_catalog.pg_size_pretty(pg_namespace_size(n.oid)) AS \"%s\"", + gettext_noop("Size")); } appendPQExpBufferStr(&buf, diff --git a/src/bin/psql/describe.h b/src/bin/psql/describe.h index fd6079679c6..5a1b97805df 100644 --- a/src/bin/psql/describe.h +++ b/src/bin/psql/describe.h @@ -13,10 +13,10 @@ extern bool describeAggregates(const char *pattern, bool verbose, bool showSystem); /* \dA */ -extern bool describeAccessMethods(const char *pattern, bool verbose); +extern bool describeAccessMethods(const char *pattern, int verbose); /* \db */ -extern bool describeTablespaces(const char *pattern, bool verbose); +extern bool describeTablespaces(const char *pattern, int verbose); /* \df, \dfa, \dfn, \dft, \dfw, etc. */ extern bool describeFunctions(const char *functypes, const char *func_pattern, @@ -62,7 +62,7 @@ extern bool listTSDictionaries(const char *pattern, bool verbose); extern bool listTSTemplates(const char *pattern, bool verbose); /* \l */ -extern bool listAllDbs(const char *pattern, bool verbose); +extern bool listAllDbs(const char *pattern, int verbose); /* \dt, \di, \ds, \dS, etc. */ extern bool listTables(const char *tabtypes, const char *pattern, bool verbose, bool showSystem); @@ -83,7 +83,7 @@ extern bool listCasts(const char *pattern, bool verbose); extern bool listCollations(const char *pattern, bool verbose, bool showSystem); /* \dn */ -extern bool listSchemas(const char *pattern, bool verbose, bool showSystem); +extern bool listSchemas(const char *pattern, int verbose, bool showSystem); /* \dew */ extern bool listForeignDataWrappers(const char *pattern, bool verbose); -- 2.17.1
0003-f-convert-the-other-verbose-to-int-too.patch (text/x-diff, 40.3K) download From cece72e72b35110f222228e8f71397e4fc72469a Mon Sep 17 00:00:00 2001 From: Justin Pryzby <pryzbyj@telsasoft.com> Date: Thu, 15 Jul 2021 03:19:58 -0500 Subject: [PATCH 3/4] f!convert the other verbose to int, too --- 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
0004-Move-the-double-plus-Size-columns-to-the-right.patch (text/x-diff, 10.0K) download From 25671fe1088283adce706ba5dace7323c6de7da9 Mon Sep 17 00:00:00 2001 From: Justin Pryzby <pryzbyj@telsasoft.com> Date: Fri, 17 Dec 2021 09:35:46 -0600 Subject: [PATCH 4/4] Move the double-plus "Size" columns to the right \dn, \dA, \db, \l, \d and \dP+ It doesn't make much sense that one cannot show a database's default tablespace without also showing its size, and stat()ing every segment of every relation in the DB. --- src/bin/psql/describe.c | 42 ++++++++++++++--------- src/test/regress/expected/psql.out | 54 +++++++++++++++--------------- 2 files changed, 53 insertions(+), 43 deletions(-) diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c index ee7990ab7e4..44ae6ca9a75 100644 --- a/src/bin/psql/describe.c +++ b/src/bin/psql/describe.c @@ -224,11 +224,6 @@ describeTablespaces(const char *pattern, int verbose) appendPQExpBufferStr(&buf, ",\n "); printACLColumn(&buf, "spcacl"); - if (verbose > 1) - appendPQExpBuffer(&buf, - ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_tablespace_size(oid)) AS \"%s\"", - gettext_noop("Size")); - appendPQExpBuffer(&buf, ",\n spcoptions AS \"%s\"" ",\n pg_catalog.shobj_description(oid, 'pg_tablespace') AS \"%s\"", @@ -236,6 +231,11 @@ describeTablespaces(const char *pattern, int verbose) gettext_noop("Description")); } + if (verbose > 1) + appendPQExpBuffer(&buf, + ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_tablespace_size(oid)) AS \"%s\"", + gettext_noop("Size")); + appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_tablespace\n"); @@ -907,17 +907,22 @@ listAllDbs(const char *pattern, int verbose) gettext_noop("Ctype")); appendPQExpBufferStr(&buf, " "); printACLColumn(&buf, "d.datacl"); - if (verbose > 1) + + if (verbose > 0) appendPQExpBuffer(&buf, - ",\n CASE WHEN pg_catalog.has_database_privilege(d.datname, 'CONNECT')\n" - " THEN pg_catalog.pg_size_pretty(pg_catalog.pg_database_size(d.datname))\n" - " ELSE 'No Access'\n" - " END as \"%s\"" ",\n t.spcname as \"%s\"" ",\n pg_catalog.shobj_description(d.oid, 'pg_database') as \"%s\"", - gettext_noop("Size"), gettext_noop("Tablespace"), gettext_noop("Description")); + + if (verbose > 1) + appendPQExpBuffer(&buf, + ",\n CASE WHEN pg_catalog.has_database_privilege(d.datname, 'CONNECT')\n" + " THEN pg_catalog.pg_size_pretty(pg_catalog.pg_database_size(d.datname))\n" + " ELSE 'No Access'\n" + " END as \"%s\"", + gettext_noop("Size")); + appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_database d\n"); if (verbose > 0) @@ -3780,10 +3785,13 @@ listTables(const char *tabtypes, const char *pattern, int verbose, bool showSyst gettext_noop("Access method")); appendPQExpBuffer(&buf, - ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_table_size(c.oid)) as \"%s\"" ",\n pg_catalog.obj_description(c.oid, 'pg_class') as \"%s\"", - gettext_noop("Size"), gettext_noop("Description")); + + if (verbose > 1) + appendPQExpBuffer(&buf, + ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_table_size(c.oid)) as \"%s\"", + gettext_noop("Size")); } appendPQExpBufferStr(&buf, @@ -3962,6 +3970,11 @@ listPartitionedTables(const char *reltypes, const char *pattern, int verbose) gettext_noop("Table")); if (verbose > 0) + appendPQExpBuffer(&buf, + ",\n pg_catalog.obj_description(c.oid, 'pg_class') as \"%s\"", + gettext_noop("Description")); + + if (verbose > 1) { if (showNested) { @@ -3978,9 +3991,6 @@ listPartitionedTables(const char *reltypes, const char *pattern, int verbose) ",\n s.tps as \"%s\"", gettext_noop("Total size")); - appendPQExpBuffer(&buf, - ",\n pg_catalog.obj_description(c.oid, 'pg_class') as \"%s\"", - gettext_noop("Description")); } appendPQExpBufferStr(&buf, diff --git a/src/test/regress/expected/psql.out b/src/test/regress/expected/psql.out index 6428ebc507d..47166727318 100644 --- a/src/test/regress/expected/psql.out +++ b/src/test/regress/expected/psql.out @@ -2857,47 +2857,47 @@ Access method: heap -- AM is displayed for tables, indexes and materialized views. \d+ - List of relations - Schema | Name | Type | Owner | Persistence | Access method | Size | Description ------------------+--------------------+-------------------+----------------------+-------------+---------------+---------+------------- - tableam_display | mat_view_heap_psql | materialized view | regress_display_role | permanent | heap_psql | 0 bytes | - tableam_display | tbl_heap | table | regress_display_role | permanent | heap | 0 bytes | - tableam_display | tbl_heap_psql | table | regress_display_role | permanent | heap_psql | 0 bytes | - tableam_display | view_heap_psql | view | regress_display_role | permanent | | 0 bytes | + List of relations + Schema | Name | Type | Owner | Persistence | Access method | Description +-----------------+--------------------+-------------------+----------------------+-------------+---------------+------------- + tableam_display | mat_view_heap_psql | materialized view | regress_display_role | permanent | heap_psql | + tableam_display | tbl_heap | table | regress_display_role | permanent | heap | + tableam_display | tbl_heap_psql | table | regress_display_role | permanent | heap_psql | + tableam_display | view_heap_psql | view | regress_display_role | permanent | | (4 rows) \dt+ - List of relations - Schema | Name | Type | Owner | Persistence | Access method | Size | Description ------------------+---------------+-------+----------------------+-------------+---------------+---------+------------- - tableam_display | tbl_heap | table | regress_display_role | permanent | heap | 0 bytes | - tableam_display | tbl_heap_psql | table | regress_display_role | permanent | heap_psql | 0 bytes | + List of relations + Schema | Name | Type | Owner | Persistence | Access method | Description +-----------------+---------------+-------+----------------------+-------------+---------------+------------- + tableam_display | tbl_heap | table | regress_display_role | permanent | heap | + tableam_display | tbl_heap_psql | table | regress_display_role | permanent | heap_psql | (2 rows) \dm+ - List of relations - Schema | Name | Type | Owner | Persistence | Access method | Size | Description ------------------+--------------------+-------------------+----------------------+-------------+---------------+---------+------------- - tableam_display | mat_view_heap_psql | materialized view | regress_display_role | permanent | heap_psql | 0 bytes | + List of relations + Schema | Name | Type | Owner | Persistence | Access method | Description +-----------------+--------------------+-------------------+----------------------+-------------+---------------+------------- + tableam_display | mat_view_heap_psql | materialized view | regress_display_role | permanent | heap_psql | (1 row) -- But not for views and sequences. \dv+ - List of relations - Schema | Name | Type | Owner | Persistence | Size | Description ------------------+----------------+------+----------------------+-------------+---------+------------- - tableam_display | view_heap_psql | view | regress_display_role | permanent | 0 bytes | + List of relations + Schema | Name | Type | Owner | Persistence | Description +-----------------+----------------+------+----------------------+-------------+------------- + tableam_display | view_heap_psql | view | regress_display_role | permanent | (1 row) \set HIDE_TABLEAM on \d+ - List of relations - Schema | Name | Type | Owner | Persistence | Size | Description ------------------+--------------------+-------------------+----------------------+-------------+---------+------------- - tableam_display | mat_view_heap_psql | materialized view | regress_display_role | permanent | 0 bytes | - tableam_display | tbl_heap | table | regress_display_role | permanent | 0 bytes | - tableam_display | tbl_heap_psql | table | regress_display_role | permanent | 0 bytes | - tableam_display | view_heap_psql | view | regress_display_role | permanent | 0 bytes | + List of relations + Schema | Name | Type | Owner | Persistence | Description +-----------------+--------------------+-------------------+----------------------+-------------+------------- + tableam_display | mat_view_heap_psql | materialized view | regress_display_role | permanent | + tableam_display | tbl_heap | table | regress_display_role | permanent | + tableam_display | tbl_heap_psql | table | regress_display_role | permanent | + tableam_display | view_heap_psql | view | regress_display_role | permanent | (4 rows) RESET ROLE; -- 2.17.1
^ permalink raw reply [nested|flat] 22+ messages in thread

* Re: [PATCH] psql: \dn+ to show size of each schema (and \dA+ for AMs)
@ 2022-01-14 16:46  Pavel Stehule <pavel.stehule@gmail.com>
  parent: Justin Pryzby <pryzby@telsasoft.com>
  1 sibling, 0 replies; 22+ messages in thread

From: Pavel Stehule @ 2022-01-14 16:46 UTC (permalink / raw)
  To: Justin Pryzby <pryzby@telsasoft.com>; +Cc: Laurenz Albe <laurenz.albe@cybertec.at>; Ian Lawrence Barwick <barwick@gmail.com>; pgsql-hackers; Gilles Darold <gilles@darold.net>

Hi

I like this feature, but I don't like the introduction of double + too
much. I think it is confusing.

Is it really necessary? Cannot be enough just reorganization of \dn and
\dn+.

Regards

Pavel

pá 14. 1. 2022 v 17:35 odesílatel Justin Pryzby <pryzby@telsasoft.com>
napsal:

> Rebased before Julian asks.
>

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

* Re: [PATCH] psql: \dn+ to show size of each schema (and \dA+ for AMs)
@ 2022-06-10 11:48  Justin Pryzby <pryzby@telsasoft.com>
  parent: Justin Pryzby <pryzby@telsasoft.com>
  1 sibling, 1 reply; 22+ messages in thread

From: Justin Pryzby @ 2022-06-10 11:48 UTC (permalink / raw)
  To: Pavel Stehule <pavel.stehule@gmail.com>; +Cc: Laurenz Albe <laurenz.albe@cybertec.at>; Ian Lawrence Barwick <barwick@gmail.com>; pgsql-hackers@postgresql.org, Gilles Darold <gilles@darold.net>

Rebased

Attachments: download all (4 files, .tar.gz)

0001-Add-pg_am_size-pg_namespace_size.patch (text/x-diff, 5.6K) download From 4d88986706e334e2dccc6f576139342c102033f8 Mon Sep 17 00:00:00 2001 From: Justin Pryzby <pryzbyj@telsasoft.com> Date: Tue, 13 Jul 2021 21:25:48 -0500 Subject: [PATCH 1/4] Add pg_am_size(), pg_namespace_size() .. See also: 358a897fa, 528ac10c7 --- src/backend/utils/adt/dbsize.c | 130 ++++++++++++++++++++++++++++++++ src/include/catalog/pg_proc.dat | 19 +++++ 2 files changed, 149 insertions(+) diff --git a/src/backend/utils/adt/dbsize.c b/src/backend/utils/adt/dbsize.c index b4a2c8d2197..a1348083ba3 100644 --- a/src/backend/utils/adt/dbsize.c +++ b/src/backend/utils/adt/dbsize.c @@ -13,18 +13,23 @@ #include <sys/stat.h> +#include "access/genam.h" #include "access/htup_details.h" #include "access/relation.h" +#include "access/table.h" #include "catalog/catalog.h" #include "catalog/namespace.h" #include "catalog/pg_authid.h" #include "catalog/pg_tablespace.h" #include "commands/dbcommands.h" +#include "commands/defrem.h" #include "commands/tablespace.h" #include "miscadmin.h" #include "storage/fd.h" #include "utils/acl.h" #include "utils/builtins.h" +#include "utils/fmgroids.h" +#include "utils/lsyscache.h" #include "utils/numeric.h" #include "utils/rel.h" #include "utils/relfilenodemap.h" @@ -832,6 +837,131 @@ pg_size_bytes(PG_FUNCTION_ARGS) PG_RETURN_INT64(result); } +/* + * Return the sum of size of relations for which the given attribute of + * pg_class matches the specified OID value. + */ +static int64 +calculate_size_attvalue(int attnum, Oid attval) +{ + int64 totalsize = 0; + ScanKeyData skey; + Relation pg_class; + SysScanDesc scan; + HeapTuple tuple; + + ScanKeyInit(&skey, attnum, + BTEqualStrategyNumber, F_OIDEQ, attval); + + pg_class = table_open(RelationRelationId, AccessShareLock); + scan = systable_beginscan(pg_class, InvalidOid, false, NULL, 1, &skey); + while (HeapTupleIsValid(tuple = systable_getnext(scan))) + { + Relation rel; + Form_pg_class classtuple = (Form_pg_class) GETSTRUCT(tuple); + + rel = try_relation_open(classtuple->oid, AccessShareLock); + if (!rel) + continue; + + for (ForkNumber forkNum = 0; forkNum <= MAX_FORKNUM; forkNum++) + totalsize += calculate_relation_size(&rel->rd_node, rel->rd_backend, forkNum); + + relation_close(rel, AccessShareLock); + } + + systable_endscan(scan); + table_close(pg_class, AccessShareLock); + return totalsize; +} + +/* Compute the size of relations in a schema (namespace) */ +static int64 +calculate_namespace_size(Oid nspOid) +{ + /* + * User must be a member of pg_read_all_stats or have CREATE privilege for + * target namespace. + */ + if (!is_member_of_role(GetUserId(), ROLE_PG_READ_ALL_STATS)) + { + AclResult aclresult; + aclresult = pg_namespace_aclcheck(nspOid, GetUserId(), ACL_CREATE); + if (aclresult != ACLCHECK_OK) + aclcheck_error(aclresult, OBJECT_SCHEMA, + get_namespace_name(nspOid)); + } + + return calculate_size_attvalue(Anum_pg_class_relnamespace, nspOid); +} + +Datum +pg_namespace_size_oid(PG_FUNCTION_ARGS) +{ + int64 size; + Oid nspOid = PG_GETARG_OID(0); + + size = calculate_namespace_size(nspOid); + + if (size < 0) + PG_RETURN_NULL(); + + PG_RETURN_INT64(size); +} + +Datum +pg_namespace_size_name(PG_FUNCTION_ARGS) +{ + int64 size; + Name nspName = PG_GETARG_NAME(0); + Oid nspOid = get_namespace_oid(NameStr(*nspName), false); + + size = calculate_namespace_size(nspOid); + + if (size < 0) + PG_RETURN_NULL(); + + PG_RETURN_INT64(size); +} + +/* Compute the size of relations using the given access method */ +static int64 +calculate_am_size(Oid amOid) +{ + /* XXX acl_check? */ + + return calculate_size_attvalue(Anum_pg_class_relam, amOid); +} + +Datum +pg_am_size_oid(PG_FUNCTION_ARGS) +{ + int64 size; + Oid amOid = PG_GETARG_OID(0); + + size = calculate_am_size(amOid); + + if (size < 0) + PG_RETURN_NULL(); + + PG_RETURN_INT64(size); +} + +Datum +pg_am_size_name(PG_FUNCTION_ARGS) +{ + int64 size; + Name amName = PG_GETARG_NAME(0); + Oid amOid = get_am_oid(NameStr(*amName), false); + + size = calculate_am_size(amOid); + + if (size < 0) + PG_RETURN_NULL(); + + PG_RETURN_INT64(size); +} + /* * Get the filenode of a relation * diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat index 87aa571a331..7507193f85d 100644 --- a/src/include/catalog/pg_proc.dat +++ b/src/include/catalog/pg_proc.dat @@ -7281,6 +7281,25 @@ descr => 'total disk space usage for the specified tablespace', proname => 'pg_tablespace_size', provolatile => 'v', prorettype => 'int8', proargtypes => 'name', prosrc => 'pg_tablespace_size_name' }, + +{ oid => '9410', + descr => 'total disk space usage for the specified namespace', + proname => 'pg_namespace_size', provolatile => 'v', prorettype => 'int8', + proargtypes => 'oid', prosrc => 'pg_namespace_size_oid' }, +{ oid => '9411', + descr => 'total disk space usage for the specified namespace', + proname => 'pg_namespace_size', provolatile => 'v', prorettype => 'int8', + proargtypes => 'name', prosrc => 'pg_namespace_size_name' }, + +{ oid => '9412', + descr => 'total disk space usage for the specified access method', + proname => 'pg_am_size', provolatile => 'v', prorettype => 'int8', + proargtypes => 'oid', prosrc => 'pg_am_size_oid' }, +{ oid => '9413', + descr => 'total disk space usage for the specified access method', + proname => 'pg_am_size', provolatile => 'v', prorettype => 'int8', + proargtypes => 'name', prosrc => 'pg_am_size_name' }, + { oid => '2324', descr => 'total disk space usage for the specified database', proname => 'pg_database_size', provolatile => 'v', prorettype => 'int8', proargtypes => 'oid', prosrc => 'pg_database_size_oid' }, -- 2.17.1
0002-psql-add-convenience-commands-dA-and-dn.patch (text/x-diff, 8.5K) download From c8db22278993a2456563df0a6f30c6dadbf6f059 Mon Sep 17 00:00:00 2001 From: Justin Pryzby <pryzbyj@telsasoft.com> Date: Sat, 18 Dec 2021 14:58:06 -0600 Subject: [PATCH 2/4] psql: add convenience commands: \dA+ and \dn+ show the size only with ++ in \dn, \dA, \db and (for consistency) \l \dt+ and \dP+ are not changed, since showing the table sizes seems to be their primary purpose. --- src/bin/psql/command.c | 22 ++++++++++++++-------- src/bin/psql/describe.c | 30 ++++++++++++++++++++++-------- src/bin/psql/describe.h | 8 ++++---- 3 files changed, 40 insertions(+), 20 deletions(-) diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c index b51d28780b1..cb65283547c 100644 --- a/src/bin/psql/command.c +++ b/src/bin/psql/command.c @@ -366,7 +366,8 @@ exec_command(const char *cmd, else if (strcmp(cmd, "if") == 0) status = exec_command_if(scan_state, cstack, query_buf); else if (strcmp(cmd, "l") == 0 || strcmp(cmd, "list") == 0 || - strcmp(cmd, "l+") == 0 || strcmp(cmd, "list+") == 0) + strcmp(cmd, "l+") == 0 || strcmp(cmd, "l++") == 0 || + strcmp(cmd, "list+") == 0 || strcmp(cmd, "list++") == 0) status = exec_command_list(scan_state, active_branch, cmd); else if (strncmp(cmd, "lo_", 3) == 0) status = exec_command_lo(scan_state, active_branch, cmd); @@ -718,6 +719,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) if (active_branch) { char *pattern; + int verbose = 0; bool show_verbose, show_system; @@ -725,7 +727,10 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) pattern = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, true); - show_verbose = strchr(cmd, '+') ? true : false; + for (const char *t = cmd; *t != '\0'; ++t) + verbose += *t == '+' ? 1 : 0; + + show_verbose = (bool) (verbose != 0); show_system = strchr(cmd, 'S') ? true : false; switch (cmd[1]) @@ -750,7 +755,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) { case '\0': case '+': - success = describeAccessMethods(pattern, show_verbose); + success = describeAccessMethods(pattern, verbose); break; case 'c': success = listOperatorClasses(pattern, pattern2, show_verbose); @@ -777,7 +782,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) success = describeAggregates(pattern, show_verbose, show_system); break; case 'b': - success = describeTablespaces(pattern, show_verbose); + success = describeTablespaces(pattern, verbose); break; case 'c': if (strncmp(cmd, "dconfig", 7) == 0) @@ -831,7 +836,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) success = listLanguages(pattern, show_verbose, show_system); break; case 'n': - success = listSchemas(pattern, show_verbose, show_system); + success = listSchemas(pattern, verbose, show_system); break; case 'o': success = exec_command_dfo(scan_state, cmd, pattern, @@ -1911,14 +1916,15 @@ exec_command_list(PsqlScanState scan_state, bool active_branch, const char *cmd) if (active_branch) { char *pattern; - bool show_verbose; + int verbose = 0; pattern = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, true); - show_verbose = strchr(cmd, '+') ? true : false; + for (const char *t = cmd; *t != '\0'; ++t) + verbose += *t == '+' ? 1 : 0; - success = listAllDbs(pattern, show_verbose); + success = listAllDbs(pattern, verbose); if (pattern) free(pattern); diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c index 1a5d924a23f..67163e834bc 100644 --- a/src/bin/psql/describe.c +++ b/src/bin/psql/describe.c @@ -136,12 +136,12 @@ 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; printQueryOpt myopt = pset.popt; - static const bool translate_columns[] = {false, true, false, false}; + static const bool translate_columns[] = {false, true, false, false, false}; if (pset.sversion < 90600) { @@ -173,6 +173,11 @@ describeAccessMethods(const char *pattern, bool verbose) " pg_catalog.obj_description(oid, 'pg_am') AS \"%s\"", gettext_noop("Handler"), gettext_noop("Description")); + + if (verbose > 1 && pset.sversion >= 160000) + appendPQExpBuffer(&buf, + ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_am_size(oid)) AS \"%s\"", + gettext_noop("Size")); } appendPQExpBufferStr(&buf, @@ -208,7 +213,7 @@ describeAccessMethods(const char *pattern, bool verbose) * Takes an optional regexp to select particular tablespaces */ bool -describeTablespaces(const char *pattern, bool verbose) +describeTablespaces(const char *pattern, int verbose) { PQExpBufferData buf; PGresult *res; @@ -228,12 +233,16 @@ describeTablespaces(const char *pattern, bool verbose) { appendPQExpBufferStr(&buf, ",\n "); printACLColumn(&buf, "spcacl"); + + if (verbose > 1) + appendPQExpBuffer(&buf, + ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_tablespace_size(oid)) AS \"%s\"", + gettext_noop("Size")); + appendPQExpBuffer(&buf, ",\n spcoptions AS \"%s\"" - ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_tablespace_size(oid)) AS \"%s\"" ",\n pg_catalog.shobj_description(oid, 'pg_tablespace') AS \"%s\"", gettext_noop("Options"), - gettext_noop("Size"), gettext_noop("Description")); } @@ -899,7 +908,7 @@ describeOperators(const char *oper_pattern, * for \l, \list, and -l switch */ bool -listAllDbs(const char *pattern, bool verbose) +listAllDbs(const char *pattern, int verbose) { PGresult *res; PQExpBufferData buf; @@ -932,7 +941,7 @@ listAllDbs(const char *pattern, bool verbose) gettext_noop("Locale Provider")); appendPQExpBufferStr(&buf, " "); printACLColumn(&buf, "d.datacl"); - if (verbose) + if (verbose > 1) appendPQExpBuffer(&buf, ",\n CASE WHEN pg_catalog.has_database_privilege(d.datname, 'CONNECT')\n" " THEN pg_catalog.pg_size_pretty(pg_catalog.pg_database_size(d.datname))\n" @@ -4881,7 +4890,7 @@ listCollations(const char *pattern, bool verbose, bool showSystem) * Describes schemas (namespaces) */ bool -listSchemas(const char *pattern, bool verbose, bool showSystem) +listSchemas(const char *pattern, int verbose, bool showSystem) { PQExpBufferData buf; PGresult *res; @@ -4903,6 +4912,11 @@ listSchemas(const char *pattern, bool verbose, bool showSystem) appendPQExpBuffer(&buf, ",\n pg_catalog.obj_description(n.oid, 'pg_namespace') AS \"%s\"", gettext_noop("Description")); + + if (verbose > 1 && pset.sversion >= 160000) + appendPQExpBuffer(&buf, + ",\n pg_catalog.pg_size_pretty(pg_namespace_size(n.oid)) AS \"%s\"", + gettext_noop("Size")); } appendPQExpBufferStr(&buf, diff --git a/src/bin/psql/describe.h b/src/bin/psql/describe.h index 7872c71f58d..4d889c71368 100644 --- a/src/bin/psql/describe.h +++ b/src/bin/psql/describe.h @@ -13,10 +13,10 @@ extern bool describeAggregates(const char *pattern, bool verbose, bool showSystem); /* \dA */ -extern bool describeAccessMethods(const char *pattern, bool verbose); +extern bool describeAccessMethods(const char *pattern, int verbose); /* \db */ -extern bool describeTablespaces(const char *pattern, bool verbose); +extern bool describeTablespaces(const char *pattern, int verbose); /* \df, \dfa, \dfn, \dft, \dfw, etc. */ extern bool describeFunctions(const char *functypes, const char *func_pattern, @@ -62,7 +62,7 @@ extern bool listTSDictionaries(const char *pattern, bool verbose); extern bool listTSTemplates(const char *pattern, bool verbose); /* \l */ -extern bool listAllDbs(const char *pattern, bool verbose); +extern bool listAllDbs(const char *pattern, int verbose); /* \dt, \di, \ds, \dS, etc. */ extern bool listTables(const char *tabtypes, const char *pattern, bool verbose, bool showSystem); @@ -87,7 +87,7 @@ extern bool listCasts(const char *pattern, bool verbose); extern bool listCollations(const char *pattern, bool verbose, bool showSystem); /* \dn */ -extern bool listSchemas(const char *pattern, bool verbose, bool showSystem); +extern bool listSchemas(const char *pattern, int verbose, bool showSystem); /* \dew */ extern bool listForeignDataWrappers(const char *pattern, bool verbose); -- 2.17.1
0003-f-convert-the-other-verbose-to-int-too.patch (text/x-diff, 41.0K) download From 8e35b070f37fec54445d40c0b152aef111ba3931 Mon Sep 17 00:00:00 2001 From: Justin Pryzby <pryzbyj@telsasoft.com> Date: Thu, 15 Jul 2021 03:19:58 -0500 Subject: [PATCH 3/4] f!convert the other verbose to int, too --- 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
0004-Move-the-double-plus-Size-columns-to-the-right.patch (text/x-diff, 10.0K) download From 5b09d2d3d97d840af3718e6005f1f2a65648b93d Mon Sep 17 00:00:00 2001 From: Justin Pryzby <pryzbyj@telsasoft.com> Date: Fri, 17 Dec 2021 09:35:46 -0600 Subject: [PATCH 4/4] Move the double-plus "Size" columns to the right \dn, \dA, \db, \l, \d and \dP+ It doesn't make much sense that one cannot show a database's default tablespace without also showing its size, and stat()ing every segment of every relation in the DB. --- src/bin/psql/describe.c | 42 ++++++++++++++--------- src/test/regress/expected/psql.out | 54 +++++++++++++++--------------- 2 files changed, 53 insertions(+), 43 deletions(-) diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c index 220262aa84c..9f73e90df23 100644 --- a/src/bin/psql/describe.c +++ b/src/bin/psql/describe.c @@ -234,11 +234,6 @@ describeTablespaces(const char *pattern, int verbose) appendPQExpBufferStr(&buf, ",\n "); printACLColumn(&buf, "spcacl"); - if (verbose > 1) - appendPQExpBuffer(&buf, - ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_tablespace_size(oid)) AS \"%s\"", - gettext_noop("Size")); - appendPQExpBuffer(&buf, ",\n spcoptions AS \"%s\"" ",\n pg_catalog.shobj_description(oid, 'pg_tablespace') AS \"%s\"", @@ -246,6 +241,11 @@ describeTablespaces(const char *pattern, int verbose) gettext_noop("Description")); } + if (verbose > 1) + appendPQExpBuffer(&buf, + ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_tablespace_size(oid)) AS \"%s\"", + gettext_noop("Size")); + appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_tablespace\n"); @@ -941,17 +941,22 @@ listAllDbs(const char *pattern, int verbose) gettext_noop("Locale Provider")); appendPQExpBufferStr(&buf, " "); printACLColumn(&buf, "d.datacl"); - if (verbose > 1) + + if (verbose > 0) appendPQExpBuffer(&buf, - ",\n CASE WHEN pg_catalog.has_database_privilege(d.datname, 'CONNECT')\n" - " THEN pg_catalog.pg_size_pretty(pg_catalog.pg_database_size(d.datname))\n" - " ELSE 'No Access'\n" - " END as \"%s\"" ",\n t.spcname as \"%s\"" ",\n pg_catalog.shobj_description(d.oid, 'pg_database') as \"%s\"", - gettext_noop("Size"), gettext_noop("Tablespace"), gettext_noop("Description")); + + if (verbose > 1) + appendPQExpBuffer(&buf, + ",\n CASE WHEN pg_catalog.has_database_privilege(d.datname, 'CONNECT')\n" + " THEN pg_catalog.pg_size_pretty(pg_catalog.pg_database_size(d.datname))\n" + " ELSE 'No Access'\n" + " END as \"%s\"", + gettext_noop("Size")); + appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_database d\n"); if (verbose > 0) @@ -3898,10 +3903,13 @@ listTables(const char *tabtypes, const char *pattern, int verbose, bool showSyst gettext_noop("Access method")); appendPQExpBuffer(&buf, - ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_table_size(c.oid)) as \"%s\"" ",\n pg_catalog.obj_description(c.oid, 'pg_class') as \"%s\"", - gettext_noop("Size"), gettext_noop("Description")); + + if (verbose > 1) + appendPQExpBuffer(&buf, + ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_table_size(c.oid)) as \"%s\"", + gettext_noop("Size")); } appendPQExpBufferStr(&buf, @@ -4082,6 +4090,11 @@ listPartitionedTables(const char *reltypes, const char *pattern, int verbose) gettext_noop("Table")); if (verbose > 0) + appendPQExpBuffer(&buf, + ",\n pg_catalog.obj_description(c.oid, 'pg_class') as \"%s\"", + gettext_noop("Description")); + + if (verbose > 1) { if (showNested) { @@ -4098,9 +4111,6 @@ listPartitionedTables(const char *reltypes, const char *pattern, int verbose) ",\n s.tps as \"%s\"", gettext_noop("Total size")); - appendPQExpBuffer(&buf, - ",\n pg_catalog.obj_description(c.oid, 'pg_class') as \"%s\"", - gettext_noop("Description")); } appendPQExpBufferStr(&buf, diff --git a/src/test/regress/expected/psql.out b/src/test/regress/expected/psql.out index 60acbd1241e..8da23d7216c 100644 --- a/src/test/regress/expected/psql.out +++ b/src/test/regress/expected/psql.out @@ -2857,47 +2857,47 @@ Access method: heap -- AM is displayed for tables, indexes and materialized views. \d+ - List of relations - Schema | Name | Type | Owner | Persistence | Access method | Size | Description ------------------+--------------------+-------------------+----------------------+-------------+---------------+---------+------------- - tableam_display | mat_view_heap_psql | materialized view | regress_display_role | permanent | heap_psql | 0 bytes | - tableam_display | tbl_heap | table | regress_display_role | permanent | heap | 0 bytes | - tableam_display | tbl_heap_psql | table | regress_display_role | permanent | heap_psql | 0 bytes | - tableam_display | view_heap_psql | view | regress_display_role | permanent | | 0 bytes | + List of relations + Schema | Name | Type | Owner | Persistence | Access method | Description +-----------------+--------------------+-------------------+----------------------+-------------+---------------+------------- + tableam_display | mat_view_heap_psql | materialized view | regress_display_role | permanent | heap_psql | + tableam_display | tbl_heap | table | regress_display_role | permanent | heap | + tableam_display | tbl_heap_psql | table | regress_display_role | permanent | heap_psql | + tableam_display | view_heap_psql | view | regress_display_role | permanent | | (4 rows) \dt+ - List of relations - Schema | Name | Type | Owner | Persistence | Access method | Size | Description ------------------+---------------+-------+----------------------+-------------+---------------+---------+------------- - tableam_display | tbl_heap | table | regress_display_role | permanent | heap | 0 bytes | - tableam_display | tbl_heap_psql | table | regress_display_role | permanent | heap_psql | 0 bytes | + List of relations + Schema | Name | Type | Owner | Persistence | Access method | Description +-----------------+---------------+-------+----------------------+-------------+---------------+------------- + tableam_display | tbl_heap | table | regress_display_role | permanent | heap | + tableam_display | tbl_heap_psql | table | regress_display_role | permanent | heap_psql | (2 rows) \dm+ - List of relations - Schema | Name | Type | Owner | Persistence | Access method | Size | Description ------------------+--------------------+-------------------+----------------------+-------------+---------------+---------+------------- - tableam_display | mat_view_heap_psql | materialized view | regress_display_role | permanent | heap_psql | 0 bytes | + List of relations + Schema | Name | Type | Owner | Persistence | Access method | Description +-----------------+--------------------+-------------------+----------------------+-------------+---------------+------------- + tableam_display | mat_view_heap_psql | materialized view | regress_display_role | permanent | heap_psql | (1 row) -- But not for views and sequences. \dv+ - List of relations - Schema | Name | Type | Owner | Persistence | Size | Description ------------------+----------------+------+----------------------+-------------+---------+------------- - tableam_display | view_heap_psql | view | regress_display_role | permanent | 0 bytes | + List of relations + Schema | Name | Type | Owner | Persistence | Description +-----------------+----------------+------+----------------------+-------------+------------- + tableam_display | view_heap_psql | view | regress_display_role | permanent | (1 row) \set HIDE_TABLEAM on \d+ - List of relations - Schema | Name | Type | Owner | Persistence | Size | Description ------------------+--------------------+-------------------+----------------------+-------------+---------+------------- - tableam_display | mat_view_heap_psql | materialized view | regress_display_role | permanent | 0 bytes | - tableam_display | tbl_heap | table | regress_display_role | permanent | 0 bytes | - tableam_display | tbl_heap_psql | table | regress_display_role | permanent | 0 bytes | - tableam_display | view_heap_psql | view | regress_display_role | permanent | 0 bytes | + List of relations + Schema | Name | Type | Owner | Persistence | Description +-----------------+--------------------+-------------------+----------------------+-------------+------------- + tableam_display | mat_view_heap_psql | materialized view | regress_display_role | permanent | + tableam_display | tbl_heap | table | regress_display_role | permanent | + tableam_display | tbl_heap_psql | table | regress_display_role | permanent | + tableam_display | view_heap_psql | view | regress_display_role | permanent | (4 rows) RESET ROLE; -- 2.17.1
^ permalink raw reply [nested|flat] 22+ messages in thread

* Re: [PATCH] psql: \dn+ to show size of each schema (and \dA+ for AMs)
@ 2022-07-30 05:35  Justin Pryzby <pryzby@telsasoft.com>
  parent: Justin Pryzby <pryzby@telsasoft.com>
  0 siblings, 2 replies; 22+ messages in thread

From: Justin Pryzby @ 2022-07-30 05:35 UTC (permalink / raw)
  To: Pavel Stehule <pavel.stehule@gmail.com>; +Cc: Laurenz Albe <laurenz.albe@cybertec.at>; Ian Lawrence Barwick <barwick@gmail.com>; pgsql-hackers@postgresql.org, Gilles Darold <gilles@darold.net>

rebased

Attachments: download all (4 files, .tar.gz)

v8-0001-Add-pg_am_size-pg_namespace_size.patch (text/x-diff, 5.6K) download From 1e560284832c157ca18a43f44b090e5b35b0cfb3 Mon Sep 17 00:00:00 2001 From: Justin Pryzby <pryzbyj@telsasoft.com> Date: Tue, 13 Jul 2021 21:25:48 -0500 Subject: [PATCH v8 1/4] Add pg_am_size(), pg_namespace_size() .. See also: 358a897fa, 528ac10c7 --- src/backend/utils/adt/dbsize.c | 130 ++++++++++++++++++++++++++++++++ src/include/catalog/pg_proc.dat | 19 +++++ 2 files changed, 149 insertions(+) diff --git a/src/backend/utils/adt/dbsize.c b/src/backend/utils/adt/dbsize.c index 34efa121b40..85a3dd4b7ab 100644 --- a/src/backend/utils/adt/dbsize.c +++ b/src/backend/utils/adt/dbsize.c @@ -13,18 +13,23 @@ #include <sys/stat.h> +#include "access/genam.h" #include "access/htup_details.h" #include "access/relation.h" +#include "access/table.h" #include "catalog/catalog.h" #include "catalog/namespace.h" #include "catalog/pg_authid.h" #include "catalog/pg_tablespace.h" #include "commands/dbcommands.h" +#include "commands/defrem.h" #include "commands/tablespace.h" #include "miscadmin.h" #include "storage/fd.h" #include "utils/acl.h" #include "utils/builtins.h" +#include "utils/fmgroids.h" +#include "utils/lsyscache.h" #include "utils/numeric.h" #include "utils/rel.h" #include "utils/relfilenumbermap.h" @@ -832,6 +837,131 @@ pg_size_bytes(PG_FUNCTION_ARGS) PG_RETURN_INT64(result); } +/* + * Return the sum of size of relations for which the given attribute of + * pg_class matches the specified OID value. + */ +static int64 +calculate_size_attvalue(int attnum, Oid attval) +{ + int64 totalsize = 0; + ScanKeyData skey; + Relation pg_class; + SysScanDesc scan; + HeapTuple tuple; + + ScanKeyInit(&skey, attnum, + BTEqualStrategyNumber, F_OIDEQ, attval); + + pg_class = table_open(RelationRelationId, AccessShareLock); + scan = systable_beginscan(pg_class, InvalidOid, false, NULL, 1, &skey); + while (HeapTupleIsValid(tuple = systable_getnext(scan))) + { + Relation rel; + Form_pg_class classtuple = (Form_pg_class) GETSTRUCT(tuple); + + rel = try_relation_open(classtuple->oid, AccessShareLock); + if (!rel) + continue; + + for (ForkNumber forkNum = 0; forkNum <= MAX_FORKNUM; forkNum++) + totalsize += calculate_relation_size(&(rel->rd_locator), rel->rd_backend, forkNum); + + relation_close(rel, AccessShareLock); + } + + systable_endscan(scan); + table_close(pg_class, AccessShareLock); + return totalsize; +} + +/* Compute the size of relations in a schema (namespace) */ +static int64 +calculate_namespace_size(Oid nspOid) +{ + /* + * User must be a member of pg_read_all_stats or have CREATE privilege for + * target namespace. + */ + if (!is_member_of_role(GetUserId(), ROLE_PG_READ_ALL_STATS)) + { + AclResult aclresult; + aclresult = pg_namespace_aclcheck(nspOid, GetUserId(), ACL_CREATE); + if (aclresult != ACLCHECK_OK) + aclcheck_error(aclresult, OBJECT_SCHEMA, + get_namespace_name(nspOid)); + } + + return calculate_size_attvalue(Anum_pg_class_relnamespace, nspOid); +} + +Datum +pg_namespace_size_oid(PG_FUNCTION_ARGS) +{ + int64 size; + Oid nspOid = PG_GETARG_OID(0); + + size = calculate_namespace_size(nspOid); + + if (size < 0) + PG_RETURN_NULL(); + + PG_RETURN_INT64(size); +} + +Datum +pg_namespace_size_name(PG_FUNCTION_ARGS) +{ + int64 size; + Name nspName = PG_GETARG_NAME(0); + Oid nspOid = get_namespace_oid(NameStr(*nspName), false); + + size = calculate_namespace_size(nspOid); + + if (size < 0) + PG_RETURN_NULL(); + + PG_RETURN_INT64(size); +} + +/* Compute the size of relations using the given access method */ +static int64 +calculate_am_size(Oid amOid) +{ + /* XXX acl_check? */ + + return calculate_size_attvalue(Anum_pg_class_relam, amOid); +} + +Datum +pg_am_size_oid(PG_FUNCTION_ARGS) +{ + int64 size; + Oid amOid = PG_GETARG_OID(0); + + size = calculate_am_size(amOid); + + if (size < 0) + PG_RETURN_NULL(); + + PG_RETURN_INT64(size); +} + +Datum +pg_am_size_name(PG_FUNCTION_ARGS) +{ + int64 size; + Name amName = PG_GETARG_NAME(0); + Oid amOid = get_am_oid(NameStr(*amName), false); + + size = calculate_am_size(amOid); + + if (size < 0) + PG_RETURN_NULL(); + + PG_RETURN_INT64(size); +} + /* * Get the filenode of a relation * diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat index be47583122b..6c29b9f9d5f 100644 --- a/src/include/catalog/pg_proc.dat +++ b/src/include/catalog/pg_proc.dat @@ -7289,6 +7289,25 @@ descr => 'total disk space usage for the specified tablespace', proname => 'pg_tablespace_size', provolatile => 'v', prorettype => 'int8', proargtypes => 'name', prosrc => 'pg_tablespace_size_name' }, + +{ oid => '9410', + descr => 'total disk space usage for the specified namespace', + proname => 'pg_namespace_size', provolatile => 'v', prorettype => 'int8', + proargtypes => 'oid', prosrc => 'pg_namespace_size_oid' }, +{ oid => '9411', + descr => 'total disk space usage for the specified namespace', + proname => 'pg_namespace_size', provolatile => 'v', prorettype => 'int8', + proargtypes => 'name', prosrc => 'pg_namespace_size_name' }, + +{ oid => '9412', + descr => 'total disk space usage for the specified access method', + proname => 'pg_am_size', provolatile => 'v', prorettype => 'int8', + proargtypes => 'oid', prosrc => 'pg_am_size_oid' }, +{ oid => '9413', + descr => 'total disk space usage for the specified access method', + proname => 'pg_am_size', provolatile => 'v', prorettype => 'int8', + proargtypes => 'name', prosrc => 'pg_am_size_name' }, + { oid => '2324', descr => 'total disk space usage for the specified database', proname => 'pg_database_size', provolatile => 'v', prorettype => 'int8', proargtypes => 'oid', prosrc => 'pg_database_size_oid' }, -- 2.17.1
v8-0002-psql-add-convenience-commands-dA-and-dn.patch (text/x-diff, 8.6K) download From 6ccdd7f2c1b9e7302d7121055855b3d16c33eabc Mon Sep 17 00:00:00 2001 From: Justin Pryzby <pryzbyj@telsasoft.com> Date: Sat, 18 Dec 2021 14:58:06 -0600 Subject: [PATCH v8 2/4] psql: add convenience commands: \dA+ and \dn+ show the size only with ++ in \dn, \dA, \db and (for consistency) \l \dt+ and \dP+ are not changed, since showing the table sizes seems to be their primary purpose. The idea for plusplus commands were previously discussed here. https://www.postgresql.org/message-id/20190506163359.GA29291%40alvherre.pgsql --- src/bin/psql/command.c | 22 ++++++++++++++-------- src/bin/psql/describe.c | 30 ++++++++++++++++++++++-------- src/bin/psql/describe.h | 8 ++++---- 3 files changed, 40 insertions(+), 20 deletions(-) diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c index a81bd3307b4..99ee47f436a 100644 --- a/src/bin/psql/command.c +++ b/src/bin/psql/command.c @@ -366,7 +366,8 @@ exec_command(const char *cmd, else if (strcmp(cmd, "if") == 0) status = exec_command_if(scan_state, cstack, query_buf); else if (strcmp(cmd, "l") == 0 || strcmp(cmd, "list") == 0 || - strcmp(cmd, "l+") == 0 || strcmp(cmd, "list+") == 0) + strcmp(cmd, "l+") == 0 || strcmp(cmd, "l++") == 0 || + strcmp(cmd, "list+") == 0 || strcmp(cmd, "list++") == 0) status = exec_command_list(scan_state, active_branch, cmd); else if (strncmp(cmd, "lo_", 3) == 0) status = exec_command_lo(scan_state, active_branch, cmd); @@ -717,6 +718,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) if (active_branch) { char *pattern; + int verbose = 0; bool show_verbose, show_system; @@ -724,7 +726,10 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) pattern = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, true); - show_verbose = strchr(cmd, '+') ? true : false; + for (const char *t = cmd; *t != '\0'; ++t) + verbose += *t == '+' ? 1 : 0; + + show_verbose = (bool) (verbose != 0); show_system = strchr(cmd, 'S') ? true : false; switch (cmd[1]) @@ -749,7 +754,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) { case '\0': case '+': - success = describeAccessMethods(pattern, show_verbose); + success = describeAccessMethods(pattern, verbose); break; case 'c': success = listOperatorClasses(pattern, pattern2, show_verbose); @@ -775,7 +780,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) success = describeAggregates(pattern, show_verbose, show_system); break; case 'b': - success = describeTablespaces(pattern, show_verbose); + success = describeTablespaces(pattern, verbose); break; case 'c': if (strncmp(cmd, "dconfig", 7) == 0) @@ -829,7 +834,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) success = listLanguages(pattern, show_verbose, show_system); break; case 'n': - success = listSchemas(pattern, show_verbose, show_system); + success = listSchemas(pattern, verbose, show_system); break; case 'o': success = exec_command_dfo(scan_state, cmd, pattern, @@ -1904,14 +1909,15 @@ exec_command_list(PsqlScanState scan_state, bool active_branch, const char *cmd) if (active_branch) { char *pattern; - bool show_verbose; + int verbose = 0; pattern = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, true); - show_verbose = strchr(cmd, '+') ? true : false; + for (const char *t = cmd; *t != '\0'; ++t) + verbose += *t == '+' ? 1 : 0; - success = listAllDbs(pattern, show_verbose); + success = listAllDbs(pattern, verbose); free(pattern); } diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c index 327a69487bb..677dd64cda0 100644 --- a/src/bin/psql/describe.c +++ b/src/bin/psql/describe.c @@ -139,12 +139,12 @@ 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; printQueryOpt myopt = pset.popt; - static const bool translate_columns[] = {false, true, false, false}; + static const bool translate_columns[] = {false, true, false, false, false}; if (pset.sversion < 90600) { @@ -176,6 +176,11 @@ describeAccessMethods(const char *pattern, bool verbose) " pg_catalog.obj_description(oid, 'pg_am') AS \"%s\"", gettext_noop("Handler"), gettext_noop("Description")); + + if (verbose > 1 && pset.sversion >= 160000) + appendPQExpBuffer(&buf, + ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_am_size(oid)) AS \"%s\"", + gettext_noop("Size")); } appendPQExpBufferStr(&buf, @@ -214,7 +219,7 @@ describeAccessMethods(const char *pattern, bool verbose) * Takes an optional regexp to select particular tablespaces */ bool -describeTablespaces(const char *pattern, bool verbose) +describeTablespaces(const char *pattern, int verbose) { PQExpBufferData buf; PGresult *res; @@ -234,12 +239,16 @@ describeTablespaces(const char *pattern, bool verbose) { appendPQExpBufferStr(&buf, ",\n "); printACLColumn(&buf, "spcacl"); + + if (verbose > 1) + appendPQExpBuffer(&buf, + ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_tablespace_size(oid)) AS \"%s\"", + gettext_noop("Size")); + appendPQExpBuffer(&buf, ",\n spcoptions AS \"%s\"" - ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_tablespace_size(oid)) AS \"%s\"" ",\n pg_catalog.shobj_description(oid, 'pg_tablespace') AS \"%s\"", gettext_noop("Options"), - gettext_noop("Size"), gettext_noop("Description")); } @@ -919,7 +928,7 @@ error_return: * for \l, \list, and -l switch */ bool -listAllDbs(const char *pattern, bool verbose) +listAllDbs(const char *pattern, int verbose) { PGresult *res; PQExpBufferData buf; @@ -952,7 +961,7 @@ listAllDbs(const char *pattern, bool verbose) gettext_noop("Locale Provider")); appendPQExpBufferStr(&buf, " "); printACLColumn(&buf, "d.datacl"); - if (verbose) + if (verbose > 1) appendPQExpBuffer(&buf, ",\n CASE WHEN pg_catalog.has_database_privilege(d.datname, 'CONNECT')\n" " THEN pg_catalog.pg_size_pretty(pg_catalog.pg_database_size(d.datname))\n" @@ -4949,7 +4958,7 @@ listCollations(const char *pattern, bool verbose, bool showSystem) * Describes schemas (namespaces) */ bool -listSchemas(const char *pattern, bool verbose, bool showSystem) +listSchemas(const char *pattern, int verbose, bool showSystem) { PQExpBufferData buf; PGresult *res; @@ -4971,6 +4980,11 @@ listSchemas(const char *pattern, bool verbose, bool showSystem) appendPQExpBuffer(&buf, ",\n pg_catalog.obj_description(n.oid, 'pg_namespace') AS \"%s\"", gettext_noop("Description")); + + if (verbose > 1 && pset.sversion >= 160000) + appendPQExpBuffer(&buf, + ",\n pg_catalog.pg_size_pretty(pg_namespace_size(n.oid)) AS \"%s\"", + gettext_noop("Size")); } appendPQExpBufferStr(&buf, diff --git a/src/bin/psql/describe.h b/src/bin/psql/describe.h index 7872c71f58d..4d889c71368 100644 --- a/src/bin/psql/describe.h +++ b/src/bin/psql/describe.h @@ -13,10 +13,10 @@ extern bool describeAggregates(const char *pattern, bool verbose, bool showSystem); /* \dA */ -extern bool describeAccessMethods(const char *pattern, bool verbose); +extern bool describeAccessMethods(const char *pattern, int verbose); /* \db */ -extern bool describeTablespaces(const char *pattern, bool verbose); +extern bool describeTablespaces(const char *pattern, int verbose); /* \df, \dfa, \dfn, \dft, \dfw, etc. */ extern bool describeFunctions(const char *functypes, const char *func_pattern, @@ -62,7 +62,7 @@ extern bool listTSDictionaries(const char *pattern, bool verbose); extern bool listTSTemplates(const char *pattern, bool verbose); /* \l */ -extern bool listAllDbs(const char *pattern, bool verbose); +extern bool listAllDbs(const char *pattern, int verbose); /* \dt, \di, \ds, \dS, etc. */ extern bool listTables(const char *tabtypes, const char *pattern, bool verbose, bool showSystem); @@ -87,7 +87,7 @@ extern bool listCasts(const char *pattern, bool verbose); extern bool listCollations(const char *pattern, bool verbose, bool showSystem); /* \dn */ -extern bool listSchemas(const char *pattern, bool verbose, bool showSystem); +extern bool listSchemas(const char *pattern, int verbose, bool showSystem); /* \dew */ extern bool listForeignDataWrappers(const char *pattern, bool verbose); -- 2.17.1
v8-0003-f-convert-the-other-verbose-to-int-too.patch (text/x-diff, 40.7K) download From aeea61db0844b6742bd95949d2f05bcea342458e Mon Sep 17 00:00:00 2001 From: Justin Pryzby <pryzbyj@telsasoft.com> Date: Thu, 15 Jul 2021 03:19:58 -0500 Subject: [PATCH v8 3/4] f!convert the other verbose to int, too --- 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
v8-0004-Move-the-double-plus-Size-columns-to-the-right.patch (text/x-diff, 10.0K) download From 58b3d5a2b4be561707ed85fd86a156b26239cf03 Mon Sep 17 00:00:00 2001 From: Justin Pryzby <pryzbyj@telsasoft.com> Date: Fri, 17 Dec 2021 09:35:46 -0600 Subject: [PATCH v8 4/4] Move the double-plus "Size" columns to the right \dn, \dA, \db, \l, \d and \dP+ It doesn't make much sense that one cannot show a database's default tablespace without also showing its size, and stat()ing every segment of every relation in the DB. --- src/bin/psql/describe.c | 42 ++++++++++++++--------- src/test/regress/expected/psql.out | 54 +++++++++++++++--------------- 2 files changed, 53 insertions(+), 43 deletions(-) diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c index 2e47ea448f7..22fc19a47dd 100644 --- a/src/bin/psql/describe.c +++ b/src/bin/psql/describe.c @@ -240,11 +240,6 @@ describeTablespaces(const char *pattern, int verbose) appendPQExpBufferStr(&buf, ",\n "); printACLColumn(&buf, "spcacl"); - if (verbose > 1) - appendPQExpBuffer(&buf, - ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_tablespace_size(oid)) AS \"%s\"", - gettext_noop("Size")); - appendPQExpBuffer(&buf, ",\n spcoptions AS \"%s\"" ",\n pg_catalog.shobj_description(oid, 'pg_tablespace') AS \"%s\"", @@ -252,6 +247,11 @@ describeTablespaces(const char *pattern, int verbose) gettext_noop("Description")); } + if (verbose > 1) + appendPQExpBuffer(&buf, + ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_tablespace_size(oid)) AS \"%s\"", + gettext_noop("Size")); + appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_tablespace\n"); @@ -961,17 +961,22 @@ listAllDbs(const char *pattern, int verbose) gettext_noop("Locale Provider")); appendPQExpBufferStr(&buf, " "); printACLColumn(&buf, "d.datacl"); - if (verbose > 1) + + if (verbose > 0) appendPQExpBuffer(&buf, - ",\n CASE WHEN pg_catalog.has_database_privilege(d.datname, 'CONNECT')\n" - " THEN pg_catalog.pg_size_pretty(pg_catalog.pg_database_size(d.datname))\n" - " ELSE 'No Access'\n" - " END as \"%s\"" ",\n t.spcname as \"%s\"" ",\n pg_catalog.shobj_description(d.oid, 'pg_database') as \"%s\"", - gettext_noop("Size"), gettext_noop("Tablespace"), gettext_noop("Description")); + + if (verbose > 1) + appendPQExpBuffer(&buf, + ",\n CASE WHEN pg_catalog.has_database_privilege(d.datname, 'CONNECT')\n" + " THEN pg_catalog.pg_size_pretty(pg_catalog.pg_database_size(d.datname))\n" + " ELSE 'No Access'\n" + " END as \"%s\"", + gettext_noop("Size")); + appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_database d\n"); if (verbose > 0) @@ -3936,10 +3941,13 @@ listTables(const char *tabtypes, const char *pattern, int verbose, bool showSyst gettext_noop("Access method")); appendPQExpBuffer(&buf, - ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_table_size(c.oid)) as \"%s\"" ",\n pg_catalog.obj_description(c.oid, 'pg_class') as \"%s\"", - gettext_noop("Size"), gettext_noop("Description")); + + if (verbose > 1) + appendPQExpBuffer(&buf, + ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_table_size(c.oid)) as \"%s\"", + gettext_noop("Size")); } appendPQExpBufferStr(&buf, @@ -4123,6 +4131,11 @@ listPartitionedTables(const char *reltypes, const char *pattern, int verbose) gettext_noop("Table")); if (verbose > 0) + appendPQExpBuffer(&buf, + ",\n pg_catalog.obj_description(c.oid, 'pg_class') as \"%s\"", + gettext_noop("Description")); + + if (verbose > 1) { if (showNested) { @@ -4139,9 +4152,6 @@ listPartitionedTables(const char *reltypes, const char *pattern, int verbose) ",\n s.tps as \"%s\"", gettext_noop("Total size")); - appendPQExpBuffer(&buf, - ",\n pg_catalog.obj_description(c.oid, 'pg_class') as \"%s\"", - gettext_noop("Description")); } appendPQExpBufferStr(&buf, diff --git a/src/test/regress/expected/psql.out b/src/test/regress/expected/psql.out index a7f5700edc1..2daa4685b4b 100644 --- a/src/test/regress/expected/psql.out +++ b/src/test/regress/expected/psql.out @@ -2858,47 +2858,47 @@ Access method: heap -- AM is displayed for tables, indexes and materialized views. \d+ - List of relations - Schema | Name | Type | Owner | Persistence | Access method | Size | Description ------------------+--------------------+-------------------+----------------------+-------------+---------------+---------+------------- - tableam_display | mat_view_heap_psql | materialized view | regress_display_role | permanent | heap_psql | 0 bytes | - tableam_display | tbl_heap | table | regress_display_role | permanent | heap | 0 bytes | - tableam_display | tbl_heap_psql | table | regress_display_role | permanent | heap_psql | 0 bytes | - tableam_display | view_heap_psql | view | regress_display_role | permanent | | 0 bytes | + List of relations + Schema | Name | Type | Owner | Persistence | Access method | Description +-----------------+--------------------+-------------------+----------------------+-------------+---------------+------------- + tableam_display | mat_view_heap_psql | materialized view | regress_display_role | permanent | heap_psql | + tableam_display | tbl_heap | table | regress_display_role | permanent | heap | + tableam_display | tbl_heap_psql | table | regress_display_role | permanent | heap_psql | + tableam_display | view_heap_psql | view | regress_display_role | permanent | | (4 rows) \dt+ - List of relations - Schema | Name | Type | Owner | Persistence | Access method | Size | Description ------------------+---------------+-------+----------------------+-------------+---------------+---------+------------- - tableam_display | tbl_heap | table | regress_display_role | permanent | heap | 0 bytes | - tableam_display | tbl_heap_psql | table | regress_display_role | permanent | heap_psql | 0 bytes | + List of relations + Schema | Name | Type | Owner | Persistence | Access method | Description +-----------------+---------------+-------+----------------------+-------------+---------------+------------- + tableam_display | tbl_heap | table | regress_display_role | permanent | heap | + tableam_display | tbl_heap_psql | table | regress_display_role | permanent | heap_psql | (2 rows) \dm+ - List of relations - Schema | Name | Type | Owner | Persistence | Access method | Size | Description ------------------+--------------------+-------------------+----------------------+-------------+---------------+---------+------------- - tableam_display | mat_view_heap_psql | materialized view | regress_display_role | permanent | heap_psql | 0 bytes | + List of relations + Schema | Name | Type | Owner | Persistence | Access method | Description +-----------------+--------------------+-------------------+----------------------+-------------+---------------+------------- + tableam_display | mat_view_heap_psql | materialized view | regress_display_role | permanent | heap_psql | (1 row) -- But not for views and sequences. \dv+ - List of relations - Schema | Name | Type | Owner | Persistence | Size | Description ------------------+----------------+------+----------------------+-------------+---------+------------- - tableam_display | view_heap_psql | view | regress_display_role | permanent | 0 bytes | + List of relations + Schema | Name | Type | Owner | Persistence | Description +-----------------+----------------+------+----------------------+-------------+------------- + tableam_display | view_heap_psql | view | regress_display_role | permanent | (1 row) \set HIDE_TABLEAM on \d+ - List of relations - Schema | Name | Type | Owner | Persistence | Size | Description ------------------+--------------------+-------------------+----------------------+-------------+---------+------------- - tableam_display | mat_view_heap_psql | materialized view | regress_display_role | permanent | 0 bytes | - tableam_display | tbl_heap | table | regress_display_role | permanent | 0 bytes | - tableam_display | tbl_heap_psql | table | regress_display_role | permanent | 0 bytes | - tableam_display | view_heap_psql | view | regress_display_role | permanent | 0 bytes | + List of relations + Schema | Name | Type | Owner | Persistence | Description +-----------------+--------------------+-------------------+----------------------+-------------+------------- + tableam_display | mat_view_heap_psql | materialized view | regress_display_role | permanent | + tableam_display | tbl_heap | table | regress_display_role | permanent | + tableam_display | tbl_heap_psql | table | regress_display_role | permanent | + tableam_display | view_heap_psql | view | regress_display_role | permanent | (4 rows) RESET ROLE; -- 2.17.1
^ permalink raw reply [nested|flat] 22+ messages in thread

* Re: [PATCH] psql: \dn+ to show size of each schema (and \dA+ for AMs)
@ 2022-08-01 20:47  Jacob Champion <jchampion@timescale.com>
  parent: Justin Pryzby <pryzby@telsasoft.com>
  1 sibling, 0 replies; 22+ messages in thread

From: Jacob Champion @ 2022-08-01 20:47 UTC (permalink / raw)
  To: Justin Pryzby <pryzby@telsasoft.com>; Pavel Stehule <pavel.stehule@gmail.com>; +Cc: Laurenz Albe <laurenz.albe@cybertec.at>; Ian Lawrence Barwick <barwick@gmail.com>; pgsql-hackers@postgresql.org, Gilles Darold <gilles@darold.net>

As discussed in [1], we're taking this opportunity to return some
patchsets that don't appear to be getting enough reviewer interest.

This is not a rejection, since we don't necessarily think there's
anything unacceptable about the entry, but it differs from a standard
"Returned with Feedback" in that there's probably not much actionable
feedback at all. Rather than code changes, what this patch needs is more
community interest. You might

- ask people for help with your approach,
- see if there are similar patches that your code could supplement,
- get interested parties to agree to review your patch in a CF, or
- possibly present the functionality in a way that's easier to review
  overall.

(Doing these things is no guarantee that there will be interest, but
it's hopefully better than endlessly rebasing a patchset that is not
receiving any feedback from the community.)

Once you think you've built up some community support and the patchset
is ready for review, you (or any interested party) can resurrect the
patch entry by visiting

    https://commitfest.postgresql.org/38/3256/

and changing the status to "Needs Review", and then changing the
status again to "Move to next CF". (Don't forget the second step;
hopefully we will have streamlined this in the near future!)

Thanks,
--Jacob

[1] https://postgr.es/m/86140760-8ba5-6f3a-3e6e-5ca6c060bd24@timescale.com






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

* Re: [PATCH] psql: \dn+ to show size of each schema (and \dA+ for AMs)
@ 2022-12-15 16:13  Justin Pryzby <pryzby@telsasoft.com>
  parent: Justin Pryzby <pryzby@telsasoft.com>
  1 sibling, 2 replies; 22+ messages in thread

From: Justin Pryzby @ 2022-12-15 16:13 UTC (permalink / raw)
  To: Pavel Stehule <pavel.stehule@gmail.com>; +Cc: Laurenz Albe <laurenz.albe@cybertec.at>; Ian Lawrence Barwick <barwick@gmail.com>; pgsql-hackers@postgresql.org, Gilles Darold <gilles@darold.net>; Julien Rouhaud <rjuju123@gmail.com>

Rebased on c727f511b.

This patch record was "closed for lack of interest", but I think what's
actually needed is committer review of which approach to take.

 - add backend functions but do not modify psql ?
 - add to psql slash-plus commnds ?
 - introduce psql double-plus commands for new options ?
 - change pre-existing psql plus commands to only show size with
   double-plus ?
 - go back to the original, two-line client-side sum() ?

Until then, the patchset is organized with those questions in mind.

-- 
Justin

Attachments: download all (4 files, .tar.gz)

0001-Add-pg_am_size-pg_namespace_size.patch (text/x-diff, 5.6K) download From 84316b06d1a6286d30e163c4815c840548d639db Mon Sep 17 00:00:00 2001 From: Justin Pryzby <pryzbyj@telsasoft.com> Date: Tue, 13 Jul 2021 21:25:48 -0500 Subject: [PATCH 1/4] Add pg_am_size(), pg_namespace_size() .. See also: 358a897fa, 528ac10c7 --- src/backend/utils/adt/dbsize.c | 131 ++++++++++++++++++++++++++++++++ src/include/catalog/pg_proc.dat | 19 +++++ 2 files changed, 150 insertions(+) diff --git a/src/backend/utils/adt/dbsize.c b/src/backend/utils/adt/dbsize.c index 141db7c9c1c..2e7e98f5676 100644 --- a/src/backend/utils/adt/dbsize.c +++ b/src/backend/utils/adt/dbsize.c @@ -13,19 +13,25 @@ #include <sys/stat.h> +#include "access/genam.h" #include "access/htup_details.h" #include "access/relation.h" +#include "access/table.h" #include "catalog/catalog.h" #include "catalog/namespace.h" #include "catalog/pg_authid.h" #include "catalog/pg_database.h" +#include "catalog/pg_namespace.h" #include "catalog/pg_tablespace.h" #include "commands/dbcommands.h" +#include "commands/defrem.h" #include "commands/tablespace.h" #include "miscadmin.h" #include "storage/fd.h" #include "utils/acl.h" #include "utils/builtins.h" +#include "utils/fmgroids.h" +#include "utils/lsyscache.h" #include "utils/numeric.h" #include "utils/rel.h" #include "utils/relfilenumbermap.h" @@ -833,6 +839,131 @@ pg_size_bytes(PG_FUNCTION_ARGS) PG_RETURN_INT64(result); } +/* + * Return the sum of size of relations for which the given attribute of + * pg_class matches the specified OID value. + */ +static int64 +calculate_size_attvalue(int attnum, Oid attval) +{ + int64 totalsize = 0; + ScanKeyData skey; + Relation pg_class; + SysScanDesc scan; + HeapTuple tuple; + + ScanKeyInit(&skey, attnum, + BTEqualStrategyNumber, F_OIDEQ, attval); + + pg_class = table_open(RelationRelationId, AccessShareLock); + scan = systable_beginscan(pg_class, InvalidOid, false, NULL, 1, &skey); + while (HeapTupleIsValid(tuple = systable_getnext(scan))) + { + Relation rel; + Form_pg_class classtuple = (Form_pg_class) GETSTRUCT(tuple); + + rel = try_relation_open(classtuple->oid, AccessShareLock); + if (!rel) + continue; + + for (ForkNumber forkNum = 0; forkNum <= MAX_FORKNUM; forkNum++) + totalsize += calculate_relation_size(&(rel->rd_locator), rel->rd_backend, forkNum); + + relation_close(rel, AccessShareLock); + } + + systable_endscan(scan); + table_close(pg_class, AccessShareLock); + return totalsize; +} + +/* Compute the size of relations in a schema (namespace) */ +static int64 +calculate_namespace_size(Oid nspOid) +{ + /* + * User must be a member of pg_read_all_stats or have CREATE privilege for + * target namespace. + */ + if (!is_member_of_role(GetUserId(), ROLE_PG_READ_ALL_STATS)) + { + AclResult aclresult; + aclresult = object_aclcheck(NamespaceRelationId, nspOid, GetUserId(), ACL_CREATE); + if (aclresult != ACLCHECK_OK) + aclcheck_error(aclresult, OBJECT_SCHEMA, + get_namespace_name(nspOid)); + } + + return calculate_size_attvalue(Anum_pg_class_relnamespace, nspOid); +} + +Datum +pg_namespace_size_oid(PG_FUNCTION_ARGS) +{ + int64 size; + Oid nspOid = PG_GETARG_OID(0); + + size = calculate_namespace_size(nspOid); + + if (size < 0) + PG_RETURN_NULL(); + + PG_RETURN_INT64(size); +} + +Datum +pg_namespace_size_name(PG_FUNCTION_ARGS) +{ + int64 size; + Name nspName = PG_GETARG_NAME(0); + Oid nspOid = get_namespace_oid(NameStr(*nspName), false); + + size = calculate_namespace_size(nspOid); + + if (size < 0) + PG_RETURN_NULL(); + + PG_RETURN_INT64(size); +} + +/* Compute the size of relations using the given access method */ +static int64 +calculate_am_size(Oid amOid) +{ + /* XXX acl_check? */ + + return calculate_size_attvalue(Anum_pg_class_relam, amOid); +} + +Datum +pg_am_size_oid(PG_FUNCTION_ARGS) +{ + int64 size; + Oid amOid = PG_GETARG_OID(0); + + size = calculate_am_size(amOid); + + if (size < 0) + PG_RETURN_NULL(); + + PG_RETURN_INT64(size); +} + +Datum +pg_am_size_name(PG_FUNCTION_ARGS) +{ + int64 size; + Name amName = PG_GETARG_NAME(0); + Oid amOid = get_am_oid(NameStr(*amName), false); + + size = calculate_am_size(amOid); + + if (size < 0) + PG_RETURN_NULL(); + + PG_RETURN_INT64(size); +} + /* * Get the filenode of a relation * diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat index 719599649a9..cd4342c864f 100644 --- a/src/include/catalog/pg_proc.dat +++ b/src/include/catalog/pg_proc.dat @@ -7331,6 +7331,25 @@ descr => 'total disk space usage for the specified tablespace', proname => 'pg_tablespace_size', provolatile => 'v', prorettype => 'int8', proargtypes => 'name', prosrc => 'pg_tablespace_size_name' }, + +{ oid => '9410', + descr => 'total disk space usage for the specified namespace', + proname => 'pg_namespace_size', provolatile => 'v', prorettype => 'int8', + proargtypes => 'oid', prosrc => 'pg_namespace_size_oid' }, +{ oid => '9411', + descr => 'total disk space usage for the specified namespace', + proname => 'pg_namespace_size', provolatile => 'v', prorettype => 'int8', + proargtypes => 'name', prosrc => 'pg_namespace_size_name' }, + +{ oid => '9412', + descr => 'total disk space usage for the specified access method', + proname => 'pg_am_size', provolatile => 'v', prorettype => 'int8', + proargtypes => 'oid', prosrc => 'pg_am_size_oid' }, +{ oid => '9413', + descr => 'total disk space usage for the specified access method', + proname => 'pg_am_size', provolatile => 'v', prorettype => 'int8', + proargtypes => 'name', prosrc => 'pg_am_size_name' }, + { oid => '2324', descr => 'total disk space usage for the specified database', proname => 'pg_database_size', provolatile => 'v', prorettype => 'int8', proargtypes => 'oid', prosrc => 'pg_database_size_oid' }, -- 2.25.1
0002-psql-add-convenience-commands-dA-and-dn.patch (text/x-diff, 8.6K) download From fe3ff020b26a6b75dd27ca18e64ec77f5034816a Mon Sep 17 00:00:00 2001 From: Justin Pryzby <pryzbyj@telsasoft.com> Date: Sat, 18 Dec 2021 14:58:06 -0600 Subject: [PATCH 2/4] psql: add convenience commands: \dA+ and \dn+ show the size only with ++ in \dn, \dA, \db and (for consistency) \l \dt+ and \dP+ are not changed, since showing the table sizes seems to be their primary purpose. The idea for plusplus commands were previously discussed here. https://www.postgresql.org/message-id/20190506163359.GA29291%40alvherre.pgsql --- src/bin/psql/command.c | 22 ++++++++++++++-------- src/bin/psql/describe.c | 30 ++++++++++++++++++++++-------- src/bin/psql/describe.h | 8 ++++---- 3 files changed, 40 insertions(+), 20 deletions(-) diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c index de6a3a71f8a..40956cc32dc 100644 --- a/src/bin/psql/command.c +++ b/src/bin/psql/command.c @@ -368,7 +368,8 @@ exec_command(const char *cmd, else if (strcmp(cmd, "if") == 0) status = exec_command_if(scan_state, cstack, query_buf); else if (strcmp(cmd, "l") == 0 || strcmp(cmd, "list") == 0 || - strcmp(cmd, "l+") == 0 || strcmp(cmd, "list+") == 0) + strcmp(cmd, "l+") == 0 || strcmp(cmd, "l++") == 0 || + strcmp(cmd, "list+") == 0 || strcmp(cmd, "list++") == 0) status = exec_command_list(scan_state, active_branch, cmd); else if (strncmp(cmd, "lo_", 3) == 0) status = exec_command_lo(scan_state, active_branch, cmd); @@ -753,6 +754,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) if (active_branch) { char *pattern; + int verbose = 0; bool show_verbose, show_system; @@ -760,7 +762,10 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) pattern = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, true); - show_verbose = strchr(cmd, '+') ? true : false; + for (const char *t = cmd; *t != '\0'; ++t) + verbose += *t == '+' ? 1 : 0; + + show_verbose = (bool) (verbose != 0); show_system = strchr(cmd, 'S') ? true : false; switch (cmd[1]) @@ -785,7 +790,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) { case '\0': case '+': - success = describeAccessMethods(pattern, show_verbose); + success = describeAccessMethods(pattern, verbose); break; case 'c': success = listOperatorClasses(pattern, pattern2, show_verbose); @@ -811,7 +816,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) success = describeAggregates(pattern, show_verbose, show_system); break; case 'b': - success = describeTablespaces(pattern, show_verbose); + success = describeTablespaces(pattern, verbose); break; case 'c': if (strncmp(cmd, "dconfig", 7) == 0) @@ -865,7 +870,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) success = listLanguages(pattern, show_verbose, show_system); break; case 'n': - success = listSchemas(pattern, show_verbose, show_system); + success = listSchemas(pattern, verbose, show_system); break; case 'o': success = exec_command_dfo(scan_state, cmd, pattern, @@ -1942,14 +1947,15 @@ exec_command_list(PsqlScanState scan_state, bool active_branch, const char *cmd) if (active_branch) { char *pattern; - bool show_verbose; + int verbose = 0; pattern = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, true); - show_verbose = strchr(cmd, '+') ? true : false; + for (const char *t = cmd; *t != '\0'; ++t) + verbose += *t == '+' ? 1 : 0; - success = listAllDbs(pattern, show_verbose); + success = listAllDbs(pattern, verbose); free(pattern); } diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c index df166365e81..57666d8c5b8 100644 --- a/src/bin/psql/describe.c +++ b/src/bin/psql/describe.c @@ -139,12 +139,12 @@ 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; printQueryOpt myopt = pset.popt; - static const bool translate_columns[] = {false, true, false, false}; + static const bool translate_columns[] = {false, true, false, false, false}; if (pset.sversion < 90600) { @@ -176,6 +176,11 @@ describeAccessMethods(const char *pattern, bool verbose) " pg_catalog.obj_description(oid, 'pg_am') AS \"%s\"", gettext_noop("Handler"), gettext_noop("Description")); + + if (verbose > 1 && pset.sversion >= 160000) + appendPQExpBuffer(&buf, + ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_am_size(oid)) AS \"%s\"", + gettext_noop("Size")); } appendPQExpBufferStr(&buf, @@ -214,7 +219,7 @@ describeAccessMethods(const char *pattern, bool verbose) * Takes an optional regexp to select particular tablespaces */ bool -describeTablespaces(const char *pattern, bool verbose) +describeTablespaces(const char *pattern, int verbose) { PQExpBufferData buf; PGresult *res; @@ -234,12 +239,16 @@ describeTablespaces(const char *pattern, bool verbose) { appendPQExpBufferStr(&buf, ",\n "); printACLColumn(&buf, "spcacl"); + + if (verbose > 1) + appendPQExpBuffer(&buf, + ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_tablespace_size(oid)) AS \"%s\"", + gettext_noop("Size")); + appendPQExpBuffer(&buf, ",\n spcoptions AS \"%s\"" - ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_tablespace_size(oid)) AS \"%s\"" ",\n pg_catalog.shobj_description(oid, 'pg_tablespace') AS \"%s\"", gettext_noop("Options"), - gettext_noop("Size"), gettext_noop("Description")); } @@ -919,7 +928,7 @@ error_return: * for \l, \list, and -l switch */ bool -listAllDbs(const char *pattern, bool verbose) +listAllDbs(const char *pattern, int verbose) { PGresult *res; PQExpBufferData buf; @@ -952,7 +961,7 @@ listAllDbs(const char *pattern, bool verbose) gettext_noop("Locale Provider")); appendPQExpBufferStr(&buf, " "); printACLColumn(&buf, "d.datacl"); - if (verbose) + if (verbose > 1) appendPQExpBuffer(&buf, ",\n CASE WHEN pg_catalog.has_database_privilege(d.datname, 'CONNECT')\n" " THEN pg_catalog.pg_size_pretty(pg_catalog.pg_database_size(d.datname))\n" @@ -4954,7 +4963,7 @@ listCollations(const char *pattern, bool verbose, bool showSystem) * Describes schemas (namespaces) */ bool -listSchemas(const char *pattern, bool verbose, bool showSystem) +listSchemas(const char *pattern, int verbose, bool showSystem) { PQExpBufferData buf; PGresult *res; @@ -4976,6 +4985,11 @@ listSchemas(const char *pattern, bool verbose, bool showSystem) appendPQExpBuffer(&buf, ",\n pg_catalog.obj_description(n.oid, 'pg_namespace') AS \"%s\"", gettext_noop("Description")); + + if (verbose > 1 && pset.sversion >= 160000) + appendPQExpBuffer(&buf, + ",\n pg_catalog.pg_size_pretty(pg_namespace_size(n.oid)) AS \"%s\"", + gettext_noop("Size")); } appendPQExpBufferStr(&buf, diff --git a/src/bin/psql/describe.h b/src/bin/psql/describe.h index bd051e09cbb..84df35f4623 100644 --- a/src/bin/psql/describe.h +++ b/src/bin/psql/describe.h @@ -13,10 +13,10 @@ extern bool describeAggregates(const char *pattern, bool verbose, bool showSystem); /* \dA */ -extern bool describeAccessMethods(const char *pattern, bool verbose); +extern bool describeAccessMethods(const char *pattern, int verbose); /* \db */ -extern bool describeTablespaces(const char *pattern, bool verbose); +extern bool describeTablespaces(const char *pattern, int verbose); /* \df, \dfa, \dfn, \dft, \dfw, etc. */ extern bool describeFunctions(const char *functypes, const char *func_pattern, @@ -62,7 +62,7 @@ extern bool listTSDictionaries(const char *pattern, bool verbose); extern bool listTSTemplates(const char *pattern, bool verbose); /* \l */ -extern bool listAllDbs(const char *pattern, bool verbose); +extern bool listAllDbs(const char *pattern, int verbose); /* \dt, \di, \ds, \dS, etc. */ extern bool listTables(const char *tabtypes, const char *pattern, bool verbose, bool showSystem); @@ -87,7 +87,7 @@ extern bool listCasts(const char *pattern, bool verbose); extern bool listCollations(const char *pattern, bool verbose, bool showSystem); /* \dn */ -extern bool listSchemas(const char *pattern, bool verbose, bool showSystem); +extern bool listSchemas(const char *pattern, int verbose, bool showSystem); /* \dew */ extern bool listForeignDataWrappers(const char *pattern, bool verbose); -- 2.25.1
0003-f-convert-the-other-verbose-to-int-too.patch (text/x-diff, 40.7K) download From 512ee3cc9773d7e945f1973f094806a4340276fa Mon Sep 17 00:00:00 2001 From: Justin Pryzby <pryzbyj@telsasoft.com> Date: Thu, 15 Jul 2021 03:19:58 -0500 Subject: [PATCH 3/4] f!convert the other verbose to int, too --- 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
0004-Move-the-double-plus-Size-columns-to-the-right.patch (text/x-diff, 10.0K) download From c9011ebee742378788b393270773193c02358b74 Mon Sep 17 00:00:00 2001 From: Justin Pryzby <pryzbyj@telsasoft.com> Date: Fri, 17 Dec 2021 09:35:46 -0600 Subject: [PATCH 4/4] Move the double-plus "Size" columns to the right \dn, \dA, \db, \l, \d and \dP+ It doesn't make much sense that one cannot show a database's default tablespace without also showing its size, and stat()ing every segment of every relation in the DB. --- src/bin/psql/describe.c | 42 ++++++++++++++--------- src/test/regress/expected/psql.out | 54 +++++++++++++++--------------- 2 files changed, 53 insertions(+), 43 deletions(-) diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c index f7b646062bd..77a883815fe 100644 --- a/src/bin/psql/describe.c +++ b/src/bin/psql/describe.c @@ -240,11 +240,6 @@ describeTablespaces(const char *pattern, int verbose) appendPQExpBufferStr(&buf, ",\n "); printACLColumn(&buf, "spcacl"); - if (verbose > 1) - appendPQExpBuffer(&buf, - ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_tablespace_size(oid)) AS \"%s\"", - gettext_noop("Size")); - appendPQExpBuffer(&buf, ",\n spcoptions AS \"%s\"" ",\n pg_catalog.shobj_description(oid, 'pg_tablespace') AS \"%s\"", @@ -252,6 +247,11 @@ describeTablespaces(const char *pattern, int verbose) gettext_noop("Description")); } + if (verbose > 1) + appendPQExpBuffer(&buf, + ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_tablespace_size(oid)) AS \"%s\"", + gettext_noop("Size")); + appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_tablespace\n"); @@ -961,17 +961,22 @@ listAllDbs(const char *pattern, int verbose) gettext_noop("Locale Provider")); appendPQExpBufferStr(&buf, " "); printACLColumn(&buf, "d.datacl"); - if (verbose > 1) + + if (verbose > 0) appendPQExpBuffer(&buf, - ",\n CASE WHEN pg_catalog.has_database_privilege(d.datname, 'CONNECT')\n" - " THEN pg_catalog.pg_size_pretty(pg_catalog.pg_database_size(d.datname))\n" - " ELSE 'No Access'\n" - " END as \"%s\"" ",\n t.spcname as \"%s\"" ",\n pg_catalog.shobj_description(d.oid, 'pg_database') as \"%s\"", - gettext_noop("Size"), gettext_noop("Tablespace"), gettext_noop("Description")); + + if (verbose > 1) + appendPQExpBuffer(&buf, + ",\n CASE WHEN pg_catalog.has_database_privilege(d.datname, 'CONNECT')\n" + " THEN pg_catalog.pg_size_pretty(pg_catalog.pg_database_size(d.datname))\n" + " ELSE 'No Access'\n" + " END as \"%s\"", + gettext_noop("Size")); + appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_database d\n"); if (verbose > 0) @@ -3941,10 +3946,13 @@ listTables(const char *tabtypes, const char *pattern, int verbose, bool showSyst gettext_noop("Access method")); appendPQExpBuffer(&buf, - ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_table_size(c.oid)) as \"%s\"" ",\n pg_catalog.obj_description(c.oid, 'pg_class') as \"%s\"", - gettext_noop("Size"), gettext_noop("Description")); + + if (verbose > 1) + appendPQExpBuffer(&buf, + ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_table_size(c.oid)) as \"%s\"", + gettext_noop("Size")); } appendPQExpBufferStr(&buf, @@ -4128,6 +4136,11 @@ listPartitionedTables(const char *reltypes, const char *pattern, int verbose) gettext_noop("Table")); if (verbose > 0) + appendPQExpBuffer(&buf, + ",\n pg_catalog.obj_description(c.oid, 'pg_class') as \"%s\"", + gettext_noop("Description")); + + if (verbose > 1) { if (showNested) { @@ -4144,9 +4157,6 @@ listPartitionedTables(const char *reltypes, const char *pattern, int verbose) ",\n s.tps as \"%s\"", gettext_noop("Total size")); - appendPQExpBuffer(&buf, - ",\n pg_catalog.obj_description(c.oid, 'pg_class') as \"%s\"", - gettext_noop("Description")); } appendPQExpBufferStr(&buf, diff --git a/src/test/regress/expected/psql.out b/src/test/regress/expected/psql.out index 8fc62cebd2d..cd95680994b 100644 --- a/src/test/regress/expected/psql.out +++ b/src/test/regress/expected/psql.out @@ -2889,47 +2889,47 @@ Access method: heap -- AM is displayed for tables, indexes and materialized views. \d+ - List of relations - Schema | Name | Type | Owner | Persistence | Access method | Size | Description ------------------+--------------------+-------------------+----------------------+-------------+---------------+---------+------------- - tableam_display | mat_view_heap_psql | materialized view | regress_display_role | permanent | heap_psql | 0 bytes | - tableam_display | tbl_heap | table | regress_display_role | permanent | heap | 0 bytes | - tableam_display | tbl_heap_psql | table | regress_display_role | permanent | heap_psql | 0 bytes | - tableam_display | view_heap_psql | view | regress_display_role | permanent | | 0 bytes | + List of relations + Schema | Name | Type | Owner | Persistence | Access method | Description +-----------------+--------------------+-------------------+----------------------+-------------+---------------+------------- + tableam_display | mat_view_heap_psql | materialized view | regress_display_role | permanent | heap_psql | + tableam_display | tbl_heap | table | regress_display_role | permanent | heap | + tableam_display | tbl_heap_psql | table | regress_display_role | permanent | heap_psql | + tableam_display | view_heap_psql | view | regress_display_role | permanent | | (4 rows) \dt+ - List of relations - Schema | Name | Type | Owner | Persistence | Access method | Size | Description ------------------+---------------+-------+----------------------+-------------+---------------+---------+------------- - tableam_display | tbl_heap | table | regress_display_role | permanent | heap | 0 bytes | - tableam_display | tbl_heap_psql | table | regress_display_role | permanent | heap_psql | 0 bytes | + List of relations + Schema | Name | Type | Owner | Persistence | Access method | Description +-----------------+---------------+-------+----------------------+-------------+---------------+------------- + tableam_display | tbl_heap | table | regress_display_role | permanent | heap | + tableam_display | tbl_heap_psql | table | regress_display_role | permanent | heap_psql | (2 rows) \dm+ - List of relations - Schema | Name | Type | Owner | Persistence | Access method | Size | Description ------------------+--------------------+-------------------+----------------------+-------------+---------------+---------+------------- - tableam_display | mat_view_heap_psql | materialized view | regress_display_role | permanent | heap_psql | 0 bytes | + List of relations + Schema | Name | Type | Owner | Persistence | Access method | Description +-----------------+--------------------+-------------------+----------------------+-------------+---------------+------------- + tableam_display | mat_view_heap_psql | materialized view | regress_display_role | permanent | heap_psql | (1 row) -- But not for views and sequences. \dv+ - List of relations - Schema | Name | Type | Owner | Persistence | Size | Description ------------------+----------------+------+----------------------+-------------+---------+------------- - tableam_display | view_heap_psql | view | regress_display_role | permanent | 0 bytes | + List of relations + Schema | Name | Type | Owner | Persistence | Description +-----------------+----------------+------+----------------------+-------------+------------- + tableam_display | view_heap_psql | view | regress_display_role | permanent | (1 row) \set HIDE_TABLEAM on \d+ - List of relations - Schema | Name | Type | Owner | Persistence | Size | Description ------------------+--------------------+-------------------+----------------------+-------------+---------+------------- - tableam_display | mat_view_heap_psql | materialized view | regress_display_role | permanent | 0 bytes | - tableam_display | tbl_heap | table | regress_display_role | permanent | 0 bytes | - tableam_display | tbl_heap_psql | table | regress_display_role | permanent | 0 bytes | - tableam_display | view_heap_psql | view | regress_display_role | permanent | 0 bytes | + List of relations + Schema | Name | Type | Owner | Persistence | Description +-----------------+--------------------+-------------------+----------------------+-------------+------------- + tableam_display | mat_view_heap_psql | materialized view | regress_display_role | permanent | + tableam_display | tbl_heap | table | regress_display_role | permanent | + tableam_display | tbl_heap_psql | table | regress_display_role | permanent | + tableam_display | view_heap_psql | view | regress_display_role | permanent | (4 rows) RESET ROLE; -- 2.25.1
^ permalink raw reply [nested|flat] 22+ messages in thread

* Re: [PATCH] psql: \dn+ to show size of each schema (and \dA+ for AMs)
@ 2022-12-16 08:05  Pavel Stehule <pavel.stehule@gmail.com>
  parent: Justin Pryzby <pryzby@telsasoft.com>
  1 sibling, 0 replies; 22+ messages in thread

From: Pavel Stehule @ 2022-12-16 08:05 UTC (permalink / raw)
  To: Justin Pryzby <pryzby@telsasoft.com>; +Cc: Laurenz Albe <laurenz.albe@cybertec.at>; Ian Lawrence Barwick <barwick@gmail.com>; pgsql-hackers@postgresql.org, Gilles Darold <gilles@darold.net>; Julien Rouhaud <rjuju123@gmail.com>

čt 15. 12. 2022 v 17:13 odesílatel Justin Pryzby <pryzby@telsasoft.com>
napsal:

> Rebased on c727f511b.
>
> This patch record was "closed for lack of interest", but I think what's
> actually needed is committer review of which approach to take.
>
>  - add backend functions but do not modify psql ?
>  - add to psql slash-plus commnds ?
>  - introduce psql double-plus commands for new options ?
>  - change pre-existing psql plus commands to only show size with
>    double-plus ?
>  - go back to the original, two-line client-side sum() ?
>
> Until then, the patchset is organized with those questions in mind.
>

+1

This format makes sense to me.

Regards

Pavel

>
> --
> Justin
>

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

* Re: [PATCH] psql: \dn+ to show size of each schema (and \dA+ for AMs)
@ 2023-03-11 22:55  Justin Pryzby <pryzby@telsasoft.com>
  parent: Justin Pryzby <pryzby@telsasoft.com>
  1 sibling, 1 reply; 22+ messages in thread

From: Justin Pryzby @ 2023-03-11 22:55 UTC (permalink / raw)
  To: Pavel Stehule <pavel.stehule@gmail.com>; +Cc: Laurenz Albe <laurenz.albe@cybertec.at>; Ian Lawrence Barwick <barwick@gmail.com>; pgsql-hackers@postgresql.org, Gilles Darold <gilles@darold.net>; Julien Rouhaud <rjuju123@gmail.com>

On Thu, Dec 15, 2022 at 10:13:23AM -0600, Justin Pryzby wrote:
> Rebased on c727f511b.

Rebased on 30a53b792.
With minor changes including fixes to an intermediate patch.

> This patch record was "closed for lack of interest", but I think what's
> actually needed is committer review of which approach to take.
> 
>  - add backend functions but do not modify psql ?
>  - add to psql slash-plus commnds ?
>  - introduce psql double-plus commands for new options ?
>  - change pre-existing psql plus commands to only show size with
>    double-plus ?
>  - go back to the original, two-line client-side sum() ?
> 
> Until then, the patchset is organized with those questions in mind.

Attachments: download all (4 files, .tar.gz)

0001-Add-pg_am_size-pg_namespace_size.patch (text/x-diff, 5.7K) download From cf1596faa449ff1bd1d8b56306118d5eac764291 Mon Sep 17 00:00:00 2001 From: Justin Pryzby <pryzbyj@telsasoft.com> Date: Tue, 13 Jul 2021 21:25:48 -0500 Subject: [PATCH 1/4] Add pg_am_size(), pg_namespace_size() .. See also: 358a897fa, 528ac10c7 --- src/backend/utils/adt/dbsize.c | 132 ++++++++++++++++++++++++++++++++ src/include/catalog/pg_proc.dat | 19 +++++ 2 files changed, 151 insertions(+) diff --git a/src/backend/utils/adt/dbsize.c b/src/backend/utils/adt/dbsize.c index e5c0f1c45b6..af0955d1790 100644 --- a/src/backend/utils/adt/dbsize.c +++ b/src/backend/utils/adt/dbsize.c @@ -13,19 +13,25 @@ #include <sys/stat.h> +#include "access/genam.h" #include "access/htup_details.h" #include "access/relation.h" +#include "access/table.h" #include "catalog/catalog.h" #include "catalog/namespace.h" #include "catalog/pg_authid.h" #include "catalog/pg_database.h" +#include "catalog/pg_namespace.h" #include "catalog/pg_tablespace.h" #include "commands/dbcommands.h" +#include "commands/defrem.h" #include "commands/tablespace.h" #include "miscadmin.h" #include "storage/fd.h" #include "utils/acl.h" #include "utils/builtins.h" +#include "utils/fmgroids.h" +#include "utils/lsyscache.h" #include "utils/numeric.h" #include "utils/rel.h" #include "utils/relfilenumbermap.h" @@ -858,6 +864,132 @@ pg_size_bytes(PG_FUNCTION_ARGS) PG_RETURN_INT64(result); } +/* + * Return the sum of size of relations for which the given attribute of + * pg_class matches the specified OID value. + */ +static int64 +calculate_size_attvalue(AttrNumber attnum, Oid attval) +{ + int64 totalsize = 0; + ScanKeyData skey; + Relation pg_class; + SysScanDesc scan; + HeapTuple tuple; + + ScanKeyInit(&skey, attnum, + BTEqualStrategyNumber, F_OIDEQ, attval); + + pg_class = table_open(RelationRelationId, AccessShareLock); + scan = systable_beginscan(pg_class, InvalidOid, false, NULL, 1, &skey); + while (HeapTupleIsValid(tuple = systable_getnext(scan))) + { + Form_pg_class classtuple = (Form_pg_class) GETSTRUCT(tuple); + Relation rel; + + rel = try_relation_open(classtuple->oid, AccessShareLock); + if (!rel) + continue; + + for (ForkNumber forkNum = 0; forkNum <= MAX_FORKNUM; forkNum++) + totalsize += calculate_relation_size(&(rel->rd_locator), rel->rd_backend, forkNum); + + relation_close(rel, AccessShareLock); + } + + systable_endscan(scan); + table_close(pg_class, AccessShareLock); + return totalsize; +} + +/* Compute the size of relations in a schema (namespace) */ +static int64 +calculate_namespace_size(Oid nspOid) +{ + /* + * User must be a member of pg_read_all_stats or have CREATE privilege for + * target namespace. + */ + if (!is_member_of_role(GetUserId(), ROLE_PG_READ_ALL_STATS)) + { + AclResult aclresult; + + aclresult = object_aclcheck(NamespaceRelationId, nspOid, GetUserId(), ACL_CREATE); + if (aclresult != ACLCHECK_OK) + aclcheck_error(aclresult, OBJECT_SCHEMA, + get_namespace_name(nspOid)); + } + + return calculate_size_attvalue(Anum_pg_class_relnamespace, nspOid); +} + +Datum +pg_namespace_size_oid(PG_FUNCTION_ARGS) +{ + Oid nspOid = PG_GETARG_OID(0); + int64 size; + + size = calculate_namespace_size(nspOid); + + if (size < 0) + PG_RETURN_NULL(); + + PG_RETURN_INT64(size); +} + +Datum +pg_namespace_size_name(PG_FUNCTION_ARGS) +{ + Name nspName = PG_GETARG_NAME(0); + Oid nspOid = get_namespace_oid(NameStr(*nspName), false); + int64 size; + + size = calculate_namespace_size(nspOid); + + if (size < 0) + PG_RETURN_NULL(); + + PG_RETURN_INT64(size); +} + +/* Compute the size of relations using the given access method */ +static int64 +calculate_am_size(Oid amOid) +{ + /* XXX acl_check? */ + + return calculate_size_attvalue(Anum_pg_class_relam, amOid); +} + +Datum +pg_am_size_oid(PG_FUNCTION_ARGS) +{ + Oid amOid = PG_GETARG_OID(0); + int64 size; + + size = calculate_am_size(amOid); + + if (size < 0) + PG_RETURN_NULL(); + + PG_RETURN_INT64(size); +} + +Datum +pg_am_size_name(PG_FUNCTION_ARGS) +{ + Name amName = PG_GETARG_NAME(0); + Oid amOid = get_am_oid(NameStr(*amName), false); + int64 size; + + size = calculate_am_size(amOid); + + if (size < 0) + PG_RETURN_NULL(); + + PG_RETURN_INT64(size); +} + /* * Get the filenode of a relation * diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat index 1351d4be67c..ae658e721fd 100644 --- a/src/include/catalog/pg_proc.dat +++ b/src/include/catalog/pg_proc.dat @@ -7389,6 +7389,25 @@ descr => 'total disk space usage for the specified tablespace', proname => 'pg_tablespace_size', provolatile => 'v', prorettype => 'int8', proargtypes => 'name', prosrc => 'pg_tablespace_size_name' }, + +{ oid => '9410', + descr => 'total disk space usage for the specified namespace', + proname => 'pg_namespace_size', provolatile => 'v', prorettype => 'int8', + proargtypes => 'oid', prosrc => 'pg_namespace_size_oid' }, +{ oid => '9411', + descr => 'total disk space usage for the specified namespace', + proname => 'pg_namespace_size', provolatile => 'v', prorettype => 'int8', + proargtypes => 'name', prosrc => 'pg_namespace_size_name' }, + +{ oid => '9412', + descr => 'total disk space usage for the specified access method', + proname => 'pg_am_size', provolatile => 'v', prorettype => 'int8', + proargtypes => 'oid', prosrc => 'pg_am_size_oid' }, +{ oid => '9413', + descr => 'total disk space usage for the specified access method', + proname => 'pg_am_size', provolatile => 'v', prorettype => 'int8', + proargtypes => 'name', prosrc => 'pg_am_size_name' }, + { oid => '2324', descr => 'total disk space usage for the specified database', proname => 'pg_database_size', provolatile => 'v', prorettype => 'int8', proargtypes => 'oid', prosrc => 'pg_database_size_oid' }, -- 2.34.1
0002-psql-add-convenience-commands-dA-and-dn.patch (text/x-diff, 9.4K) download From a9b9a3736403521ad3c1bd5dd4c8fefefd630917 Mon Sep 17 00:00:00 2001 From: Justin Pryzby <pryzbyj@telsasoft.com> Date: Sat, 18 Dec 2021 14:58:06 -0600 Subject: [PATCH 2/4] psql: add convenience commands: \dA+ and \dn+ show the size only with \dA++ and \dn++ (for which the single-plus commands have historically not done any slow operations). Also change to show the size only with \db++ and \l++ (for which it's useful to show the ACL without also doing any slow operations). \dt+ and \dP+ are not changed, since showing the table sizes seems to be their primary purpose. The idea for plusplus commands were previously discussed here. https://www.postgresql.org/message-id/20190506163359.GA29291%40alvherre.pgsql --- src/bin/psql/command.c | 20 +++++++++++------- src/bin/psql/describe.c | 46 +++++++++++++++++++++++++++++------------ src/bin/psql/describe.h | 8 +++---- 3 files changed, 50 insertions(+), 24 deletions(-) diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c index 955397ee9dc..875b659a26d 100644 --- a/src/bin/psql/command.c +++ b/src/bin/psql/command.c @@ -369,6 +369,7 @@ exec_command(const char *cmd, else if (strcmp(cmd, "if") == 0) status = exec_command_if(scan_state, cstack, query_buf); else if (strcmp(cmd, "l") == 0 || strcmp(cmd, "list") == 0 || + strcmp(cmd, "l++") == 0 || strcmp(cmd, "list++") == 0 || strcmp(cmd, "l+") == 0 || strcmp(cmd, "list+") == 0) status = exec_command_list(scan_state, active_branch, cmd); else if (strncmp(cmd, "lo_", 3) == 0) @@ -754,6 +755,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) if (active_branch) { char *pattern; + int verbose = 0; bool show_verbose, show_system; @@ -761,7 +763,10 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) pattern = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, true); - show_verbose = strchr(cmd, '+') ? true : false; + for (const char *t = cmd; *t != '\0'; ++t) + verbose += *t == '+' ? 1 : 0; + + show_verbose = (bool) (verbose != 0); show_system = strchr(cmd, 'S') ? true : false; switch (cmd[1]) @@ -786,7 +791,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) { case '\0': case '+': - success = describeAccessMethods(pattern, show_verbose); + success = describeAccessMethods(pattern, verbose); break; case 'c': success = listOperatorClasses(pattern, pattern2, show_verbose); @@ -812,7 +817,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) success = describeAggregates(pattern, show_verbose, show_system); break; case 'b': - success = describeTablespaces(pattern, show_verbose); + success = describeTablespaces(pattern, verbose); break; case 'c': if (strncmp(cmd, "dconfig", 7) == 0) @@ -866,7 +871,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) success = listLanguages(pattern, show_verbose, show_system); break; case 'n': - success = listSchemas(pattern, show_verbose, show_system); + success = listSchemas(pattern, verbose, show_system); break; case 'o': success = exec_command_dfo(scan_state, cmd, pattern, @@ -1943,14 +1948,15 @@ exec_command_list(PsqlScanState scan_state, bool active_branch, const char *cmd) if (active_branch) { char *pattern; - bool show_verbose; + int verbose = 0; pattern = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, true); - show_verbose = strchr(cmd, '+') ? true : false; + for (const char *t = cmd; *t != '\0'; ++t) + verbose += *t == '+' ? 1 : 0; - success = listAllDbs(pattern, show_verbose); + success = listAllDbs(pattern, verbose); free(pattern); } diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c index 99e28f607e8..7de604a894d 100644 --- a/src/bin/psql/describe.c +++ b/src/bin/psql/describe.c @@ -139,12 +139,12 @@ 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; printQueryOpt myopt = pset.popt; - static const bool translate_columns[] = {false, true, false, false}; + static const bool translate_columns[] = {false, true, false, false, false}; if (pset.sversion < 90600) { @@ -176,6 +176,11 @@ describeAccessMethods(const char *pattern, bool verbose) " pg_catalog.obj_description(oid, 'pg_am') AS \"%s\"", gettext_noop("Handler"), gettext_noop("Description")); + + if (verbose > 1 && pset.sversion >= 160000) + appendPQExpBuffer(&buf, + ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_am_size(oid)) AS \"%s\"", + gettext_noop("Size")); } appendPQExpBufferStr(&buf, @@ -214,7 +219,7 @@ describeAccessMethods(const char *pattern, bool verbose) * Takes an optional regexp to select particular tablespaces */ bool -describeTablespaces(const char *pattern, bool verbose) +describeTablespaces(const char *pattern, int verbose) { PQExpBufferData buf; PGresult *res; @@ -234,12 +239,18 @@ describeTablespaces(const char *pattern, bool verbose) { appendPQExpBufferStr(&buf, ",\n "); printACLColumn(&buf, "spcacl"); + + appendPQExpBuffer(&buf, + ",\n spcoptions AS \"%s\"", + gettext_noop("Options")); + + if (verbose > 1) + appendPQExpBuffer(&buf, + ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_tablespace_size(oid)) AS \"%s\"", + gettext_noop("Size")); + appendPQExpBuffer(&buf, - ",\n spcoptions AS \"%s\"" - ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_tablespace_size(oid)) AS \"%s\"" ",\n pg_catalog.shobj_description(oid, 'pg_tablespace') AS \"%s\"", - gettext_noop("Options"), - gettext_noop("Size"), gettext_noop("Description")); } @@ -914,7 +925,7 @@ error_return: * for \l, \list, and -l switch */ bool -listAllDbs(const char *pattern, bool verbose) +listAllDbs(const char *pattern, int verbose) { PGresult *res; PQExpBufferData buf; @@ -961,20 +972,24 @@ listAllDbs(const char *pattern, bool verbose) gettext_noop("ICU Rules")); appendPQExpBufferStr(&buf, " "); printACLColumn(&buf, "d.datacl"); - if (verbose) + if (verbose > 1) appendPQExpBuffer(&buf, ",\n CASE WHEN pg_catalog.has_database_privilege(d.datname, 'CONNECT')\n" " THEN pg_catalog.pg_size_pretty(pg_catalog.pg_database_size(d.datname))\n" " ELSE 'No Access'\n" - " END as \"%s\"" + " END as \"%s\"", + gettext_noop("Size")); + + if (verbose > 0) + appendPQExpBuffer(&buf, ",\n t.spcname as \"%s\"" ",\n pg_catalog.shobj_description(d.oid, 'pg_database') as \"%s\"", - gettext_noop("Size"), gettext_noop("Tablespace"), 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"); @@ -4973,7 +4988,7 @@ listCollations(const char *pattern, bool verbose, bool showSystem) * Describes schemas (namespaces) */ bool -listSchemas(const char *pattern, bool verbose, bool showSystem) +listSchemas(const char *pattern, int verbose, bool showSystem) { PQExpBufferData buf; PGresult *res; @@ -4995,6 +5010,11 @@ listSchemas(const char *pattern, bool verbose, bool showSystem) appendPQExpBuffer(&buf, ",\n pg_catalog.obj_description(n.oid, 'pg_namespace') AS \"%s\"", gettext_noop("Description")); + + if (verbose > 1 && pset.sversion >= 160000) + appendPQExpBuffer(&buf, + ",\n pg_catalog.pg_size_pretty(pg_namespace_size(n.oid)) AS \"%s\"", + gettext_noop("Size")); } appendPQExpBufferStr(&buf, diff --git a/src/bin/psql/describe.h b/src/bin/psql/describe.h index 554fe867255..d2fd8a72a36 100644 --- a/src/bin/psql/describe.h +++ b/src/bin/psql/describe.h @@ -13,10 +13,10 @@ extern bool describeAggregates(const char *pattern, bool verbose, bool showSystem); /* \dA */ -extern bool describeAccessMethods(const char *pattern, bool verbose); +extern bool describeAccessMethods(const char *pattern, int verbose); /* \db */ -extern bool describeTablespaces(const char *pattern, bool verbose); +extern bool describeTablespaces(const char *pattern, int verbose); /* \df, \dfa, \dfn, \dft, \dfw, etc. */ extern bool describeFunctions(const char *functypes, const char *func_pattern, @@ -62,7 +62,7 @@ extern bool listTSDictionaries(const char *pattern, bool verbose); extern bool listTSTemplates(const char *pattern, bool verbose); /* \l */ -extern bool listAllDbs(const char *pattern, bool verbose); +extern bool listAllDbs(const char *pattern, int verbose); /* \dt, \di, \ds, \dS, etc. */ extern bool listTables(const char *tabtypes, const char *pattern, bool verbose, bool showSystem); @@ -87,7 +87,7 @@ extern bool listCasts(const char *pattern, bool verbose); extern bool listCollations(const char *pattern, bool verbose, bool showSystem); /* \dn */ -extern bool listSchemas(const char *pattern, bool verbose, bool showSystem); +extern bool listSchemas(const char *pattern, int verbose, bool showSystem); /* \dew */ extern bool listForeignDataWrappers(const char *pattern, bool verbose); -- 2.34.1
0003-f-convert-the-other-verbose-to-int-too.patch (text/x-diff, 40.4K) download From 853c193c880a5a58b799d16e76c02d209321614e Mon Sep 17 00:00:00 2001 From: Justin Pryzby <pryzbyj@telsasoft.com> Date: Thu, 15 Jul 2021 03:19:58 -0500 Subject: [PATCH 3/4] f!convert the other verbose to int, too --- 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
0004-Move-the-double-plus-Size-columns-to-the-right.patch (text/x-diff, 9.9K) download From 767df8a196a515708cdc5b017db10f2118566613 Mon Sep 17 00:00:00 2001 From: Justin Pryzby <pryzbyj@telsasoft.com> Date: Fri, 17 Dec 2021 09:35:46 -0600 Subject: [PATCH 4/4] Move the double-plus "Size" columns to the right \dn, \dA, \db, \l, and (for consistency) \d and \dP+ It doesn't make much sense that one cannot show a database's default tablespace without also showing its size, and stat()ing every segment of every relation in the DB. --- src/bin/psql/describe.c | 40 ++++++++++++---------- src/test/regress/expected/psql.out | 54 +++++++++++++++--------------- 2 files changed, 49 insertions(+), 45 deletions(-) diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c index 5fc4f5774e8..a64e4ccba4d 100644 --- a/src/bin/psql/describe.c +++ b/src/bin/psql/describe.c @@ -241,17 +241,15 @@ describeTablespaces(const char *pattern, int verbose) printACLColumn(&buf, "spcacl"); appendPQExpBuffer(&buf, - ",\n spcoptions AS \"%s\"", - gettext_noop("Options")); + ",\n spcoptions AS \"%s\"" + ",\n pg_catalog.shobj_description(oid, 'pg_tablespace') AS \"%s\"", + gettext_noop("Options"), + gettext_noop("Description")); if (verbose > 1) appendPQExpBuffer(&buf, ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_tablespace_size(oid)) AS \"%s\"", gettext_noop("Size")); - - appendPQExpBuffer(&buf, - ",\n pg_catalog.shobj_description(oid, 'pg_tablespace') AS \"%s\"", - gettext_noop("Description")); } appendPQExpBufferStr(&buf, @@ -972,13 +970,6 @@ listAllDbs(const char *pattern, int verbose) gettext_noop("ICU Rules")); appendPQExpBufferStr(&buf, " "); printACLColumn(&buf, "d.datacl"); - if (verbose > 1) - appendPQExpBuffer(&buf, - ",\n CASE WHEN pg_catalog.has_database_privilege(d.datname, 'CONNECT')\n" - " THEN pg_catalog.pg_size_pretty(pg_catalog.pg_database_size(d.datname))\n" - " ELSE 'No Access'\n" - " END as \"%s\"", - gettext_noop("Size")); if (verbose > 0) appendPQExpBuffer(&buf, @@ -987,6 +978,14 @@ listAllDbs(const char *pattern, int verbose) gettext_noop("Tablespace"), gettext_noop("Description")); + if (verbose > 1) + appendPQExpBuffer(&buf, + ",\n CASE WHEN pg_catalog.has_database_privilege(d.datname, 'CONNECT')\n" + " THEN pg_catalog.pg_size_pretty(pg_catalog.pg_database_size(d.datname))\n" + " ELSE 'No Access'\n" + " END as \"%s\"", + gettext_noop("Size")); + appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_database d\n"); if (verbose > 0) @@ -3954,10 +3953,13 @@ listTables(const char *tabtypes, const char *pattern, int verbose, bool showSyst gettext_noop("Access method")); appendPQExpBuffer(&buf, - ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_table_size(c.oid)) as \"%s\"" ",\n pg_catalog.obj_description(c.oid, 'pg_class') as \"%s\"", - gettext_noop("Size"), gettext_noop("Description")); + + if (verbose > 1) + appendPQExpBuffer(&buf, + ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_table_size(c.oid)) as \"%s\"", + gettext_noop("Size")); } appendPQExpBufferStr(&buf, @@ -4141,6 +4143,11 @@ listPartitionedTables(const char *reltypes, const char *pattern, int verbose) gettext_noop("Table")); if (verbose > 0) + appendPQExpBuffer(&buf, + ",\n pg_catalog.obj_description(c.oid, 'pg_class') as \"%s\"", + gettext_noop("Description")); + + if (verbose > 1) { if (showNested) { @@ -4157,9 +4164,6 @@ listPartitionedTables(const char *reltypes, const char *pattern, int verbose) ",\n s.tps as \"%s\"", gettext_noop("Total size")); - appendPQExpBuffer(&buf, - ",\n pg_catalog.obj_description(c.oid, 'pg_class') as \"%s\"", - gettext_noop("Description")); } appendPQExpBufferStr(&buf, diff --git a/src/test/regress/expected/psql.out b/src/test/regress/expected/psql.out index c00e28361c7..b9c95502a45 100644 --- a/src/test/regress/expected/psql.out +++ b/src/test/regress/expected/psql.out @@ -2889,47 +2889,47 @@ Access method: heap -- AM is displayed for tables, indexes and materialized views. \d+ - List of relations - Schema | Name | Type | Owner | Persistence | Access method | Size | Description ------------------+--------------------+-------------------+----------------------+-------------+---------------+---------+------------- - tableam_display | mat_view_heap_psql | materialized view | regress_display_role | permanent | heap_psql | 0 bytes | - tableam_display | tbl_heap | table | regress_display_role | permanent | heap | 0 bytes | - tableam_display | tbl_heap_psql | table | regress_display_role | permanent | heap_psql | 0 bytes | - tableam_display | view_heap_psql | view | regress_display_role | permanent | | 0 bytes | + List of relations + Schema | Name | Type | Owner | Persistence | Access method | Description +-----------------+--------------------+-------------------+----------------------+-------------+---------------+------------- + tableam_display | mat_view_heap_psql | materialized view | regress_display_role | permanent | heap_psql | + tableam_display | tbl_heap | table | regress_display_role | permanent | heap | + tableam_display | tbl_heap_psql | table | regress_display_role | permanent | heap_psql | + tableam_display | view_heap_psql | view | regress_display_role | permanent | | (4 rows) \dt+ - List of relations - Schema | Name | Type | Owner | Persistence | Access method | Size | Description ------------------+---------------+-------+----------------------+-------------+---------------+---------+------------- - tableam_display | tbl_heap | table | regress_display_role | permanent | heap | 0 bytes | - tableam_display | tbl_heap_psql | table | regress_display_role | permanent | heap_psql | 0 bytes | + List of relations + Schema | Name | Type | Owner | Persistence | Access method | Description +-----------------+---------------+-------+----------------------+-------------+---------------+------------- + tableam_display | tbl_heap | table | regress_display_role | permanent | heap | + tableam_display | tbl_heap_psql | table | regress_display_role | permanent | heap_psql | (2 rows) \dm+ - List of relations - Schema | Name | Type | Owner | Persistence | Access method | Size | Description ------------------+--------------------+-------------------+----------------------+-------------+---------------+---------+------------- - tableam_display | mat_view_heap_psql | materialized view | regress_display_role | permanent | heap_psql | 0 bytes | + List of relations + Schema | Name | Type | Owner | Persistence | Access method | Description +-----------------+--------------------+-------------------+----------------------+-------------+---------------+------------- + tableam_display | mat_view_heap_psql | materialized view | regress_display_role | permanent | heap_psql | (1 row) -- But not for views and sequences. \dv+ - List of relations - Schema | Name | Type | Owner | Persistence | Size | Description ------------------+----------------+------+----------------------+-------------+---------+------------- - tableam_display | view_heap_psql | view | regress_display_role | permanent | 0 bytes | + List of relations + Schema | Name | Type | Owner | Persistence | Description +-----------------+----------------+------+----------------------+-------------+------------- + tableam_display | view_heap_psql | view | regress_display_role | permanent | (1 row) \set HIDE_TABLEAM on \d+ - List of relations - Schema | Name | Type | Owner | Persistence | Size | Description ------------------+--------------------+-------------------+----------------------+-------------+---------+------------- - tableam_display | mat_view_heap_psql | materialized view | regress_display_role | permanent | 0 bytes | - tableam_display | tbl_heap | table | regress_display_role | permanent | 0 bytes | - tableam_display | tbl_heap_psql | table | regress_display_role | permanent | 0 bytes | - tableam_display | view_heap_psql | view | regress_display_role | permanent | 0 bytes | + List of relations + Schema | Name | Type | Owner | Persistence | Description +-----------------+--------------------+-------------------+----------------------+-------------+------------- + tableam_display | mat_view_heap_psql | materialized view | regress_display_role | permanent | + tableam_display | tbl_heap | table | regress_display_role | permanent | + tableam_display | tbl_heap_psql | table | regress_display_role | permanent | + tableam_display | view_heap_psql | view | regress_display_role | permanent | (4 rows) RESET ROLE; -- 2.34.1
^ permalink raw reply [nested|flat] 22+ messages in thread

* Re: [PATCH] psql: \dn+ to show size of each schema (and \dA+ for AMs)
@ 2023-05-24 21:05  Justin Pryzby <pryzby@telsasoft.com>
  parent: Justin Pryzby <pryzby@telsasoft.com>
  0 siblings, 1 reply; 22+ messages in thread

From: Justin Pryzby @ 2023-05-24 21:05 UTC (permalink / raw)
  To: Pavel Stehule <pavel.stehule@gmail.com>; +Cc: Laurenz Albe <laurenz.albe@cybertec.at>; Ian Lawrence Barwick <barwick@gmail.com>; pgsql-hackers@postgresql.org, Gilles Darold <gilles@darold.net>; Julien Rouhaud <rjuju123@gmail.com>

I added documentation for the SQL functions in 001.
And updated to say 170000

I'm planning to set this patch as ready - it has not changed
significantly in 18 months.  Not for the first time, I've implemented a
workaround at a higher layer.

-- 
Justin

Attachments: download all (4 files, .tar.gz)

0001-Add-pg_am_size-pg_namespace_size.patch (text/x-diff, 7.6K) download From 917e5e36d14018b6de457ba9eafe8936c0e88c3c Mon Sep 17 00:00:00 2001 From: Justin Pryzby <pryzbyj@telsasoft.com> Date: Tue, 13 Jul 2021 21:25:48 -0500 Subject: [PATCH 1/4] Add pg_am_size(), pg_namespace_size() .. See also: 358a897fa, 528ac10c7 --- doc/src/sgml/func.sgml | 39 ++++++++++ src/backend/utils/adt/dbsize.c | 132 ++++++++++++++++++++++++++++++++ src/include/catalog/pg_proc.dat | 19 +++++ 3 files changed, 190 insertions(+) diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index 5a47ce43434..6cbf4e9aa56 100644 --- a/doc/src/sgml/func.sgml +++ b/doc/src/sgml/func.sgml @@ -27762,6 +27762,45 @@ postgres=# SELECT '0/0'::pg_lsn + pd.segment_number * ps.setting::int + :offset </para></entry> </row> + <row> + <entry role="func_table_entry"><para role="func_signature"> + <indexterm> + <primary>pg_namespace_size</primary> + </indexterm> + <function>pg_namespace_size</function> ( <type>name</type> ) + <returnvalue>bigint</returnvalue> + </para> + <para role="func_signature"> + <function>pg_namespace_size</function> ( <type>oid</type> ) + <returnvalue>bigint</returnvalue> + </para> + <para> + Computes the total disk space used by relations in the namespace (schema) + with the specified name or OID. To use this function, you must + have <literal>CREATE</literal> privilege on the specified namespace + or have privileges of the <literal>pg_read_all_stats</literal> role, + unless it is the default namespace for the current database. + </para></entry> + </row> + + <row> + <entry role="func_table_entry"><para role="func_signature"> + <indexterm> + <primary>pg_am_size</primary> + </indexterm> + <function>pg_am_size</function> ( <type>name</type> ) + <returnvalue>bigint</returnvalue> + </para> + <para role="func_signature"> + <function>pg_am_size</function> ( <type>oid</type> ) + <returnvalue>bigint</returnvalue> + </para> + <para> + Computes the total disk space used by relations using the access method + with the specified name or OID. + </para></entry> + </row> + <row> <entry role="func_table_entry"><para role="func_signature"> <indexterm> diff --git a/src/backend/utils/adt/dbsize.c b/src/backend/utils/adt/dbsize.c index e5c0f1c45b6..af0955d1790 100644 --- a/src/backend/utils/adt/dbsize.c +++ b/src/backend/utils/adt/dbsize.c @@ -13,19 +13,25 @@ #include <sys/stat.h> +#include "access/genam.h" #include "access/htup_details.h" #include "access/relation.h" +#include "access/table.h" #include "catalog/catalog.h" #include "catalog/namespace.h" #include "catalog/pg_authid.h" #include "catalog/pg_database.h" +#include "catalog/pg_namespace.h" #include "catalog/pg_tablespace.h" #include "commands/dbcommands.h" +#include "commands/defrem.h" #include "commands/tablespace.h" #include "miscadmin.h" #include "storage/fd.h" #include "utils/acl.h" #include "utils/builtins.h" +#include "utils/fmgroids.h" +#include "utils/lsyscache.h" #include "utils/numeric.h" #include "utils/rel.h" #include "utils/relfilenumbermap.h" @@ -858,6 +864,132 @@ pg_size_bytes(PG_FUNCTION_ARGS) PG_RETURN_INT64(result); } +/* + * Return the sum of size of relations for which the given attribute of + * pg_class matches the specified OID value. + */ +static int64 +calculate_size_attvalue(AttrNumber attnum, Oid attval) +{ + int64 totalsize = 0; + ScanKeyData skey; + Relation pg_class; + SysScanDesc scan; + HeapTuple tuple; + + ScanKeyInit(&skey, attnum, + BTEqualStrategyNumber, F_OIDEQ, attval); + + pg_class = table_open(RelationRelationId, AccessShareLock); + scan = systable_beginscan(pg_class, InvalidOid, false, NULL, 1, &skey); + while (HeapTupleIsValid(tuple = systable_getnext(scan))) + { + Form_pg_class classtuple = (Form_pg_class) GETSTRUCT(tuple); + Relation rel; + + rel = try_relation_open(classtuple->oid, AccessShareLock); + if (!rel) + continue; + + for (ForkNumber forkNum = 0; forkNum <= MAX_FORKNUM; forkNum++) + totalsize += calculate_relation_size(&(rel->rd_locator), rel->rd_backend, forkNum); + + relation_close(rel, AccessShareLock); + } + + systable_endscan(scan); + table_close(pg_class, AccessShareLock); + return totalsize; +} + +/* Compute the size of relations in a schema (namespace) */ +static int64 +calculate_namespace_size(Oid nspOid) +{ + /* + * User must be a member of pg_read_all_stats or have CREATE privilege for + * target namespace. + */ + if (!is_member_of_role(GetUserId(), ROLE_PG_READ_ALL_STATS)) + { + AclResult aclresult; + + aclresult = object_aclcheck(NamespaceRelationId, nspOid, GetUserId(), ACL_CREATE); + if (aclresult != ACLCHECK_OK) + aclcheck_error(aclresult, OBJECT_SCHEMA, + get_namespace_name(nspOid)); + } + + return calculate_size_attvalue(Anum_pg_class_relnamespace, nspOid); +} + +Datum +pg_namespace_size_oid(PG_FUNCTION_ARGS) +{ + Oid nspOid = PG_GETARG_OID(0); + int64 size; + + size = calculate_namespace_size(nspOid); + + if (size < 0) + PG_RETURN_NULL(); + + PG_RETURN_INT64(size); +} + +Datum +pg_namespace_size_name(PG_FUNCTION_ARGS) +{ + Name nspName = PG_GETARG_NAME(0); + Oid nspOid = get_namespace_oid(NameStr(*nspName), false); + int64 size; + + size = calculate_namespace_size(nspOid); + + if (size < 0) + PG_RETURN_NULL(); + + PG_RETURN_INT64(size); +} + +/* Compute the size of relations using the given access method */ +static int64 +calculate_am_size(Oid amOid) +{ + /* XXX acl_check? */ + + return calculate_size_attvalue(Anum_pg_class_relam, amOid); +} + +Datum +pg_am_size_oid(PG_FUNCTION_ARGS) +{ + Oid amOid = PG_GETARG_OID(0); + int64 size; + + size = calculate_am_size(amOid); + + if (size < 0) + PG_RETURN_NULL(); + + PG_RETURN_INT64(size); +} + +Datum +pg_am_size_name(PG_FUNCTION_ARGS) +{ + Name amName = PG_GETARG_NAME(0); + Oid amOid = get_am_oid(NameStr(*amName), false); + int64 size; + + size = calculate_am_size(amOid); + + if (size < 0) + PG_RETURN_NULL(); + + PG_RETURN_INT64(size); +} + /* * Get the filenode of a relation * diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat index 6996073989a..a14a4ac53d5 100644 --- a/src/include/catalog/pg_proc.dat +++ b/src/include/catalog/pg_proc.dat @@ -7411,6 +7411,25 @@ descr => 'total disk space usage for the specified tablespace', proname => 'pg_tablespace_size', provolatile => 'v', prorettype => 'int8', proargtypes => 'name', prosrc => 'pg_tablespace_size_name' }, + +{ oid => '9410', + descr => 'total disk space usage for the specified namespace', + proname => 'pg_namespace_size', provolatile => 'v', prorettype => 'int8', + proargtypes => 'oid', prosrc => 'pg_namespace_size_oid' }, +{ oid => '9411', + descr => 'total disk space usage for the specified namespace', + proname => 'pg_namespace_size', provolatile => 'v', prorettype => 'int8', + proargtypes => 'name', prosrc => 'pg_namespace_size_name' }, + +{ oid => '9412', + descr => 'total disk space usage for the specified access method', + proname => 'pg_am_size', provolatile => 'v', prorettype => 'int8', + proargtypes => 'oid', prosrc => 'pg_am_size_oid' }, +{ oid => '9413', + descr => 'total disk space usage for the specified access method', + proname => 'pg_am_size', provolatile => 'v', prorettype => 'int8', + proargtypes => 'name', prosrc => 'pg_am_size_name' }, + { oid => '2324', descr => 'total disk space usage for the specified database', proname => 'pg_database_size', provolatile => 'v', prorettype => 'int8', proargtypes => 'oid', prosrc => 'pg_database_size_oid' }, -- 2.34.1
0002-psql-add-convenience-commands-dA-and-dn.patch (text/x-diff, 9.4K) download From c01392a36a0dcc774ccc816ff67f125c4c28b356 Mon Sep 17 00:00:00 2001 From: Justin Pryzby <pryzbyj@telsasoft.com> Date: Sat, 18 Dec 2021 14:58:06 -0600 Subject: [PATCH 2/4] psql: add convenience commands: \dA+ and \dn+ show the size only with \dA++ and \dn++ (for which the single-plus commands have historically not done any slow operations). Also change to show the size only with \db++ and \l++ (for which it's useful to show the ACL without also doing any slow operations). \dt+ and \dP+ are not changed, since showing the table sizes seems to be their primary purpose (??) The idea for plusplus commands were previously discussed here. https://www.postgresql.org/message-id/20190506163359.GA29291%40alvherre.pgsql --- src/bin/psql/command.c | 20 +++++++++++------- src/bin/psql/describe.c | 46 +++++++++++++++++++++++++++++------------ src/bin/psql/describe.h | 8 +++---- 3 files changed, 50 insertions(+), 24 deletions(-) diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c index 511debbe814..b695e09017d 100644 --- a/src/bin/psql/command.c +++ b/src/bin/psql/command.c @@ -369,6 +369,7 @@ exec_command(const char *cmd, else if (strcmp(cmd, "if") == 0) status = exec_command_if(scan_state, cstack, query_buf); else if (strcmp(cmd, "l") == 0 || strcmp(cmd, "list") == 0 || + strcmp(cmd, "l++") == 0 || strcmp(cmd, "list++") == 0 || strcmp(cmd, "l+") == 0 || strcmp(cmd, "list+") == 0) status = exec_command_list(scan_state, active_branch, cmd); else if (strncmp(cmd, "lo_", 3) == 0) @@ -754,6 +755,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) if (active_branch) { char *pattern; + int verbose = 0; bool show_verbose, show_system; @@ -761,7 +763,10 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) pattern = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, true); - show_verbose = strchr(cmd, '+') ? true : false; + for (const char *t = cmd; *t != '\0'; ++t) + verbose += *t == '+' ? 1 : 0; + + show_verbose = (bool) (verbose != 0); show_system = strchr(cmd, 'S') ? true : false; switch (cmd[1]) @@ -786,7 +791,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) { case '\0': case '+': - success = describeAccessMethods(pattern, show_verbose); + success = describeAccessMethods(pattern, verbose); break; case 'c': success = listOperatorClasses(pattern, pattern2, show_verbose); @@ -812,7 +817,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) success = describeAggregates(pattern, show_verbose, show_system); break; case 'b': - success = describeTablespaces(pattern, show_verbose); + success = describeTablespaces(pattern, verbose); break; case 'c': if (strncmp(cmd, "dconfig", 7) == 0) @@ -866,7 +871,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) success = listLanguages(pattern, show_verbose, show_system); break; case 'n': - success = listSchemas(pattern, show_verbose, show_system); + success = listSchemas(pattern, verbose, show_system); break; case 'o': success = exec_command_dfo(scan_state, cmd, pattern, @@ -1943,14 +1948,15 @@ exec_command_list(PsqlScanState scan_state, bool active_branch, const char *cmd) if (active_branch) { char *pattern; - bool show_verbose; + int verbose = 0; pattern = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, true); - show_verbose = strchr(cmd, '+') ? true : false; + for (const char *t = cmd; *t != '\0'; ++t) + verbose += *t == '+' ? 1 : 0; - success = listAllDbs(pattern, show_verbose); + success = listAllDbs(pattern, verbose); free(pattern); } diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c index 9325a46b8fd..f7f737e8b59 100644 --- a/src/bin/psql/describe.c +++ b/src/bin/psql/describe.c @@ -139,12 +139,12 @@ 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; printQueryOpt myopt = pset.popt; - static const bool translate_columns[] = {false, true, false, false}; + static const bool translate_columns[] = {false, true, false, false, false}; if (pset.sversion < 90600) { @@ -176,6 +176,11 @@ describeAccessMethods(const char *pattern, bool verbose) " pg_catalog.obj_description(oid, 'pg_am') AS \"%s\"", gettext_noop("Handler"), gettext_noop("Description")); + + if (verbose > 1 && pset.sversion >= 170000) + appendPQExpBuffer(&buf, + ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_am_size(oid)) AS \"%s\"", + gettext_noop("Size")); } appendPQExpBufferStr(&buf, @@ -214,7 +219,7 @@ describeAccessMethods(const char *pattern, bool verbose) * Takes an optional regexp to select particular tablespaces */ bool -describeTablespaces(const char *pattern, bool verbose) +describeTablespaces(const char *pattern, int verbose) { PQExpBufferData buf; PGresult *res; @@ -234,12 +239,18 @@ describeTablespaces(const char *pattern, bool verbose) { appendPQExpBufferStr(&buf, ",\n "); printACLColumn(&buf, "spcacl"); + + appendPQExpBuffer(&buf, + ",\n spcoptions AS \"%s\"", + gettext_noop("Options")); + + if (verbose > 1) + appendPQExpBuffer(&buf, + ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_tablespace_size(oid)) AS \"%s\"", + gettext_noop("Size")); + appendPQExpBuffer(&buf, - ",\n spcoptions AS \"%s\"" - ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_tablespace_size(oid)) AS \"%s\"" ",\n pg_catalog.shobj_description(oid, 'pg_tablespace') AS \"%s\"", - gettext_noop("Options"), - gettext_noop("Size"), gettext_noop("Description")); } @@ -914,7 +925,7 @@ error_return: * for \l, \list, and -l switch */ bool -listAllDbs(const char *pattern, bool verbose) +listAllDbs(const char *pattern, int verbose) { PGresult *res; PQExpBufferData buf; @@ -961,20 +972,24 @@ listAllDbs(const char *pattern, bool verbose) gettext_noop("ICU Rules")); appendPQExpBufferStr(&buf, " "); printACLColumn(&buf, "d.datacl"); - if (verbose) + if (verbose > 1) appendPQExpBuffer(&buf, ",\n CASE WHEN pg_catalog.has_database_privilege(d.datname, 'CONNECT')\n" " THEN pg_catalog.pg_size_pretty(pg_catalog.pg_database_size(d.datname))\n" " ELSE 'No Access'\n" - " END as \"%s\"" + " END as \"%s\"", + gettext_noop("Size")); + + if (verbose > 0) + appendPQExpBuffer(&buf, ",\n t.spcname as \"%s\"" ",\n pg_catalog.shobj_description(d.oid, 'pg_database') as \"%s\"", - gettext_noop("Size"), gettext_noop("Tablespace"), 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"); @@ -4970,7 +4985,7 @@ listCollations(const char *pattern, bool verbose, bool showSystem) * Describes schemas (namespaces) */ bool -listSchemas(const char *pattern, bool verbose, bool showSystem) +listSchemas(const char *pattern, int verbose, bool showSystem) { PQExpBufferData buf; PGresult *res; @@ -4992,6 +5007,11 @@ listSchemas(const char *pattern, bool verbose, bool showSystem) appendPQExpBuffer(&buf, ",\n pg_catalog.obj_description(n.oid, 'pg_namespace') AS \"%s\"", gettext_noop("Description")); + + if (verbose > 1 && pset.sversion >= 170000) + appendPQExpBuffer(&buf, + ",\n pg_catalog.pg_size_pretty(pg_namespace_size(n.oid)) AS \"%s\"", + gettext_noop("Size")); } appendPQExpBufferStr(&buf, diff --git a/src/bin/psql/describe.h b/src/bin/psql/describe.h index 554fe867255..d2fd8a72a36 100644 --- a/src/bin/psql/describe.h +++ b/src/bin/psql/describe.h @@ -13,10 +13,10 @@ extern bool describeAggregates(const char *pattern, bool verbose, bool showSystem); /* \dA */ -extern bool describeAccessMethods(const char *pattern, bool verbose); +extern bool describeAccessMethods(const char *pattern, int verbose); /* \db */ -extern bool describeTablespaces(const char *pattern, bool verbose); +extern bool describeTablespaces(const char *pattern, int verbose); /* \df, \dfa, \dfn, \dft, \dfw, etc. */ extern bool describeFunctions(const char *functypes, const char *func_pattern, @@ -62,7 +62,7 @@ extern bool listTSDictionaries(const char *pattern, bool verbose); extern bool listTSTemplates(const char *pattern, bool verbose); /* \l */ -extern bool listAllDbs(const char *pattern, bool verbose); +extern bool listAllDbs(const char *pattern, int verbose); /* \dt, \di, \ds, \dS, etc. */ extern bool listTables(const char *tabtypes, const char *pattern, bool verbose, bool showSystem); @@ -87,7 +87,7 @@ extern bool listCasts(const char *pattern, bool verbose); extern bool listCollations(const char *pattern, bool verbose, bool showSystem); /* \dn */ -extern bool listSchemas(const char *pattern, bool verbose, bool showSystem); +extern bool listSchemas(const char *pattern, int verbose, bool showSystem); /* \dew */ extern bool listForeignDataWrappers(const char *pattern, bool verbose); -- 2.34.1
0003-f-convert-the-other-verbose-to-int-too.patch (text/x-diff, 40.4K) download From 902e0d29e272d68586bc616fae2db2fe3df39e39 Mon Sep 17 00:00:00 2001 From: Justin Pryzby <pryzbyj@telsasoft.com> Date: Thu, 15 Jul 2021 03:19:58 -0500 Subject: [PATCH 3/4] f!convert the other verbose to int, too --- 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
0004-Move-the-double-plus-Size-columns-to-the-right.patch (text/x-diff, 9.9K) download From 13c1dae0013665769c9c07839eac9fdccadfddad Mon Sep 17 00:00:00 2001 From: Justin Pryzby <pryzbyj@telsasoft.com> Date: Fri, 17 Dec 2021 09:35:46 -0600 Subject: [PATCH 4/4] Move the double-plus "Size" columns to the right \dn, \dA, \db, \l, and (for consistency) \d and \dP+ It doesn't make much sense that one cannot show a database's default tablespace without also showing its size, and stat()ing every segment of every relation in the DB. --- src/bin/psql/describe.c | 40 ++++++++++++---------- src/test/regress/expected/psql.out | 54 +++++++++++++++--------------- 2 files changed, 49 insertions(+), 45 deletions(-) diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c index 8ab4b4cb46a..1b7e5c5bcd2 100644 --- a/src/bin/psql/describe.c +++ b/src/bin/psql/describe.c @@ -241,17 +241,15 @@ describeTablespaces(const char *pattern, int verbose) printACLColumn(&buf, "spcacl"); appendPQExpBuffer(&buf, - ",\n spcoptions AS \"%s\"", - gettext_noop("Options")); + ",\n spcoptions AS \"%s\"" + ",\n pg_catalog.shobj_description(oid, 'pg_tablespace') AS \"%s\"", + gettext_noop("Options"), + gettext_noop("Description")); if (verbose > 1) appendPQExpBuffer(&buf, ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_tablespace_size(oid)) AS \"%s\"", gettext_noop("Size")); - - appendPQExpBuffer(&buf, - ",\n pg_catalog.shobj_description(oid, 'pg_tablespace') AS \"%s\"", - gettext_noop("Description")); } appendPQExpBufferStr(&buf, @@ -972,13 +970,6 @@ listAllDbs(const char *pattern, int verbose) gettext_noop("ICU Rules")); appendPQExpBufferStr(&buf, " "); printACLColumn(&buf, "d.datacl"); - if (verbose > 1) - appendPQExpBuffer(&buf, - ",\n CASE WHEN pg_catalog.has_database_privilege(d.datname, 'CONNECT')\n" - " THEN pg_catalog.pg_size_pretty(pg_catalog.pg_database_size(d.datname))\n" - " ELSE 'No Access'\n" - " END as \"%s\"", - gettext_noop("Size")); if (verbose > 0) appendPQExpBuffer(&buf, @@ -987,6 +978,14 @@ listAllDbs(const char *pattern, int verbose) gettext_noop("Tablespace"), gettext_noop("Description")); + if (verbose > 1) + appendPQExpBuffer(&buf, + ",\n CASE WHEN pg_catalog.has_database_privilege(d.datname, 'CONNECT')\n" + " THEN pg_catalog.pg_size_pretty(pg_catalog.pg_database_size(d.datname))\n" + " ELSE 'No Access'\n" + " END as \"%s\"", + gettext_noop("Size")); + appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_database d\n"); if (verbose > 0) @@ -3951,10 +3950,13 @@ listTables(const char *tabtypes, const char *pattern, int verbose, bool showSyst gettext_noop("Access method")); appendPQExpBuffer(&buf, - ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_table_size(c.oid)) as \"%s\"" ",\n pg_catalog.obj_description(c.oid, 'pg_class') as \"%s\"", - gettext_noop("Size"), gettext_noop("Description")); + + if (verbose > 1) + appendPQExpBuffer(&buf, + ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_table_size(c.oid)) as \"%s\"", + gettext_noop("Size")); } appendPQExpBufferStr(&buf, @@ -4138,6 +4140,11 @@ listPartitionedTables(const char *reltypes, const char *pattern, int verbose) gettext_noop("Table")); if (verbose > 0) + appendPQExpBuffer(&buf, + ",\n pg_catalog.obj_description(c.oid, 'pg_class') as \"%s\"", + gettext_noop("Description")); + + if (verbose > 1) { if (showNested) { @@ -4154,9 +4161,6 @@ listPartitionedTables(const char *reltypes, const char *pattern, int verbose) ",\n s.tps as \"%s\"", gettext_noop("Total size")); - appendPQExpBuffer(&buf, - ",\n pg_catalog.obj_description(c.oid, 'pg_class') as \"%s\"", - gettext_noop("Description")); } appendPQExpBufferStr(&buf, diff --git a/src/test/regress/expected/psql.out b/src/test/regress/expected/psql.out index 8f930283636..4666333f73f 100644 --- a/src/test/regress/expected/psql.out +++ b/src/test/regress/expected/psql.out @@ -2889,47 +2889,47 @@ Access method: heap -- AM is displayed for tables, indexes and materialized views. \d+ - List of relations - Schema | Name | Type | Owner | Persistence | Access method | Size | Description ------------------+--------------------+-------------------+----------------------+-------------+---------------+---------+------------- - tableam_display | mat_view_heap_psql | materialized view | regress_display_role | permanent | heap_psql | 0 bytes | - tableam_display | tbl_heap | table | regress_display_role | permanent | heap | 0 bytes | - tableam_display | tbl_heap_psql | table | regress_display_role | permanent | heap_psql | 0 bytes | - tableam_display | view_heap_psql | view | regress_display_role | permanent | | 0 bytes | + List of relations + Schema | Name | Type | Owner | Persistence | Access method | Description +-----------------+--------------------+-------------------+----------------------+-------------+---------------+------------- + tableam_display | mat_view_heap_psql | materialized view | regress_display_role | permanent | heap_psql | + tableam_display | tbl_heap | table | regress_display_role | permanent | heap | + tableam_display | tbl_heap_psql | table | regress_display_role | permanent | heap_psql | + tableam_display | view_heap_psql | view | regress_display_role | permanent | | (4 rows) \dt+ - List of relations - Schema | Name | Type | Owner | Persistence | Access method | Size | Description ------------------+---------------+-------+----------------------+-------------+---------------+---------+------------- - tableam_display | tbl_heap | table | regress_display_role | permanent | heap | 0 bytes | - tableam_display | tbl_heap_psql | table | regress_display_role | permanent | heap_psql | 0 bytes | + List of relations + Schema | Name | Type | Owner | Persistence | Access method | Description +-----------------+---------------+-------+----------------------+-------------+---------------+------------- + tableam_display | tbl_heap | table | regress_display_role | permanent | heap | + tableam_display | tbl_heap_psql | table | regress_display_role | permanent | heap_psql | (2 rows) \dm+ - List of relations - Schema | Name | Type | Owner | Persistence | Access method | Size | Description ------------------+--------------------+-------------------+----------------------+-------------+---------------+---------+------------- - tableam_display | mat_view_heap_psql | materialized view | regress_display_role | permanent | heap_psql | 0 bytes | + List of relations + Schema | Name | Type | Owner | Persistence | Access method | Description +-----------------+--------------------+-------------------+----------------------+-------------+---------------+------------- + tableam_display | mat_view_heap_psql | materialized view | regress_display_role | permanent | heap_psql | (1 row) -- But not for views and sequences. \dv+ - List of relations - Schema | Name | Type | Owner | Persistence | Size | Description ------------------+----------------+------+----------------------+-------------+---------+------------- - tableam_display | view_heap_psql | view | regress_display_role | permanent | 0 bytes | + List of relations + Schema | Name | Type | Owner | Persistence | Description +-----------------+----------------+------+----------------------+-------------+------------- + tableam_display | view_heap_psql | view | regress_display_role | permanent | (1 row) \set HIDE_TABLEAM on \d+ - List of relations - Schema | Name | Type | Owner | Persistence | Size | Description ------------------+--------------------+-------------------+----------------------+-------------+---------+------------- - tableam_display | mat_view_heap_psql | materialized view | regress_display_role | permanent | 0 bytes | - tableam_display | tbl_heap | table | regress_display_role | permanent | 0 bytes | - tableam_display | tbl_heap_psql | table | regress_display_role | permanent | 0 bytes | - tableam_display | view_heap_psql | view | regress_display_role | permanent | 0 bytes | + List of relations + Schema | Name | Type | Owner | Persistence | Description +-----------------+--------------------+-------------------+----------------------+-------------+------------- + tableam_display | mat_view_heap_psql | materialized view | regress_display_role | permanent | + tableam_display | tbl_heap | table | regress_display_role | permanent | + tableam_display | tbl_heap_psql | table | regress_display_role | permanent | + tableam_display | view_heap_psql | view | regress_display_role | permanent | (4 rows) RESET ROLE; -- 2.34.1
^ permalink raw reply [nested|flat] 22+ messages in thread

* Re: [PATCH] psql: \dn+ to show size of each schema (and \dA+ for AMs)
@ 2023-08-01 07:54  Daniel Gustafsson <daniel@yesql.se>
  parent: Justin Pryzby <pryzby@telsasoft.com>
  0 siblings, 1 reply; 22+ messages in thread

From: Daniel Gustafsson @ 2023-08-01 07:54 UTC (permalink / raw)
  To: Justin Pryzby <pryzby@telsasoft.com>; +Cc: Pavel Stehule <pavel.stehule@gmail.com>; Laurenz Albe <laurenz.albe@cybertec.at>; Ian Lawrence Barwick <barwick@gmail.com>; pgsql-hackers; Gilles Darold <gilles@darold.net>; Julien Rouhaud <rjuju123@gmail.com>

> On 24 May 2023, at 23:05, Justin Pryzby <pryzby@telsasoft.com> wrote:

> I'm planning to set this patch as ready

This is marked RfC so I'm moving this to the next CF, but the patch no longer
applies so it needs a rebase.

--
Daniel Gustafsson






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

* Re: [PATCH] psql: \dn+ to show size of each schema (and \dA+ for AMs)
@ 2023-08-14 15:03  Justin Pryzby <pryzby@telsasoft.com>
  parent: Daniel Gustafsson <daniel@yesql.se>
  0 siblings, 2 replies; 22+ messages in thread

From: Justin Pryzby @ 2023-08-14 15:03 UTC (permalink / raw)
  To: Daniel Gustafsson <daniel@yesql.se>; +Cc: Pavel Stehule <pavel.stehule@gmail.com>; Laurenz Albe <laurenz.albe@cybertec.at>; Ian Lawrence Barwick <barwick@gmail.com>; pgsql-hackers@postgresql.org, Gilles Darold <gilles@darold.net>; Julien Rouhaud <rjuju123@gmail.com>

On Thu, Dec 15, 2022 at 10:13:23AM -0600, Justin Pryzby wrote:
> This patch record was "closed for lack of interest", but I think what's
> actually needed is committer review of which approach to take.

On Tue, Aug 01, 2023 at 09:54:34AM +0200, Daniel Gustafsson wrote:
> > On 24 May 2023, at 23:05, Justin Pryzby <pryzby@telsasoft.com> wrote:
> 
> > I'm planning to set this patch as ready
> 
> This is marked RfC so I'm moving this to the next CF, but the patch no longer
> applies so it needs a rebase.

I was still hoping to receive some feedback on which patches to squish.

-- 
Justin

Attachments: download all (4 files, .tar.gz)

0001-Add-pg_am_size-pg_namespace_size.patch (text/x-diff, 7.6K) download From 2b97b0fe27199a343f00f31aaf3fcd79fd1228f1 Mon Sep 17 00:00:00 2001 From: Justin Pryzby <pryzbyj@telsasoft.com> Date: Tue, 13 Jul 2021 21:25:48 -0500 Subject: [PATCH 1/4] Add pg_am_size(), pg_namespace_size() .. See also: 358a897fa, 528ac10c7 --- doc/src/sgml/func.sgml | 39 ++++++++++ src/backend/utils/adt/dbsize.c | 132 ++++++++++++++++++++++++++++++++ src/include/catalog/pg_proc.dat | 19 +++++ 3 files changed, 190 insertions(+) diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index be2f54c9141..8a1c8226c48 100644 --- a/doc/src/sgml/func.sgml +++ b/doc/src/sgml/func.sgml @@ -27814,6 +27814,45 @@ postgres=# SELECT '0/0'::pg_lsn + pd.segment_number * ps.setting::int + :offset </para></entry> </row> + <row> + <entry role="func_table_entry"><para role="func_signature"> + <indexterm> + <primary>pg_namespace_size</primary> + </indexterm> + <function>pg_namespace_size</function> ( <type>name</type> ) + <returnvalue>bigint</returnvalue> + </para> + <para role="func_signature"> + <function>pg_namespace_size</function> ( <type>oid</type> ) + <returnvalue>bigint</returnvalue> + </para> + <para> + Computes the total disk space used by relations in the namespace (schema) + with the specified name or OID. To use this function, you must + have <literal>CREATE</literal> privilege on the specified namespace + or have privileges of the <literal>pg_read_all_stats</literal> role, + unless it is the default namespace for the current database. + </para></entry> + </row> + + <row> + <entry role="func_table_entry"><para role="func_signature"> + <indexterm> + <primary>pg_am_size</primary> + </indexterm> + <function>pg_am_size</function> ( <type>name</type> ) + <returnvalue>bigint</returnvalue> + </para> + <para role="func_signature"> + <function>pg_am_size</function> ( <type>oid</type> ) + <returnvalue>bigint</returnvalue> + </para> + <para> + Computes the total disk space used by relations using the access method + with the specified name or OID. + </para></entry> + </row> + <row> <entry role="func_table_entry"><para role="func_signature"> <indexterm> diff --git a/src/backend/utils/adt/dbsize.c b/src/backend/utils/adt/dbsize.c index e5c0f1c45b6..af0955d1790 100644 --- a/src/backend/utils/adt/dbsize.c +++ b/src/backend/utils/adt/dbsize.c @@ -13,19 +13,25 @@ #include <sys/stat.h> +#include "access/genam.h" #include "access/htup_details.h" #include "access/relation.h" +#include "access/table.h" #include "catalog/catalog.h" #include "catalog/namespace.h" #include "catalog/pg_authid.h" #include "catalog/pg_database.h" +#include "catalog/pg_namespace.h" #include "catalog/pg_tablespace.h" #include "commands/dbcommands.h" +#include "commands/defrem.h" #include "commands/tablespace.h" #include "miscadmin.h" #include "storage/fd.h" #include "utils/acl.h" #include "utils/builtins.h" +#include "utils/fmgroids.h" +#include "utils/lsyscache.h" #include "utils/numeric.h" #include "utils/rel.h" #include "utils/relfilenumbermap.h" @@ -858,6 +864,132 @@ pg_size_bytes(PG_FUNCTION_ARGS) PG_RETURN_INT64(result); } +/* + * Return the sum of size of relations for which the given attribute of + * pg_class matches the specified OID value. + */ +static int64 +calculate_size_attvalue(AttrNumber attnum, Oid attval) +{ + int64 totalsize = 0; + ScanKeyData skey; + Relation pg_class; + SysScanDesc scan; + HeapTuple tuple; + + ScanKeyInit(&skey, attnum, + BTEqualStrategyNumber, F_OIDEQ, attval); + + pg_class = table_open(RelationRelationId, AccessShareLock); + scan = systable_beginscan(pg_class, InvalidOid, false, NULL, 1, &skey); + while (HeapTupleIsValid(tuple = systable_getnext(scan))) + { + Form_pg_class classtuple = (Form_pg_class) GETSTRUCT(tuple); + Relation rel; + + rel = try_relation_open(classtuple->oid, AccessShareLock); + if (!rel) + continue; + + for (ForkNumber forkNum = 0; forkNum <= MAX_FORKNUM; forkNum++) + totalsize += calculate_relation_size(&(rel->rd_locator), rel->rd_backend, forkNum); + + relation_close(rel, AccessShareLock); + } + + systable_endscan(scan); + table_close(pg_class, AccessShareLock); + return totalsize; +} + +/* Compute the size of relations in a schema (namespace) */ +static int64 +calculate_namespace_size(Oid nspOid) +{ + /* + * User must be a member of pg_read_all_stats or have CREATE privilege for + * target namespace. + */ + if (!is_member_of_role(GetUserId(), ROLE_PG_READ_ALL_STATS)) + { + AclResult aclresult; + + aclresult = object_aclcheck(NamespaceRelationId, nspOid, GetUserId(), ACL_CREATE); + if (aclresult != ACLCHECK_OK) + aclcheck_error(aclresult, OBJECT_SCHEMA, + get_namespace_name(nspOid)); + } + + return calculate_size_attvalue(Anum_pg_class_relnamespace, nspOid); +} + +Datum +pg_namespace_size_oid(PG_FUNCTION_ARGS) +{ + Oid nspOid = PG_GETARG_OID(0); + int64 size; + + size = calculate_namespace_size(nspOid); + + if (size < 0) + PG_RETURN_NULL(); + + PG_RETURN_INT64(size); +} + +Datum +pg_namespace_size_name(PG_FUNCTION_ARGS) +{ + Name nspName = PG_GETARG_NAME(0); + Oid nspOid = get_namespace_oid(NameStr(*nspName), false); + int64 size; + + size = calculate_namespace_size(nspOid); + + if (size < 0) + PG_RETURN_NULL(); + + PG_RETURN_INT64(size); +} + +/* Compute the size of relations using the given access method */ +static int64 +calculate_am_size(Oid amOid) +{ + /* XXX acl_check? */ + + return calculate_size_attvalue(Anum_pg_class_relam, amOid); +} + +Datum +pg_am_size_oid(PG_FUNCTION_ARGS) +{ + Oid amOid = PG_GETARG_OID(0); + int64 size; + + size = calculate_am_size(amOid); + + if (size < 0) + PG_RETURN_NULL(); + + PG_RETURN_INT64(size); +} + +Datum +pg_am_size_name(PG_FUNCTION_ARGS) +{ + Name amName = PG_GETARG_NAME(0); + Oid amOid = get_am_oid(NameStr(*amName), false); + int64 size; + + size = calculate_am_size(amOid); + + if (size < 0) + PG_RETURN_NULL(); + + PG_RETURN_INT64(size); +} + /* * Get the filenode of a relation * diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat index 6996073989a..a14a4ac53d5 100644 --- a/src/include/catalog/pg_proc.dat +++ b/src/include/catalog/pg_proc.dat @@ -7411,6 +7411,25 @@ descr => 'total disk space usage for the specified tablespace', proname => 'pg_tablespace_size', provolatile => 'v', prorettype => 'int8', proargtypes => 'name', prosrc => 'pg_tablespace_size_name' }, + +{ oid => '9410', + descr => 'total disk space usage for the specified namespace', + proname => 'pg_namespace_size', provolatile => 'v', prorettype => 'int8', + proargtypes => 'oid', prosrc => 'pg_namespace_size_oid' }, +{ oid => '9411', + descr => 'total disk space usage for the specified namespace', + proname => 'pg_namespace_size', provolatile => 'v', prorettype => 'int8', + proargtypes => 'name', prosrc => 'pg_namespace_size_name' }, + +{ oid => '9412', + descr => 'total disk space usage for the specified access method', + proname => 'pg_am_size', provolatile => 'v', prorettype => 'int8', + proargtypes => 'oid', prosrc => 'pg_am_size_oid' }, +{ oid => '9413', + descr => 'total disk space usage for the specified access method', + proname => 'pg_am_size', provolatile => 'v', prorettype => 'int8', + proargtypes => 'name', prosrc => 'pg_am_size_name' }, + { oid => '2324', descr => 'total disk space usage for the specified database', proname => 'pg_database_size', provolatile => 'v', prorettype => 'int8', proargtypes => 'oid', prosrc => 'pg_database_size_oid' }, -- 2.34.1
0002-psql-add-convenience-commands-dA-and-dn.patch (text/x-diff, 9.4K) download From cb1f2efc9f5bf4a5f5249917e07e7c231bf9423c Mon Sep 17 00:00:00 2001 From: Justin Pryzby <pryzbyj@telsasoft.com> Date: Sat, 18 Dec 2021 14:58:06 -0600 Subject: [PATCH 2/4] psql: add convenience commands: \dA+ and \dn+ show the size only with \dA++ and \dn++ (for which the single-plus commands have historically not done any slow operations). Also change to show the size only with \db++ and \l++ (for which it's useful to show the ACL without also doing any slow operations). \dt+ and \dP+ are not changed, since showing the table sizes seems to be their primary purpose (??) The idea for plusplus commands were previously discussed here. https://www.postgresql.org/message-id/20190506163359.GA29291%40alvherre.pgsql --- src/bin/psql/command.c | 20 +++++++++++------- src/bin/psql/describe.c | 46 +++++++++++++++++++++++++++++------------ src/bin/psql/describe.h | 8 +++---- 3 files changed, 50 insertions(+), 24 deletions(-) diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c index 1300869d797..667beb1b16e 100644 --- a/src/bin/psql/command.c +++ b/src/bin/psql/command.c @@ -369,6 +369,7 @@ exec_command(const char *cmd, else if (strcmp(cmd, "if") == 0) status = exec_command_if(scan_state, cstack, query_buf); else if (strcmp(cmd, "l") == 0 || strcmp(cmd, "list") == 0 || + strcmp(cmd, "l++") == 0 || strcmp(cmd, "list++") == 0 || strcmp(cmd, "l+") == 0 || strcmp(cmd, "list+") == 0) status = exec_command_list(scan_state, active_branch, cmd); else if (strncmp(cmd, "lo_", 3) == 0) @@ -754,6 +755,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) if (active_branch) { char *pattern; + int verbose = 0; bool show_verbose, show_system; @@ -761,7 +763,10 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) pattern = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, true); - show_verbose = strchr(cmd, '+') ? true : false; + for (const char *t = cmd; *t != '\0'; ++t) + verbose += *t == '+' ? 1 : 0; + + show_verbose = (bool) (verbose != 0); show_system = strchr(cmd, 'S') ? true : false; switch (cmd[1]) @@ -786,7 +791,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) { case '\0': case '+': - success = describeAccessMethods(pattern, show_verbose); + success = describeAccessMethods(pattern, verbose); break; case 'c': success = listOperatorClasses(pattern, pattern2, show_verbose); @@ -812,7 +817,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) success = describeAggregates(pattern, show_verbose, show_system); break; case 'b': - success = describeTablespaces(pattern, show_verbose); + success = describeTablespaces(pattern, verbose); break; case 'c': if (strncmp(cmd, "dconfig", 7) == 0) @@ -866,7 +871,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) success = listLanguages(pattern, show_verbose, show_system); break; case 'n': - success = listSchemas(pattern, show_verbose, show_system); + success = listSchemas(pattern, verbose, show_system); break; case 'o': success = exec_command_dfo(scan_state, cmd, pattern, @@ -1945,14 +1950,15 @@ exec_command_list(PsqlScanState scan_state, bool active_branch, const char *cmd) if (active_branch) { char *pattern; - bool show_verbose; + int verbose = 0; pattern = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, true); - show_verbose = strchr(cmd, '+') ? true : false; + for (const char *t = cmd; *t != '\0'; ++t) + verbose += *t == '+' ? 1 : 0; - success = listAllDbs(pattern, show_verbose); + success = listAllDbs(pattern, verbose); free(pattern); } diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c index 45f6a86b872..3be7a5b8dc8 100644 --- a/src/bin/psql/describe.c +++ b/src/bin/psql/describe.c @@ -139,12 +139,12 @@ 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; printQueryOpt myopt = pset.popt; - static const bool translate_columns[] = {false, true, false, false}; + static const bool translate_columns[] = {false, true, false, false, false}; if (pset.sversion < 90600) { @@ -176,6 +176,11 @@ describeAccessMethods(const char *pattern, bool verbose) " pg_catalog.obj_description(oid, 'pg_am') AS \"%s\"", gettext_noop("Handler"), gettext_noop("Description")); + + if (verbose > 1 && pset.sversion >= 170000) + appendPQExpBuffer(&buf, + ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_am_size(oid)) AS \"%s\"", + gettext_noop("Size")); } appendPQExpBufferStr(&buf, @@ -214,7 +219,7 @@ describeAccessMethods(const char *pattern, bool verbose) * Takes an optional regexp to select particular tablespaces */ bool -describeTablespaces(const char *pattern, bool verbose) +describeTablespaces(const char *pattern, int verbose) { PQExpBufferData buf; PGresult *res; @@ -234,12 +239,18 @@ describeTablespaces(const char *pattern, bool verbose) { appendPQExpBufferStr(&buf, ",\n "); printACLColumn(&buf, "spcacl"); + + appendPQExpBuffer(&buf, + ",\n spcoptions AS \"%s\"", + gettext_noop("Options")); + + if (verbose > 1) + appendPQExpBuffer(&buf, + ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_tablespace_size(oid)) AS \"%s\"", + gettext_noop("Size")); + appendPQExpBuffer(&buf, - ",\n spcoptions AS \"%s\"" - ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_tablespace_size(oid)) AS \"%s\"" ",\n pg_catalog.shobj_description(oid, 'pg_tablespace') AS \"%s\"", - gettext_noop("Options"), - gettext_noop("Size"), gettext_noop("Description")); } @@ -914,7 +925,7 @@ error_return: * for \l, \list, and -l switch */ bool -listAllDbs(const char *pattern, bool verbose) +listAllDbs(const char *pattern, int verbose) { PGresult *res; PQExpBufferData buf; @@ -961,20 +972,24 @@ listAllDbs(const char *pattern, bool verbose) gettext_noop("ICU Rules")); appendPQExpBufferStr(&buf, " "); printACLColumn(&buf, "d.datacl"); - if (verbose) + if (verbose > 1) appendPQExpBuffer(&buf, ",\n CASE WHEN pg_catalog.has_database_privilege(d.datname, 'CONNECT')\n" " THEN pg_catalog.pg_size_pretty(pg_catalog.pg_database_size(d.datname))\n" " ELSE 'No Access'\n" - " END as \"%s\"" + " END as \"%s\"", + gettext_noop("Size")); + + if (verbose > 0) + appendPQExpBuffer(&buf, ",\n t.spcname as \"%s\"" ",\n pg_catalog.shobj_description(d.oid, 'pg_database') as \"%s\"", - gettext_noop("Size"), gettext_noop("Tablespace"), 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"); @@ -5031,7 +5046,7 @@ listCollations(const char *pattern, bool verbose, bool showSystem) * Describes schemas (namespaces) */ bool -listSchemas(const char *pattern, bool verbose, bool showSystem) +listSchemas(const char *pattern, int verbose, bool showSystem) { PQExpBufferData buf; PGresult *res; @@ -5053,6 +5068,11 @@ listSchemas(const char *pattern, bool verbose, bool showSystem) appendPQExpBuffer(&buf, ",\n pg_catalog.obj_description(n.oid, 'pg_namespace') AS \"%s\"", gettext_noop("Description")); + + if (verbose > 1 && pset.sversion >= 170000) + appendPQExpBuffer(&buf, + ",\n pg_catalog.pg_size_pretty(pg_namespace_size(n.oid)) AS \"%s\"", + gettext_noop("Size")); } appendPQExpBufferStr(&buf, diff --git a/src/bin/psql/describe.h b/src/bin/psql/describe.h index 24c0884a347..f11579a7bbc 100644 --- a/src/bin/psql/describe.h +++ b/src/bin/psql/describe.h @@ -13,10 +13,10 @@ extern bool describeAggregates(const char *pattern, bool verbose, bool showSystem); /* \dA */ -extern bool describeAccessMethods(const char *pattern, bool verbose); +extern bool describeAccessMethods(const char *pattern, int verbose); /* \db */ -extern bool describeTablespaces(const char *pattern, bool verbose); +extern bool describeTablespaces(const char *pattern, int verbose); /* \df, \dfa, \dfn, \dft, \dfw, etc. */ extern bool describeFunctions(const char *functypes, const char *func_pattern, @@ -65,7 +65,7 @@ extern bool listTSDictionaries(const char *pattern, bool verbose); extern bool listTSTemplates(const char *pattern, bool verbose); /* \l */ -extern bool listAllDbs(const char *pattern, bool verbose); +extern bool listAllDbs(const char *pattern, int verbose); /* \dt, \di, \ds, \dS, etc. */ extern bool listTables(const char *tabtypes, const char *pattern, bool verbose, bool showSystem); @@ -90,7 +90,7 @@ extern bool listCasts(const char *pattern, bool verbose); extern bool listCollations(const char *pattern, bool verbose, bool showSystem); /* \dn */ -extern bool listSchemas(const char *pattern, bool verbose, bool showSystem); +extern bool listSchemas(const char *pattern, int verbose, bool showSystem); /* \dew */ extern bool listForeignDataWrappers(const char *pattern, bool verbose); -- 2.34.1
0003-f-convert-the-other-verbose-to-int-too.patch (text/x-diff, 40.4K) download From b41f6a5613bb25b46eadbfc5b89ab0a129490697 Mon Sep 17 00:00:00 2001 From: Justin Pryzby <pryzbyj@telsasoft.com> Date: Thu, 15 Jul 2021 03:19:58 -0500 Subject: [PATCH 3/4] f!convert the other verbose to int, too --- 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
0004-Move-the-double-plus-Size-columns-to-the-right.patch (text/x-diff, 9.9K) download From 372a74a3c89329cf9a3309ac6de242a7700f4dfa Mon Sep 17 00:00:00 2001 From: Justin Pryzby <pryzbyj@telsasoft.com> Date: Fri, 17 Dec 2021 09:35:46 -0600 Subject: [PATCH 4/4] Move the double-plus "Size" columns to the right \dn, \dA, \db, \l, and (for consistency) \d and \dP+ It doesn't make much sense that one cannot show a database's default tablespace without also showing its size, and stat()ing every segment of every relation in the DB. --- src/bin/psql/describe.c | 40 ++++++++++++---------- src/test/regress/expected/psql.out | 54 +++++++++++++++--------------- 2 files changed, 49 insertions(+), 45 deletions(-) diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c index 7eff1249015..cc5f00fffe7 100644 --- a/src/bin/psql/describe.c +++ b/src/bin/psql/describe.c @@ -241,17 +241,15 @@ describeTablespaces(const char *pattern, int verbose) printACLColumn(&buf, "spcacl"); appendPQExpBuffer(&buf, - ",\n spcoptions AS \"%s\"", - gettext_noop("Options")); + ",\n spcoptions AS \"%s\"" + ",\n pg_catalog.shobj_description(oid, 'pg_tablespace') AS \"%s\"", + gettext_noop("Options"), + gettext_noop("Description")); if (verbose > 1) appendPQExpBuffer(&buf, ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_tablespace_size(oid)) AS \"%s\"", gettext_noop("Size")); - - appendPQExpBuffer(&buf, - ",\n pg_catalog.shobj_description(oid, 'pg_tablespace') AS \"%s\"", - gettext_noop("Description")); } appendPQExpBufferStr(&buf, @@ -972,13 +970,6 @@ listAllDbs(const char *pattern, int verbose) gettext_noop("ICU Rules")); appendPQExpBufferStr(&buf, " "); printACLColumn(&buf, "d.datacl"); - if (verbose > 1) - appendPQExpBuffer(&buf, - ",\n CASE WHEN pg_catalog.has_database_privilege(d.datname, 'CONNECT')\n" - " THEN pg_catalog.pg_size_pretty(pg_catalog.pg_database_size(d.datname))\n" - " ELSE 'No Access'\n" - " END as \"%s\"", - gettext_noop("Size")); if (verbose > 0) appendPQExpBuffer(&buf, @@ -987,6 +978,14 @@ listAllDbs(const char *pattern, int verbose) gettext_noop("Tablespace"), gettext_noop("Description")); + if (verbose > 1) + appendPQExpBuffer(&buf, + ",\n CASE WHEN pg_catalog.has_database_privilege(d.datname, 'CONNECT')\n" + " THEN pg_catalog.pg_size_pretty(pg_catalog.pg_database_size(d.datname))\n" + " ELSE 'No Access'\n" + " END as \"%s\"", + gettext_noop("Size")); + appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_database d\n"); if (verbose > 0) @@ -4012,10 +4011,13 @@ listTables(const char *tabtypes, const char *pattern, int verbose, bool showSyst gettext_noop("Access method")); appendPQExpBuffer(&buf, - ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_table_size(c.oid)) as \"%s\"" ",\n pg_catalog.obj_description(c.oid, 'pg_class') as \"%s\"", - gettext_noop("Size"), gettext_noop("Description")); + + if (verbose > 1) + appendPQExpBuffer(&buf, + ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_table_size(c.oid)) as \"%s\"", + gettext_noop("Size")); } appendPQExpBufferStr(&buf, @@ -4199,6 +4201,11 @@ listPartitionedTables(const char *reltypes, const char *pattern, int verbose) gettext_noop("Table")); if (verbose > 0) + appendPQExpBuffer(&buf, + ",\n pg_catalog.obj_description(c.oid, 'pg_class') as \"%s\"", + gettext_noop("Description")); + + if (verbose > 1) { if (showNested) { @@ -4215,9 +4222,6 @@ listPartitionedTables(const char *reltypes, const char *pattern, int verbose) ",\n s.tps as \"%s\"", gettext_noop("Total size")); - appendPQExpBuffer(&buf, - ",\n pg_catalog.obj_description(c.oid, 'pg_class') as \"%s\"", - gettext_noop("Description")); } appendPQExpBufferStr(&buf, diff --git a/src/test/regress/expected/psql.out b/src/test/regress/expected/psql.out index 7cd0c27cca8..e623a2df7c9 100644 --- a/src/test/regress/expected/psql.out +++ b/src/test/regress/expected/psql.out @@ -2900,47 +2900,47 @@ Access method: heap -- AM is displayed for tables, indexes and materialized views. \d+ - List of relations - Schema | Name | Type | Owner | Persistence | Access method | Size | Description ------------------+--------------------+-------------------+----------------------+-------------+---------------+---------+------------- - tableam_display | mat_view_heap_psql | materialized view | regress_display_role | permanent | heap_psql | 0 bytes | - tableam_display | tbl_heap | table | regress_display_role | permanent | heap | 0 bytes | - tableam_display | tbl_heap_psql | table | regress_display_role | permanent | heap_psql | 0 bytes | - tableam_display | view_heap_psql | view | regress_display_role | permanent | | 0 bytes | + List of relations + Schema | Name | Type | Owner | Persistence | Access method | Description +-----------------+--------------------+-------------------+----------------------+-------------+---------------+------------- + tableam_display | mat_view_heap_psql | materialized view | regress_display_role | permanent | heap_psql | + tableam_display | tbl_heap | table | regress_display_role | permanent | heap | + tableam_display | tbl_heap_psql | table | regress_display_role | permanent | heap_psql | + tableam_display | view_heap_psql | view | regress_display_role | permanent | | (4 rows) \dt+ - List of relations - Schema | Name | Type | Owner | Persistence | Access method | Size | Description ------------------+---------------+-------+----------------------+-------------+---------------+---------+------------- - tableam_display | tbl_heap | table | regress_display_role | permanent | heap | 0 bytes | - tableam_display | tbl_heap_psql | table | regress_display_role | permanent | heap_psql | 0 bytes | + List of relations + Schema | Name | Type | Owner | Persistence | Access method | Description +-----------------+---------------+-------+----------------------+-------------+---------------+------------- + tableam_display | tbl_heap | table | regress_display_role | permanent | heap | + tableam_display | tbl_heap_psql | table | regress_display_role | permanent | heap_psql | (2 rows) \dm+ - List of relations - Schema | Name | Type | Owner | Persistence | Access method | Size | Description ------------------+--------------------+-------------------+----------------------+-------------+---------------+---------+------------- - tableam_display | mat_view_heap_psql | materialized view | regress_display_role | permanent | heap_psql | 0 bytes | + List of relations + Schema | Name | Type | Owner | Persistence | Access method | Description +-----------------+--------------------+-------------------+----------------------+-------------+---------------+------------- + tableam_display | mat_view_heap_psql | materialized view | regress_display_role | permanent | heap_psql | (1 row) -- But not for views and sequences. \dv+ - List of relations - Schema | Name | Type | Owner | Persistence | Size | Description ------------------+----------------+------+----------------------+-------------+---------+------------- - tableam_display | view_heap_psql | view | regress_display_role | permanent | 0 bytes | + List of relations + Schema | Name | Type | Owner | Persistence | Description +-----------------+----------------+------+----------------------+-------------+------------- + tableam_display | view_heap_psql | view | regress_display_role | permanent | (1 row) \set HIDE_TABLEAM on \d+ - List of relations - Schema | Name | Type | Owner | Persistence | Size | Description ------------------+--------------------+-------------------+----------------------+-------------+---------+------------- - tableam_display | mat_view_heap_psql | materialized view | regress_display_role | permanent | 0 bytes | - tableam_display | tbl_heap | table | regress_display_role | permanent | 0 bytes | - tableam_display | tbl_heap_psql | table | regress_display_role | permanent | 0 bytes | - tableam_display | view_heap_psql | view | regress_display_role | permanent | 0 bytes | + List of relations + Schema | Name | Type | Owner | Persistence | Description +-----------------+--------------------+-------------------+----------------------+-------------+------------- + tableam_display | mat_view_heap_psql | materialized view | regress_display_role | permanent | + tableam_display | tbl_heap | table | regress_display_role | permanent | + tableam_display | tbl_heap_psql | table | regress_display_role | permanent | + tableam_display | view_heap_psql | view | regress_display_role | permanent | (4 rows) RESET ROLE; -- 2.34.1
^ permalink raw reply [nested|flat] 22+ messages in thread

* Re: [PATCH] psql: \dn+ to show size of each schema (and \dA+ for AMs)
@ 2024-01-22 00:10  Peter Smith <smithpb2250@gmail.com>
  parent: Justin Pryzby <pryzby@telsasoft.com>
  1 sibling, 0 replies; 22+ messages in thread

From: Peter Smith @ 2024-01-22 00:10 UTC (permalink / raw)
  To: Justin Pryzby <pryzby@telsasoft.com>; +Cc: Daniel Gustafsson <daniel@yesql.se>; Pavel Stehule <pavel.stehule@gmail.com>; Laurenz Albe <laurenz.albe@cybertec.at>; Ian Lawrence Barwick <barwick@gmail.com>; pgsql-hackers@postgresql.org, Gilles Darold <gilles@darold.net>; Julien Rouhaud <rjuju123@gmail.com>

2024-01 Commitfest.

Hi, This patch had a CF status of "Ready for Committer", but the
thread has been inactive for 5+ months.

Since the last post from Justin said "hoping to receive some feedback"
I have changed the CF status back to "Needs Review" [1].

======
[1] https://commitfest.postgresql.org/46/3256/

Kind Regards,
Peter Smith.





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

* Re: [PATCH] psql: \dn+ to show size of each schema (and \dA+ for AMs)
@ 2024-05-30 17:59  David Christensen <david+pg@pgguru.net>
  parent: Justin Pryzby <pryzby@telsasoft.com>
  1 sibling, 1 reply; 22+ messages in thread

From: David Christensen @ 2024-05-30 17:59 UTC (permalink / raw)
  To: Justin Pryzby <pryzby@telsasoft.com>; +Cc: Daniel Gustafsson <daniel@yesql.se>; Pavel Stehule <pavel.stehule@gmail.com>; Laurenz Albe <laurenz.albe@cybertec.at>; Ian Lawrence Barwick <barwick@gmail.com>; pgsql-hackers@postgresql.org, Gilles Darold <gilles@darold.net>; Julien Rouhaud <rjuju123@gmail.com>; Stefan Fercot <stefan.fercot@protonmail.com>; Joseph Koshakow <koshy44@gmail.com>

Hi Justin,

Thanks for the patch and the work on it.  In reviewing the basic
feature, I think this is something that has utility and is worthwhile
at the high level.

A few more specific notes:

The pg_namespace_size() function can stand on its own, and probably
has some utility for the released Postgres versions.

I do think the psql implementation for the \dn+ or \dA+ commands
shouldn't need to use this same function; it's a straightforward
expansion of the SQL query that can be run in a way that will be
backwards-compatible with any connected postgres version, so no reason
to exclude this information for this cases.  (This may have been in an
earlier revision of the patchset; I didn't check everything.)

I think the \dX++ command versions add code complexity without a real
need for it.  We have precedence with \l(+) to show permissions on the
basic display and size on the extended display, and I think this is
sufficient in this case here.  While moving the permissions to \dn is
a behavior change, it's adding information, not taking it away, and as
an interactive command it is unlikely to introduce significant
breakage in any scripting scenario.

(In reviewing the patch we've also seen a bit of odd behavior/possible
bug with the existing extended + commands, which introducing
significant ++ overloading might be confusing, but not the
fault/concern of this patch.)

Quickie summary:

0001-Add-pg_am_size-pg_namespace_size.patch
- fine, but needs rebase to work
0002-psql-add-convenience-commands-dA-and-dn.patch
- split into just + variant; remove \l++
- make the \dn show permission and \dn+ show size
0003-f-convert-the-other-verbose-to-int-too.patch
- unneeded
0004-Move-the-double-plus-Size-columns-to-the-right.patch
- unneeded

Docs on the first patch seemed fine; I do think we'll need docs
changes for the psql changes.

Best,

David





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

* Re: [PATCH] psql: \dn+ to show size of each schema (and \dA+ for AMs)
@ 2024-06-03 14:10  Justin Pryzby <pryzby@telsasoft.com>
  parent: David Christensen <david+pg@pgguru.net>
  0 siblings, 2 replies; 22+ messages in thread

From: Justin Pryzby @ 2024-06-03 14:10 UTC (permalink / raw)
  To: David Christensen <david+pg@pgguru.net>; +Cc: Daniel Gustafsson <daniel@yesql.se>; Pavel Stehule <pavel.stehule@gmail.com>; Laurenz Albe <laurenz.albe@cybertec.at>; Ian Lawrence Barwick <barwick@gmail.com>; pgsql-hackers@postgresql.org, Gilles Darold <gilles@darold.net>; Julien Rouhaud <rjuju123@gmail.com>; Stefan Fercot <stefan.fercot@protonmail.com>; Joseph Koshakow <koshy44@gmail.com>

On Thu, May 30, 2024 at 10:59:06AM -0700, David Christensen wrote:
> Hi Justin,
> 
> Thanks for the patch and the work on it.  In reviewing the basic
> feature, I think this is something that has utility and is worthwhile
> at the high level.

Thanks for looking.

> A few more specific notes:
> 
> The pg_namespace_size() function can stand on its own, and probably
> has some utility for the released Postgres versions.

Are you suggesting to add the C function retroactively in back branches?
I don't think anybody would consider doing that.

It wouldn't be used by anything internally, and any module that wanted
to use it would have to check the minor version, instead of just the
major version, which is wrong.

> I do think the psql implementation for the \dn+ or \dA+ commands
> shouldn't need to use this same function; it's a straightforward
> expansion of the SQL query that can be run in a way that will be
> backwards-compatible with any connected postgres version, so no reason
> to exclude this information for this cases.  (This may have been in an
> earlier revision of the patchset; I didn't check everything.)

I think you're suggesting to write the query in SQL rather than in C.

But I did that in the first version of the patch, and the response was
that maybe in the future someone would want to add permission checks
that would compromize the ability to get correct results from SQL, so
then I presented the functionality writen in C.

I recommend that reviewers try to read the existing communication on the
thread, otherwise we end up going back and forth about the same things.

> I think the \dX++ command versions add code complexity without a real
> need for it.

If you view this as a way to "show schema sizes", then you're right,
there's no need.  But I don't want this patch to necessary further
embrace the idea that it's okay for "plus commands to be slow and show
nonportable results".  If there were a consensus that it'd be fine in a
plus command, I would be okay with that, though.

> We have precedence with \l(+) to show permissions on the
> basic display and size on the extended display, and I think this is
> sufficient in this case here.

You also have the precedence that \db doesn't show the ACL, and you
can't get it without also computing the sizes.  That's 1) inconsistent
with \l and 2) pretty inconvenient for someone who wants to show the
ACL (as mentioned in the first message on this thread).

> 0001-Add-pg_am_size-pg_namespace_size.patch
> - fine, but needs rebase to work

I suggest reviewers to consider sending a rebased patch, optionally with
any proposed changes in a separate patch.

> 0002-psql-add-convenience-commands-dA-and-dn.patch
> - split into just + variant; remove \l++
> - make the \dn show permission and \dn+ show size

> 0003-f-convert-the-other-verbose-to-int-too.patch
> - unneeded
> 0004-Move-the-double-plus-Size-columns-to-the-right.patch
> - unneeded

You say they're unneeded, but what I've been hoping for is a committer
interested enough to at least suggest whether to run with 001, 001+002,
001+002+003, or 001+002+003+004.  They're intentionally presented as
such.

I've also thought about submitting a patch specifically dedicated to
"moving size out of + and into ++".  I find the idea compelling, for the
reasons I wrote in the the patch description.  That'd be like presenting
003+004 first.

I'm opened to changing the behavior or the implementation.  But changing
the patch as I've presented it based on one suggestion I think will lead
to incoherent code trashing.  I need to hear a wider agreement.

-- 
Justin

Attachments: download all (4 files, .tar.gz)

0001-Add-pg_am_size-pg_namespace_size.patch (text/x-diff, 7.6K) download From 713213bb75dd4b7c45eab9219422a3ab4339df25 Mon Sep 17 00:00:00 2001 From: Justin Pryzby <pryzbyj@telsasoft.com> Date: Tue, 13 Jul 2021 21:25:48 -0500 Subject: [PATCH 1/4] Add pg_am_size(), pg_namespace_size() .. See also: 358a897fa, 528ac10c7 --- doc/src/sgml/func.sgml | 39 ++++++++++ src/backend/utils/adt/dbsize.c | 132 ++++++++++++++++++++++++++++++++ src/include/catalog/pg_proc.dat | 19 +++++ 3 files changed, 190 insertions(+) diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index 17c44bc3384..0515412ed30 100644 --- a/doc/src/sgml/func.sgml +++ b/doc/src/sgml/func.sgml @@ -29596,6 +29596,45 @@ postgres=# SELECT '0/0'::pg_lsn + pd.segment_number * ps.setting::int + :offset </para></entry> </row> + <row> + <entry role="func_table_entry"><para role="func_signature"> + <indexterm> + <primary>pg_namespace_size</primary> + </indexterm> + <function>pg_namespace_size</function> ( <type>name</type> ) + <returnvalue>bigint</returnvalue> + </para> + <para role="func_signature"> + <function>pg_namespace_size</function> ( <type>oid</type> ) + <returnvalue>bigint</returnvalue> + </para> + <para> + Computes the total disk space used by relations in the namespace (schema) + with the specified name or OID. To use this function, you must + have <literal>CREATE</literal> privilege on the specified namespace + or have privileges of the <literal>pg_read_all_stats</literal> role, + unless it is the default namespace for the current database. + </para></entry> + </row> + + <row> + <entry role="func_table_entry"><para role="func_signature"> + <indexterm> + <primary>pg_am_size</primary> + </indexterm> + <function>pg_am_size</function> ( <type>name</type> ) + <returnvalue>bigint</returnvalue> + </para> + <para role="func_signature"> + <function>pg_am_size</function> ( <type>oid</type> ) + <returnvalue>bigint</returnvalue> + </para> + <para> + Computes the total disk space used by relations using the access method + with the specified name or OID. + </para></entry> + </row> + <row> <entry role="func_table_entry"><para role="func_signature"> <indexterm> diff --git a/src/backend/utils/adt/dbsize.c b/src/backend/utils/adt/dbsize.c index 25d7110c130..90f9639051b 100644 --- a/src/backend/utils/adt/dbsize.c +++ b/src/backend/utils/adt/dbsize.c @@ -13,18 +13,24 @@ #include <sys/stat.h> +#include "access/genam.h" #include "access/htup_details.h" #include "access/relation.h" +#include "access/table.h" #include "catalog/namespace.h" #include "catalog/pg_authid.h" #include "catalog/pg_database.h" +#include "catalog/pg_namespace.h" #include "catalog/pg_tablespace.h" #include "commands/dbcommands.h" +#include "commands/defrem.h" #include "commands/tablespace.h" #include "miscadmin.h" #include "storage/fd.h" #include "utils/acl.h" #include "utils/builtins.h" +#include "utils/fmgroids.h" +#include "utils/lsyscache.h" #include "utils/numeric.h" #include "utils/rel.h" #include "utils/relfilenumbermap.h" @@ -857,6 +863,132 @@ pg_size_bytes(PG_FUNCTION_ARGS) PG_RETURN_INT64(result); } +/* + * Return the sum of size of relations for which the given attribute of + * pg_class matches the specified OID value. + */ +static int64 +calculate_size_attvalue(AttrNumber attnum, Oid attval) +{ + int64 totalsize = 0; + ScanKeyData skey; + Relation pg_class; + SysScanDesc scan; + HeapTuple tuple; + + ScanKeyInit(&skey, attnum, + BTEqualStrategyNumber, F_OIDEQ, attval); + + pg_class = table_open(RelationRelationId, AccessShareLock); + scan = systable_beginscan(pg_class, InvalidOid, false, NULL, 1, &skey); + while (HeapTupleIsValid(tuple = systable_getnext(scan))) + { + Form_pg_class classtuple = (Form_pg_class) GETSTRUCT(tuple); + Relation rel; + + rel = try_relation_open(classtuple->oid, AccessShareLock); + if (!rel) + continue; + + for (ForkNumber forkNum = 0; forkNum <= MAX_FORKNUM; forkNum++) + totalsize += calculate_relation_size(&(rel->rd_locator), rel->rd_backend, forkNum); + + relation_close(rel, AccessShareLock); + } + + systable_endscan(scan); + table_close(pg_class, AccessShareLock); + return totalsize; +} + +/* Compute the size of relations in a schema (namespace) */ +static int64 +calculate_namespace_size(Oid nspOid) +{ + /* + * User must be a member of pg_read_all_stats or have CREATE privilege for + * target namespace. + */ + if (!is_member_of_role(GetUserId(), ROLE_PG_READ_ALL_STATS)) + { + AclResult aclresult; + + aclresult = object_aclcheck(NamespaceRelationId, nspOid, GetUserId(), ACL_CREATE); + if (aclresult != ACLCHECK_OK) + aclcheck_error(aclresult, OBJECT_SCHEMA, + get_namespace_name(nspOid)); + } + + return calculate_size_attvalue(Anum_pg_class_relnamespace, nspOid); +} + +Datum +pg_namespace_size_oid(PG_FUNCTION_ARGS) +{ + Oid nspOid = PG_GETARG_OID(0); + int64 size; + + size = calculate_namespace_size(nspOid); + + if (size < 0) + PG_RETURN_NULL(); + + PG_RETURN_INT64(size); +} + +Datum +pg_namespace_size_name(PG_FUNCTION_ARGS) +{ + Name nspName = PG_GETARG_NAME(0); + Oid nspOid = get_namespace_oid(NameStr(*nspName), false); + int64 size; + + size = calculate_namespace_size(nspOid); + + if (size < 0) + PG_RETURN_NULL(); + + PG_RETURN_INT64(size); +} + +/* Compute the size of relations using the given access method */ +static int64 +calculate_am_size(Oid amOid) +{ + /* XXX acl_check? */ + + return calculate_size_attvalue(Anum_pg_class_relam, amOid); +} + +Datum +pg_am_size_oid(PG_FUNCTION_ARGS) +{ + Oid amOid = PG_GETARG_OID(0); + int64 size; + + size = calculate_am_size(amOid); + + if (size < 0) + PG_RETURN_NULL(); + + PG_RETURN_INT64(size); +} + +Datum +pg_am_size_name(PG_FUNCTION_ARGS) +{ + Name amName = PG_GETARG_NAME(0); + Oid amOid = get_am_oid(NameStr(*amName), false); + int64 size; + + size = calculate_am_size(amOid); + + if (size < 0) + PG_RETURN_NULL(); + + PG_RETURN_INT64(size); +} + /* * Get the filenode of a relation * diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat index 6a5476d3c4c..e8acaf6e5e5 100644 --- a/src/include/catalog/pg_proc.dat +++ b/src/include/catalog/pg_proc.dat @@ -7478,6 +7478,25 @@ descr => 'total disk space usage for the specified tablespace', proname => 'pg_tablespace_size', provolatile => 'v', prorettype => 'int8', proargtypes => 'name', prosrc => 'pg_tablespace_size_name' }, + +{ oid => '9410', + descr => 'total disk space usage for the specified namespace', + proname => 'pg_namespace_size', provolatile => 'v', prorettype => 'int8', + proargtypes => 'oid', prosrc => 'pg_namespace_size_oid' }, +{ oid => '9411', + descr => 'total disk space usage for the specified namespace', + proname => 'pg_namespace_size', provolatile => 'v', prorettype => 'int8', + proargtypes => 'name', prosrc => 'pg_namespace_size_name' }, + +{ oid => '9412', + descr => 'total disk space usage for the specified access method', + proname => 'pg_am_size', provolatile => 'v', prorettype => 'int8', + proargtypes => 'oid', prosrc => 'pg_am_size_oid' }, +{ oid => '9413', + descr => 'total disk space usage for the specified access method', + proname => 'pg_am_size', provolatile => 'v', prorettype => 'int8', + proargtypes => 'name', prosrc => 'pg_am_size_name' }, + { oid => '2324', descr => 'total disk space usage for the specified database', proname => 'pg_database_size', provolatile => 'v', prorettype => 'int8', proargtypes => 'oid', prosrc => 'pg_database_size_oid' }, -- 2.42.0
0002-psql-add-convenience-commands-dA-and-dn.patch (text/x-diff, 9.4K) download From a89d18fdbee65ec9ee6bc7d5bd98190a21512386 Mon Sep 17 00:00:00 2001 From: Justin Pryzby <pryzbyj@telsasoft.com> Date: Sat, 18 Dec 2021 14:58:06 -0600 Subject: [PATCH 2/4] psql: add convenience commands: \dA+ and \dn+ show the size only with \dA++ and \dn++ (for which the single-plus commands have historically not done any slow operations). Also change to show the size only with \db++ and \l++ (for which it's useful to show the ACL without also doing any slow operations). \dt+ and \dP+ are not changed, since showing the table sizes seems to be their primary purpose (??) The idea for plusplus commands were previously discussed here. https://www.postgresql.org/message-id/20190506163359.GA29291%40alvherre.pgsql --- src/bin/psql/command.c | 20 +++++++++++------- src/bin/psql/describe.c | 46 +++++++++++++++++++++++++++++------------ src/bin/psql/describe.h | 8 +++---- 3 files changed, 50 insertions(+), 24 deletions(-) diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c index fae5940b54e..14c772c18f3 100644 --- a/src/bin/psql/command.c +++ b/src/bin/psql/command.c @@ -370,6 +370,7 @@ exec_command(const char *cmd, else if (strcmp(cmd, "if") == 0) status = exec_command_if(scan_state, cstack, query_buf); else if (strcmp(cmd, "l") == 0 || strcmp(cmd, "list") == 0 || + strcmp(cmd, "l++") == 0 || strcmp(cmd, "list++") == 0 || strcmp(cmd, "l+") == 0 || strcmp(cmd, "list+") == 0) status = exec_command_list(scan_state, active_branch, cmd); else if (strncmp(cmd, "lo_", 3) == 0) @@ -757,6 +758,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) if (active_branch) { char *pattern; + int verbose = 0; bool show_verbose, show_system; @@ -764,7 +766,10 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) pattern = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, true); - show_verbose = strchr(cmd, '+') ? true : false; + for (const char *t = cmd; *t != '\0'; ++t) + verbose += *t == '+' ? 1 : 0; + + show_verbose = (bool) (verbose != 0); show_system = strchr(cmd, 'S') ? true : false; switch (cmd[1]) @@ -789,7 +794,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) { case '\0': case '+': - success = describeAccessMethods(pattern, show_verbose); + success = describeAccessMethods(pattern, verbose); break; case 'c': success = listOperatorClasses(pattern, pattern2, show_verbose); @@ -815,7 +820,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) success = describeAggregates(pattern, show_verbose, show_system); break; case 'b': - success = describeTablespaces(pattern, show_verbose); + success = describeTablespaces(pattern, verbose); break; case 'c': if (strncmp(cmd, "dconfig", 7) == 0) @@ -869,7 +874,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) success = listLanguages(pattern, show_verbose, show_system); break; case 'n': - success = listSchemas(pattern, show_verbose, show_system); + success = listSchemas(pattern, verbose, show_system); break; case 'o': success = exec_command_dfo(scan_state, cmd, pattern, @@ -1952,14 +1957,15 @@ exec_command_list(PsqlScanState scan_state, bool active_branch, const char *cmd) if (active_branch) { char *pattern; - bool show_verbose; + int verbose = 0; pattern = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, true); - show_verbose = strchr(cmd, '+') ? true : false; + for (const char *t = cmd; *t != '\0'; ++t) + verbose += *t == '+' ? 1 : 0; - success = listAllDbs(pattern, show_verbose); + success = listAllDbs(pattern, verbose); free(pattern); } diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c index f67bf0b8925..1d18f7c6cd9 100644 --- a/src/bin/psql/describe.c +++ b/src/bin/psql/describe.c @@ -138,12 +138,12 @@ 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; printQueryOpt myopt = pset.popt; - static const bool translate_columns[] = {false, true, false, false}; + static const bool translate_columns[] = {false, true, false, false, false}; if (pset.sversion < 90600) { @@ -175,6 +175,11 @@ describeAccessMethods(const char *pattern, bool verbose) " pg_catalog.obj_description(oid, 'pg_am') AS \"%s\"", gettext_noop("Handler"), gettext_noop("Description")); + + if (verbose > 1 && pset.sversion >= 170000) + appendPQExpBuffer(&buf, + ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_am_size(oid)) AS \"%s\"", + gettext_noop("Size")); } appendPQExpBufferStr(&buf, @@ -212,7 +217,7 @@ describeAccessMethods(const char *pattern, bool verbose) * Takes an optional regexp to select particular tablespaces */ bool -describeTablespaces(const char *pattern, bool verbose) +describeTablespaces(const char *pattern, int verbose) { PQExpBufferData buf; PGresult *res; @@ -232,12 +237,18 @@ describeTablespaces(const char *pattern, bool verbose) { appendPQExpBufferStr(&buf, ",\n "); printACLColumn(&buf, "spcacl"); + + appendPQExpBuffer(&buf, + ",\n spcoptions AS \"%s\"", + gettext_noop("Options")); + + if (verbose > 1) + appendPQExpBuffer(&buf, + ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_tablespace_size(oid)) AS \"%s\"", + gettext_noop("Size")); + appendPQExpBuffer(&buf, - ",\n spcoptions AS \"%s\"" - ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_tablespace_size(oid)) AS \"%s\"" ",\n pg_catalog.shobj_description(oid, 'pg_tablespace') AS \"%s\"", - gettext_noop("Options"), - gettext_noop("Size"), gettext_noop("Description")); } @@ -908,7 +919,7 @@ error_return: * for \l, \list, and -l switch */ bool -listAllDbs(const char *pattern, bool verbose) +listAllDbs(const char *pattern, int verbose) { PGresult *res; PQExpBufferData buf; @@ -959,20 +970,24 @@ listAllDbs(const char *pattern, bool verbose) gettext_noop("ICU Rules")); appendPQExpBufferStr(&buf, " "); printACLColumn(&buf, "d.datacl"); - if (verbose) + if (verbose > 1) appendPQExpBuffer(&buf, ",\n CASE WHEN pg_catalog.has_database_privilege(d.datname, 'CONNECT')\n" " THEN pg_catalog.pg_size_pretty(pg_catalog.pg_database_size(d.datname))\n" " ELSE 'No Access'\n" - " END as \"%s\"" + " END as \"%s\"", + gettext_noop("Size")); + + if (verbose > 0) + appendPQExpBuffer(&buf, ",\n t.spcname as \"%s\"" ",\n pg_catalog.shobj_description(d.oid, 'pg_database') as \"%s\"", - gettext_noop("Size"), gettext_noop("Tablespace"), 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"); @@ -5023,7 +5038,7 @@ listCollations(const char *pattern, bool verbose, bool showSystem) * Describes schemas (namespaces) */ bool -listSchemas(const char *pattern, bool verbose, bool showSystem) +listSchemas(const char *pattern, int verbose, bool showSystem) { PQExpBufferData buf; PGresult *res; @@ -5045,6 +5060,11 @@ listSchemas(const char *pattern, bool verbose, bool showSystem) appendPQExpBuffer(&buf, ",\n pg_catalog.obj_description(n.oid, 'pg_namespace') AS \"%s\"", gettext_noop("Description")); + + if (verbose > 1 && pset.sversion >= 170000) + appendPQExpBuffer(&buf, + ",\n pg_catalog.pg_size_pretty(pg_namespace_size(n.oid)) AS \"%s\"", + gettext_noop("Size")); } appendPQExpBufferStr(&buf, diff --git a/src/bin/psql/describe.h b/src/bin/psql/describe.h index 273f974538e..10271ba1393 100644 --- a/src/bin/psql/describe.h +++ b/src/bin/psql/describe.h @@ -13,10 +13,10 @@ extern bool describeAggregates(const char *pattern, bool verbose, bool showSystem); /* \dA */ -extern bool describeAccessMethods(const char *pattern, bool verbose); +extern bool describeAccessMethods(const char *pattern, int verbose); /* \db */ -extern bool describeTablespaces(const char *pattern, bool verbose); +extern bool describeTablespaces(const char *pattern, int verbose); /* \df, \dfa, \dfn, \dft, \dfw, etc. */ extern bool describeFunctions(const char *functypes, const char *func_pattern, @@ -65,7 +65,7 @@ extern bool listTSDictionaries(const char *pattern, bool verbose); extern bool listTSTemplates(const char *pattern, bool verbose); /* \l */ -extern bool listAllDbs(const char *pattern, bool verbose); +extern bool listAllDbs(const char *pattern, int verbose); /* \dt, \di, \ds, \dS, etc. */ extern bool listTables(const char *tabtypes, const char *pattern, bool verbose, bool showSystem); @@ -90,7 +90,7 @@ extern bool listCasts(const char *pattern, bool verbose); extern bool listCollations(const char *pattern, bool verbose, bool showSystem); /* \dn */ -extern bool listSchemas(const char *pattern, bool verbose, bool showSystem); +extern bool listSchemas(const char *pattern, int verbose, bool showSystem); /* \dew */ extern bool listForeignDataWrappers(const char *pattern, bool verbose); -- 2.42.0
0003-f-convert-the-other-verbose-to-int-too.patch (text/x-diff, 40.4K) download From e60146531711890993042f00667734097aca021d Mon Sep 17 00:00:00 2001 From: Justin Pryzby <pryzbyj@telsasoft.com> Date: Thu, 15 Jul 2021 03:19:58 -0500 Subject: [PATCH 3/4] f!convert the other verbose to int, too --- 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 14c772c18f3..6ee91bd2892 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, @@ -759,8 +759,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, @@ -769,7 +768,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]) @@ -778,10 +776,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': { @@ -797,16 +795,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; @@ -817,7 +815,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); @@ -825,15 +823,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) @@ -842,7 +840,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]) @@ -856,7 +854,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; @@ -865,23 +863,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); @@ -895,7 +893,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; @@ -904,7 +902,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': @@ -912,7 +910,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') @@ -935,36 +933,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; @@ -975,16 +973,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; @@ -992,7 +990,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); @@ -1001,7 +999,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; @@ -1022,7 +1020,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]; @@ -1045,11 +1043,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]); @@ -2023,9 +2021,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 1d18f7c6cd9..83f51d6c880 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; @@ -168,7 +168,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" @@ -233,7 +233,7 @@ describeTablespaces(const char *pattern, int verbose) gettext_noop("Owner"), gettext_noop("Location")); - if (verbose) + if (verbose > 0) { appendPQExpBufferStr(&buf, ",\n "); printACLColumn(&buf, "spcacl"); @@ -298,7 +298,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; @@ -383,7 +383,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" @@ -438,7 +438,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"); @@ -623,7 +623,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; @@ -636,7 +636,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" @@ -780,7 +780,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; @@ -816,7 +816,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")); @@ -1454,10 +1454,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; @@ -1543,7 +1543,7 @@ static bool describeOneTableDetails(const char *schemaname, const char *relationname, const char *oid, - bool verbose) + int verbose) { bool retval = false; PQExpBufferData buf; @@ -1916,7 +1916,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++; @@ -2174,7 +2174,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, @@ -2197,7 +2197,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); @@ -3921,7 +3922,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; @@ -3980,7 +3981,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. @@ -4119,7 +4120,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; @@ -4194,7 +4195,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) { @@ -4229,7 +4230,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) { @@ -4319,7 +4320,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; @@ -4335,7 +4336,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" @@ -4395,7 +4396,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; @@ -4422,7 +4423,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"); @@ -4435,7 +4436,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 " @@ -4478,7 +4479,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; @@ -4502,7 +4503,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")); @@ -4512,7 +4513,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" @@ -4558,7 +4559,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; @@ -4626,7 +4627,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; @@ -4667,7 +4668,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")); @@ -4802,7 +4803,7 @@ listExtendedStats(const char *pattern) * Describes casts. */ bool -listCasts(const char *pattern, bool verbose) +listCasts(const char *pattern, int verbose) { PQExpBufferData buf; PGresult *res; @@ -4843,7 +4844,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")); @@ -4864,7 +4865,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 = " @@ -4920,7 +4921,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; @@ -4984,7 +4985,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")); @@ -5053,7 +5054,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"); @@ -5164,13 +5165,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); @@ -5411,7 +5412,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; @@ -5426,7 +5427,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" @@ -5476,7 +5477,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; @@ -5484,7 +5485,7 @@ listTSTemplates(const char *pattern, bool verbose) initPQExpBuffer(&buf); - if (verbose) + if (verbose > 0) printfPQExpBuffer(&buf, "SELECT\n" " n.nspname AS \"%s\",\n" @@ -5541,13 +5542,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); @@ -5745,7 +5746,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; @@ -5762,7 +5763,7 @@ listForeignDataWrappers(const char *pattern, bool verbose) gettext_noop("Handler"), gettext_noop("Validator")); - if (verbose) + if (verbose > 0) { appendPQExpBufferStr(&buf, ",\n "); printACLColumn(&buf, "fdwacl"); @@ -5780,7 +5781,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 " @@ -5816,7 +5817,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; @@ -5831,7 +5832,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"); @@ -5856,7 +5857,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 " @@ -5892,7 +5893,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; @@ -5905,7 +5906,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 " @@ -5947,7 +5948,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; @@ -5962,7 +5963,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 " @@ -5982,7 +5983,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 " @@ -6542,7 +6543,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; @@ -6573,7 +6574,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) @@ -6695,7 +6696,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; @@ -6730,7 +6731,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" @@ -6746,7 +6747,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"); @@ -6796,7 +6797,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; @@ -6821,7 +6822,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")); @@ -6885,7 +6886,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; @@ -6918,7 +6919,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")); @@ -6927,7 +6928,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"); @@ -6983,7 +6984,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; @@ -7010,7 +7011,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")); @@ -7071,7 +7072,7 @@ error_return: * Lists large objects */ bool -listLargeObjects(bool verbose) +listLargeObjects(int verbose) { PQExpBufferData buf; PGresult *res; @@ -7085,7 +7086,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 10271ba1393..e0181bb3877 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.42.0
0004-Move-the-double-plus-Size-columns-to-the-right.patch (text/x-diff, 9.9K) download From b291f61f15e54306cc653faf6c87fee1e95ca94b Mon Sep 17 00:00:00 2001 From: Justin Pryzby <pryzbyj@telsasoft.com> Date: Fri, 17 Dec 2021 09:35:46 -0600 Subject: [PATCH 4/4] Move the double-plus "Size" columns to the right \dn, \dA, \db, \l, and (for consistency) \d and \dP+ It doesn't make much sense that one cannot show a database's default tablespace without also showing its size, and stat()ing every segment of every relation in the DB. --- src/bin/psql/describe.c | 40 ++++++++++++---------- src/test/regress/expected/psql.out | 54 +++++++++++++++--------------- 2 files changed, 49 insertions(+), 45 deletions(-) diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c index 83f51d6c880..b62355f2a58 100644 --- a/src/bin/psql/describe.c +++ b/src/bin/psql/describe.c @@ -239,17 +239,15 @@ describeTablespaces(const char *pattern, int verbose) printACLColumn(&buf, "spcacl"); appendPQExpBuffer(&buf, - ",\n spcoptions AS \"%s\"", - gettext_noop("Options")); + ",\n spcoptions AS \"%s\"" + ",\n pg_catalog.shobj_description(oid, 'pg_tablespace') AS \"%s\"", + gettext_noop("Options"), + gettext_noop("Description")); if (verbose > 1) appendPQExpBuffer(&buf, ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_tablespace_size(oid)) AS \"%s\"", gettext_noop("Size")); - - appendPQExpBuffer(&buf, - ",\n pg_catalog.shobj_description(oid, 'pg_tablespace') AS \"%s\"", - gettext_noop("Description")); } appendPQExpBufferStr(&buf, @@ -970,13 +968,6 @@ listAllDbs(const char *pattern, int verbose) gettext_noop("ICU Rules")); appendPQExpBufferStr(&buf, " "); printACLColumn(&buf, "d.datacl"); - if (verbose > 1) - appendPQExpBuffer(&buf, - ",\n CASE WHEN pg_catalog.has_database_privilege(d.datname, 'CONNECT')\n" - " THEN pg_catalog.pg_size_pretty(pg_catalog.pg_database_size(d.datname))\n" - " ELSE 'No Access'\n" - " END as \"%s\"", - gettext_noop("Size")); if (verbose > 0) appendPQExpBuffer(&buf, @@ -985,6 +976,14 @@ listAllDbs(const char *pattern, int verbose) gettext_noop("Tablespace"), gettext_noop("Description")); + if (verbose > 1) + appendPQExpBuffer(&buf, + ",\n CASE WHEN pg_catalog.has_database_privilege(d.datname, 'CONNECT')\n" + " THEN pg_catalog.pg_size_pretty(pg_catalog.pg_database_size(d.datname))\n" + " ELSE 'No Access'\n" + " END as \"%s\"", + gettext_noop("Size")); + appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_database d\n"); if (verbose > 0) @@ -4010,10 +4009,13 @@ listTables(const char *tabtypes, const char *pattern, int verbose, bool showSyst gettext_noop("Access method")); appendPQExpBuffer(&buf, - ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_table_size(c.oid)) as \"%s\"" ",\n pg_catalog.obj_description(c.oid, 'pg_class') as \"%s\"", - gettext_noop("Size"), gettext_noop("Description")); + + if (verbose > 1) + appendPQExpBuffer(&buf, + ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_table_size(c.oid)) as \"%s\"", + gettext_noop("Size")); } appendPQExpBufferStr(&buf, @@ -4196,6 +4198,11 @@ listPartitionedTables(const char *reltypes, const char *pattern, int verbose) gettext_noop("Table")); if (verbose > 0) + appendPQExpBuffer(&buf, + ",\n pg_catalog.obj_description(c.oid, 'pg_class') as \"%s\"", + gettext_noop("Description")); + + if (verbose > 1) { if (showNested) { @@ -4212,9 +4219,6 @@ listPartitionedTables(const char *reltypes, const char *pattern, int verbose) ",\n s.tps as \"%s\"", gettext_noop("Total size")); - appendPQExpBuffer(&buf, - ",\n pg_catalog.obj_description(c.oid, 'pg_class') as \"%s\"", - gettext_noop("Description")); } appendPQExpBufferStr(&buf, diff --git a/src/test/regress/expected/psql.out b/src/test/regress/expected/psql.out index 3bbe4c5f974..4b2db3174b0 100644 --- a/src/test/regress/expected/psql.out +++ b/src/test/regress/expected/psql.out @@ -2905,47 +2905,47 @@ Access method: heap -- AM is displayed for tables, indexes and materialized views. \d+ - List of relations - Schema | Name | Type | Owner | Persistence | Access method | Size | Description ------------------+--------------------+-------------------+----------------------+-------------+---------------+---------+------------- - tableam_display | mat_view_heap_psql | materialized view | regress_display_role | permanent | heap_psql | 0 bytes | - tableam_display | tbl_heap | table | regress_display_role | permanent | heap | 0 bytes | - tableam_display | tbl_heap_psql | table | regress_display_role | permanent | heap_psql | 0 bytes | - tableam_display | view_heap_psql | view | regress_display_role | permanent | | 0 bytes | + List of relations + Schema | Name | Type | Owner | Persistence | Access method | Description +-----------------+--------------------+-------------------+----------------------+-------------+---------------+------------- + tableam_display | mat_view_heap_psql | materialized view | regress_display_role | permanent | heap_psql | + tableam_display | tbl_heap | table | regress_display_role | permanent | heap | + tableam_display | tbl_heap_psql | table | regress_display_role | permanent | heap_psql | + tableam_display | view_heap_psql | view | regress_display_role | permanent | | (4 rows) \dt+ - List of relations - Schema | Name | Type | Owner | Persistence | Access method | Size | Description ------------------+---------------+-------+----------------------+-------------+---------------+---------+------------- - tableam_display | tbl_heap | table | regress_display_role | permanent | heap | 0 bytes | - tableam_display | tbl_heap_psql | table | regress_display_role | permanent | heap_psql | 0 bytes | + List of relations + Schema | Name | Type | Owner | Persistence | Access method | Description +-----------------+---------------+-------+----------------------+-------------+---------------+------------- + tableam_display | tbl_heap | table | regress_display_role | permanent | heap | + tableam_display | tbl_heap_psql | table | regress_display_role | permanent | heap_psql | (2 rows) \dm+ - List of relations - Schema | Name | Type | Owner | Persistence | Access method | Size | Description ------------------+--------------------+-------------------+----------------------+-------------+---------------+---------+------------- - tableam_display | mat_view_heap_psql | materialized view | regress_display_role | permanent | heap_psql | 0 bytes | + List of relations + Schema | Name | Type | Owner | Persistence | Access method | Description +-----------------+--------------------+-------------------+----------------------+-------------+---------------+------------- + tableam_display | mat_view_heap_psql | materialized view | regress_display_role | permanent | heap_psql | (1 row) -- But not for views and sequences. \dv+ - List of relations - Schema | Name | Type | Owner | Persistence | Size | Description ------------------+----------------+------+----------------------+-------------+---------+------------- - tableam_display | view_heap_psql | view | regress_display_role | permanent | 0 bytes | + List of relations + Schema | Name | Type | Owner | Persistence | Description +-----------------+----------------+------+----------------------+-------------+------------- + tableam_display | view_heap_psql | view | regress_display_role | permanent | (1 row) \set HIDE_TABLEAM on \d+ - List of relations - Schema | Name | Type | Owner | Persistence | Size | Description ------------------+--------------------+-------------------+----------------------+-------------+---------+------------- - tableam_display | mat_view_heap_psql | materialized view | regress_display_role | permanent | 0 bytes | - tableam_display | tbl_heap | table | regress_display_role | permanent | 0 bytes | - tableam_display | tbl_heap_psql | table | regress_display_role | permanent | 0 bytes | - tableam_display | view_heap_psql | view | regress_display_role | permanent | 0 bytes | + List of relations + Schema | Name | Type | Owner | Persistence | Description +-----------------+--------------------+-------------------+----------------------+-------------+------------- + tableam_display | mat_view_heap_psql | materialized view | regress_display_role | permanent | + tableam_display | tbl_heap | table | regress_display_role | permanent | + tableam_display | tbl_heap_psql | table | regress_display_role | permanent | + tableam_display | view_heap_psql | view | regress_display_role | permanent | (4 rows) RESET ROLE; -- 2.42.0
^ permalink raw reply [nested|flat] 22+ messages in thread

* Re: [PATCH] psql: \dn+ to show size of each schema (and \dA+ for AMs)
@ 2024-06-03 14:49  Pavel Stehule <pavel.stehule@gmail.com>
  parent: Justin Pryzby <pryzby@telsasoft.com>
  1 sibling, 0 replies; 22+ messages in thread

From: Pavel Stehule @ 2024-06-03 14:49 UTC (permalink / raw)
  To: Justin Pryzby <pryzby@telsasoft.com>; +Cc: David Christensen <david+pg@pgguru.net>; Daniel Gustafsson <daniel@yesql.se>; Laurenz Albe <laurenz.albe@cybertec.at>; Ian Lawrence Barwick <barwick@gmail.com>; pgsql-hackers@postgresql.org, Gilles Darold <gilles@darold.net>; Julien Rouhaud <rjuju123@gmail.com>; Stefan Fercot <stefan.fercot@protonmail.com>; Joseph Koshakow <koshy44@gmail.com>

po 3. 6. 2024 v 16:10 odesílatel Justin Pryzby <pryzby@telsasoft.com>
napsal:

> On Thu, May 30, 2024 at 10:59:06AM -0700, David Christensen wrote:
> > Hi Justin,
> >
> > Thanks for the patch and the work on it.  In reviewing the basic
> > feature, I think this is something that has utility and is worthwhile
> > at the high level.
>
> Thanks for looking.
>
> > A few more specific notes:
> >
> > The pg_namespace_size() function can stand on its own, and probably
> > has some utility for the released Postgres versions.
>
> Are you suggesting to add the C function retroactively in back branches?
> I don't think anybody would consider doing that.
>
> It wouldn't be used by anything internally, and any module that wanted
> to use it would have to check the minor version, instead of just the
> major version, which is wrong.
>
> > I do think the psql implementation for the \dn+ or \dA+ commands
> > shouldn't need to use this same function; it's a straightforward
> > expansion of the SQL query that can be run in a way that will be
> > backwards-compatible with any connected postgres version, so no reason
> > to exclude this information for this cases.  (This may have been in an
> > earlier revision of the patchset; I didn't check everything.)
>
> I think you're suggesting to write the query in SQL rather than in C.
>
> But I did that in the first version of the patch, and the response was
> that maybe in the future someone would want to add permission checks
> that would compromize the ability to get correct results from SQL, so
> then I presented the functionality writen in C.
>
> I recommend that reviewers try to read the existing communication on the
> thread, otherwise we end up going back and forth about the same things.
>
> > I think the \dX++ command versions add code complexity without a real
> > need for it.
>
> If you view this as a way to "show schema sizes", then you're right,
> there's no need.  But I don't want this patch to necessary further
> embrace the idea that it's okay for "plus commands to be slow and show
> nonportable results".  If there were a consensus that it'd be fine in a
> plus command, I would be okay with that, though.
>

I think showing size in \dX+ command is consistent with any other +
commands and the introduction ++ variant is inconsistent and not too
intuitive.

So I personally vote just for \dX+ without the introduction ++ command. Any
time, in this case we can introduce ++ in future when we see some
performance problems.


> > We have precedence with \l(+) to show permissions on the
> > basic display and size on the extended display, and I think this is
> > sufficient in this case here.
>
> You also have the precedence that \db doesn't show the ACL, and you
> can't get it without also computing the sizes.  That's 1) inconsistent
> with \l and 2) pretty inconvenient for someone who wants to show the
> ACL (as mentioned in the first message on this thread).
>
> > 0001-Add-pg_am_size-pg_namespace_size.patch
> > - fine, but needs rebase to work
>
> I suggest reviewers to consider sending a rebased patch, optionally with
> any proposed changes in a separate patch.
>
> > 0002-psql-add-convenience-commands-dA-and-dn.patch
> > - split into just + variant; remove \l++
> > - make the \dn show permission and \dn+ show size
>
> > 0003-f-convert-the-other-verbose-to-int-too.patch
> > - unneeded
> > 0004-Move-the-double-plus-Size-columns-to-the-right.patch
> > - unneeded
>
> You say they're unneeded, but what I've been hoping for is a committer
> interested enough to at least suggest whether to run with 001, 001+002,
> 001+002+003, or 001+002+003+004.  They're intentionally presented as
> such.
>
> I've also thought about submitting a patch specifically dedicated to
> "moving size out of + and into ++".  I find the idea compelling, for the
> reasons I wrote in the the patch description.  That'd be like presenting
> 003+004 first.
>
> I'm opened to changing the behavior or the implementation.  But changing
> the patch as I've presented it based on one suggestion I think will lead
> to incoherent code trashing.  I need to hear a wider agreement.
>
> --
> Justin
>

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

* Re: [PATCH] psql: \dn+ to show size of each schema (and \dA+ for AMs)
@ 2024-06-03 20:48  David Christensen <david+pg@pgguru.net>
  parent: Justin Pryzby <pryzby@telsasoft.com>
  1 sibling, 0 replies; 22+ messages in thread

From: David Christensen @ 2024-06-03 20:48 UTC (permalink / raw)
  To: Justin Pryzby <pryzby@telsasoft.com>; +Cc: Daniel Gustafsson <daniel@yesql.se>; Pavel Stehule <pavel.stehule@gmail.com>; Laurenz Albe <laurenz.albe@cybertec.at>; Ian Lawrence Barwick <barwick@gmail.com>; pgsql-hackers@postgresql.org, Gilles Darold <gilles@darold.net>; Julien Rouhaud <rjuju123@gmail.com>; Stefan Fercot <stefan.fercot@protonmail.com>; Joseph Koshakow <koshy44@gmail.com>

On Mon, Jun 3, 2024 at 9:10 AM Justin Pryzby <pryzby@telsasoft.com> wrote:
>
> On Thu, May 30, 2024 at 10:59:06AM -0700, David Christensen wrote:
> > Hi Justin,
> >
> > Thanks for the patch and the work on it.  In reviewing the basic
> > feature, I think this is something that has utility and is worthwhile
> > at the high level.
>
> Thanks for looking.
>
> > A few more specific notes:
> >
> > The pg_namespace_size() function can stand on its own, and probably
> > has some utility for the released Postgres versions.
>
> Are you suggesting to add the C function retroactively in back branches?
> I don't think anybody would consider doing that.
>
> It wouldn't be used by anything internally, and any module that wanted
> to use it would have to check the minor version, instead of just the
> major version, which is wrong.

Ah, I meant once released it would be useful going forward, but
re-reading it can see the ambiguity.  No, definitely not suggesting
adding to back branches.

> > I do think the psql implementation for the \dn+ or \dA+ commands
> > shouldn't need to use this same function; it's a straightforward
> > expansion of the SQL query that can be run in a way that will be
> > backwards-compatible with any connected postgres version, so no reason
> > to exclude this information for this cases.  (This may have been in an
> > earlier revision of the patchset; I didn't check everything.)
>
> I think you're suggesting to write the query in SQL rather than in C.

Yes.

> But I did that in the first version of the patch, and the response was
> that maybe in the future someone would want to add permission checks
> that would compromize the ability to get correct results from SQL, so
> then I presented the functionality writen in C.
>
> I recommend that reviewers try to read the existing communication on the
> thread, otherwise we end up going back and forth about the same things.

Yes, I reviewed the whole thread, just not all of the patch contents.
I'd agree that suggestion flapping is not useful, but just presenting
my take on this at this time (as well as several others in the Patch
Review workshop at PGConf.dev, which is where this one got revived).

> > I think the \dX++ command versions add code complexity without a real
> > need for it.
>
> If you view this as a way to "show schema sizes", then you're right,
> there's no need.  But I don't want this patch to necessary further
> embrace the idea that it's okay for "plus commands to be slow and show
> nonportable results".  If there were a consensus that it'd be fine in a
> plus command, I would be okay with that, though.

I think this is a separate discussion in terms of introducing
verbosity levels and not needed at this point for this feature.
Certainly revamping all inconsistencies with the psql command
interfaces is out of scope, just thinking about which one we'd want to
model going forward and providing an opinion there (for what it's
worth... :D)

> > We have precedence with \l(+) to show permissions on the
> > basic display and size on the extended display, and I think this is
> > sufficient in this case here.
>
> You also have the precedence that \db doesn't show the ACL, and you
> can't get it without also computing the sizes.  That's 1) inconsistent
> with \l and 2) pretty inconvenient for someone who wants to show the
> ACL (as mentioned in the first message on this thread).

I can't speak to this one, just think that adding more command options
adds to the overall complexity so probably to be avoided unless we
can't.

> > 0001-Add-pg_am_size-pg_namespace_size.patch
> > - fine, but needs rebase to work
>
> I suggest reviewers to consider sending a rebased patch, optionally with
> any proposed changes in a separate patch.

Sure, if you don't have time to do this; agree with your later remarks
that consensus is important before moving forward, so same applies
here.

> > 0002-psql-add-convenience-commands-dA-and-dn.patch
> > - split into just + variant; remove \l++
> > - make the \dn show permission and \dn+ show size
>
> > 0003-f-convert-the-other-verbose-to-int-too.patch
> > - unneeded
> > 0004-Move-the-double-plus-Size-columns-to-the-right.patch
> > - unneeded
>
> You say they're unneeded, but what I've been hoping for is a committer
> interested enough to at least suggest whether to run with 001, 001+002,
> 001+002+003, or 001+002+003+004.  They're intentionally presented as
> such.
>
> I've also thought about submitting a patch specifically dedicated to
> "moving size out of + and into ++".  I find the idea compelling, for the
> reasons I wrote in the the patch description.  That'd be like presenting
> 003+004 first.
>
> I'm opened to changing the behavior or the implementation.  But changing
> the patch as I've presented it based on one suggestion I think will lead
> to incoherent code trashing.  I need to hear a wider agreement.

Agreed that some sort of consensus is important.





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


end of thread, other threads:[~2024-06-03 20:48 UTC | newest]

Thread overview: 22+ messages (download: mbox mbox.gz follow: Atom feed)
-- links below jump to the message on this page --
2021-07-16 01:16 Re: [PATCH] psql: \dn+ to show size of each schema (and \dA+ for AMs) Justin Pryzby <pryzby@telsasoft.com>
2021-07-16 09:10 ` Laurenz Albe <laurenz.albe@cybertec.at>
2021-09-17 10:05 ` Pavel Stehule <pavel.stehule@gmail.com>
2021-09-28 02:46   ` Justin Pryzby <pryzby@telsasoft.com>
2021-09-28 04:33     ` Pavel Stehule <pavel.stehule@gmail.com>
2021-12-18 22:10     ` Justin Pryzby <pryzby@telsasoft.com>
2022-01-14 16:35       ` Justin Pryzby <pryzby@telsasoft.com>
2022-01-14 16:46         ` Pavel Stehule <pavel.stehule@gmail.com>
2022-06-10 11:48         ` Justin Pryzby <pryzby@telsasoft.com>
2022-07-30 05:35           ` Justin Pryzby <pryzby@telsasoft.com>
2022-08-01 20:47             ` Jacob Champion <jchampion@timescale.com>
2022-12-15 16:13             ` Justin Pryzby <pryzby@telsasoft.com>
2022-12-16 08:05               ` Pavel Stehule <pavel.stehule@gmail.com>
2023-03-11 22:55               ` Justin Pryzby <pryzby@telsasoft.com>
2023-05-24 21:05                 ` Justin Pryzby <pryzby@telsasoft.com>
2023-08-01 07:54                   ` Daniel Gustafsson <daniel@yesql.se>
2023-08-14 15:03                     ` Justin Pryzby <pryzby@telsasoft.com>
2024-01-22 00:10                       ` Peter Smith <smithpb2250@gmail.com>
2024-05-30 17:59                       ` David Christensen <david+pg@pgguru.net>
2024-06-03 14:10                         ` Justin Pryzby <pryzby@telsasoft.com>
2024-06-03 14:49                           ` Pavel Stehule <pavel.stehule@gmail.com>
2024-06-03 20:48                           ` David Christensen <david+pg@pgguru.net>

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