diff options
author | Robert Haas <rhaas@postgresql.org> | 2011-01-01 23:48:11 -0500 |
---|---|---|
committer | Robert Haas <rhaas@postgresql.org> | 2011-01-01 23:48:11 -0500 |
commit | 0d692a0dc9f0e532c67c577187fe5d7d323cb95b (patch) | |
tree | 5177be3794b8ffa768a3cd852221425bd2a74347 /src/bin/psql/describe.c | |
parent | 6600d5e91c754789002ed794c18cb856c190f58f (diff) | |
download | postgresql-0d692a0dc9f0e532c67c577187fe5d7d323cb95b.tar.gz postgresql-0d692a0dc9f0e532c67c577187fe5d7d323cb95b.zip |
Basic foreign table support.
Foreign tables are a core component of SQL/MED. This commit does
not provide a working SQL/MED infrastructure, because foreign tables
cannot yet be queried. Support for foreign table scans will need to
be added in a future patch. However, this patch creates the necessary
system catalog structure, syntax support, and support for ancillary
operations such as COMMENT and SECURITY LABEL.
Shigeru Hanada, heavily revised by Robert Haas
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. |