From 78d72563ef141ddc507ddd5ae77db613a309041a Mon Sep 17 00:00:00 2001 From: Stephen Frost Date: Fri, 3 Oct 2014 16:31:53 -0400 Subject: [PATCH] Fix CreatePolicy, pg_dump -v; psql and doc updates MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Peter G pointed out that valgrind was, rightfully, complaining about CreatePolicy() ending up copying beyond the end of the parsed policy name. Name is a fixed-size type and we need to use namein (through DirectFunctionCall1()) to flush out the entire array before we pass it down to heap_form_tuple. Michael Paquier pointed out that pg_dump --verbose was missing a newline and Fabrízio de Royes Mello further pointed out that the schema was also missing from the messages, so fix those also. Also, based on an off-list comment from Kevin, rework the psql \d output to facilitate copy/pasting into a new CREATE or ALTER POLICY command. Lastly, improve the pg_policies view and update the documentation for it, along with a few other minor doc corrections based on an off-list discussion with Adam Brightwell. --- doc/src/sgml/catalogs.sgml | 91 +++++++++++++++++++++++++++- src/backend/catalog/system_views.sql | 10 +-- src/backend/commands/policy.c | 2 +- src/bin/pg_dump/pg_dump.c | 6 +- src/bin/psql/describe.c | 28 +++++---- src/test/regress/expected/rules.out | 12 ++-- 6 files changed, 122 insertions(+), 27 deletions(-) diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml index a6ca290cb3..f4617b67e9 100644 --- a/doc/src/sgml/catalogs.sgml +++ b/doc/src/sgml/catalogs.sgml @@ -5396,6 +5396,13 @@ The command type to which the row-security policy is applied. + + rsecroles + char + + The roles to which the row-security policy is applied. + + rsecqual pg_node_tree @@ -5417,8 +5424,8 @@ pg_class.relrowsecurity - True if the table has row-security enabled. - Must be true if the table has a row-security policy in this catalog. + True if the table has row-security enabled. Policies will not be applied + unless row-security is enabled on the table. @@ -7299,6 +7306,11 @@ materialized views + + pg_policies + policies + + pg_prepared_statements prepared statements @@ -8146,6 +8158,81 @@ SELECT * FROM pg_locks pl LEFT JOIN pg_prepared_xacts ppx + + <structname>pg_policies</structname> + + + pg_policies + + + + The view pg_policies provides access to + useful information about each policy in the database. + + + + <structname>pg_policies</> Columns + + + + + Name + Type + References + Description + + + + + schemaname + name + pg_namespace.nspname + Name of schema containing table policy is on + + + tablename + name + pg_class.relname + Name of table policy is on + + + policyname + name + pg_class.relname + Name of policy + + + cmd + text + + The command type to which the policy is applied. + + + roles + name[] + + The roles to which this policy applies. + + + qual + text + + The expression added to the security barrier qualifications for + queries which this policy applies to. + + + with_check + text + + The expression added to the with check qualifications for + queries which attempt to add rows to this table. + + + +
+ +
+ <structname>pg_prepared_statements</structname> diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql index da99fd63e8..a819952c75 100644 --- a/src/backend/catalog/system_views.sql +++ b/src/backend/catalog/system_views.sql @@ -65,8 +65,9 @@ CREATE VIEW pg_user AS CREATE VIEW pg_policies AS SELECT + N.nspname AS schemaname, + C.relname AS tablename, rs.rsecpolname AS policyname, - (SELECT relname FROM pg_catalog.pg_class WHERE oid = rs.rsecrelid) AS tablename, CASE WHEN rs.rsecroles = '{0}' THEN string_to_array('public', '') @@ -78,8 +79,8 @@ CREATE VIEW pg_policies AS WHERE oid = ANY (rs.rsecroles) ORDER BY 1 ) END AS roles, - CASE WHEN rs.rseccmd IS NULL THEN 'ALL' ELSE - CASE rs.rseccmd + CASE WHEN rs.rseccmd IS NULL THEN 'ALL' ELSE + CASE rs.rseccmd WHEN 'r' THEN 'SELECT' WHEN 'a' THEN 'INSERT' WHEN 'u' THEN 'UPDATE' @@ -89,7 +90,8 @@ CREATE VIEW pg_policies AS pg_catalog.pg_get_expr(rs.rsecqual, rs.rsecrelid) AS qual, pg_catalog.pg_get_expr(rs.rsecwithcheck, rs.rsecrelid) AS with_check FROM pg_catalog.pg_rowsecurity rs - ORDER BY 1; + JOIN pg_catalog.pg_class C ON (C.oid = rs.rsecrelid) + LEFT JOIN pg_catalog.pg_namespace N ON (N.oid = C.relnamespace); CREATE VIEW pg_rules AS SELECT diff --git a/src/backend/commands/policy.c b/src/backend/commands/policy.c index 33bf031346..8e6393c8c0 100644 --- a/src/backend/commands/policy.c +++ b/src/backend/commands/policy.c @@ -556,7 +556,7 @@ CreatePolicy(CreatePolicyStmt *stmt) values[Anum_pg_rowsecurity_rsecrelid - 1] = ObjectIdGetDatum(table_id); values[Anum_pg_rowsecurity_rsecpolname - 1] - = CStringGetDatum(stmt->policy_name); + = DirectFunctionCall1(namein, CStringGetDatum(stmt->policy_name)); if (rseccmd) values[Anum_pg_rowsecurity_rseccmd - 1] = CharGetDatum(rseccmd); diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index 12811a801a..1a9e82e920 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -2803,7 +2803,8 @@ getRowSecurity(Archive *fout, TableInfo tblinfo[], int numTables) continue; if (g_verbose) - write_msg(NULL, "reading row-security enabled for table \"%s\"", + write_msg(NULL, "reading row-security enabled for table \"%s\".\"%s\"\n", + tbinfo->dobj.namespace->dobj.name, tbinfo->dobj.name); /* @@ -2833,7 +2834,8 @@ getRowSecurity(Archive *fout, TableInfo tblinfo[], int numTables) } if (g_verbose) - write_msg(NULL, "reading row-security policies for table \"%s\"\n", + write_msg(NULL, "reading row-security policies for table \"%s\".\"%s\"\n", + tbinfo->dobj.namespace->dobj.name, tbinfo->dobj.name); /* diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c index 074be57696..267f365170 100644 --- a/src/bin/psql/describe.c +++ b/src/bin/psql/describe.c @@ -2011,10 +2011,15 @@ describeOneTableDetails(const char *schemaname, 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" + "CASE WHEN rs.rsecroles = '{0}' THEN NULL ELSE array_to_string(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" + "CASE rs.rseccmd \n" + "WHEN 'r' THEN 'SELECT'\n" + "WHEN 'u' THEN 'UPDATE'\n" + "WHEN 'a' THEN 'INSERT'\n" + "WHEN 'd' THEN 'DELETE'\n" + "END AS cmd\n" "FROM pg_catalog.pg_rowsecurity rs\n" "WHERE rs.rsecrelid = '%s' ORDER BY 1;", oid); @@ -2046,26 +2051,25 @@ describeOneTableDetails(const char *schemaname, PQgetvalue(result, i, 0)); if (!PQgetisnull(result, i, 4)) - appendPQExpBuffer(&buf, " (%s)", + 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, " EXPRESSION %s", + appendPQExpBuffer(&buf, "\n USING %s", PQgetvalue(result, i, 2)); if (!PQgetisnull(result, i, 3)) - appendPQExpBuffer(&buf, " WITH CHECK %s", + appendPQExpBuffer(&buf, "\n 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); } diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out index c53e7851cc..c79b45c53a 100644 --- a/src/test/regress/expected/rules.out +++ b/src/test/regress/expected/rules.out @@ -1353,10 +1353,9 @@ pg_matviews| SELECT n.nspname AS schemaname, LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) LEFT JOIN pg_tablespace t ON ((t.oid = c.reltablespace))) WHERE (c.relkind = 'm'::"char"); -pg_policies| SELECT rs.rsecpolname AS policyname, - ( SELECT pg_class.relname - FROM pg_class - WHERE (pg_class.oid = rs.rsecrelid)) AS tablename, +pg_policies| SELECT n.nspname AS schemaname, + c.relname AS tablename, + rs.rsecpolname AS policyname, CASE WHEN (rs.rsecroles = '{0}'::oid[]) THEN (string_to_array('public'::text, ''::text))::name[] ELSE ARRAY( SELECT pg_authid.rolname @@ -1377,8 +1376,9 @@ pg_policies| SELECT rs.rsecpolname AS policyname, END AS cmd, pg_get_expr(rs.rsecqual, rs.rsecrelid) AS qual, pg_get_expr(rs.rsecwithcheck, rs.rsecrelid) AS with_check - FROM pg_rowsecurity rs - ORDER BY rs.rsecpolname; + FROM ((pg_rowsecurity rs + JOIN pg_class c ON ((c.oid = rs.rsecrelid))) + LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))); pg_prepared_statements| SELECT p.name, p.statement, p.prepare_time,