Rebased before Julian asks.
>From cf57143c85a2a6088fe6038e6d41771fd60aae34 Mon Sep 17 00:00:00 2001 From: Justin Pryzby <pryz...@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
>From 771086b0b1d6116309a831e1e122cdce05d7dd6b Mon Sep 17 00:00:00 2001 From: Justin Pryzby <pryz...@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
>From cece72e72b35110f222228e8f71397e4fc72469a Mon Sep 17 00:00:00 2001 From: Justin Pryzby <pryz...@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
>From 25671fe1088283adce706ba5dace7323c6de7da9 Mon Sep 17 00:00:00 2001 From: Justin Pryzby <pryz...@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