diff options
Diffstat (limited to 'src/bin/psql/describe.c')
-rw-r--r-- | src/bin/psql/describe.c | 123 |
1 files changed, 111 insertions, 12 deletions
diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c index 19ba517d1ba..205190f729e 100644 --- a/src/bin/psql/describe.c +++ b/src/bin/psql/describe.c @@ -687,11 +687,12 @@ permissionsList(const char *pattern) printfPQExpBuffer(&buf, "SELECT n.nspname as \"%s\",\n" " c.relname as \"%s\",\n" - " CASE c.relkind WHEN 'r' THEN '%s' WHEN 'v' THEN '%s' WHEN 'S' THEN '%s' END as \"%s\",\n" + " CASE c.relkind WHEN 'r' THEN '%s' WHEN 'v' THEN '%s' WHEN 'S' THEN '%s' WHEN 'f' THEN '%s' END as \"%s\",\n" " ", gettext_noop("Schema"), gettext_noop("Name"), gettext_noop("table"), gettext_noop("view"), gettext_noop("sequence"), + gettext_noop("foreign table"), gettext_noop("Type")); printACLColumn(&buf, "c.relacl"); @@ -707,7 +708,7 @@ permissionsList(const char *pattern) appendPQExpBuffer(&buf, "\nFROM pg_catalog.pg_class c\n" " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace\n" - "WHERE c.relkind IN ('r', 'v', 'S')\n"); + "WHERE c.relkind IN ('r', 'v', 'S', 'f')\n"); /* * Unless a schema pattern is specified, we suppress system and temp @@ -921,15 +922,16 @@ objectDescription(const char *pattern, bool showSystem) " n.nspname as nspname,\n" " CAST(c.relname AS pg_catalog.text) as name,\n" " CAST(\n" - " CASE c.relkind WHEN 'r' THEN '%s' WHEN 'v' THEN '%s' WHEN 'i' THEN '%s' WHEN 'S' THEN '%s' END" + " CASE c.relkind WHEN 'r' THEN '%s' WHEN 'v' THEN '%s' WHEN 'i' THEN '%s' WHEN 'S' THEN '%s' WHEN 'f' THEN '%s' END" " AS pg_catalog.text) as object\n" " FROM pg_catalog.pg_class c\n" " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace\n" - " WHERE c.relkind IN ('r', 'v', 'i', 'S')\n", + " WHERE c.relkind IN ('r', 'v', 'i', 'S', 'f')\n", gettext_noop("table"), gettext_noop("view"), gettext_noop("index"), - gettext_noop("sequence")); + gettext_noop("sequence"), + gettext_noop("foreign table")); if (!showSystem && !pattern) appendPQExpBuffer(&buf, " AND n.nspname <> 'pg_catalog'\n" @@ -1325,6 +1327,10 @@ describeOneTableDetails(const char *schemaname, printfPQExpBuffer(&title, _("Composite type \"%s.%s\""), schemaname, relationname); break; + case 'f': + printfPQExpBuffer(&title, _("Foreign table \"%s.%s\""), + schemaname, relationname); + break; default: /* untranslated unknown relkind */ printfPQExpBuffer(&title, "?%c? \"%s.%s\"", @@ -1337,7 +1343,8 @@ describeOneTableDetails(const char *schemaname, headers[1] = gettext_noop("Type"); cols = 2; - if (tableinfo.relkind == 'r' || tableinfo.relkind == 'v') + if (tableinfo.relkind == 'r' || tableinfo.relkind == 'v' || + tableinfo.relkind == 'f') { show_modifiers = true; headers[cols++] = gettext_noop("Modifiers"); @@ -1565,7 +1572,7 @@ describeOneTableDetails(const char *schemaname, PQclear(result); } } - else if (tableinfo.relkind == 'r') + else if (tableinfo.relkind == 'r' || tableinfo.relkind == 'f') { /* Footer information about a table */ PGresult *result = NULL; @@ -1984,11 +1991,36 @@ describeOneTableDetails(const char *schemaname, /* * Finish printing the footer information about a table. */ - if (tableinfo.relkind == 'r') + if (tableinfo.relkind == 'r' || tableinfo.relkind == 'f') { PGresult *result; int tuples; + /* print foreign server name */ + if (tableinfo.relkind == 'f') + { + /* Footer information about foreign table */ + printfPQExpBuffer(&buf, + "SELECT s.srvname\n" + "FROM pg_catalog.pg_foreign_table f,\n" + " pg_catalog.pg_foreign_server s\n" + "WHERE f.ftrelid = %s AND s.oid = f.ftserver", + oid); + result = PSQLexec(buf.data, false); + if (!result) + goto error_return; + else if (PQntuples(result) != 1) + { + PQclear(result); + goto error_return; + } + + printfPQExpBuffer(&buf, "Server: %s", + PQgetvalue(result, 0, 0)); + printTableAddFooter(&cont, buf.data); + PQclear(result); + } + /* print inherited tables */ printfPQExpBuffer(&buf, "SELECT c.oid::pg_catalog.regclass FROM pg_catalog.pg_class c, pg_catalog.pg_inherits i WHERE c.oid=i.inhparent AND i.inhrelid = '%s' ORDER BY inhseqno", oid); @@ -2406,8 +2438,9 @@ listDbRoleSettings(const char *pattern, const char *pattern2) * i - indexes * v - views * s - sequences + * E - foreign table (Note: different from 'f', the relkind value) * (any order of the above is fine) - * If tabtypes is empty, we default to \dtvs. + * If tabtypes is empty, we default to \dtvsE. */ bool listTables(const char *tabtypes, const char *pattern, bool verbose, bool showSystem) @@ -2416,14 +2449,15 @@ listTables(const char *tabtypes, const char *pattern, bool verbose, bool showSys bool showIndexes = strchr(tabtypes, 'i') != NULL; bool showViews = strchr(tabtypes, 'v') != NULL; bool showSeq = strchr(tabtypes, 's') != NULL; + bool showForeign = strchr(tabtypes, 'E') != NULL; PQExpBufferData buf; PGresult *res; printQueryOpt myopt = pset.popt; static const bool translate_columns[] = {false, false, true, false, false, false, false}; - if (!(showTables || showIndexes || showViews || showSeq)) - showTables = showViews = showSeq = true; + if (!(showTables || showIndexes || showViews || showSeq || showForeign)) + showTables = showViews = showSeq = showForeign = true; initPQExpBuffer(&buf); @@ -2434,7 +2468,7 @@ listTables(const char *tabtypes, const char *pattern, bool verbose, bool showSys printfPQExpBuffer(&buf, "SELECT n.nspname as \"%s\",\n" " c.relname as \"%s\",\n" - " CASE c.relkind WHEN 'r' THEN '%s' WHEN 'v' THEN '%s' WHEN 'i' THEN '%s' WHEN 'S' THEN '%s' WHEN 's' THEN '%s' END as \"%s\",\n" + " CASE c.relkind WHEN 'r' THEN '%s' WHEN 'v' THEN '%s' WHEN 'i' THEN '%s' WHEN 'S' THEN '%s' WHEN 's' THEN '%s' WHEN 'f' THEN '%s' END as \"%s\",\n" " pg_catalog.pg_get_userbyid(c.relowner) as \"%s\"", gettext_noop("Schema"), gettext_noop("Name"), @@ -2443,6 +2477,7 @@ listTables(const char *tabtypes, const char *pattern, bool verbose, bool showSys gettext_noop("index"), gettext_noop("sequence"), gettext_noop("special"), + gettext_noop("foreign table"), gettext_noop("Type"), gettext_noop("Owner")); @@ -2480,6 +2515,9 @@ listTables(const char *tabtypes, const char *pattern, bool verbose, bool showSys if (showSystem || pattern) appendPQExpBuffer(&buf, "'s',"); /* was RELKIND_SPECIAL in <= * 8.1 */ + if (showForeign) + appendPQExpBuffer(&buf, "'f',"); + appendPQExpBuffer(&buf, "''"); /* dummy */ appendPQExpBuffer(&buf, ")\n"); @@ -3530,6 +3568,67 @@ listUserMappings(const char *pattern, bool verbose) } /* + * \det + * + * Describes foreign tables. + */ +bool +listForeignTables(const char *pattern, bool verbose) +{ + PQExpBufferData buf; + PGresult *res; + printQueryOpt myopt = pset.popt; + + if (pset.sversion < 90100) + { + fprintf(stderr, _("The server (version %d.%d) does not support foreign table.\n"), + pset.sversion / 10000, (pset.sversion / 100) % 100); + return true; + } + + initPQExpBuffer(&buf); + printfPQExpBuffer(&buf, + "SELECT n.nspname AS \"%s\",\n" + " c.relname AS \"%s\",\n" + " s.srvname AS \"%s\"", + gettext_noop("Schema"), + gettext_noop("Table"), + gettext_noop("Server")); + + if (verbose) + appendPQExpBuffer(&buf, + ",\n ft.ftoptions AS \"%s\"", + gettext_noop("Options")); + + appendPQExpBuffer(&buf, "\nFROM pg_catalog.pg_foreign_table ft,"); + appendPQExpBuffer(&buf, "\n pg_catalog.pg_class c,"); + appendPQExpBuffer(&buf, "\n pg_catalog.pg_namespace n,"); + appendPQExpBuffer(&buf, "\n pg_catalog.pg_foreign_server s\n"); + appendPQExpBuffer(&buf, "\nWHERE c.oid = ft.ftrelid"); + appendPQExpBuffer(&buf, "\nAND s.oid = ft.ftserver\n"); + appendPQExpBuffer(&buf, "\nAND n.oid = c.relnamespace\n"); + + processSQLNamePattern(pset.db, &buf, pattern, true, false, + NULL, "n.nspname", "c.relname", NULL); + + appendPQExpBuffer(&buf, "ORDER BY 1, 2;"); + + res = PSQLexec(buf.data, false); + termPQExpBuffer(&buf); + if (!res) + return false; + + myopt.nullPrint = NULL; + myopt.title = _("List of foreign tables"); + myopt.translate_header = true; + + printQuery(res, &myopt, pset.queryFout, pset.logfile); + + PQclear(res); + return true; +} + +/* * printACLColumn * * Helper function for consistently formatting ACL (privilege) columns. |