]> granicus.if.org Git - postgresql/blobdiff - src/bin/psql/describe.c
Add missing translate_columns array entry
[postgresql] / src / bin / psql / describe.c
index a194ce7e269804702fee26940ad455366a06ea9a..2cdc5acf30264355c2d5784eca1c8bd9529e3141 100644 (file)
@@ -6,7 +6,7 @@
  * with servers of versions 7.4 and up.  It's okay to omit irrelevant
  * information for an old server, but not to fail outright.
  *
- * Copyright (c) 2000-2014, PostgreSQL Global Development Group
+ * Copyright (c) 2000-2016, PostgreSQL Global Development Group
  *
  * src/bin/psql/describe.c
  */
 #include <ctype.h>
 
 #include "catalog/pg_default_acl.h"
+#include "fe_utils/string_utils.h"
 
 #include "common.h"
 #include "describe.h"
-#include "dumputils.h"
-#include "mbprint.h"
-#include "print.h"
+#include "fe_utils/mbprint.h"
+#include "fe_utils/print.h"
 #include "settings.h"
 #include "variables.h"
 
@@ -106,7 +106,7 @@ describeAggregates(const char *pattern, bool verbose, bool showSystem)
 
        if (!showSystem && !pattern)
                appendPQExpBufferStr(&buf, "      AND n.nspname <> 'pg_catalog'\n"
-                                                 "      AND n.nspname <> 'information_schema'\n");
+                                                        "      AND n.nspname <> 'information_schema'\n");
 
        processSQLNamePattern(pset.db, &buf, pattern, true, false,
                                                  "n.nspname", "p.proname", NULL,
@@ -114,7 +114,7 @@ describeAggregates(const char *pattern, bool verbose, bool showSystem)
 
        appendPQExpBufferStr(&buf, "ORDER BY 1, 2, 4;");
 
-       res = PSQLexec(buf.data, false);
+       res = PSQLexec(buf.data);
        termPQExpBuffer(&buf);
        if (!res)
                return false;
@@ -123,7 +123,71 @@ describeAggregates(const char *pattern, bool verbose, bool showSystem)
        myopt.title = _("List of aggregate functions");
        myopt.translate_header = true;
 
-       printQuery(res, &myopt, pset.queryFout, pset.logfile);
+       printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
+
+       PQclear(res);
+       return true;
+}
+
+/* \dA
+ * Takes an optional regexp to select particular access methods
+ */
+bool
+describeAccessMethods(const char *pattern, bool verbose)
+{
+       PQExpBufferData buf;
+       PGresult   *res;
+       printQueryOpt myopt = pset.popt;
+       static const bool translate_columns[] = {false, true, false, false};
+
+       if (pset.sversion < 90600)
+       {
+               psql_error("The server (version %d.%d) does not support access methods.\n",
+                                  pset.sversion / 10000, (pset.sversion / 100) % 100);
+               return true;
+       }
+
+       initPQExpBuffer(&buf);
+
+       printfPQExpBuffer(&buf,
+                                         "SELECT amname AS \"%s\",\n"
+                                         "  CASE amtype"
+                                         " WHEN 'i' THEN '%s'"
+                                         " END AS \"%s\"",
+                                         gettext_noop("Name"),
+                                         gettext_noop("Index"),
+                                         gettext_noop("Type"));
+
+       if (verbose)
+       {
+               appendPQExpBuffer(&buf,
+                                                 ",\n  amhandler AS \"%s\",\n"
+                                         "  pg_catalog.obj_description(oid, 'pg_am') AS \"%s\"",
+                                                 gettext_noop("Handler"),
+                                                 gettext_noop("Description"));
+       }
+
+       appendPQExpBufferStr(&buf,
+                                                "\nFROM pg_catalog.pg_am\n");
+
+       processSQLNamePattern(pset.db, &buf, pattern, false, false,
+                                                 NULL, "amname", NULL,
+                                                 NULL);
+
+       appendPQExpBufferStr(&buf, "ORDER BY 1;");
+
+       res = PSQLexec(buf.data);
+       termPQExpBuffer(&buf);
+       if (!res)
+               return false;
+
+       myopt.nullPrint = NULL;
+       myopt.title = _("List of access methods");
+       myopt.translate_header = true;
+       myopt.translate_columns = translate_columns;
+       myopt.n_translate_columns = lengthof(translate_columns);
+
+       printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
 
        PQclear(res);
        return true;
@@ -176,6 +240,11 @@ describeTablespaces(const char *pattern, bool verbose)
                                                  ",\n  spcoptions AS \"%s\"",
                                                  gettext_noop("Options"));
 
+       if (verbose && pset.sversion >= 90200)
+               appendPQExpBuffer(&buf,
+                                                 ",\n  pg_catalog.pg_size_pretty(pg_catalog.pg_tablespace_size(oid)) AS \"%s\"",
+                                                 gettext_noop("Size"));
+
        if (verbose && pset.sversion >= 80200)
                appendPQExpBuffer(&buf,
                 ",\n  pg_catalog.shobj_description(oid, 'pg_tablespace') AS \"%s\"",
@@ -190,7 +259,7 @@ describeTablespaces(const char *pattern, bool verbose)
 
        appendPQExpBufferStr(&buf, "ORDER BY 1;");
 
-       res = PSQLexec(buf.data, false);
+       res = PSQLexec(buf.data);
        termPQExpBuffer(&buf);
        if (!res)
                return false;
@@ -199,7 +268,7 @@ describeTablespaces(const char *pattern, bool verbose)
        myopt.title = _("List of tablespaces");
        myopt.translate_header = true;
 
-       printQuery(res, &myopt, pset.queryFout, pset.logfile);
+       printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
 
        PQclear(res);
        return true;
@@ -449,11 +518,11 @@ describeFunctions(const char *functypes, const char *pattern, bool verbose, bool
 
        if (!showSystem && !pattern)
                appendPQExpBufferStr(&buf, "      AND n.nspname <> 'pg_catalog'\n"
-                                                 "      AND n.nspname <> 'information_schema'\n");
+                                                        "      AND n.nspname <> 'information_schema'\n");
 
        appendPQExpBufferStr(&buf, "ORDER BY 1, 2, 4;");
 
-       res = PSQLexec(buf.data, false);
+       res = PSQLexec(buf.data);
        termPQExpBuffer(&buf);
        if (!res)
                return false;
@@ -464,7 +533,7 @@ describeFunctions(const char *functypes, const char *pattern, bool verbose, bool
        myopt.translate_columns = translate_columns;
        myopt.n_translate_columns = lengthof(translate_columns);
 
-       printQuery(res, &myopt, pset.queryFout, pset.logfile);
+       printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
 
        PQclear(res);
        return true;
@@ -523,6 +592,12 @@ describeTypes(const char *pattern, bool verbose, bool showSystem)
                                                  "  ) AS \"%s\",\n",
                                                  gettext_noop("Elements"));
        }
+       if (verbose)
+       {
+               appendPQExpBuffer(&buf,
+                                        "  pg_catalog.pg_get_userbyid(t.typowner) AS \"%s\",\n",
+                                                 gettext_noop("Owner"));
+       }
        if (verbose && pset.sversion >= 90200)
        {
                printACLColumn(&buf, "t.typacl");
@@ -542,7 +617,7 @@ describeTypes(const char *pattern, bool verbose, bool showSystem)
         */
        appendPQExpBufferStr(&buf, "WHERE (t.typrelid = 0 ");
        appendPQExpBufferStr(&buf, "OR (SELECT c.relkind = 'c' FROM pg_catalog.pg_class c "
-                                         "WHERE c.oid = t.typrelid))\n");
+                                                "WHERE c.oid = t.typrelid))\n");
 
        /*
         * do not include array types (before 8.3 we have to use the assumption
@@ -555,7 +630,7 @@ describeTypes(const char *pattern, bool verbose, bool showSystem)
 
        if (!showSystem && !pattern)
                appendPQExpBufferStr(&buf, "      AND n.nspname <> 'pg_catalog'\n"
-                                                                  "      AND n.nspname <> 'information_schema'\n");
+                                                        "      AND n.nspname <> 'information_schema'\n");
 
        /* Match name pattern against either internal or external name */
        processSQLNamePattern(pset.db, &buf, pattern, true, false,
@@ -565,7 +640,7 @@ describeTypes(const char *pattern, bool verbose, bool showSystem)
 
        appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
 
-       res = PSQLexec(buf.data, false);
+       res = PSQLexec(buf.data);
        termPQExpBuffer(&buf);
        if (!res)
                return false;
@@ -574,7 +649,7 @@ describeTypes(const char *pattern, bool verbose, bool showSystem)
        myopt.title = _("List of data types");
        myopt.translate_header = true;
 
-       printQuery(res, &myopt, pset.queryFout, pset.logfile);
+       printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
 
        PQclear(res);
        return true;
@@ -640,7 +715,7 @@ describeOperators(const char *pattern, bool verbose, bool showSystem)
 
        appendPQExpBufferStr(&buf, "ORDER BY 1, 2, 3, 4;");
 
-       res = PSQLexec(buf.data, false);
+       res = PSQLexec(buf.data);
        termPQExpBuffer(&buf);
        if (!res)
                return false;
@@ -649,7 +724,7 @@ describeOperators(const char *pattern, bool verbose, bool showSystem)
        myopt.title = _("List of operators");
        myopt.translate_header = true;
 
-       printQuery(res, &myopt, pset.queryFout, pset.logfile);
+       printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
 
        PQclear(res);
        return true;
@@ -711,7 +786,7 @@ listAllDbs(const char *pattern, bool verbose)
                                                          NULL, "d.datname", NULL, NULL);
 
        appendPQExpBufferStr(&buf, "ORDER BY 1;");
-       res = PSQLexec(buf.data, false);
+       res = PSQLexec(buf.data);
        termPQExpBuffer(&buf);
        if (!res)
                return false;
@@ -720,7 +795,7 @@ listAllDbs(const char *pattern, bool verbose)
        myopt.title = _("List of databases");
        myopt.translate_header = true;
 
-       printQuery(res, &myopt, pset.queryFout, pset.logfile);
+       printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
 
        PQclear(res);
        return true;
@@ -737,7 +812,7 @@ permissionsList(const char *pattern)
        PQExpBufferData buf;
        PGresult   *res;
        printQueryOpt myopt = pset.popt;
-       static const bool translate_columns[] = {false, false, true, false, false};
+       static const bool translate_columns[] = {false, false, true, false, false, false};
 
        initPQExpBuffer(&buf);
 
@@ -773,11 +848,42 @@ permissionsList(const char *pattern)
                                                  "    FROM pg_catalog.pg_attribute a\n"
                                                  "    WHERE attrelid = c.oid AND NOT attisdropped AND attacl IS NOT NULL\n"
                                                  "  ), E'\\n') AS \"%s\"",
-                                                 gettext_noop("Column access privileges"));
+                                                 gettext_noop("Column privileges"));
+
+       if (pset.sversion >= 90500)
+               appendPQExpBuffer(&buf,
+                                                 ",\n  pg_catalog.array_to_string(ARRAY(\n"
+                                                 "    SELECT polname\n"
+                                                 "    || CASE WHEN polcmd != '*' THEN\n"
+                                                 "           E' (' || polcmd || E'):'\n"
+                                                 "       ELSE E':' \n"
+                                                 "       END\n"
+                                                 "    || CASE WHEN polqual IS NOT NULL THEN\n"
+                                                 "           E'\\n  (u): ' || pg_catalog.pg_get_expr(polqual, polrelid)\n"
+                                                 "       ELSE E''\n"
+                                                 "       END\n"
+                                                 "    || CASE WHEN polwithcheck IS NOT NULL THEN\n"
+                                                 "           E'\\n  (c): ' || pg_catalog.pg_get_expr(polwithcheck, polrelid)\n"
+                                                 "       ELSE E''\n"
+                                                 "       END"
+                                                 "    || CASE WHEN polroles <> '{0}' THEN\n"
+                                  "           E'\\n  to: ' || pg_catalog.array_to_string(\n"
+                                                 "               ARRAY(\n"
+                                                 "                   SELECT rolname\n"
+                                                 "                   FROM pg_catalog.pg_roles\n"
+                                                 "                   WHERE oid = ANY (polroles)\n"
+                                                 "                   ORDER BY 1\n"
+                                                 "               ), E', ')\n"
+                                                 "       ELSE E''\n"
+                                                 "       END\n"
+                                                 "    FROM pg_catalog.pg_policy pol\n"
+                                                 "    WHERE polrelid = c.oid), E'\\n')\n"
+                                                 "    AS \"%s\"",
+                                                 gettext_noop("Policies"));
 
        appendPQExpBufferStr(&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', 'm', 'S', 'f')\n");
+                                                "WHERE c.relkind IN ('r', 'v', 'm', 'S', 'f')\n");
 
        /*
         * Unless a schema pattern is specified, we suppress system and temp
@@ -791,7 +897,7 @@ permissionsList(const char *pattern)
 
        appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
 
-       res = PSQLexec(buf.data, false);
+       res = PSQLexec(buf.data);
        if (!res)
        {
                termPQExpBuffer(&buf);
@@ -805,7 +911,7 @@ permissionsList(const char *pattern)
        myopt.translate_columns = translate_columns;
        myopt.n_translate_columns = lengthof(translate_columns);
 
-       printQuery(res, &myopt, pset.queryFout, pset.logfile);
+       printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
 
        termPQExpBuffer(&buf);
        PQclear(res);
@@ -865,7 +971,7 @@ listDefaultACLs(const char *pattern)
 
        appendPQExpBufferStr(&buf, "ORDER BY 1, 2, 3;");
 
-       res = PSQLexec(buf.data, false);
+       res = PSQLexec(buf.data);
        if (!res)
        {
                termPQExpBuffer(&buf);
@@ -879,7 +985,7 @@ listDefaultACLs(const char *pattern)
        myopt.translate_columns = translate_columns;
        myopt.n_translate_columns = lengthof(translate_columns);
 
-       printQuery(res, &myopt, pset.queryFout, pset.logfile);
+       printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
 
        termPQExpBuffer(&buf);
        PQclear(res);
@@ -916,7 +1022,7 @@ objectDescription(const char *pattern, bool showSystem)
                                          gettext_noop("Object"),
                                          gettext_noop("Description"));
 
-       /* Constraint descriptions */
+       /* Table constraint descriptions */
        appendPQExpBuffer(&buf,
                                          "  SELECT pgc.oid as oid, pgc.tableoid AS tableoid,\n"
                                          "  n.nspname as nspname,\n"
@@ -927,7 +1033,7 @@ objectDescription(const char *pattern, bool showSystem)
                                          "ON c.oid = pgc.conrelid\n"
                                          "    LEFT JOIN pg_catalog.pg_namespace n "
                                          "    ON n.oid = c.relnamespace\n",
-                                         gettext_noop("constraint"));
+                                         gettext_noop("table constraint"));
 
        if (!showSystem && !pattern)
                appendPQExpBufferStr(&buf, "WHERE n.nspname <> 'pg_catalog'\n"
@@ -937,6 +1043,29 @@ objectDescription(const char *pattern, bool showSystem)
                                                  false, "n.nspname", "pgc.conname", NULL,
                                                  "pg_catalog.pg_table_is_visible(c.oid)");
 
+       /* Domain constraint descriptions */
+       appendPQExpBuffer(&buf,
+                                         "UNION ALL\n"
+                                         "  SELECT pgc.oid as oid, pgc.tableoid AS tableoid,\n"
+                                         "  n.nspname as nspname,\n"
+                                         "  CAST(pgc.conname AS pg_catalog.text) as name,"
+                                         "  CAST('%s' AS pg_catalog.text) as object\n"
+                                         "  FROM pg_catalog.pg_constraint pgc\n"
+                                         "    JOIN pg_catalog.pg_type t "
+                                         "ON t.oid = pgc.contypid\n"
+                                         "    LEFT JOIN pg_catalog.pg_namespace n "
+                                         "    ON n.oid = t.typnamespace\n",
+                                         gettext_noop("domain constraint"));
+
+       if (!showSystem && !pattern)
+               appendPQExpBufferStr(&buf, "WHERE n.nspname <> 'pg_catalog'\n"
+                                                        "      AND n.nspname <> 'information_schema'\n");
+
+       processSQLNamePattern(pset.db, &buf, pattern, !showSystem && !pattern,
+                                                 false, "n.nspname", "pgc.conname", NULL,
+                                                 "pg_catalog.pg_type_is_visible(t.oid)");
+
+
        /*
         * pg_opclass.opcmethod only available in 8.3+
         */
@@ -958,7 +1087,7 @@ objectDescription(const char *pattern, bool showSystem)
 
                if (!showSystem && !pattern)
                        appendPQExpBufferStr(&buf, "      AND n.nspname <> 'pg_catalog'\n"
-                                                                "      AND n.nspname <> 'information_schema'\n");
+                                                       "      AND n.nspname <> 'information_schema'\n");
 
                processSQLNamePattern(pset.db, &buf, pattern, true, false,
                                                          "n.nspname", "o.opcname", NULL,
@@ -987,7 +1116,7 @@ objectDescription(const char *pattern, bool showSystem)
 
                if (!showSystem && !pattern)
                        appendPQExpBufferStr(&buf, "      AND n.nspname <> 'pg_catalog'\n"
-                                                                "      AND n.nspname <> 'information_schema'\n");
+                                                       "      AND n.nspname <> 'information_schema'\n");
 
                processSQLNamePattern(pset.db, &buf, pattern, true, false,
                                                          "n.nspname", "opf.opfname", NULL,
@@ -1041,7 +1170,7 @@ objectDescription(const char *pattern, bool showSystem)
 
        appendPQExpBufferStr(&buf, "ORDER BY 1, 2, 3;");
 
-       res = PSQLexec(buf.data, false);
+       res = PSQLexec(buf.data);
        termPQExpBuffer(&buf);
        if (!res)
                return false;
@@ -1052,7 +1181,7 @@ objectDescription(const char *pattern, bool showSystem)
        myopt.translate_columns = translate_columns;
        myopt.n_translate_columns = lengthof(translate_columns);
 
-       printQuery(res, &myopt, pset.queryFout, pset.logfile);
+       printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
 
        PQclear(res);
        return true;
@@ -1093,7 +1222,7 @@ describeTableDetails(const char *pattern, bool verbose, bool showSystem)
 
        appendPQExpBufferStr(&buf, "ORDER BY 2, 3;");
 
-       res = PSQLexec(buf.data, false);
+       res = PSQLexec(buf.data);
        termPQExpBuffer(&buf);
        if (!res)
                return false;
@@ -1168,6 +1297,8 @@ describeOneTableDetails(const char *schemaname,
                bool            hasindex;
                bool            hasrules;
                bool            hastriggers;
+               bool            rowsecurity;
+               bool            forcerowsecurity;
                bool            hasoids;
                Oid                     tablespace;
                char       *reloptions;
@@ -1189,11 +1320,28 @@ describeOneTableDetails(const char *schemaname,
        initPQExpBuffer(&tmpbuf);
 
        /* Get general table info */
-       if (pset.sversion >= 90400)
+       if (pset.sversion >= 90500)
+       {
+               printfPQExpBuffer(&buf,
+                         "SELECT c.relchecks, c.relkind, c.relhasindex, c.relhasrules, "
+                               "c.relhastriggers, c.relrowsecurity, c.relforcerowsecurity, "
+                                                 "c.relhasoids, %s, c.reltablespace, "
+                                                 "CASE WHEN c.reloftype = 0 THEN '' ELSE c.reloftype::pg_catalog.regtype::pg_catalog.text END, "
+                                                 "c.relpersistence, c.relreplident\n"
+                                                 "FROM pg_catalog.pg_class c\n "
+                  "LEFT JOIN pg_catalog.pg_class tc ON (c.reltoastrelid = tc.oid)\n"
+                                                 "WHERE c.oid = '%s';",
+                                                 (verbose ?
+                                                  "pg_catalog.array_to_string(c.reloptions || "
+                                                  "array(select 'toast.' || x from pg_catalog.unnest(tc.reloptions) x), ', ')\n"
+                                                  : "''"),
+                                                 oid);
+       }
+       else if (pset.sversion >= 90400)
        {
                printfPQExpBuffer(&buf,
                          "SELECT c.relchecks, c.relkind, c.relhasindex, c.relhasrules, "
-                                                 "c.relhastriggers, c.relhasoids, "
+                                                 "c.relhastriggers, false, false, c.relhasoids, "
                                                  "%s, c.reltablespace, "
                                                  "CASE WHEN c.reloftype = 0 THEN '' ELSE c.reloftype::pg_catalog.regtype::pg_catalog.text END, "
                                                  "c.relpersistence, c.relreplident\n"
@@ -1210,7 +1358,7 @@ describeOneTableDetails(const char *schemaname,
        {
                printfPQExpBuffer(&buf,
                          "SELECT c.relchecks, c.relkind, c.relhasindex, c.relhasrules, "
-                                                 "c.relhastriggers, c.relhasoids, "
+                                                 "c.relhastriggers, false, false, c.relhasoids, "
                                                  "%s, c.reltablespace, "
                                                  "CASE WHEN c.reloftype = 0 THEN '' ELSE c.reloftype::pg_catalog.regtype::pg_catalog.text END, "
                                                  "c.relpersistence\n"
@@ -1227,7 +1375,7 @@ describeOneTableDetails(const char *schemaname,
        {
                printfPQExpBuffer(&buf,
                          "SELECT c.relchecks, c.relkind, c.relhasindex, c.relhasrules, "
-                                                 "c.relhastriggers, c.relhasoids, "
+                                                 "c.relhastriggers, false, false, c.relhasoids, "
                                                  "%s, c.reltablespace, "
                                                  "CASE WHEN c.reloftype = 0 THEN '' ELSE c.reloftype::pg_catalog.regtype::pg_catalog.text END\n"
                                                  "FROM pg_catalog.pg_class c\n "
@@ -1243,7 +1391,7 @@ describeOneTableDetails(const char *schemaname,
        {
                printfPQExpBuffer(&buf,
                          "SELECT c.relchecks, c.relkind, c.relhasindex, c.relhasrules, "
-                                                 "c.relhastriggers, c.relhasoids, "
+                                                 "c.relhastriggers, false, false, c.relhasoids, "
                                                  "%s, c.reltablespace\n"
                                                  "FROM pg_catalog.pg_class c\n "
                   "LEFT JOIN pg_catalog.pg_class tc ON (c.reltoastrelid = tc.oid)\n"
@@ -1258,7 +1406,7 @@ describeOneTableDetails(const char *schemaname,
        {
                printfPQExpBuffer(&buf,
                                          "SELECT relchecks, relkind, relhasindex, relhasrules, "
-                                                 "reltriggers <> 0, relhasoids, "
+                                                 "reltriggers <> 0, false, false, relhasoids, "
                                                  "%s, reltablespace\n"
                                                  "FROM pg_catalog.pg_class WHERE oid = '%s';",
                                                  (verbose ?
@@ -1269,7 +1417,7 @@ describeOneTableDetails(const char *schemaname,
        {
                printfPQExpBuffer(&buf,
                                          "SELECT relchecks, relkind, relhasindex, relhasrules, "
-                                                 "reltriggers <> 0, relhasoids, "
+                                                 "reltriggers <> 0, false, false, relhasoids, "
                                                  "'', reltablespace\n"
                                                  "FROM pg_catalog.pg_class WHERE oid = '%s';",
                                                  oid);
@@ -1278,13 +1426,13 @@ describeOneTableDetails(const char *schemaname,
        {
                printfPQExpBuffer(&buf,
                                          "SELECT relchecks, relkind, relhasindex, relhasrules, "
-                                                 "reltriggers <> 0, relhasoids, "
+                                                 "reltriggers <> 0, false, false, relhasoids, "
                                                  "'', ''\n"
                                                  "FROM pg_catalog.pg_class WHERE oid = '%s';",
                                                  oid);
        }
 
-       res = PSQLexec(buf.data, false);
+       res = PSQLexec(buf.data);
        if (!res)
                goto error_return;
 
@@ -1301,18 +1449,20 @@ describeOneTableDetails(const char *schemaname,
        tableinfo.hasindex = strcmp(PQgetvalue(res, 0, 2), "t") == 0;
        tableinfo.hasrules = strcmp(PQgetvalue(res, 0, 3), "t") == 0;
        tableinfo.hastriggers = strcmp(PQgetvalue(res, 0, 4), "t") == 0;
-       tableinfo.hasoids = strcmp(PQgetvalue(res, 0, 5), "t") == 0;
+       tableinfo.rowsecurity = strcmp(PQgetvalue(res, 0, 5), "t") == 0;
+       tableinfo.forcerowsecurity = strcmp(PQgetvalue(res, 0, 6), "t") == 0;
+       tableinfo.hasoids = strcmp(PQgetvalue(res, 0, 7), "t") == 0;
        tableinfo.reloptions = (pset.sversion >= 80200) ?
-               pg_strdup(PQgetvalue(res, 0, 6)) : NULL;
+               pg_strdup(PQgetvalue(res, 0, 8)) : NULL;
        tableinfo.tablespace = (pset.sversion >= 80000) ?
-               atooid(PQgetvalue(res, 0, 7)) : 0;
+               atooid(PQgetvalue(res, 0, 9)) : 0;
        tableinfo.reloftype = (pset.sversion >= 90000 &&
-                                                  strcmp(PQgetvalue(res, 0, 8), "") != 0) ?
-               pg_strdup(PQgetvalue(res, 0, 8)) : NULL;
+                                                  strcmp(PQgetvalue(res, 0, 10), "") != 0) ?
+               pg_strdup(PQgetvalue(res, 0, 10)) : NULL;
        tableinfo.relpersistence = (pset.sversion >= 90100) ?
-               *(PQgetvalue(res, 0, 9)) : 0;
+               *(PQgetvalue(res, 0, 11)) : 0;
        tableinfo.relreplident = (pset.sversion >= 90400) ?
-               *(PQgetvalue(res, 0, 10)) : 'd';
+               *(PQgetvalue(res, 0, 12)) : 'd';
        PQclear(res);
        res = NULL;
 
@@ -1326,7 +1476,7 @@ describeOneTableDetails(const char *schemaname,
                /* must be separate because fmtId isn't reentrant */
                appendPQExpBuffer(&buf, ".%s;", fmtId(relationname));
 
-               res = PSQLexec(buf.data, false);
+               res = PSQLexec(buf.data);
                if (!res)
                        goto error_return;
 
@@ -1363,8 +1513,8 @@ describeOneTableDetails(const char *schemaname,
                appendPQExpBufferStr(&buf, ",\n  NULL AS indexdef");
        if (tableinfo.relkind == 'f' && pset.sversion >= 90200)
                appendPQExpBufferStr(&buf, ",\n  CASE WHEN attfdwoptions IS NULL THEN '' ELSE "
-                                                 "  '(' || array_to_string(ARRAY(SELECT quote_ident(option_name) ||  ' ' || quote_literal(option_value)  FROM "
-                                                 "  pg_options_to_table(attfdwoptions)), ', ') || ')' END AS attfdwoptions");
+                                                        "  '(' || array_to_string(ARRAY(SELECT quote_ident(option_name) ||  ' ' || quote_literal(option_value)  FROM "
+                                                        "  pg_options_to_table(attfdwoptions)), ', ') || ')' END AS attfdwoptions");
        else
                appendPQExpBufferStr(&buf, ",\n  NULL AS attfdwoptions");
        if (verbose)
@@ -1386,7 +1536,7 @@ describeOneTableDetails(const char *schemaname,
        appendPQExpBuffer(&buf, "\nWHERE a.attrelid = '%s' AND a.attnum > 0 AND NOT a.attisdropped", oid);
        appendPQExpBufferStr(&buf, "\nORDER BY a.attnum;");
 
-       res = PSQLexec(buf.data, false);
+       res = PSQLexec(buf.data);
        if (!res)
                goto error_return;
        numrows = PQntuples(res);
@@ -1500,7 +1650,7 @@ describeOneTableDetails(const char *schemaname,
                printfPQExpBuffer(&buf,
                         "SELECT pg_catalog.pg_get_viewdef('%s'::pg_catalog.oid, true);",
                                                  oid);
-               result = PSQLexec(buf.data, false);
+               result = PSQLexec(buf.data);
                if (!result)
                        goto error_return;
 
@@ -1527,7 +1677,7 @@ describeOneTableDetails(const char *schemaname,
                        if (!PQgetisnull(res, i, 5))
                        {
                                if (tmpbuf.len > 0)
-                                       appendPQExpBufferStr(&tmpbuf, " ");
+                                       appendPQExpBufferChar(&tmpbuf, ' ');
                                appendPQExpBuffer(&tmpbuf, _("collate %s"),
                                                                  PQgetvalue(res, i, 5));
                        }
@@ -1535,7 +1685,7 @@ describeOneTableDetails(const char *schemaname,
                        if (strcmp(PQgetvalue(res, i, 3), "t") == 0)
                        {
                                if (tmpbuf.len > 0)
-                                       appendPQExpBufferStr(&tmpbuf, " ");
+                                       appendPQExpBufferChar(&tmpbuf, ' ');
                                appendPQExpBufferStr(&tmpbuf, _("not null"));
                        }
 
@@ -1544,7 +1694,7 @@ describeOneTableDetails(const char *schemaname,
                        if (strlen(PQgetvalue(res, i, 2)) != 0)
                        {
                                if (tmpbuf.len > 0)
-                                       appendPQExpBufferStr(&tmpbuf, " ");
+                                       appendPQExpBufferChar(&tmpbuf, ' ');
                                /* translator: default values of column definitions */
                                appendPQExpBuffer(&tmpbuf, _("default %s"),
                                                                  PQgetvalue(res, i, 2));
@@ -1612,13 +1762,13 @@ describeOneTableDetails(const char *schemaname,
                if (pset.sversion >= 90000)
                        appendPQExpBufferStr(&buf,
                                                                 "  (NOT i.indimmediate) AND "
-                                                               "EXISTS (SELECT 1 FROM pg_catalog.pg_constraint "
+                                                       "EXISTS (SELECT 1 FROM pg_catalog.pg_constraint "
                                                                 "WHERE conrelid = i.indrelid AND "
                                                                 "conindid = i.indexrelid AND "
                                                                 "contype IN ('p','u','x') AND "
                                                                 "condeferrable) AS condeferrable,\n"
                                                                 "  (NOT i.indimmediate) AND "
-                                                               "EXISTS (SELECT 1 FROM pg_catalog.pg_constraint "
+                                                       "EXISTS (SELECT 1 FROM pg_catalog.pg_constraint "
                                                                 "WHERE conrelid = i.indrelid AND "
                                                                 "conindid = i.indexrelid AND "
                                                                 "contype IN ('p','u','x') AND "
@@ -1639,7 +1789,7 @@ describeOneTableDetails(const char *schemaname,
                                                  "AND i.indrelid = c2.oid;",
                                                  oid);
 
-               result = PSQLexec(buf.data, false);
+               result = PSQLexec(buf.data);
                if (!result)
                        goto error_return;
                else if (PQntuples(result) != 1)
@@ -1718,7 +1868,7 @@ describeOneTableDetails(const char *schemaname,
                                                  "\n AND d.deptype='a'",
                                                  oid);
 
-               result = PSQLexec(buf.data, false);
+               result = PSQLexec(buf.data);
                if (!result)
                        goto error_return;
                else if (PQntuples(result) == 1)
@@ -1755,11 +1905,11 @@ describeOneTableDetails(const char *schemaname,
                        if (pset.sversion >= 90000)
                                appendPQExpBufferStr(&buf,
                                                   "pg_catalog.pg_get_constraintdef(con.oid, true), "
-                                                                 "contype, condeferrable, condeferred");
+                                                                        "contype, condeferrable, condeferred");
                        else
                                appendPQExpBufferStr(&buf,
-                                                                        "null AS constraintdef, null AS contype, "
-                                                                        "false AS condeferrable, false AS condeferred");
+                                                                  "null AS constraintdef, null AS contype, "
+                                                        "false AS condeferrable, false AS condeferred");
                        if (pset.sversion >= 90400)
                                appendPQExpBufferStr(&buf, ", i.indisreplident");
                        else
@@ -1775,7 +1925,7 @@ describeOneTableDetails(const char *schemaname,
                                                          "WHERE c.oid = '%s' AND c.oid = i.indrelid AND i.indexrelid = c2.oid\n"
                         "ORDER BY i.indisprimary DESC, i.indisunique DESC, c2.relname;",
                                                          oid);
-                       result = PSQLexec(buf.data, false);
+                       result = PSQLexec(buf.data);
                        if (!result)
                                goto error_return;
                        else
@@ -1859,7 +2009,7 @@ describeOneTableDetails(const char *schemaname,
                                                          "WHERE r.conrelid = '%s' AND r.contype = 'c'\n"
                                                          "ORDER BY 1;",
                                                          oid);
-                       result = PSQLexec(buf.data, false);
+                       result = PSQLexec(buf.data);
                        if (!result)
                                goto error_return;
                        else
@@ -1890,7 +2040,7 @@ describeOneTableDetails(const char *schemaname,
                                                          "FROM pg_catalog.pg_constraint r\n"
                                   "WHERE r.conrelid = '%s' AND r.contype = 'f' ORDER BY 1;",
                                                          oid);
-                       result = PSQLexec(buf.data, false);
+                       result = PSQLexec(buf.data);
                        if (!result)
                                goto error_return;
                        else
@@ -1921,7 +2071,7 @@ describeOneTableDetails(const char *schemaname,
                                                          "FROM pg_catalog.pg_constraint c\n"
                                  "WHERE c.confrelid = '%s' AND c.contype = 'f' ORDER BY 1;",
                                                          oid);
-                       result = PSQLexec(buf.data, false);
+                       result = PSQLexec(buf.data);
                        if (!result)
                                goto error_return;
                        else
@@ -1943,6 +2093,81 @@ describeOneTableDetails(const char *schemaname,
                        PQclear(result);
                }
 
+               /* print any row-level policies */
+               if (pset.sversion >= 90500)
+               {
+                       printfPQExpBuffer(&buf,
+                                                         "SELECT pol.polname,\n"
+                                                         "CASE WHEN pol.polroles = '{0}' THEN NULL ELSE array_to_string(array(select rolname from pg_roles where oid = any (pol.polroles) order by 1),',') END,\n"
+                                          "pg_catalog.pg_get_expr(pol.polqual, pol.polrelid),\n"
+                                 "pg_catalog.pg_get_expr(pol.polwithcheck, pol.polrelid),\n"
+                                                         "CASE pol.polcmd \n"
+                                                         "WHEN 'r' THEN 'SELECT'\n"
+                                                         "WHEN 'a' THEN 'INSERT'\n"
+                                                         "WHEN 'w' THEN 'UPDATE'\n"
+                                                         "WHEN 'd' THEN 'DELETE'\n"
+                                                         "WHEN '*' THEN 'ALL'\n"
+                                                         "END AS cmd\n"
+                                                         "FROM pg_catalog.pg_policy pol\n"
+                                                         "WHERE pol.polrelid = '%s' ORDER BY 1;",
+                                                         oid);
+
+                       result = PSQLexec(buf.data);
+                       if (!result)
+                               goto error_return;
+                       else
+                               tuples = PQntuples(result);
+
+                       /*
+                        * Handle cases where RLS is enabled and there are policies, or
+                        * there aren't policies, or RLS isn't enabled but there are
+                        * policies
+                        */
+                       if (tableinfo.rowsecurity && !tableinfo.forcerowsecurity && tuples > 0)
+                               printTableAddFooter(&cont, _("Policies:"));
+
+                       if (tableinfo.rowsecurity && tableinfo.forcerowsecurity && tuples > 0)
+                               printTableAddFooter(&cont, _("Policies (forced row security enabled):"));
+
+                       if (tableinfo.rowsecurity && !tableinfo.forcerowsecurity && tuples == 0)
+                               printTableAddFooter(&cont, _("Policies (row security enabled): (none)"));
+
+                       if (tableinfo.rowsecurity && tableinfo.forcerowsecurity && tuples == 0)
+                               printTableAddFooter(&cont, _("Policies (forced row security enabled): (none)"));
+
+                       if (!tableinfo.rowsecurity && tuples > 0)
+                               printTableAddFooter(&cont, _("Policies (row security disabled):"));
+
+                       /* Might be an empty set - that's ok */
+                       for (i = 0; i < tuples; i++)
+                       {
+                               printfPQExpBuffer(&buf, "    POLICY \"%s\"",
+                                                                 PQgetvalue(result, i, 0));
+
+                               if (!PQgetisnull(result, i, 4))
+                                       appendPQExpBuffer(&buf, " FOR %s",
+                                                                         PQgetvalue(result, i, 4));
+
+                               if (!PQgetisnull(result, i, 1))
+                               {
+                                       appendPQExpBuffer(&buf, "\n      TO %s",
+                                                                         PQgetvalue(result, i, 1));
+                               }
+
+                               if (!PQgetisnull(result, i, 2))
+                                       appendPQExpBuffer(&buf, "\n      USING (%s)",
+                                                                         PQgetvalue(result, i, 2));
+
+                               if (!PQgetisnull(result, i, 3))
+                                       appendPQExpBuffer(&buf, "\n      WITH CHECK (%s)",
+                                                                         PQgetvalue(result, i, 3));
+
+                               printTableAddFooter(&cont, buf.data);
+
+                       }
+                       PQclear(result);
+               }
+
                /* print rules */
                if (tableinfo.hasrules && tableinfo.relkind != 'm')
                {
@@ -1964,7 +2189,7 @@ describeOneTableDetails(const char *schemaname,
                                                                  "WHERE r.ev_class = '%s' ORDER BY 1;",
                                                                  oid);
                        }
-                       result = PSQLexec(buf.data, false);
+                       result = PSQLexec(buf.data);
                        if (!result)
                                goto error_return;
                        else
@@ -2055,7 +2280,7 @@ describeOneTableDetails(const char *schemaname,
                                                          "FROM pg_catalog.pg_rewrite r\n"
                        "WHERE r.ev_class = '%s' AND r.rulename != '_RETURN' ORDER BY 1;",
                                                          oid);
-                       result = PSQLexec(buf.data, false);
+                       result = PSQLexec(buf.data);
                        if (!result)
                                goto error_return;
 
@@ -2112,7 +2337,7 @@ describeOneTableDetails(const char *schemaname,
                                                                 "   WHERE d.classid = t.tableoid AND d.objid = t.oid AND d.deptype = 'i' AND c.contype = 'f'))");
                appendPQExpBufferStr(&buf, "\nORDER BY 1;");
 
-               result = PSQLexec(buf.data, false);
+               result = PSQLexec(buf.data);
                if (!result)
                        goto error_return;
                else
@@ -2188,7 +2413,7 @@ describeOneTableDetails(const char *schemaname,
                                                                        printfPQExpBuffer(&buf, _("Disabled triggers:"));
                                                                break;
                                                        case 2:
-                                                                       printfPQExpBuffer(&buf, _("Disabled internal triggers:"));
+                                                               printfPQExpBuffer(&buf, _("Disabled internal triggers:"));
                                                                break;
                                                        case 3:
                                                                printfPQExpBuffer(&buf, _("Triggers firing always:"));
@@ -2241,7 +2466,7 @@ describeOneTableDetails(const char *schemaname,
                                                          "     pg_catalog.pg_foreign_server s\n"
                                                          "WHERE f.ftrelid = %s AND s.oid = f.ftserver;",
                                                          oid);
-                       result = PSQLexec(buf.data, false);
+                       result = PSQLexec(buf.data);
                        if (!result)
                                goto error_return;
                        else if (PQntuples(result) != 1)
@@ -2268,7 +2493,7 @@ describeOneTableDetails(const char *schemaname,
                /* 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);
 
-               result = PSQLexec(buf.data, false);
+               result = PSQLexec(buf.data);
                if (!result)
                        goto error_return;
                else
@@ -2287,7 +2512,7 @@ describeOneTableDetails(const char *schemaname,
                                        printfPQExpBuffer(&buf, "%*s  %s",
                                                                          sw, "", PQgetvalue(result, i, 0));
                                if (i < tuples - 1)
-                                       appendPQExpBufferStr(&buf, ",");
+                                       appendPQExpBufferChar(&buf, ',');
 
                                printTableAddFooter(&cont, buf.data);
                        }
@@ -2301,7 +2526,7 @@ describeOneTableDetails(const char *schemaname,
                else
                        printfPQExpBuffer(&buf, "SELECT c.oid::pg_catalog.regclass FROM pg_catalog.pg_class c, pg_catalog.pg_inherits i WHERE c.oid=i.inhrelid AND i.inhparent = '%s' ORDER BY c.relname;", oid);
 
-               result = PSQLexec(buf.data, false);
+               result = PSQLexec(buf.data);
                if (!result)
                        goto error_return;
                else
@@ -2345,26 +2570,30 @@ describeOneTableDetails(const char *schemaname,
                        printTableAddFooter(&cont, buf.data);
                }
 
-               if ((tableinfo.relkind == 'r' || tableinfo.relkind == 'm') &&
-                       tableinfo.relreplident != 'd' && tableinfo.relreplident != 'i')
+               if (verbose && (tableinfo.relkind == 'r' || tableinfo.relkind == 'm') &&
+
+               /*
+                * No need to display default values;  we already display a REPLICA
+                * IDENTITY marker on indexes.
+                */
+                       tableinfo.relreplident != 'i' &&
+                       ((strcmp(schemaname, "pg_catalog") != 0 && tableinfo.relreplident != 'd') ||
+                        (strcmp(schemaname, "pg_catalog") == 0 && tableinfo.relreplident != 'n')))
                {
                        const char *s = _("Replica Identity");
 
                        printfPQExpBuffer(&buf, "%s: %s",
                                                          s,
-                                                         tableinfo.relreplident == 'n' ? "NOTHING" : "FULL");
+                                                         tableinfo.relreplident == 'f' ? "FULL" :
+                                                         tableinfo.relreplident == 'n' ? "NOTHING" :
+                                                         "???");
+
                        printTableAddFooter(&cont, buf.data);
                }
 
                /* OIDs, if verbose and not a materialized view */
-               if (verbose && tableinfo.relkind != 'm')
-               {
-                       const char *s = _("Has OIDs");
-
-                       printfPQExpBuffer(&buf, "%s: %s", s,
-                                                         (tableinfo.hasoids ? _("yes") : _("no")));
-                       printTableAddFooter(&cont, buf.data);
-               }
+               if (verbose && tableinfo.relkind != 'm' && tableinfo.hasoids)
+                       printTableAddFooter(&cont, _("Has OIDs: yes"));
 
                /* Tablespace info */
                add_tablespace_footer(&cont, tableinfo.relkind, tableinfo.tablespace,
@@ -2381,8 +2610,7 @@ describeOneTableDetails(const char *schemaname,
                printTableAddFooter(&cont, buf.data);
        }
 
-       printTable(&cont, pset.queryFout, pset.logfile);
-       printTableCleanup(&cont);
+       printTable(&cont, pset.queryFout, false, pset.logfile);
 
        retval = true;
 
@@ -2444,7 +2672,7 @@ add_tablespace_footer(printTableContent *const cont, char relkind,
                        printfPQExpBuffer(&buf,
                                                          "SELECT spcname FROM pg_catalog.pg_tablespace\n"
                                                          "WHERE oid = '%u';", tablespace);
-                       result = PSQLexec(buf.data, false);
+                       result = PSQLexec(buf.data);
                        if (!result)
                                return;
                        /* Should always be the case, but.... */
@@ -2482,7 +2710,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)
+describeRoles(const char *pattern, bool verbose, bool showSystem)
 {
        PQExpBufferData buf;
        PGresult   *res;
@@ -2520,8 +2748,16 @@ describeRoles(const char *pattern, bool verbose)
                        appendPQExpBufferStr(&buf, "\n, r.rolreplication");
                }
 
+               if (pset.sversion >= 90500)
+               {
+                       appendPQExpBufferStr(&buf, "\n, r.rolbypassrls");
+               }
+
                appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_roles r\n");
 
+               if (!showSystem && !pattern)
+                       appendPQExpBufferStr(&buf, "WHERE r.rolname !~ '^pg_'\n");
+
                processSQLNamePattern(pset.db, &buf, pattern, false, false,
                                                          NULL, "r.rolname", NULL, NULL);
        }
@@ -2543,7 +2779,7 @@ describeRoles(const char *pattern, bool verbose)
 
        appendPQExpBufferStr(&buf, "ORDER BY 1;");
 
-       res = PSQLexec(buf.data, false);
+       res = PSQLexec(buf.data);
        if (!res)
                return false;
 
@@ -2583,6 +2819,10 @@ describeRoles(const char *pattern, bool verbose)
                        if (strcmp(PQgetvalue(res, i, (verbose ? 10 : 9)), "t") == 0)
                                add_role_attribute(&buf, _("Replication"));
 
+               if (pset.sversion >= 90500)
+                       if (strcmp(PQgetvalue(res, i, (verbose ? 11 : 10)), "t") == 0)
+                               add_role_attribute(&buf, _("Bypass RLS"));
+
                conns = atoi(PQgetvalue(res, i, 6));
                if (conns >= 0)
                {
@@ -2617,7 +2857,7 @@ describeRoles(const char *pattern, bool verbose)
        }
        termPQExpBuffer(&buf);
 
-       printTable(&cont, pset.queryFout, pset.logfile);
+       printTable(&cont, pset.queryFout, false, pset.logfile);
        printTableCleanup(&cont);
 
        for (i = 0; i < nrows; i++)
@@ -2674,7 +2914,7 @@ listDbRoleSettings(const char *pattern, const char *pattern2)
                return false;
        }
 
-       res = PSQLexec(buf.data, false);
+       res = PSQLexec(buf.data);
        if (!res)
                return false;
 
@@ -2691,7 +2931,7 @@ listDbRoleSettings(const char *pattern, const char *pattern2)
                myopt.title = _("List of settings");
                myopt.translate_header = true;
 
-               printQuery(res, &myopt, pset.queryFout, pset.logfile);
+               printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
        }
 
        PQclear(res);
@@ -2814,7 +3054,7 @@ listTables(const char *tabtypes, const char *pattern, bool verbose, bool showSys
        if (showForeign)
                appendPQExpBufferStr(&buf, "'f',");
 
-       appendPQExpBufferStr(&buf, "''");               /* dummy */
+       appendPQExpBufferStr(&buf, "''");       /* dummy */
        appendPQExpBufferStr(&buf, ")\n");
 
        if (!showSystem && !pattern)
@@ -2835,7 +3075,7 @@ listTables(const char *tabtypes, const char *pattern, bool verbose, bool showSys
 
        appendPQExpBufferStr(&buf, "ORDER BY 1,2;");
 
-       res = PSQLexec(buf.data, false);
+       res = PSQLexec(buf.data);
        termPQExpBuffer(&buf);
        if (!res)
                return false;
@@ -2855,7 +3095,7 @@ listTables(const char *tabtypes, const char *pattern, bool verbose, bool showSys
                myopt.translate_columns = translate_columns;
                myopt.n_translate_columns = lengthof(translate_columns);
 
-               printQuery(res, &myopt, pset.queryFout, pset.logfile);
+               printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
        }
 
        PQclear(res);
@@ -2922,7 +3162,7 @@ listLanguages(const char *pattern, bool verbose, bool showSystem)
 
        appendPQExpBufferStr(&buf, "ORDER BY 1;");
 
-       res = PSQLexec(buf.data, false);
+       res = PSQLexec(buf.data);
        termPQExpBuffer(&buf);
        if (!res)
                return false;
@@ -2931,7 +3171,7 @@ listLanguages(const char *pattern, bool verbose, bool showSystem)
        myopt.title = _("List of languages");
        myopt.translate_header = true;
 
-       printQuery(res, &myopt, pset.queryFout, pset.logfile);
+       printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
 
        PQclear(res);
        return true;
@@ -2994,7 +3234,7 @@ listDomains(const char *pattern, bool verbose, bool showSystem)
        if (verbose)
                appendPQExpBufferStr(&buf,
                                                         "     LEFT JOIN pg_catalog.pg_description d "
-                                                        "ON d.classoid = t.tableoid AND d.objoid = t.oid "
+                                                  "ON d.classoid = t.tableoid AND d.objoid = t.oid "
                                                         "AND d.objsubid = 0\n");
 
        appendPQExpBufferStr(&buf, "WHERE t.typtype = 'd'\n");
@@ -3009,7 +3249,7 @@ listDomains(const char *pattern, bool verbose, bool showSystem)
 
        appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
 
-       res = PSQLexec(buf.data, false);
+       res = PSQLexec(buf.data);
        termPQExpBuffer(&buf);
        if (!res)
                return false;
@@ -3018,7 +3258,7 @@ listDomains(const char *pattern, bool verbose, bool showSystem)
        myopt.title = _("List of domains");
        myopt.translate_header = true;
 
-       printQuery(res, &myopt, pset.queryFout, pset.logfile);
+       printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
 
        PQclear(res);
        return true;
@@ -3036,7 +3276,7 @@ listConversions(const char *pattern, bool verbose, bool showSystem)
        PGresult   *res;
        printQueryOpt myopt = pset.popt;
        static const bool translate_columns[] =
-               {false, false, false, false, true, false};
+       {false, false, false, false, true, false};
 
        initPQExpBuffer(&buf);
 
@@ -3075,7 +3315,7 @@ listConversions(const char *pattern, bool verbose, bool showSystem)
 
        if (!showSystem && !pattern)
                appendPQExpBufferStr(&buf, "  AND n.nspname <> 'pg_catalog'\n"
-                                                 "  AND n.nspname <> 'information_schema'\n");
+                                                        "  AND n.nspname <> 'information_schema'\n");
 
        processSQLNamePattern(pset.db, &buf, pattern, true, false,
                                                  "n.nspname", "c.conname", NULL,
@@ -3083,7 +3323,7 @@ listConversions(const char *pattern, bool verbose, bool showSystem)
 
        appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
 
-       res = PSQLexec(buf.data, false);
+       res = PSQLexec(buf.data);
        termPQExpBuffer(&buf);
        if (!res)
                return false;
@@ -3094,7 +3334,7 @@ listConversions(const char *pattern, bool verbose, bool showSystem)
        myopt.translate_columns = translate_columns;
        myopt.n_translate_columns = lengthof(translate_columns);
 
-       printQuery(res, &myopt, pset.queryFout, pset.logfile);
+       printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
 
        PQclear(res);
        return true;
@@ -3126,7 +3366,7 @@ listEventTriggers(const char *pattern, bool verbose)
                                          "  when 'D' then '%s' end as \"%s\",\n"
                                          " e.evtfoid::pg_catalog.regproc as \"%s\", "
                                          "pg_catalog.array_to_string(array(select x"
-                                         " from pg_catalog.unnest(evttags) as t(x)), ', ') as \"%s\"",
+                               " from pg_catalog.unnest(evttags) as t(x)), ', ') as \"%s\"",
                                          gettext_noop("Name"),
                                          gettext_noop("Event"),
                                          gettext_noop("Owner"),
@@ -3149,7 +3389,7 @@ listEventTriggers(const char *pattern, bool verbose)
 
        appendPQExpBufferStr(&buf, "ORDER BY 1");
 
-       res = PSQLexec(buf.data, false);
+       res = PSQLexec(buf.data);
        termPQExpBuffer(&buf);
        if (!res)
                return false;
@@ -3160,7 +3400,7 @@ listEventTriggers(const char *pattern, bool verbose)
        myopt.translate_columns = translate_columns;
        myopt.n_translate_columns = lengthof(translate_columns);
 
-       printQuery(res, &myopt, pset.queryFout, pset.logfile);
+       printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
 
        PQclear(res);
        return true;
@@ -3248,7 +3488,7 @@ listCasts(const char *pattern, bool verbose)
 
        appendPQExpBufferStr(&buf, ") )\nORDER BY 1, 2;");
 
-       res = PSQLexec(buf.data, false);
+       res = PSQLexec(buf.data);
        termPQExpBuffer(&buf);
        if (!res)
                return false;
@@ -3259,7 +3499,7 @@ listCasts(const char *pattern, bool verbose)
        myopt.translate_columns = translate_columns;
        myopt.n_translate_columns = lengthof(translate_columns);
 
-       printQuery(res, &myopt, pset.queryFout, pset.logfile);
+       printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
 
        PQclear(res);
        return true;
@@ -3304,11 +3544,11 @@ listCollations(const char *pattern, bool verbose, bool showSystem)
 
        appendPQExpBufferStr(&buf,
                          "\nFROM pg_catalog.pg_collation c, pg_catalog.pg_namespace n\n"
-                                         "WHERE n.oid = c.collnamespace\n");
+                                                "WHERE n.oid = c.collnamespace\n");
 
        if (!showSystem && !pattern)
                appendPQExpBufferStr(&buf, "      AND n.nspname <> 'pg_catalog'\n"
-                                                 "      AND n.nspname <> 'information_schema'\n");
+                                                        "      AND n.nspname <> 'information_schema'\n");
 
        /*
         * Hide collations that aren't usable in the current database's encoding.
@@ -3324,7 +3564,7 @@ listCollations(const char *pattern, bool verbose, bool showSystem)
 
        appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
 
-       res = PSQLexec(buf.data, false);
+       res = PSQLexec(buf.data);
        termPQExpBuffer(&buf);
        if (!res)
                return false;
@@ -3335,7 +3575,7 @@ listCollations(const char *pattern, bool verbose, bool showSystem)
        myopt.translate_columns = translate_columns;
        myopt.n_translate_columns = lengthof(translate_columns);
 
-       printQuery(res, &myopt, pset.queryFout, pset.logfile);
+       printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
 
        PQclear(res);
        return true;
@@ -3383,7 +3623,7 @@ listSchemas(const char *pattern, bool verbose, bool showSystem)
 
        appendPQExpBufferStr(&buf, "ORDER BY 1;");
 
-       res = PSQLexec(buf.data, false);
+       res = PSQLexec(buf.data);
        termPQExpBuffer(&buf);
        if (!res)
                return false;
@@ -3392,7 +3632,7 @@ listSchemas(const char *pattern, bool verbose, bool showSystem)
        myopt.title = _("List of schemas");
        myopt.translate_header = true;
 
-       printQuery(res, &myopt, pset.queryFout, pset.logfile);
+       printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
 
        PQclear(res);
        return true;
@@ -3440,7 +3680,7 @@ listTSParsers(const char *pattern, bool verbose)
 
        appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
 
-       res = PSQLexec(buf.data, false);
+       res = PSQLexec(buf.data);
        termPQExpBuffer(&buf);
        if (!res)
                return false;
@@ -3449,7 +3689,7 @@ listTSParsers(const char *pattern, bool verbose)
        myopt.title = _("List of text search parsers");
        myopt.translate_header = true;
 
-       printQuery(res, &myopt, pset.queryFout, pset.logfile);
+       printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
 
        PQclear(res);
        return true;
@@ -3481,7 +3721,7 @@ listTSParsersVerbose(const char *pattern)
 
        appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
 
-       res = PSQLexec(buf.data, false);
+       res = PSQLexec(buf.data);
        termPQExpBuffer(&buf);
        if (!res)
                return false;
@@ -3578,7 +3818,7 @@ describeOneTSParser(const char *oid, const char *nspname, const char *prsname)
                                          gettext_noop("Get token types"),
                                          oid);
 
-       res = PSQLexec(buf.data, false);
+       res = PSQLexec(buf.data);
        termPQExpBuffer(&buf);
        if (!res)
                return false;
@@ -3595,7 +3835,7 @@ describeOneTSParser(const char *oid, const char *nspname, const char *prsname)
        myopt.translate_columns = translate_columns;
        myopt.n_translate_columns = lengthof(translate_columns);
 
-       printQuery(res, &myopt, pset.queryFout, pset.logfile);
+       printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
 
        PQclear(res);
 
@@ -3610,7 +3850,7 @@ describeOneTSParser(const char *oid, const char *nspname, const char *prsname)
                                          gettext_noop("Description"),
                                          oid);
 
-       res = PSQLexec(buf.data, false);
+       res = PSQLexec(buf.data);
        termPQExpBuffer(&buf);
        if (!res)
                return false;
@@ -3627,7 +3867,7 @@ describeOneTSParser(const char *oid, const char *nspname, const char *prsname)
        myopt.translate_columns = NULL;
        myopt.n_translate_columns = 0;
 
-       printQuery(res, &myopt, pset.queryFout, pset.logfile);
+       printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
 
        PQclear(res);
        return true;
@@ -3686,7 +3926,7 @@ listTSDictionaries(const char *pattern, bool verbose)
 
        appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
 
-       res = PSQLexec(buf.data, false);
+       res = PSQLexec(buf.data);
        termPQExpBuffer(&buf);
        if (!res)
                return false;
@@ -3695,7 +3935,7 @@ listTSDictionaries(const char *pattern, bool verbose)
        myopt.title = _("List of text search dictionaries");
        myopt.translate_header = true;
 
-       printQuery(res, &myopt, pset.queryFout, pset.logfile);
+       printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
 
        PQclear(res);
        return true;
@@ -3754,7 +3994,7 @@ listTSTemplates(const char *pattern, bool verbose)
 
        appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
 
-       res = PSQLexec(buf.data, false);
+       res = PSQLexec(buf.data);
        termPQExpBuffer(&buf);
        if (!res)
                return false;
@@ -3763,7 +4003,7 @@ listTSTemplates(const char *pattern, bool verbose)
        myopt.title = _("List of text search templates");
        myopt.translate_header = true;
 
-       printQuery(res, &myopt, pset.queryFout, pset.logfile);
+       printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
 
        PQclear(res);
        return true;
@@ -3811,7 +4051,7 @@ listTSConfigs(const char *pattern, bool verbose)
 
        appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
 
-       res = PSQLexec(buf.data, false);
+       res = PSQLexec(buf.data);
        termPQExpBuffer(&buf);
        if (!res)
                return false;
@@ -3820,7 +4060,7 @@ listTSConfigs(const char *pattern, bool verbose)
        myopt.title = _("List of text search configurations");
        myopt.translate_header = true;
 
-       printQuery(res, &myopt, pset.queryFout, pset.logfile);
+       printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
 
        PQclear(res);
        return true;
@@ -3853,7 +4093,7 @@ listTSConfigsVerbose(const char *pattern)
 
        appendPQExpBufferStr(&buf, "ORDER BY 3, 2;");
 
-       res = PSQLexec(buf.data, false);
+       res = PSQLexec(buf.data);
        termPQExpBuffer(&buf);
        if (!res)
                return false;
@@ -3931,7 +4171,7 @@ describeOneTSConfig(const char *oid, const char *nspname, const char *cfgname,
                                          gettext_noop("Dictionaries"),
                                          oid);
 
-       res = PSQLexec(buf.data, false);
+       res = PSQLexec(buf.data);
        termPQExpBuffer(&buf);
        if (!res)
                return false;
@@ -3958,7 +4198,7 @@ describeOneTSConfig(const char *oid, const char *nspname, const char *cfgname,
        myopt.topt.default_footer = false;
        myopt.translate_header = true;
 
-       printQuery(res, &myopt, pset.queryFout, pset.logfile);
+       printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
 
        termPQExpBuffer(&title);
 
@@ -4032,7 +4272,7 @@ listForeignDataWrappers(const char *pattern, bool verbose)
 
        appendPQExpBufferStr(&buf, "ORDER BY 1;");
 
-       res = PSQLexec(buf.data, false);
+       res = PSQLexec(buf.data);
        termPQExpBuffer(&buf);
        if (!res)
                return false;
@@ -4041,7 +4281,7 @@ listForeignDataWrappers(const char *pattern, bool verbose)
        myopt.title = _("List of foreign-data wrappers");
        myopt.translate_header = true;
 
-       printQuery(res, &myopt, pset.queryFout, pset.logfile);
+       printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
 
        PQclear(res);
        return true;
@@ -4103,7 +4343,7 @@ listForeignServers(const char *pattern, bool verbose)
        if (verbose)
                appendPQExpBufferStr(&buf,
                                                         "LEFT JOIN pg_description d\n       "
-                                                        "ON d.classoid = s.tableoid AND d.objoid = s.oid "
+                                                  "ON d.classoid = s.tableoid AND d.objoid = s.oid "
                                                         "AND d.objsubid = 0\n");
 
        processSQLNamePattern(pset.db, &buf, pattern, false, false,
@@ -4111,7 +4351,7 @@ listForeignServers(const char *pattern, bool verbose)
 
        appendPQExpBufferStr(&buf, "ORDER BY 1;");
 
-       res = PSQLexec(buf.data, false);
+       res = PSQLexec(buf.data);
        termPQExpBuffer(&buf);
        if (!res)
                return false;
@@ -4120,7 +4360,7 @@ listForeignServers(const char *pattern, bool verbose)
        myopt.title = _("List of foreign servers");
        myopt.translate_header = true;
 
-       printQuery(res, &myopt, pset.queryFout, pset.logfile);
+       printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
 
        PQclear(res);
        return true;
@@ -4169,7 +4409,7 @@ listUserMappings(const char *pattern, bool verbose)
 
        appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
 
-       res = PSQLexec(buf.data, false);
+       res = PSQLexec(buf.data);
        termPQExpBuffer(&buf);
        if (!res)
                return false;
@@ -4178,7 +4418,7 @@ listUserMappings(const char *pattern, bool verbose)
        myopt.title = _("List of user mappings");
        myopt.translate_header = true;
 
-       printQuery(res, &myopt, pset.queryFout, pset.logfile);
+       printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
 
        PQclear(res);
        return true;
@@ -4239,11 +4479,12 @@ listForeignTables(const char *pattern, bool verbose)
                                                         "d.objoid = c.oid AND d.objsubid = 0\n");
 
        processSQLNamePattern(pset.db, &buf, pattern, false, false,
-                                                 NULL, "n.nspname", "c.relname", NULL);
+                                                 "n.nspname", "c.relname", NULL,
+                                                 "pg_catalog.pg_table_is_visible(c.oid)");
 
        appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
 
-       res = PSQLexec(buf.data, false);
+       res = PSQLexec(buf.data);
        termPQExpBuffer(&buf);
        if (!res)
                return false;
@@ -4252,7 +4493,7 @@ listForeignTables(const char *pattern, bool verbose)
        myopt.title = _("List of foreign tables");
        myopt.translate_header = true;
 
-       printQuery(res, &myopt, pset.queryFout, pset.logfile);
+       printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
 
        PQclear(res);
        return true;
@@ -4297,7 +4538,7 @@ listExtensions(const char *pattern)
 
        appendPQExpBufferStr(&buf, "ORDER BY 1;");
 
-       res = PSQLexec(buf.data, false);
+       res = PSQLexec(buf.data);
        termPQExpBuffer(&buf);
        if (!res)
                return false;
@@ -4306,7 +4547,7 @@ listExtensions(const char *pattern)
        myopt.title = _("List of installed extensions");
        myopt.translate_header = true;
 
-       printQuery(res, &myopt, pset.queryFout, pset.logfile);
+       printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
 
        PQclear(res);
        return true;
@@ -4343,7 +4584,7 @@ listExtensionContents(const char *pattern)
 
        appendPQExpBufferStr(&buf, "ORDER BY 1;");
 
-       res = PSQLexec(buf.data, false);
+       res = PSQLexec(buf.data);
        termPQExpBuffer(&buf);
        if (!res)
                return false;
@@ -4403,7 +4644,7 @@ listOneExtensionContents(const char *extname, const char *oid)
                                          gettext_noop("Object Description"),
                                          oid);
 
-       res = PSQLexec(buf.data, false);
+       res = PSQLexec(buf.data);
        termPQExpBuffer(&buf);
        if (!res)
                return false;
@@ -4413,7 +4654,7 @@ listOneExtensionContents(const char *extname, const char *oid)
        myopt.title = title;
        myopt.translate_header = true;
 
-       printQuery(res, &myopt, pset.queryFout, pset.logfile);
+       printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
 
        PQclear(res);
        return true;
@@ -4423,7 +4664,7 @@ listOneExtensionContents(const char *extname, const char *oid)
  * printACLColumn
  *
  * Helper function for consistently formatting ACL (privilege) columns.
- * The proper targetlist entry is appended to buf.     Note lack of any
+ * The proper targetlist entry is appended to buf.  Note lack of any
  * whitespace or comma decoration.
  */
 static void