aboutsummaryrefslogtreecommitdiff
path: root/src/bin/psql/describe.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/bin/psql/describe.c')
-rw-r--r--src/bin/psql/describe.c150
1 files changed, 133 insertions, 17 deletions
diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index 282cd432a27..97dc2dded2c 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -742,7 +742,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);
@@ -778,7 +778,38 @@ 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 rsecpolname\n"
+ " || CASE WHEN rseccmd IS NOT NULL THEN\n"
+ " E' (' || rseccmd || E')'\n"
+ " ELSE E':' \n"
+ " END\n"
+ " || CASE WHEN rs.rsecqual IS NOT NULL THEN\n"
+ " E'\\n (u): ' || pg_catalog.pg_get_expr(rsecqual, rsecrelid)\n"
+ " ELSE E''\n"
+ " END\n"
+ " || CASE WHEN rsecwithcheck IS NOT NULL THEN\n"
+ " E'\\n (c): ' || pg_catalog.pg_get_expr(rsecwithcheck, rsecrelid)\n"
+ " ELSE E''\n"
+ " END"
+ " || CASE WHEN rs.rsecroles <> '{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 (rs.rsecroles)\n"
+ " ORDER BY 1\n"
+ " ), E', ')\n"
+ " ELSE E''\n"
+ " END\n"
+ " FROM pg_catalog.pg_rowsecurity rs\n"
+ " WHERE rsecrelid = 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"
@@ -1173,6 +1204,7 @@ describeOneTableDetails(const char *schemaname,
bool hasindex;
bool hasrules;
bool hastriggers;
+ bool hasrowsecurity;
bool hasoids;
Oid tablespace;
char *reloptions;
@@ -1194,11 +1226,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.relhasoids, "
+ "c.relhastriggers, c.relhasrowsecurity, 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, 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"
@@ -1215,7 +1264,7 @@ describeOneTableDetails(const char *schemaname,
{
printfPQExpBuffer(&buf,
"SELECT c.relchecks, c.relkind, c.relhasindex, c.relhasrules, "
- "c.relhastriggers, c.relhasoids, "
+ "c.relhastriggers, 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"
@@ -1232,7 +1281,7 @@ describeOneTableDetails(const char *schemaname,
{
printfPQExpBuffer(&buf,
"SELECT c.relchecks, c.relkind, c.relhasindex, c.relhasrules, "
- "c.relhastriggers, c.relhasoids, "
+ "c.relhastriggers, 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 "
@@ -1248,7 +1297,7 @@ describeOneTableDetails(const char *schemaname,
{
printfPQExpBuffer(&buf,
"SELECT c.relchecks, c.relkind, c.relhasindex, c.relhasrules, "
- "c.relhastriggers, c.relhasoids, "
+ "c.relhastriggers, 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"
@@ -1263,7 +1312,7 @@ describeOneTableDetails(const char *schemaname,
{
printfPQExpBuffer(&buf,
"SELECT relchecks, relkind, relhasindex, relhasrules, "
- "reltriggers <> 0, relhasoids, "
+ "reltriggers <> 0, false, relhasoids, "
"%s, reltablespace\n"
"FROM pg_catalog.pg_class WHERE oid = '%s';",
(verbose ?
@@ -1274,7 +1323,7 @@ describeOneTableDetails(const char *schemaname,
{
printfPQExpBuffer(&buf,
"SELECT relchecks, relkind, relhasindex, relhasrules, "
- "reltriggers <> 0, relhasoids, "
+ "reltriggers <> 0, false, relhasoids, "
"'', reltablespace\n"
"FROM pg_catalog.pg_class WHERE oid = '%s';",
oid);
@@ -1283,7 +1332,7 @@ describeOneTableDetails(const char *schemaname,
{
printfPQExpBuffer(&buf,
"SELECT relchecks, relkind, relhasindex, relhasrules, "
- "reltriggers <> 0, relhasoids, "
+ "reltriggers <> 0, false, relhasoids, "
"'', ''\n"
"FROM pg_catalog.pg_class WHERE oid = '%s';",
oid);
@@ -1306,18 +1355,19 @@ 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.hasrowsecurity = strcmp(PQgetvalue(res, 0, 5), "t") == 0;
+ tableinfo.hasoids = strcmp(PQgetvalue(res, 0, 6), "t") == 0;
tableinfo.reloptions = (pset.sversion >= 80200) ?
- pg_strdup(PQgetvalue(res, 0, 6)) : NULL;
+ pg_strdup(PQgetvalue(res, 0, 7)) : NULL;
tableinfo.tablespace = (pset.sversion >= 80000) ?
- atooid(PQgetvalue(res, 0, 7)) : 0;
+ atooid(PQgetvalue(res, 0, 8)) : 0;
tableinfo.reloftype = (pset.sversion >= 90000 &&
- strcmp(PQgetvalue(res, 0, 8), "") != 0) ?
- pg_strdup(PQgetvalue(res, 0, 8)) : NULL;
+ strcmp(PQgetvalue(res, 0, 9), "") != 0) ?
+ pg_strdup(PQgetvalue(res, 0, 9)) : NULL;
tableinfo.relpersistence = (pset.sversion >= 90100) ?
- *(PQgetvalue(res, 0, 9)) : 0;
+ *(PQgetvalue(res, 0, 10)) : 0;
tableinfo.relreplident = (pset.sversion >= 90400) ?
- *(PQgetvalue(res, 0, 10)) : 'd';
+ *(PQgetvalue(res, 0, 11)) : 'd';
PQclear(res);
res = NULL;
@@ -1948,6 +1998,67 @@ describeOneTableDetails(const char *schemaname,
PQclear(result);
}
+
+ if (pset.sversion >= 90500)
+ appendPQExpBuffer(&buf,
+ ",\n pg_catalog.pg_get_expr(rs.rsecqual, c.oid) as \"%s\"",
+ gettext_noop("Row-security"));
+ if (verbose && pset.sversion >= 90500)
+ appendPQExpBuffer(&buf,
+ "\n LEFT JOIN pg_rowsecurity rs ON rs.rsecrelid = c.oid");
+
+ /* print any row-level policies */
+ if (tableinfo.hasrowsecurity)
+ {
+ printfPQExpBuffer(&buf,
+ "SELECT rs.rsecpolname,\n"
+ "CASE WHEN rs.rsecroles = '{0}' THEN NULL ELSE array(select rolname from pg_roles where oid = any (rs.rsecroles) order by 1) END,\n"
+ "pg_catalog.pg_get_expr(rs.rsecqual, rs.rsecrelid),\n"
+ "pg_catalog.pg_get_expr(rs.rsecwithcheck, rs.rsecrelid),\n"
+ "rs.rseccmd AS cmd\n"
+ "FROM pg_catalog.pg_rowsecurity rs\n"
+ "WHERE rs.rsecrelid = '%s' ORDER BY 1;",
+ oid);
+ result = PSQLexec(buf.data, false);
+ if (!result)
+ goto error_return;
+ else
+ tuples = PQntuples(result);
+
+ if (tuples > 0)
+ {
+ printTableAddFooter(&cont, _("Policies:"));
+ for (i = 0; i < tuples; i++)
+ {
+ printfPQExpBuffer(&buf, " POLICY \"%s\"",
+ PQgetvalue(result, i, 0));
+
+ if (!PQgetisnull(result, i, 4))
+ appendPQExpBuffer(&buf, " (%s)",
+ PQgetvalue(result, i, 4));
+
+ if (!PQgetisnull(result, i, 2))
+ appendPQExpBuffer(&buf, " EXPRESSION %s",
+ PQgetvalue(result, i, 2));
+
+ if (!PQgetisnull(result, i, 3))
+ appendPQExpBuffer(&buf, " WITH CHECK %s",
+ PQgetvalue(result, i, 3));
+
+ printTableAddFooter(&cont, buf.data);
+
+ if (!PQgetisnull(result, i, 1))
+ {
+ printfPQExpBuffer(&buf, " APPLIED TO %s",
+ PQgetvalue(result, i, 1));
+
+ printTableAddFooter(&cont, buf.data);
+ }
+ }
+ }
+ PQclear(result);
+ }
+
/* print rules */
if (tableinfo.hasrules && tableinfo.relkind != 'm')
{
@@ -2529,6 +2640,11 @@ 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");
processSQLNamePattern(pset.db, &buf, pattern, false, false,