From eb5472da9f83c2e432ac27a053929947e354d20c Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Tue, 23 Jul 2019 15:25:56 -0400 Subject: [PATCH] Improve psql's \d output for TOAST tables. Add the name of the owning table to the footers for a TOAST table. Also, show all the same footers as for a regular table (in practice, this adds the index and perhaps the tablespace and access method). Justin Pryzby, reviewed by Fabien Coelho Discussion: https://postgr.es/m/20190422154902.GH14223@telsasoft.com --- src/bin/psql/describe.c | 37 +++++++++++++++++++++++++++--- src/test/regress/expected/psql.out | 12 ++++++++++ src/test/regress/sql/psql.sql | 3 +++ 3 files changed, 49 insertions(+), 3 deletions(-) diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c index 8b4cd53631..b57bb8e831 100644 --- a/src/bin/psql/describe.c +++ b/src/bin/psql/describe.c @@ -2172,6 +2172,33 @@ describeOneTableDetails(const char *schemaname, PQclear(result); } + if (tableinfo.relkind == RELKIND_TOASTVALUE) + { + /* For a TOAST table, print name of owning table */ + PGresult *result; + + printfPQExpBuffer(&buf, + "SELECT n.nspname, c.relname\n" + "FROM pg_catalog.pg_class c" + " JOIN pg_catalog.pg_namespace n" + " ON n.oid = c.relnamespace\n" + "WHERE reltoastrelid = '%s';", oid); + result = PSQLexec(buf.data); + if (!result) + goto error_return; + + if (PQntuples(result) == 1) + { + char *schemaname = PQgetvalue(result, 0, 0); + char *relname = PQgetvalue(result, 0, 1); + + printfPQExpBuffer(&tmpbuf, _("Owning table: \"%s.%s\""), + schemaname, relname); + printTableAddFooter(&cont, tmpbuf.data); + } + PQclear(result); + } + if (tableinfo.relkind == RELKIND_INDEX || tableinfo.relkind == RELKIND_PARTITIONED_INDEX) { @@ -2272,10 +2299,12 @@ describeOneTableDetails(const char *schemaname, PQclear(result); } + /* If you add relkinds here, see also "Finish printing..." stanza below */ else if (tableinfo.relkind == RELKIND_RELATION || tableinfo.relkind == RELKIND_MATVIEW || tableinfo.relkind == RELKIND_FOREIGN_TABLE || - tableinfo.relkind == RELKIND_PARTITIONED_TABLE) + tableinfo.relkind == RELKIND_PARTITIONED_TABLE || + tableinfo.relkind == RELKIND_TOASTVALUE) { /* Footer information about a table */ PGresult *result = NULL; @@ -3040,7 +3069,8 @@ describeOneTableDetails(const char *schemaname, if (tableinfo.relkind == RELKIND_RELATION || tableinfo.relkind == RELKIND_MATVIEW || tableinfo.relkind == RELKIND_FOREIGN_TABLE || - tableinfo.relkind == RELKIND_PARTITIONED_TABLE) + tableinfo.relkind == RELKIND_PARTITIONED_TABLE || + tableinfo.relkind == RELKIND_TOASTVALUE) { PGresult *result; int tuples; @@ -3308,7 +3338,8 @@ add_tablespace_footer(printTableContent *const cont, char relkind, relkind == RELKIND_MATVIEW || relkind == RELKIND_INDEX || relkind == RELKIND_PARTITIONED_TABLE || - relkind == RELKIND_PARTITIONED_INDEX) + relkind == RELKIND_PARTITIONED_INDEX || + relkind == RELKIND_TOASTVALUE) { /* * We ignore the database default tablespace so that users not using diff --git a/src/test/regress/expected/psql.out b/src/test/regress/expected/psql.out index 9021c808dc..ef534a36a0 100644 --- a/src/test/regress/expected/psql.out +++ b/src/test/regress/expected/psql.out @@ -4748,3 +4748,15 @@ drop schema testpart; set search_path to default; set role to default; drop role regress_partitioning_role; +-- \d on toast table (use pg_statistic's toast table, which has a known name) +\d pg_toast.pg_toast_2619 +TOAST table "pg_toast.pg_toast_2619" + Column | Type +------------+--------- + chunk_id | oid + chunk_seq | integer + chunk_data | bytea +Owning table: "pg_catalog.pg_statistic" +Indexes: + "pg_toast_2619_index" PRIMARY KEY, btree (chunk_id, chunk_seq) + diff --git a/src/test/regress/sql/psql.sql b/src/test/regress/sql/psql.sql index cefe41bdc2..2e37984962 100644 --- a/src/test/regress/sql/psql.sql +++ b/src/test/regress/sql/psql.sql @@ -1131,3 +1131,6 @@ set search_path to default; set role to default; drop role regress_partitioning_role; + +-- \d on toast table (use pg_statistic's toast table, which has a known name) +\d pg_toast.pg_toast_2619