Fix CreatePolicy, pg_dump -v; psql and doc updates

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.
This commit is contained in:
Stephen Frost 2014-10-03 16:31:53 -04:00
parent 5968570430
commit 78d72563ef
6 changed files with 122 additions and 27 deletions

View File

@ -5396,6 +5396,13 @@
<entry>The command type to which the row-security policy is applied.</entry>
</row>
<row>
<entry><structfield>rsecroles</structfield></entry>
<entry><type>char</type></entry>
<entry></entry>
<entry>The roles to which the row-security policy is applied.</entry>
</row>
<row>
<entry><structfield>rsecqual</structfield></entry>
<entry><type>pg_node_tree</type></entry>
@ -5417,8 +5424,8 @@
<note>
<para>
<literal>pg_class.relrowsecurity</literal>
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.
</para>
</note>
@ -7299,6 +7306,11 @@
<entry>materialized views</entry>
</row>
<row>
<entry><link linkend="view-pg-policies"><structname>pg_policies</structname></link></entry>
<entry>policies</entry>
</row>
<row>
<entry><link linkend="view-pg-prepared-statements"><structname>pg_prepared_statements</structname></link></entry>
<entry>prepared statements</entry>
@ -8146,6 +8158,81 @@ SELECT * FROM pg_locks pl LEFT JOIN pg_prepared_xacts ppx
</sect1>
<sect1 id="view-pg-policies">
<title><structname>pg_policies</structname></title>
<indexterm zone="view-pg-policies">
<primary>pg_policies</primary>
</indexterm>
<para>
The view <structname>pg_policies</structname> provides access to
useful information about each policy in the database.
</para>
<table>
<title><structname>pg_policies</> Columns</title>
<tgroup cols="4">
<thead>
<row>
<entry>Name</entry>
<entry>Type</entry>
<entry>References</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry><structfield>schemaname</structfield></entry>
<entry><type>name</type></entry>
<entry><literal><link linkend="catalog-pg-namespace"><structname>pg_namespace</structname></link>.nspname</literal></entry>
<entry>Name of schema containing table policy is on</entry>
</row>
<row>
<entry><structfield>tablename</structfield></entry>
<entry><type>name</type></entry>
<entry><literal><link linkend="catalog-pg-class"><structname>pg_class</structname></link>.relname</literal></entry>
<entry>Name of table policy is on</entry>
</row>
<row>
<entry><structfield>policyname</structfield></entry>
<entry><type>name</type></entry>
<entry><literal><link linkend="catalog-pg-class"><structname>pg_class</structname></link>.relname</literal></entry>
<entry>Name of policy</entry>
</row>
<row>
<entry><structfield>cmd</structfield></entry>
<entry><type>text</type></entry>
<entry></entry>
<entry>The command type to which the policy is applied.</entry>
</row>
<row>
<entry><structfield>roles</structfield></entry>
<entry><type>name[]</type></entry>
<entry></entry>
<entry>The roles to which this policy applies.</entry>
</row>
<row>
<entry><structfield>qual</structfield></entry>
<entry><type>text</type></entry>
<entry></entry>
<entry>The expression added to the security barrier qualifications for
queries which this policy applies to.</entry>
</row>
<row>
<entry><structfield>with_check</structfield></entry>
<entry><type>text</type></entry>
<entry></entry>
<entry>The expression added to the with check qualifications for
queries which attempt to add rows to this table.</entry>
</row>
</tbody>
</tgroup>
</table>
</sect1>
<sect1 id="view-pg-prepared-statements">
<title><structname>pg_prepared_statements</structname></title>

View File

@ -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

View File

@ -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);

View File

@ -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);
/*

View File

@ -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);
}

View File

@ -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,