* 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"
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,
appendPQExpBufferStr(&buf, "ORDER BY 1, 2, 4;");
- res = PSQLexec(buf.data, false);
+ res = PSQLexec(buf.data);
termPQExpBuffer(&buf);
if (!res)
return false;
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;
",\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\"",
appendPQExpBufferStr(&buf, "ORDER BY 1;");
- res = PSQLexec(buf.data, false);
+ res = PSQLexec(buf.data);
termPQExpBuffer(&buf);
if (!res)
return false;
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;
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;
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;
" ) 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");
*/
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
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,
appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
- res = PSQLexec(buf.data, false);
+ res = PSQLexec(buf.data);
termPQExpBuffer(&buf);
if (!res)
return false;
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;
appendPQExpBufferStr(&buf, "ORDER BY 1, 2, 3, 4;");
- res = PSQLexec(buf.data, false);
+ res = PSQLexec(buf.data);
termPQExpBuffer(&buf);
if (!res)
return false;
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;
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;
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;
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);
" 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
appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
- res = PSQLexec(buf.data, false);
+ res = PSQLexec(buf.data);
if (!res)
{
termPQExpBuffer(&buf);
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);
appendPQExpBufferStr(&buf, "ORDER BY 1, 2, 3;");
- res = PSQLexec(buf.data, false);
+ res = PSQLexec(buf.data);
if (!res)
{
termPQExpBuffer(&buf);
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);
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"
"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"
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+
*/
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,
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,
appendPQExpBufferStr(&buf, "ORDER BY 1, 2, 3;");
- res = PSQLexec(buf.data, false);
+ res = PSQLexec(buf.data);
termPQExpBuffer(&buf);
if (!res)
return false;
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;
appendPQExpBufferStr(&buf, "ORDER BY 2, 3;");
- res = PSQLexec(buf.data, false);
+ res = PSQLexec(buf.data);
termPQExpBuffer(&buf);
if (!res)
return false;
bool hasindex;
bool hasrules;
bool hastriggers;
+ bool rowsecurity;
+ bool forcerowsecurity;
bool hasoids;
Oid tablespace;
char *reloptions;
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"
{
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"
{
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 "
{
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"
{
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 ?
{
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);
{
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;
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;
/* 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;
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)
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);
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;
if (!PQgetisnull(res, i, 5))
{
if (tmpbuf.len > 0)
- appendPQExpBufferStr(&tmpbuf, " ");
+ appendPQExpBufferChar(&tmpbuf, ' ');
appendPQExpBuffer(&tmpbuf, _("collate %s"),
PQgetvalue(res, i, 5));
}
if (strcmp(PQgetvalue(res, i, 3), "t") == 0)
{
if (tmpbuf.len > 0)
- appendPQExpBufferStr(&tmpbuf, " ");
+ appendPQExpBufferChar(&tmpbuf, ' ');
appendPQExpBufferStr(&tmpbuf, _("not null"));
}
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));
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 "
"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)
"\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)
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
"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
"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
"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
"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
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')
{
"WHERE r.ev_class = '%s' ORDER BY 1;",
oid);
}
- result = PSQLexec(buf.data, false);
+ result = PSQLexec(buf.data);
if (!result)
goto error_return;
else
"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;
" 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
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:"));
" 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)
/* 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
printfPQExpBuffer(&buf, "%*s %s",
sw, "", PQgetvalue(result, i, 0));
if (i < tuples - 1)
- appendPQExpBufferStr(&buf, ",");
+ appendPQExpBufferChar(&buf, ',');
printTableAddFooter(&cont, buf.data);
}
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
printTableAddFooter(&cont, buf.data);
}
- if ((tableinfo.relkind == 'r' || tableinfo.relkind == 'm') &&
- /*
- * No need to display default values; we already display a
- * REPLICA IDENTITY marker on indexes.
- */
- tableinfo.relreplident != 'd' && tableinfo.relreplident != 'i' &&
- strcmp(schemaname, "pg_catalog") != 0)
+ 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");
}
/* 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,
printTableAddFooter(&cont, buf.data);
}
- printTable(&cont, pset.queryFout, pset.logfile);
- printTableCleanup(&cont);
+ printTable(&cont, pset.queryFout, false, pset.logfile);
retval = true;
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.... */
* 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;
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);
}
appendPQExpBufferStr(&buf, "ORDER BY 1;");
- res = PSQLexec(buf.data, false);
+ res = PSQLexec(buf.data);
if (!res)
return false;
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)
{
}
termPQExpBuffer(&buf);
- printTable(&cont, pset.queryFout, pset.logfile);
+ printTable(&cont, pset.queryFout, false, pset.logfile);
printTableCleanup(&cont);
for (i = 0; i < nrows; i++)
return false;
}
- res = PSQLexec(buf.data, false);
+ res = PSQLexec(buf.data);
if (!res)
return false;
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);
if (showForeign)
appendPQExpBufferStr(&buf, "'f',");
- appendPQExpBufferStr(&buf, "''"); /* dummy */
+ appendPQExpBufferStr(&buf, "''"); /* dummy */
appendPQExpBufferStr(&buf, ")\n");
if (!showSystem && !pattern)
appendPQExpBufferStr(&buf, "ORDER BY 1,2;");
- res = PSQLexec(buf.data, false);
+ res = PSQLexec(buf.data);
termPQExpBuffer(&buf);
if (!res)
return false;
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);
appendPQExpBufferStr(&buf, "ORDER BY 1;");
- res = PSQLexec(buf.data, false);
+ res = PSQLexec(buf.data);
termPQExpBuffer(&buf);
if (!res)
return false;
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;
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");
appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
- res = PSQLexec(buf.data, false);
+ res = PSQLexec(buf.data);
termPQExpBuffer(&buf);
if (!res)
return false;
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;
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);
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,
appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
- res = PSQLexec(buf.data, false);
+ res = PSQLexec(buf.data);
termPQExpBuffer(&buf);
if (!res)
return false;
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;
" 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"),
appendPQExpBufferStr(&buf, "ORDER BY 1");
- res = PSQLexec(buf.data, false);
+ res = PSQLexec(buf.data);
termPQExpBuffer(&buf);
if (!res)
return false;
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;
appendPQExpBufferStr(&buf, ") )\nORDER BY 1, 2;");
- res = PSQLexec(buf.data, false);
+ res = PSQLexec(buf.data);
termPQExpBuffer(&buf);
if (!res)
return false;
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;
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.
appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
- res = PSQLexec(buf.data, false);
+ res = PSQLexec(buf.data);
termPQExpBuffer(&buf);
if (!res)
return false;
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;
appendPQExpBufferStr(&buf, "ORDER BY 1;");
- res = PSQLexec(buf.data, false);
+ res = PSQLexec(buf.data);
termPQExpBuffer(&buf);
if (!res)
return false;
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;
appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
- res = PSQLexec(buf.data, false);
+ res = PSQLexec(buf.data);
termPQExpBuffer(&buf);
if (!res)
return false;
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;
appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
- res = PSQLexec(buf.data, false);
+ res = PSQLexec(buf.data);
termPQExpBuffer(&buf);
if (!res)
return false;
gettext_noop("Get token types"),
oid);
- res = PSQLexec(buf.data, false);
+ res = PSQLexec(buf.data);
termPQExpBuffer(&buf);
if (!res)
return false;
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);
gettext_noop("Description"),
oid);
- res = PSQLexec(buf.data, false);
+ res = PSQLexec(buf.data);
termPQExpBuffer(&buf);
if (!res)
return false;
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;
appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
- res = PSQLexec(buf.data, false);
+ res = PSQLexec(buf.data);
termPQExpBuffer(&buf);
if (!res)
return false;
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;
appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
- res = PSQLexec(buf.data, false);
+ res = PSQLexec(buf.data);
termPQExpBuffer(&buf);
if (!res)
return false;
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;
appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
- res = PSQLexec(buf.data, false);
+ res = PSQLexec(buf.data);
termPQExpBuffer(&buf);
if (!res)
return false;
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;
appendPQExpBufferStr(&buf, "ORDER BY 3, 2;");
- res = PSQLexec(buf.data, false);
+ res = PSQLexec(buf.data);
termPQExpBuffer(&buf);
if (!res)
return false;
gettext_noop("Dictionaries"),
oid);
- res = PSQLexec(buf.data, false);
+ res = PSQLexec(buf.data);
termPQExpBuffer(&buf);
if (!res)
return false;
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);
appendPQExpBufferStr(&buf, "ORDER BY 1;");
- res = PSQLexec(buf.data, false);
+ res = PSQLexec(buf.data);
termPQExpBuffer(&buf);
if (!res)
return false;
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;
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,
appendPQExpBufferStr(&buf, "ORDER BY 1;");
- res = PSQLexec(buf.data, false);
+ res = PSQLexec(buf.data);
termPQExpBuffer(&buf);
if (!res)
return false;
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;
appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
- res = PSQLexec(buf.data, false);
+ res = PSQLexec(buf.data);
termPQExpBuffer(&buf);
if (!res)
return false;
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;
"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;
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;
appendPQExpBufferStr(&buf, "ORDER BY 1;");
- res = PSQLexec(buf.data, false);
+ res = PSQLexec(buf.data);
termPQExpBuffer(&buf);
if (!res)
return false;
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;
appendPQExpBufferStr(&buf, "ORDER BY 1;");
- res = PSQLexec(buf.data, false);
+ res = PSQLexec(buf.data);
termPQExpBuffer(&buf);
if (!res)
return false;
gettext_noop("Object Description"),
oid);
- res = PSQLexec(buf.data, false);
+ res = PSQLexec(buf.data);
termPQExpBuffer(&buf);
if (!res)
return false;
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;
* 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