diff options
Diffstat (limited to 'src/bin/psql/describe.c')
-rw-r--r-- | src/bin/psql/describe.c | 150 |
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, |