Rename pg_rowsecurity -> pg_policy and other fixes
authorStephen Frost <[email protected]>
Thu, 27 Nov 2014 06:06:36 +0000 (01:06 -0500)
committerStephen Frost <[email protected]>
Thu, 27 Nov 2014 06:15:57 +0000 (01:15 -0500)
As pointed out by Robert, we should really have named pg_rowsecurity
pg_policy, as the objects stored in that catalog are policies.  This
patch fixes that and updates the column names to start with 'pol' to
match the new catalog name.

The security consideration for COPY with row level security, also
pointed out by Robert, has also been addressed by remembering and
re-checking the OID of the relation initially referenced during COPY
processing, to make sure it hasn't changed under us by the time we
finish planning out the query which has been built.

Robert and Alvaro also commented on missing OCLASS and OBJECT entries
for POLICY (formerly ROWSECURITY or POLICY, depending) in various
places.  This patch fixes that too, which also happens to add the
ability to COMMENT on policies.

In passing, attempt to improve the consistency of messages, comments,
and documentation as well.  This removes various incarnations of
'row-security', 'row-level security', 'Row-security', etc, in favor
of 'policy', 'row level security' or 'row_security' as appropriate.

Happy Thanksgiving!

47 files changed:
doc/src/sgml/catalogs.sgml
doc/src/sgml/ddl.sgml
doc/src/sgml/ref/alter_policy.sgml
doc/src/sgml/ref/create_policy.sgml
doc/src/sgml/ref/drop_policy.sgml
doc/src/sgml/rules.sgml
src/backend/catalog/Makefile
src/backend/catalog/dependency.c
src/backend/catalog/objectaddress.c
src/backend/catalog/system_views.sql
src/backend/commands/copy.c
src/backend/commands/event_trigger.c
src/backend/commands/functioncmds.c
src/backend/commands/policy.c
src/backend/commands/tablecmds.c
src/backend/executor/execMain.c
src/backend/optimizer/path/allpaths.c
src/backend/optimizer/plan/planner.c
src/backend/optimizer/plan/setrefs.c
src/backend/parser/gram.y
src/backend/rewrite/rewriteHandler.c
src/backend/rewrite/rowsecurity.c
src/backend/utils/cache/plancache.c
src/backend/utils/cache/relcache.c
src/bin/pg_dump/common.c
src/bin/pg_dump/pg_backup_archiver.c
src/bin/pg_dump/pg_dump.c
src/bin/pg_dump/pg_dump.h
src/bin/pg_dump/pg_dump_sort.c
src/bin/psql/describe.c
src/bin/psql/tab-complete.c
src/include/catalog/catversion.h
src/include/catalog/dependency.h
src/include/catalog/indexing.h
src/include/catalog/pg_class.h
src/include/catalog/pg_policy.h [new file with mode: 0644]
src/include/catalog/pg_rowsecurity.h [deleted file]
src/include/nodes/parsenodes.h
src/include/nodes/plannodes.h
src/include/nodes/relation.h
src/include/rewrite/rowsecurity.h
src/include/utils/plancache.h
src/include/utils/rel.h
src/test/regress/expected/rowsecurity.out
src/test/regress/expected/rules.out
src/test/regress/expected/sanity_check.out
src/test/regress/sql/rowsecurity.sql

index f98e282741f71ce2968c537dccc773970695cfd4..9ceb96b54c74bc090373050e069a25897432e458 100644 (file)
      </row>
 
      <row>
-      <entry><link linkend="catalog-pg-rowsecurity"><structname>pg_rowsecurity</structname></link></entry>
-      <entry>table row-level security policies</entry>
+      <entry><link linkend="catalog-pg-policy"><structname>pg_policy</structname></link></entry>
+      <entry>table policies</entry>
      </row>
 
      <row>
       <entry><type>bool</type></entry>
       <entry></entry>
       <entry>
-       True if table has row-security enabled; see
-       <link linkend="catalog-pg-rowsecurity"><structname>pg_rowsecurity</structname></link> catalog
+       True if table has row level security enabled; see
+       <link linkend="catalog-pg-policy"><structname>pg_policy</structname></link> catalog
       </entry>
      </row>
 
   </table>
  </sect1>
 
- <sect1 id="catalog-pg-rowsecurity">
-  <title><structname>pg_rowsecurity</structname></title>
+ <sect1 id="catalog-pg-policy">
+  <title><structname>pg_policy</structname></title>
 
-  <indexterm zone="catalog-pg-rowsecurity">
-   <primary>pg_rowsecurity</primary>
+  <indexterm zone="catalog-pg-policy">
+   <primary>pg_policy</primary>
   </indexterm>
 
   <para>
-   The catalog <structname>pg_rowsecurity</structname> stores row-level
+   The catalog <structname>pg_policy</structname> stores row-level
    security policies for each table.  A policy includes the kind of
    command which it applies to (or all commands), the roles which it
    applies to, the expression to be added as a security-barrier
 
   <table>
 
-   <title><structname>pg_rowsecurity</structname> Columns</title>
+   <title><structname>pg_policy</structname> Columns</title>
 
    <tgroup cols="4">
     <thead>
 
     <tbody>
      <row>
-      <entry><structfield>rsecpolname</structfield></entry>
+      <entry><structfield>polname</structfield></entry>
       <entry><type>name</type></entry>
       <entry></entry>
-      <entry>The name of the row-security policy</entry>
+      <entry>The name of the policy</entry>
      </row>
 
      <row>
-      <entry><structfield>rsecrelid</structfield></entry>
+      <entry><structfield>polrelid</structfield></entry>
       <entry><type>oid</type></entry>
       <entry><literal><link linkend="catalog-pg-class"><structname>pg_class</structname></link>.oid</literal></entry>
-      <entry>The table to which the row-security policy belongs</entry>
+      <entry>The table to which the policy belongs</entry>
      </row>
 
      <row>
-      <entry><structfield>rseccmd</structfield></entry>
+      <entry><structfield>polcmd</structfield></entry>
       <entry><type>char</type></entry>
       <entry></entry>
-      <entry>The command type to which the row-security policy is applied.</entry>
+      <entry>The command type to which the policy is applied.</entry>
      </row>
 
      <row>
-      <entry><structfield>rsecroles</structfield></entry>
+      <entry><structfield>polroles</structfield></entry>
       <entry><type>char</type></entry>
       <entry></entry>
-      <entry>The roles to which the row-security policy is applied.</entry>
+      <entry>The roles to which the policy is applied.</entry>
      </row>
 
      <row>
-      <entry><structfield>rsecqual</structfield></entry>
+      <entry><structfield>polqual</structfield></entry>
       <entry><type>pg_node_tree</type></entry>
       <entry></entry>
       <entry>The expression tree to be added to the security barrier qualifications for queries which use the table.</entry>
      </row>
 
      <row>
-      <entry><structfield>rsecwithcheck</structfield></entry>
+      <entry><structfield>polwithcheck</structfield></entry>
       <entry><type>pg_node_tree</type></entry>
       <entry></entry>
       <entry>The expression tree to be added to the with check qualifications for queries which attempt to add rows to the table.</entry>
   <note>
    <para>
     <literal>pg_class.relrowsecurity</literal>
-    True if the table has row-security enabled.  Policies will not be applied
-    unless row-security is enabled on the table.
+    True if the table has row security enabled.  Policies will not be applied
+    unless row security is enabled on the table.
    </para>
   </note>
 
index f9dc151a0cc711df40a2cae5dedfc7e7ead2614c..570a003e4a9d37daa470dbe007342f8a824bad6c 100644 (file)
@@ -1558,8 +1558,8 @@ REVOKE ALL ON accounts FROM PUBLIC;
 
   <para>
    To specify which rows are visible and what rows can be added to the
-   table with row security, an expression is required which returns a
-   boolean result.  This expression will be evaluated for each row prior
+   table with row level security, an expression is required which returns
+   boolean result.  This expression will be evaluated for each row prior
    to other conditionals or functions which are part of the query.  The
    one exception to this rule are <literal>leakproof</literal> functions,
    which are guaranteed to not leak information.  Two expressions may be
index ab717f31c51b92b82f2b59078df3ad01ff39c3d2..796035e9da92cf4bbbf1dfe07b3e5ffba7f81d35 100644 (file)
@@ -16,7 +16,7 @@ PostgreSQL documentation
 
  <refnamediv>
   <refname>ALTER POLICY</refname>
-  <refpurpose>change the definition of a row-security policy</refpurpose>
+  <refpurpose>change the definition of a policy</refpurpose>
  </refnamediv>
 
  <refsynopsisdiv>
@@ -34,7 +34,7 @@ ALTER POLICY <replaceable class="parameter">name</replaceable> ON <replaceable c
 
   <para>
    <command>ALTER POLICY</command> changes the <replaceable class="parameter">
-   definition</replaceable> of an existing row-security policy.
+   definition</replaceable> of an existing policy.
   </para>
 
   <para>
index eff062c114f0c59d8b78587cae3915f92a3919ce..4c8c00193139600a8741b3e9a45cbebbe9873766 100644 (file)
@@ -16,7 +16,7 @@ PostgreSQL documentation
 
  <refnamediv>
   <refname>CREATE POLICY</refname>
-  <refpurpose>define a new row-security policy for a table</refpurpose>
+  <refpurpose>define a new policy for a table</refpurpose>
  </refnamediv>
 
  <refsynopsisdiv>
@@ -33,14 +33,13 @@ CREATE POLICY <replaceable class="parameter">name</replaceable> ON <replaceable
   <title>Description</title>
 
   <para>
-   The <command>CREATE POLICY</command> command defines a new row-security
-   policy for a table.  Note that row-security must also be enabled on the
-   table using <command>ALTER TABLE</command> in order for created policies
-   to be applied.
+   The <command>CREATE POLICY</command> command defines a new policy for a
+   table.  Note that row level security must also be enabled on the table using
+   <command>ALTER TABLE</command> in order for created policies to be applied.
   </para>
 
   <para>
-   A row-security policy is an expression which is added to the security-barrier
+   A policy is an expression which is added to the security-barrier
    qualifications of queries which are run against the table the policy is on,
    or an expression which is added to the with-check options for a table and
    which is applied to rows which would be added to the table.
@@ -49,7 +48,7 @@ CREATE POLICY <replaceable class="parameter">name</replaceable> ON <replaceable
    expression will be evaluated against the rows which are going to be added to
    the table.  By adding policies to a table, a user can limit the rows which a
    given user can select, insert, update, or delete.  This capability is also
-   known as Row-Level Security or RLS.
+   known as Row Level Security or RLS.
   </para>
 
   <para>
@@ -66,22 +65,22 @@ CREATE POLICY <replaceable class="parameter">name</replaceable> ON <replaceable
   </para>
 
   <para>
-   Note that while row-security policies will be applied for explicit queries
-   against tables in the system, they are not applied when the system is
-   performing internal referential integrity checks or validating constraints.
-   This means there are indirect ways to determine that a given value exists.
-   An example of this is attempting to insert a duplicate value
-   into a column which is the primary key or has a unique constraint.  If the
-   insert fails then the user can infer that the value already exists (this
-   example assumes that the user is permitted by policy to insert
-   records which they are not allowed to see).  Another example is where a user
-   is allowed to insert into a table which references another, otherwise hidden
-   table.  Existence can be determined by the user inserting values into the
-   referencing table, where success would indicate that the value exists in the
-   referenced table.  These issues can be addressed by carefully crafting
-   policies which prevent users from being able to insert, delete, or update
-   records at all which might possibly indicate a value they are not otherwise
-   able to see, or by using generated values (e.g.: surrogate keys) instead.
+   Note that while policies will be applied for explicit queries against tables
+   in the system, they are not applied when the system is performing internal
+   referential integrity checks or validating constraints.  This means there are
+   indirect ways to determine that a given value exists.  An example of this is
+   attempting to insert a duplicate value into a column which is the primary key
+   or has a unique constraint.  If the insert fails then the user can infer that
+   the value already exists (this example assumes that the user is permitted by
+   policy to insert records which they are not allowed to see).  Another example
+   is where a user is allowed to insert into a table which references another,
+   otherwise hidden table.  Existence can be determined by the user inserting
+   values into the referencing table, where success would indicate that the
+   value exists in the referenced table.  These issues can be addressed by
+   carefully crafting policies which prevent users from being able to insert,
+   delete, or update records at all which might possibly indicate a value they
+   are not otherwise able to see, or by using generated values (e.g.: surrogate
+   keys) instead.
   </para>
 
   <para>
@@ -291,8 +290,8 @@ CREATE POLICY <replaceable class="parameter">name</replaceable> ON <replaceable
 
   <para>
    In order to maintain <firstterm>referential integrity</firstterm> between
-   two related tables, row-security policies are not applied when the system
-   performs checks on foreign key constraints.
+   two related tables, policies are not applied when the system performs
+   checks on foreign key constraints.
   </para>
 
  </refsect1>
index 31ca9db220eca6148a1fe5d7e0ebae94dd64e6c6..bd4ef5cf7ce03f80d5283b4dcf60fdae4b40d436 100644 (file)
@@ -16,7 +16,7 @@ PostgreSQL documentation
 
  <refnamediv>
   <refname>DROP POLICY</refname>
-  <refpurpose>remove a row-security policy from a table</refpurpose>
+  <refpurpose>remove a policy from a table</refpurpose>
  </refnamediv>
 
  <refsynopsisdiv>
@@ -29,11 +29,11 @@ DROP POLICY [ IF EXISTS ] <replaceable class="parameter">name</replaceable> ON <
   <title>Description</title>
 
   <para>
-   <command>DROP POLICY</command> removes the specified row-security policy
-   from the table.  Note that if the last policy is removed for a table and
-   the table still has ROW POLICY enabled via <command>ALTER TABLE</command>,
-   then the default-deny policy will be used.  <command>ALTER TABLE</command>
-   can be used to disable row security for a table using
+   <command>DROP POLICY</command> removes the specified policy from the table.
+   Note that if the last policy is removed for a table and the table still has
+   row level security enabled via <command>ALTER TABLE</command>, then the
+   default-deny policy will be used.  <command>ALTER TABLE</command> can be used
+   to disable row level security for a table using
    <literal>DISABLE ROW SECURITY</literal>, whether policies for the table
    exist or not.
   </para>
@@ -80,8 +80,8 @@ DROP POLICY [ IF EXISTS ] <replaceable class="parameter">name</replaceable> ON <
   <title>Examples</title>
 
   <para>
-   To drop the row-security policy called <literal>p1</literal> on the
-   table named <literal>my_table</literal>:
+   To drop the policy called <literal>p1</literal> on the table named
+   <literal>my_table</literal>:
 
    <programlisting>
     DROP POLICY p1 ON my_table;
index 66b3cc9bf2f48d3140040f1f2650f70ac967a90b..973db7435bc58d395a60a18b11a1f6e483cc9bd2 100644 (file)
@@ -2133,7 +2133,7 @@ SELECT * FROM phone_number WHERE tricky(person, phone);
 </para>
 
 <para>
-    When it is necessary for a view to provide row-level security, the
+    When it is necessary for a view to provide row level security, the
     <literal>security_barrier</literal> attribute should be applied to
     the view.  This prevents maliciously-chosen functions and operators from
     being invoked on rows until after the view has done its work.  For
index b257b02ff5c198d56d00dff9376ac6adf02fec7d..a403c643600b82201ff6e8f0f7e310db6054839a 100644 (file)
@@ -39,7 +39,7 @@ POSTGRES_BKI_SRCS = $(addprefix $(top_srcdir)/src/include/catalog/,\
    pg_ts_config.h pg_ts_config_map.h pg_ts_dict.h \
    pg_ts_parser.h pg_ts_template.h pg_extension.h \
    pg_foreign_data_wrapper.h pg_foreign_server.h pg_user_mapping.h \
-   pg_foreign_table.h pg_rowsecurity.h \
+   pg_foreign_table.h pg_policy.h \
    pg_default_acl.h pg_seclabel.h pg_shseclabel.h pg_collation.h pg_range.h \
    toasting.h indexing.h \
     )
index f338acf827d6c7976829f6dfaac215250fcbd96d..8ba5123c101a51e0dde74a49971477c2640932de 100644 (file)
@@ -43,9 +43,9 @@
 #include "catalog/pg_opclass.h"
 #include "catalog/pg_operator.h"
 #include "catalog/pg_opfamily.h"
+#include "catalog/pg_policy.h"
 #include "catalog/pg_proc.h"
 #include "catalog/pg_rewrite.h"
-#include "catalog/pg_rowsecurity.h"
 #include "catalog/pg_tablespace.h"
 #include "catalog/pg_trigger.h"
 #include "catalog/pg_ts_config.h"
@@ -156,7 +156,8 @@ static const Oid object_classes[MAX_OCLASS] = {
    UserMappingRelationId,      /* OCLASS_USER_MAPPING */
    DefaultAclRelationId,       /* OCLASS_DEFACL */
    ExtensionRelationId,        /* OCLASS_EXTENSION */
-   EventTriggerRelationId      /* OCLASS_EVENT_TRIGGER */
+   EventTriggerRelationId,     /* OCLASS_EVENT_TRIGGER */
+   PolicyRelationId            /* OCLASS_POLICY */
 };
 
 
@@ -1251,7 +1252,7 @@ doDeletion(const ObjectAddress *object, int flags)
            RemoveEventTriggerById(object->objectId);
            break;
 
-       case OCLASS_ROWSECURITY:
+       case OCLASS_POLICY:
            RemovePolicyById(object->objectId);
            break;
 
@@ -2361,8 +2362,8 @@ getObjectClass(const ObjectAddress *object)
        case EventTriggerRelationId:
            return OCLASS_EVENT_TRIGGER;
 
-       case RowSecurityRelationId:
-           return OCLASS_ROWSECURITY;
+       case PolicyRelationId:
+           return OCLASS_POLICY;
    }
 
    /* shouldn't get here */
index b69b75bcc2e1e53b0f6f7bff51dd970fe075b88c..e261307e9d5fbce0943c2572505a5d45a09cc55a 100644 (file)
@@ -42,7 +42,7 @@
 #include "catalog/pg_opfamily.h"
 #include "catalog/pg_operator.h"
 #include "catalog/pg_proc.h"
-#include "catalog/pg_rowsecurity.h"
+#include "catalog/pg_policy.h"
 #include "catalog/pg_rewrite.h"
 #include "catalog/pg_tablespace.h"
 #include "catalog/pg_trigger.h"
@@ -346,11 +346,11 @@ static const ObjectPropertyType ObjectProperty[] =
        false
    },
    {
-       RowSecurityRelationId,
-       RowSecurityOidIndexId,
+       PolicyRelationId,
+       PolicyOidIndexId,
        -1,
        -1,
-       Anum_pg_rowsecurity_rsecpolname,
+       Anum_pg_policy_polname,
        InvalidAttrNumber,
        InvalidAttrNumber,
        InvalidAttrNumber,
@@ -998,7 +998,7 @@ get_object_address_relobject(ObjectType objtype, List *objname,
                address.objectSubId = 0;
                break;
            case OBJECT_POLICY:
-               address.classId = RowSecurityRelationId;
+               address.classId = PolicyRelationId;
                address.objectId = relation ?
                    get_relation_policy_oid(reloid, depname, missing_ok) :
                    InvalidOid;
@@ -2189,38 +2189,38 @@ getObjectDescription(const ObjectAddress *object)
                break;
            }
 
-       case OCLASS_ROWSECURITY:
+       case OCLASS_POLICY:
            {
-               Relation    rsec_rel;
+               Relation    policy_rel;
                ScanKeyData skey[1];
                SysScanDesc sscan;
                HeapTuple   tuple;
-               Form_pg_rowsecurity form_rsec;
+               Form_pg_policy form_policy;
 
-               rsec_rel = heap_open(RowSecurityRelationId, AccessShareLock);
+               policy_rel = heap_open(PolicyRelationId, AccessShareLock);
 
                ScanKeyInit(&skey[0],
                            ObjectIdAttributeNumber,
                            BTEqualStrategyNumber, F_OIDEQ,
                            ObjectIdGetDatum(object->objectId));
 
-               sscan = systable_beginscan(rsec_rel, RowSecurityOidIndexId,
+               sscan = systable_beginscan(policy_rel, PolicyOidIndexId,
                                           true, NULL, 1, skey);
 
                tuple = systable_getnext(sscan);
 
                if (!HeapTupleIsValid(tuple))
-                   elog(ERROR, "cache lookup failed for row-security relation %u",
+                   elog(ERROR, "cache lookup failed for policy %u",
                         object->objectId);
 
-               form_rsec = (Form_pg_rowsecurity) GETSTRUCT(tuple);
+               form_policy = (Form_pg_policy) GETSTRUCT(tuple);
 
                appendStringInfo(&buffer, _("policy %s on "),
-                                NameStr(form_rsec->rsecpolname));
-               getRelationDescription(&buffer, form_rsec->rsecrelid);
+                                NameStr(form_policy->polname));
+               getRelationDescription(&buffer, form_policy->polrelid);
 
                systable_endscan(sscan);
-               heap_close(rsec_rel, AccessShareLock);
+               heap_close(policy_rel, AccessShareLock);
                break;
            }
 
@@ -2635,6 +2635,10 @@ getObjectTypeDescription(const ObjectAddress *object)
            appendStringInfoString(&buffer, "event trigger");
            break;
 
+       case OCLASS_POLICY:
+           appendStringInfoString(&buffer, "policy");
+           break;
+
        default:
            appendStringInfo(&buffer, "unrecognized %u", object->classId);
            break;
@@ -3119,6 +3123,30 @@ getObjectIdentity(const ObjectAddress *object)
                break;
            }
 
+       case OCLASS_POLICY:
+           {
+               Relation    polDesc;
+               HeapTuple   tup;
+               Form_pg_policy policy;
+
+               polDesc = heap_open(PolicyRelationId, AccessShareLock);
+
+               tup = get_catalog_object_by_oid(polDesc, object->objectId);
+
+               if (!HeapTupleIsValid(tup))
+                   elog(ERROR, "could not find tuple for policy %u",
+                        object->objectId);
+
+               policy = (Form_pg_policy) GETSTRUCT(tup);
+
+               appendStringInfo(&buffer, "%s on ",
+                                quote_identifier(NameStr(policy->polname)));
+               getRelationIdentity(&buffer, policy->polrelid);
+
+               heap_close(polDesc, AccessShareLock);
+               break;
+           }
+
        case OCLASS_SCHEMA:
            {
                char       *nspname;
index a819952c75dec233d01a823925d0ce243e50e3e2..22b8ceef622603cd4eae9a334cc8305b9e3dad6a 100644 (file)
@@ -67,30 +67,30 @@ CREATE VIEW pg_policies AS
     SELECT
         N.nspname AS schemaname,
         C.relname AS tablename,
-        rs.rsecpolname AS policyname,
+        pol.polname AS policyname,
         CASE
-            WHEN rs.rsecroles = '{0}' THEN
+            WHEN pol.polroles = '{0}' THEN
                 string_to_array('public', '')
             ELSE
                 ARRAY
                 (
                     SELECT rolname
                     FROM pg_catalog.pg_authid
-                    WHERE oid = ANY (rs.rsecroles) ORDER BY 1
+                    WHERE oid = ANY (pol.polroles) ORDER BY 1
                 )
         END AS roles,
-        CASE WHEN rs.rseccmd IS NULL THEN 'ALL' ELSE
-            CASE rs.rseccmd
+        CASE WHEN pol.polcmd IS NULL THEN 'ALL' ELSE
+            CASE pol.polcmd
                 WHEN 'r' THEN 'SELECT'
                 WHEN 'a' THEN 'INSERT'
                 WHEN 'u' THEN 'UPDATE'
                 WHEN 'd' THEN 'DELETE'
             END
         END AS cmd,
-        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
-    JOIN pg_catalog.pg_class C ON (C.oid = rs.rsecrelid)
+        pg_catalog.pg_get_expr(pol.polqual, pol.polrelid) AS qual,
+        pg_catalog.pg_get_expr(pol.polwithcheck, pol.polrelid) AS with_check
+    FROM pg_catalog.pg_policy pol
+    JOIN pg_catalog.pg_class C ON (C.oid = pol.polrelid)
     LEFT JOIN pg_catalog.pg_namespace N ON (N.oid = C.relnamespace);
 
 CREATE VIEW pg_rules AS
index 83e8f891222a3137934557e4a5f67ce8d059f8ee..08abe141f4169f98d671fe22fc3be1151b48daa0 100644 (file)
@@ -282,12 +282,13 @@ static const char BinarySignature[11] = "PGCOPY\n\377\r\n\0";
 
 /* non-export function prototypes */
 static CopyState BeginCopy(bool is_from, Relation rel, Node *raw_query,
-         const char *queryString, List *attnamelist, List *options);
+         const char *queryString, const Oid queryRelId, List *attnamelist,
+         List *options);
 static void EndCopy(CopyState cstate);
 static void ClosePipeToProgram(CopyState cstate);
 static CopyState BeginCopyTo(Relation rel, Node *query, const char *queryString,
-           const char *filename, bool is_program, List *attnamelist,
-           List *options);
+           const Oid queryRelId, const char *filename, bool is_program,
+           List *attnamelist, List *options);
 static void EndCopyTo(CopyState cstate);
 static uint64 DoCopyTo(CopyState cstate);
 static uint64 CopyTo(CopyState cstate);
@@ -843,7 +844,7 @@ DoCopy(const CopyStmt *stmt, const char *queryString, uint64 *processed)
        ExecCheckRTPerms(list_make1(rte), true);
 
        /*
-        * Permission check for row security.
+        * Permission check for row security policies.
         *
         * check_enable_rls will ereport(ERROR) if the user has requested
         * something invalid and will otherwise indicate if we should enable
@@ -866,7 +867,7 @@ DoCopy(const CopyStmt *stmt, const char *queryString, uint64 *processed)
            if (is_from)
                ereport(ERROR,
                        (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-                        errmsg("COPY FROM not supported with row security."),
+                        errmsg("COPY FROM not supported with row level security."),
                         errhint("Use direct INSERT statements instead.")));
 
            /* Build target list */
@@ -886,7 +887,7 @@ DoCopy(const CopyStmt *stmt, const char *queryString, uint64 *processed)
            target->location = 1;
 
            /* Build FROM clause */
-           from = makeRangeVar(NULL, RelationGetRelationName(rel), 1);
+           from = stmt->relation;
 
            /* Build query */
            select = makeNode(SelectStmt);
@@ -895,8 +896,6 @@ DoCopy(const CopyStmt *stmt, const char *queryString, uint64 *processed)
 
            query = (Node*) select;
 
-           relid = InvalidOid;
-
            /* Close the handle to the relation as it is no longer needed. */
            heap_close(rel, (is_from ? RowExclusiveLock : AccessShareLock));
            rel = NULL;
@@ -926,7 +925,7 @@ DoCopy(const CopyStmt *stmt, const char *queryString, uint64 *processed)
    }
    else
    {
-       cstate = BeginCopyTo(rel, query, queryString,
+       cstate = BeginCopyTo(rel, query, queryString, relid,
                             stmt->filename, stmt->is_program,
                             stmt->attlist, stmt->options);
        *processed = DoCopyTo(cstate);  /* copy from database to file */
@@ -1304,6 +1303,7 @@ BeginCopy(bool is_from,
          Relation rel,
          Node *raw_query,
          const char *queryString,
+         const Oid queryRelId,
          List *attnamelist,
          List *options)
 {
@@ -1394,6 +1394,30 @@ BeginCopy(bool is_from,
        /* plan the query */
        plan = planner(query, 0, NULL);
 
+       /*
+        * If we were passed in a relid, make sure we got the same one back
+        * after planning out the query.  It's possible that it changed between
+        * when we checked the policies on the table and decided to use a query
+        * and now.
+        */
+       if (queryRelId != InvalidOid)
+       {
+           Oid relid = linitial_oid(plan->relationOids);
+
+           /*
+            * There should only be one relationOid in this case, since we will
+            * only get here when we have changed the command for the user from
+            * a "COPY relation TO" to "COPY (SELECT * FROM relation) TO", to
+            * allow row level security policies to be applied.
+            */
+           Assert(list_length(plan->relationOids) == 1);
+
+           if (relid != queryRelId)
+               ereport(ERROR,
+                       (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+                        errmsg("relation referenced by COPY statement has changed")));
+       }
+
        /*
         * Use a snapshot with an updated command ID to ensure this query sees
         * results of any previously executed queries.
@@ -1595,6 +1619,7 @@ static CopyState
 BeginCopyTo(Relation rel,
            Node *query,
            const char *queryString,
+           const Oid queryRelId,
            const char *filename,
            bool is_program,
            List *attnamelist,
@@ -1636,7 +1661,8 @@ BeginCopyTo(Relation rel,
                            RelationGetRelationName(rel))));
    }
 
-   cstate = BeginCopy(false, rel, query, queryString, attnamelist, options);
+   cstate = BeginCopy(false, rel, query, queryString, queryRelId, attnamelist,
+                      options);
    oldcontext = MemoryContextSwitchTo(cstate->copycontext);
 
    if (pipe)
@@ -2565,7 +2591,7 @@ BeginCopyFrom(Relation rel,
    MemoryContext oldcontext;
    bool        volatile_defexprs;
 
-   cstate = BeginCopy(true, rel, NULL, NULL, attnamelist, options);
+   cstate = BeginCopy(true, rel, NULL, NULL, InvalidOid, attnamelist, options);
    oldcontext = MemoryContextSwitchTo(cstate->copycontext);
 
    /* Initialize state variables */
index 1b8c94bcfdf91668a42eb317ac33c1ba8fd8c48e..6a3002f5268e33cf349fca2a4934b0916bad1aec 100644 (file)
@@ -997,7 +997,7 @@ EventTriggerSupportsObjectClass(ObjectClass objclass)
        case OCLASS_USER_MAPPING:
        case OCLASS_DEFACL:
        case OCLASS_EXTENSION:
-       case OCLASS_ROWSECURITY:
+       case OCLASS_POLICY:
            return true;
 
        case MAX_OCLASS:
index 470db5705cc57fa7838fee543d2e3aafbb80444f..d3a59aa3567c3c42e588247caedb0829d209f3d1 100644 (file)
@@ -904,9 +904,9 @@ CreateFunction(CreateFunctionStmt *stmt, const char *queryString)
    ReleaseSysCache(languageTuple);
 
    /*
-    * Only superuser is allowed to create leakproof functions because it
-    * possibly allows unprivileged users to reference invisible tuples to be
-    * filtered out using views for row-level security.
+    * Only superuser is allowed to create leakproof functions because leakproof
+    * functions can see tuples which have not yet been filtered out by security
+    * barrier views or row level security policies.
     */
    if (isLeakProof && !superuser())
        ereport(ERROR,
index 10d230ef431c5deb96161938c3be763899203b3a..290c826a68040d10b2db7b3a1da2543df7f7a789 100644 (file)
@@ -22,7 +22,7 @@
 #include "catalog/indexing.h"
 #include "catalog/namespace.h"
 #include "catalog/objectaccess.h"
-#include "catalog/pg_rowsecurity.h"
+#include "catalog/pg_policy.h"
 #include "catalog/pg_type.h"
 #include "commands/policy.h"
 #include "miscadmin.h"
@@ -46,8 +46,8 @@
 
 static void RangeVarCallbackForPolicy(const RangeVar *rv,
                Oid relid, Oid oldrelid, void *arg);
-static char parse_row_security_command(const char *cmd_name);
-static ArrayType* rls_role_list_to_array(List *roles);
+static char parse_policy_command(const char *cmd_name);
+static ArrayType* policy_role_list_to_array(List *roles);
 
 /*
  * Callback to RangeVarGetRelidExtended().
@@ -95,7 +95,7 @@ RangeVarCallbackForPolicy(const RangeVar *rv, Oid relid, Oid oldrelid,
 }
 
 /*
- * parse_row_security_command -
+ * parse_policy_command -
  *   helper function to convert full command strings to their char
  *   representation.
  *
@@ -104,7 +104,7 @@ RangeVarCallbackForPolicy(const RangeVar *rv, Oid relid, Oid oldrelid,
  *
  */
 static char
-parse_row_security_command(const char *cmd_name)
+parse_policy_command(const char *cmd_name)
 {
    char cmd;
 
@@ -128,7 +128,7 @@ parse_row_security_command(const char *cmd_name)
 }
 
 /*
- * rls_role_list_to_array
+ * policy_role_list_to_array
  *   helper function to convert a list of role names in to an array of
  *   role ids.
  *
@@ -138,7 +138,7 @@ parse_row_security_command(const char *cmd_name)
  * roles - the list of role names to convert.
  */
 static ArrayType *
-rls_role_list_to_array(List *roles)
+policy_role_list_to_array(List *roles)
 {
    ArrayType  *role_ids;
    Datum      *temp_array;
@@ -190,7 +190,7 @@ rls_role_list_to_array(List *roles)
 }
 
 /*
- * Load row-security policy from the catalog, and keep it in
+ * Load row security policy from the catalog, and keep it in
  * the relation cache.
  */
 void
@@ -204,14 +204,14 @@ RelationBuildRowSecurity(Relation relation)
    MemoryContext       rscxt = NULL;
    RowSecurityDesc    *rsdesc = NULL;
 
-   catalog = heap_open(RowSecurityRelationId, AccessShareLock);
+   catalog = heap_open(PolicyRelationId, AccessShareLock);
 
    ScanKeyInit(&skey,
-               Anum_pg_rowsecurity_rsecrelid,
+               Anum_pg_policy_polrelid,
                BTEqualStrategyNumber, F_OIDEQ,
                ObjectIdGetDatum(RelationGetRelid(relation)));
 
-   sscan = systable_beginscan(catalog, RowSecurityRelidPolnameIndexId, true,
+   sscan = systable_beginscan(catalog, PolicyPolrelidPolnameIndexId, true,
                               NULL, 1, &skey);
    PG_TRY();
    {
@@ -221,7 +221,7 @@ RelationBuildRowSecurity(Relation relation)
         * default-deny policy is created.
         */
        rscxt = AllocSetContextCreate(CacheMemoryContext,
-                                     "Row-security descriptor",
+                                     "row security descriptor",
                                      ALLOCSET_SMALL_MINSIZE,
                                      ALLOCSET_SMALL_INITSIZE,
                                      ALLOCSET_SMALL_MAXSIZE);
@@ -229,7 +229,7 @@ RelationBuildRowSecurity(Relation relation)
        rsdesc->rscxt = rscxt;
 
        /*
-        * Loop through the row-level security entries for this relation, if
+        * Loop through the row level security policies for this relation, if
         * any.
         */
        while (HeapTupleIsValid(tuple = systable_getnext(sscan)))
@@ -249,7 +249,7 @@ RelationBuildRowSecurity(Relation relation)
            oldcxt = MemoryContextSwitchTo(rscxt);
 
            /* Get policy command */
-           value_datum = heap_getattr(tuple, Anum_pg_rowsecurity_rseccmd,
+           value_datum = heap_getattr(tuple, Anum_pg_policy_polcmd,
                                 RelationGetDescr(catalog), &isnull);
            if (isnull)
                cmd_value = 0;
@@ -257,19 +257,19 @@ RelationBuildRowSecurity(Relation relation)
                cmd_value = DatumGetChar(value_datum);
 
            /* Get policy name */
-           value_datum = heap_getattr(tuple, Anum_pg_rowsecurity_rsecpolname,
+           value_datum = heap_getattr(tuple, Anum_pg_policy_polname,
                                        RelationGetDescr(catalog), &isnull);
            Assert(!isnull);
            policy_name_value = DatumGetCString(value_datum);
 
            /* Get policy roles */
-           value_datum = heap_getattr(tuple, Anum_pg_rowsecurity_rsecroles,
+           value_datum = heap_getattr(tuple, Anum_pg_policy_polroles,
                                        RelationGetDescr(catalog), &isnull);
            Assert(!isnull);
            roles = DatumGetArrayTypeP(value_datum);
 
            /* Get policy qual */
-           value_datum = heap_getattr(tuple, Anum_pg_rowsecurity_rsecqual,
+           value_datum = heap_getattr(tuple, Anum_pg_policy_polqual,
                                 RelationGetDescr(catalog), &isnull);
            if (!isnull)
            {
@@ -280,7 +280,7 @@ RelationBuildRowSecurity(Relation relation)
                qual_expr = NULL;
 
            /* Get WITH CHECK qual */
-           value_datum = heap_getattr(tuple, Anum_pg_rowsecurity_rsecwithcheck,
+           value_datum = heap_getattr(tuple, Anum_pg_policy_polwithcheck,
                                        RelationGetDescr(catalog), &isnull);
 
            if (!isnull)
@@ -295,7 +295,7 @@ RelationBuildRowSecurity(Relation relation)
 
            policy = palloc0(sizeof(RowSecurityPolicy));
            policy->policy_name = policy_name_value;
-           policy->rsecid = policy_id;
+           policy->policy_id = policy_id;
            policy->cmd = cmd_value;
            policy->roles = roles;
            policy->qual = copyObject(qual_expr);
@@ -317,7 +317,7 @@ RelationBuildRowSecurity(Relation relation)
        /*
         * Check if no policies were added
         *
-        * If no policies exist in pg_rowsecurity for this relation, then we
+        * If no policies exist in pg_policy for this relation, then we
         * need to create a single default-deny policy.  We use InvalidOid for
         * the Oid to indicate that this is the default-deny policy (we may
         * decide to ignore the default policy if an extension adds policies).
@@ -333,7 +333,7 @@ RelationBuildRowSecurity(Relation relation)
 
            policy = palloc0(sizeof(RowSecurityPolicy));
            policy->policy_name = pstrdup("default-deny policy");
-           policy->rsecid = InvalidOid;
+           policy->policy_id = InvalidOid;
            policy->cmd = '\0';
            policy->roles = construct_array(&role, 1, OIDOID, sizeof(Oid), true,
                                            'i');
@@ -364,22 +364,22 @@ RelationBuildRowSecurity(Relation relation)
 
 /*
  * RemovePolicyById -
- *   remove a row-security policy by its OID.  If a policy does not exist with
- *   the provided oid, then an error is raised.
+ *   remove a policy by its OID.  If a policy does not exist with the provided
+ *   oid, then an error is raised.
  *
- * policy_id - the oid of the row-security policy.
+ * policy_id - the oid of the policy.
  */
 void
 RemovePolicyById(Oid policy_id)
 {
-   Relation    pg_rowsecurity_rel;
+   Relation    pg_policy_rel;
    SysScanDesc sscan;
    ScanKeyData skey[1];
    HeapTuple   tuple;
    Oid         relid;
    Relation    rel;
 
-   pg_rowsecurity_rel = heap_open(RowSecurityRelationId, RowExclusiveLock);
+   pg_policy_rel = heap_open(PolicyRelationId, RowExclusiveLock);
 
    /*
     * Find the policy to delete.
@@ -389,19 +389,19 @@ RemovePolicyById(Oid policy_id)
                BTEqualStrategyNumber, F_OIDEQ,
                ObjectIdGetDatum(policy_id));
 
-   sscan = systable_beginscan(pg_rowsecurity_rel, RowSecurityOidIndexId, true,
+   sscan = systable_beginscan(pg_policy_rel, PolicyOidIndexId, true,
                               NULL, 1, skey);
 
    tuple = systable_getnext(sscan);
 
    /* If the policy exists, then remove it, otherwise raise an error. */
    if (!HeapTupleIsValid(tuple))
-       elog(ERROR, "could not find tuple for row-security %u", policy_id);
+       elog(ERROR, "could not find tuple for policy %u", policy_id);
 
    /*
     * Open and exclusive-lock the relation the policy belong to.
     */
-   relid = ((Form_pg_rowsecurity) GETSTRUCT(tuple))->rsecrelid;
+   relid = ((Form_pg_policy) GETSTRUCT(tuple))->polrelid;
 
    rel = heap_open(relid, AccessExclusiveLock);
    if (rel->rd_rel->relkind != RELKIND_RELATION)
@@ -416,7 +416,7 @@ RemovePolicyById(Oid policy_id)
                 errmsg("permission denied: \"%s\" is a system catalog",
                        RelationGetRelationName(rel))));
 
-   simple_heap_delete(pg_rowsecurity_rel, &tuple->t_self);
+   simple_heap_delete(pg_policy_rel, &tuple->t_self);
 
    systable_endscan(sscan);
    heap_close(rel, AccessExclusiveLock);
@@ -424,9 +424,8 @@ RemovePolicyById(Oid policy_id)
    /*
     * Note that, unlike some of the other flags in pg_class, relrowsecurity
     * is not just an indication of if policies exist.  When relrowsecurity
-    * is set (which can be done directly by the user or indirectly by creating
-    * a policy on the table), then all access to the relation must be through
-    * a policy.  If no policy is defined for the relation then a default-deny
+    * is set by a user, then all access to the relation must be through a
+    * policy.  If no policy is defined for the relation then a default-deny
     * policy is created and all records are filtered (except for queries from
     * the owner).
     */
@@ -434,7 +433,7 @@ RemovePolicyById(Oid policy_id)
    CacheInvalidateRelcache(rel);
 
    /* Clean up */
-   heap_close(pg_rowsecurity_rel, RowExclusiveLock);
+   heap_close(pg_policy_rel, RowExclusiveLock);
 }
 
 /*
@@ -446,11 +445,11 @@ RemovePolicyById(Oid policy_id)
 Oid
 CreatePolicy(CreatePolicyStmt *stmt)
 {
-   Relation        pg_rowsecurity_rel;
-   Oid             rowsec_id;
+   Relation        pg_policy_rel;
+   Oid             policy_id;
    Relation        target_table;
    Oid             table_id;
-   char            rseccmd;
+   char            polcmd;
    ArrayType      *role_ids;
    ParseState     *qual_pstate;
    ParseState     *with_check_pstate;
@@ -459,19 +458,19 @@ CreatePolicy(CreatePolicyStmt *stmt)
    Node           *with_check_qual;
    ScanKeyData     skey[2];
    SysScanDesc     sscan;
-   HeapTuple       rsec_tuple;
-   Datum           values[Natts_pg_rowsecurity];
-   bool            isnull[Natts_pg_rowsecurity];
+   HeapTuple       policy_tuple;
+   Datum           values[Natts_pg_policy];
+   bool            isnull[Natts_pg_policy];
    ObjectAddress   target;
    ObjectAddress   myself;
 
    /* Parse command */
-   rseccmd = parse_row_security_command(stmt->cmd);
+   polcmd = parse_policy_command(stmt->cmd);
 
    /*
     * If the command is SELECT or DELETE then WITH CHECK should be NULL.
     */
-   if ((rseccmd == ACL_SELECT_CHR || rseccmd == ACL_DELETE_CHR)
+   if ((polcmd == ACL_SELECT_CHR || polcmd == ACL_DELETE_CHR)
        && stmt->with_check != NULL)
        ereport(ERROR,
                (errcode(ERRCODE_SYNTAX_ERROR),
@@ -481,14 +480,14 @@ CreatePolicy(CreatePolicyStmt *stmt)
     * If the command is INSERT then WITH CHECK should be the only expression
     * provided.
     */
-   if (rseccmd == ACL_INSERT_CHR && stmt->qual != NULL)
+   if (polcmd == ACL_INSERT_CHR && stmt->qual != NULL)
        ereport(ERROR,
                (errcode(ERRCODE_SYNTAX_ERROR),
                 errmsg("only WITH CHECK expression allowed for INSERT")));
 
 
    /* Collect role ids */
-   role_ids = rls_role_list_to_array(stmt->roles);
+   role_ids = policy_role_list_to_array(stmt->roles);
 
    /* Parse the supplied clause */
    qual_pstate = make_parsestate(NULL);
@@ -527,74 +526,74 @@ CreatePolicy(CreatePolicyStmt *stmt)
                                EXPR_KIND_WHERE,
                                "POLICY");
 
-   /* Open pg_rowsecurity catalog */
-   pg_rowsecurity_rel = heap_open(RowSecurityRelationId, RowExclusiveLock);
+   /* Open pg_policy catalog */
+   pg_policy_rel = heap_open(PolicyRelationId, RowExclusiveLock);
 
-   /* Set key - row security relation id. */
+   /* Set key - policy's relation id. */
    ScanKeyInit(&skey[0],
-               Anum_pg_rowsecurity_rsecrelid,
+               Anum_pg_policy_polrelid,
                BTEqualStrategyNumber, F_OIDEQ,
                ObjectIdGetDatum(table_id));
 
-   /* Set key - row security policy name. */
+   /* Set key - policy's name. */
    ScanKeyInit(&skey[1],
-               Anum_pg_rowsecurity_rsecpolname,
+               Anum_pg_policy_polname,
                BTEqualStrategyNumber, F_NAMEEQ,
                CStringGetDatum(stmt->policy_name));
 
-   sscan = systable_beginscan(pg_rowsecurity_rel,
-                              RowSecurityRelidPolnameIndexId, true, NULL, 2,
+   sscan = systable_beginscan(pg_policy_rel,
+                              PolicyPolrelidPolnameIndexId, true, NULL, 2,
                               skey);
 
-   rsec_tuple = systable_getnext(sscan);
+   policy_tuple = systable_getnext(sscan);
 
    /* Complain if the policy name already exists for the table */
-   if (HeapTupleIsValid(rsec_tuple))
+   if (HeapTupleIsValid(policy_tuple))
        ereport(ERROR,
                (errcode(ERRCODE_DUPLICATE_OBJECT),
                 errmsg("policy \"%s\" for relation \"%s\" already exists",
                 stmt->policy_name, RelationGetRelationName(target_table))));
 
-   values[Anum_pg_rowsecurity_rsecrelid - 1] = ObjectIdGetDatum(table_id);
-   values[Anum_pg_rowsecurity_rsecpolname - 1]
+   values[Anum_pg_policy_polrelid - 1] = ObjectIdGetDatum(table_id);
+   values[Anum_pg_policy_polname - 1]
        = DirectFunctionCall1(namein, CStringGetDatum(stmt->policy_name));
 
-   if (rseccmd)
-       values[Anum_pg_rowsecurity_rseccmd - 1] = CharGetDatum(rseccmd);
+   if (polcmd)
+       values[Anum_pg_policy_polcmd - 1] = CharGetDatum(polcmd);
    else
-       isnull[Anum_pg_rowsecurity_rseccmd - 1] = true;
+       isnull[Anum_pg_policy_polcmd - 1] = true;
 
-   values[Anum_pg_rowsecurity_rsecroles - 1] = PointerGetDatum(role_ids);
+   values[Anum_pg_policy_polroles - 1] = PointerGetDatum(role_ids);
 
    /* Add qual if present. */
    if (qual)
-       values[Anum_pg_rowsecurity_rsecqual - 1]
+       values[Anum_pg_policy_polqual - 1]
            = CStringGetTextDatum(nodeToString(qual));
    else
-       isnull[Anum_pg_rowsecurity_rsecqual - 1] = true;
+       isnull[Anum_pg_policy_polqual - 1] = true;
 
    /* Add WITH CHECK qual if present */
    if (with_check_qual)
-       values[Anum_pg_rowsecurity_rsecwithcheck - 1]
+       values[Anum_pg_policy_polwithcheck - 1]
            = CStringGetTextDatum(nodeToString(with_check_qual));
    else
-       isnull[Anum_pg_rowsecurity_rsecwithcheck - 1] = true;
+       isnull[Anum_pg_policy_polwithcheck - 1] = true;
 
-   rsec_tuple = heap_form_tuple(RelationGetDescr(pg_rowsecurity_rel), values,
-                                isnull);
+   policy_tuple = heap_form_tuple(RelationGetDescr(pg_policy_rel), values,
+                                  isnull);
 
-   rowsec_id = simple_heap_insert(pg_rowsecurity_rel, rsec_tuple);
+   policy_id = simple_heap_insert(pg_policy_rel, policy_tuple);
 
    /* Update Indexes */
-   CatalogUpdateIndexes(pg_rowsecurity_rel, rsec_tuple);
+   CatalogUpdateIndexes(pg_policy_rel, policy_tuple);
 
    /* Record Dependencies */
    target.classId = RelationRelationId;
    target.objectId = table_id;
    target.objectSubId = 0;
 
-   myself.classId = RowSecurityRelationId;
-   myself.objectId = rowsec_id;
+   myself.classId = PolicyRelationId;
+   myself.objectId = policy_id;
    myself.objectSubId = 0;
 
    recordDependencyOn(&myself, &target, DEPENDENCY_AUTO);
@@ -609,14 +608,14 @@ CreatePolicy(CreatePolicyStmt *stmt)
    CacheInvalidateRelcache(target_table);
 
    /* Clean up. */
-   heap_freetuple(rsec_tuple);
+   heap_freetuple(policy_tuple);
    free_parsestate(qual_pstate);
    free_parsestate(with_check_pstate);
    systable_endscan(sscan);
    relation_close(target_table, NoLock);
-   heap_close(pg_rowsecurity_rel, RowExclusiveLock);
+   heap_close(pg_policy_rel, RowExclusiveLock);
 
-   return rowsec_id;
+   return policy_id;
 }
 
 /*
@@ -628,8 +627,8 @@ CreatePolicy(CreatePolicyStmt *stmt)
 Oid
 AlterPolicy(AlterPolicyStmt *stmt)
 {
-   Relation        pg_rowsecurity_rel;
-   Oid             rowsec_id;
+   Relation        pg_policy_rel;
+   Oid             policy_id;
    Relation        target_table;
    Oid             table_id;
    ArrayType      *role_ids = NULL;
@@ -639,20 +638,20 @@ AlterPolicy(AlterPolicyStmt *stmt)
    Node           *with_check_qual = NULL;
    ScanKeyData     skey[2];
    SysScanDesc     sscan;
-   HeapTuple       rsec_tuple;
+   HeapTuple       policy_tuple;
    HeapTuple       new_tuple;
-   Datum           values[Natts_pg_rowsecurity];
-   bool            isnull[Natts_pg_rowsecurity];
-   bool            replaces[Natts_pg_rowsecurity];
+   Datum           values[Natts_pg_policy];
+   bool            isnull[Natts_pg_policy];
+   bool            replaces[Natts_pg_policy];
    ObjectAddress   target;
    ObjectAddress   myself;
    Datum           cmd_datum;
-   char            rseccmd;
-   bool            rseccmd_isnull;
+   char            polcmd;
+   bool            polcmd_isnull;
 
    /* Parse role_ids */
    if (stmt->roles != NULL)
-       role_ids = rls_role_list_to_array(stmt->roles);
+       role_ids = policy_role_list_to_array(stmt->roles);
 
    /* Get id of table.  Also handles permissions checks. */
    table_id = RangeVarGetRelidExtended(stmt->table, AccessExclusiveLock,
@@ -662,7 +661,7 @@ AlterPolicy(AlterPolicyStmt *stmt)
 
    target_table = relation_open(table_id, NoLock);
 
-   /* Parse the row-security clause */
+   /* Parse the using policy clause */
    if (stmt->qual)
    {
        RangeTblEntry  *rte;
@@ -675,13 +674,13 @@ AlterPolicy(AlterPolicyStmt *stmt)
 
        qual = transformWhereClause(qual_pstate, copyObject(stmt->qual),
                                    EXPR_KIND_WHERE,
-                                   "ROW SECURITY");
+                                   "POLICY");
 
        qual_parse_rtable = qual_pstate->p_rtable;
        free_parsestate(qual_pstate);
    }
 
-   /* Parse the with-check row-security clause */
+   /* Parse the with-check policy clause */
    if (stmt->with_check)
    {
        RangeTblEntry  *rte;
@@ -695,7 +694,7 @@ AlterPolicy(AlterPolicyStmt *stmt)
        with_check_qual = transformWhereClause(with_check_pstate,
                                               copyObject(stmt->with_check),
                                               EXPR_KIND_WHERE,
-                                              "ROW SECURITY");
+                                              "POLICY");
 
        with_check_parse_rtable = with_check_pstate->p_rtable;
        free_parsestate(with_check_pstate);
@@ -707,28 +706,28 @@ AlterPolicy(AlterPolicyStmt *stmt)
    memset(isnull,   0, sizeof(isnull));
 
    /* Find policy to update. */
-   pg_rowsecurity_rel = heap_open(RowSecurityRelationId, RowExclusiveLock);
+   pg_policy_rel = heap_open(PolicyRelationId, RowExclusiveLock);
 
-   /* Set key - row security relation id. */
+   /* Set key - policy's relation id. */
    ScanKeyInit(&skey[0],
-               Anum_pg_rowsecurity_rsecrelid,
+               Anum_pg_policy_polrelid,
                BTEqualStrategyNumber, F_OIDEQ,
                ObjectIdGetDatum(table_id));
 
-   /* Set key - row security policy name. */
+   /* Set key - policy's name. */
    ScanKeyInit(&skey[1],
-               Anum_pg_rowsecurity_rsecpolname,
+               Anum_pg_policy_polname,
                BTEqualStrategyNumber, F_NAMEEQ,
                CStringGetDatum(stmt->policy_name));
 
-   sscan = systable_beginscan(pg_rowsecurity_rel,
-                              RowSecurityRelidPolnameIndexId, true, NULL, 2,
+   sscan = systable_beginscan(pg_policy_rel,
+                              PolicyPolrelidPolnameIndexId, true, NULL, 2,
                               skey);
 
-   rsec_tuple = systable_getnext(sscan);
+   policy_tuple = systable_getnext(sscan);
 
    /* Check that the policy is found, raise an error if not. */
-   if (!HeapTupleIsValid(rsec_tuple))
+   if (!HeapTupleIsValid(policy_tuple))
        ereport(ERROR,
                (errcode(ERRCODE_UNDEFINED_OBJECT),
                 errmsg("policy \"%s\" on table \"%s\" does not exist",
@@ -736,18 +735,18 @@ AlterPolicy(AlterPolicyStmt *stmt)
                        RelationGetRelationName(target_table))));
 
    /* Get policy command */
-   cmd_datum = heap_getattr(rsec_tuple, Anum_pg_rowsecurity_rseccmd,
-                            RelationGetDescr(pg_rowsecurity_rel),
-                            &rseccmd_isnull);
-   if (rseccmd_isnull)
-       rseccmd = 0;
+   cmd_datum = heap_getattr(policy_tuple, Anum_pg_policy_polcmd,
+                            RelationGetDescr(pg_policy_rel),
+                            &polcmd_isnull);
+   if (polcmd_isnull)
+       polcmd = 0;
    else
-       rseccmd = DatumGetChar(cmd_datum);
+       polcmd = DatumGetChar(cmd_datum);
 
    /*
     * If the command is SELECT or DELETE then WITH CHECK should be NULL.
     */
-   if ((rseccmd == ACL_SELECT_CHR || rseccmd == ACL_DELETE_CHR)
+   if ((polcmd == ACL_SELECT_CHR || polcmd == ACL_DELETE_CHR)
        && stmt->with_check != NULL)
        ereport(ERROR,
                (errcode(ERRCODE_SYNTAX_ERROR),
@@ -757,52 +756,52 @@ AlterPolicy(AlterPolicyStmt *stmt)
     * If the command is INSERT then WITH CHECK should be the only
     * expression provided.
     */
-   if ((rseccmd == ACL_INSERT_CHR)
+   if ((polcmd == ACL_INSERT_CHR)
        && stmt->qual != NULL)
        ereport(ERROR,
                (errcode(ERRCODE_SYNTAX_ERROR),
                 errmsg("only WITH CHECK expression allowed for INSERT")));
 
-   rowsec_id = HeapTupleGetOid(rsec_tuple);
+   policy_id = HeapTupleGetOid(policy_tuple);
 
    if (role_ids != NULL)
    {
-       replaces[Anum_pg_rowsecurity_rsecroles - 1] = true;
-       values[Anum_pg_rowsecurity_rsecroles - 1] = PointerGetDatum(role_ids);
+       replaces[Anum_pg_policy_polroles - 1] = true;
+       values[Anum_pg_policy_polroles - 1] = PointerGetDatum(role_ids);
    }
 
    if (qual != NULL)
    {
-       replaces[Anum_pg_rowsecurity_rsecqual - 1] = true;
-       values[Anum_pg_rowsecurity_rsecqual - 1]
+       replaces[Anum_pg_policy_polqual - 1] = true;
+       values[Anum_pg_policy_polqual - 1]
            = CStringGetTextDatum(nodeToString(qual));
    }
 
    if (with_check_qual != NULL)
    {
-       replaces[Anum_pg_rowsecurity_rsecwithcheck - 1] = true;
-       values[Anum_pg_rowsecurity_rsecwithcheck - 1]
+       replaces[Anum_pg_policy_polwithcheck - 1] = true;
+       values[Anum_pg_policy_polwithcheck - 1]
            = CStringGetTextDatum(nodeToString(with_check_qual));
    }
 
-   new_tuple = heap_modify_tuple(rsec_tuple,
-                                 RelationGetDescr(pg_rowsecurity_rel),
+   new_tuple = heap_modify_tuple(policy_tuple,
+                                 RelationGetDescr(pg_policy_rel),
                                  values, isnull, replaces);
-   simple_heap_update(pg_rowsecurity_rel, &new_tuple->t_self, new_tuple);
+   simple_heap_update(pg_policy_rel, &new_tuple->t_self, new_tuple);
 
    /* Update Catalog Indexes */
-   CatalogUpdateIndexes(pg_rowsecurity_rel, new_tuple);
+   CatalogUpdateIndexes(pg_policy_rel, new_tuple);
 
    /* Update Dependencies. */
-   deleteDependencyRecordsFor(RowSecurityRelationId, rowsec_id, false);
+   deleteDependencyRecordsFor(PolicyRelationId, policy_id, false);
 
    /* Record Dependencies */
    target.classId = RelationRelationId;
    target.objectId = table_id;
    target.objectSubId = 0;
 
-   myself.classId = RowSecurityRelationId;
-   myself.objectId = rowsec_id;
+   myself.classId = PolicyRelationId;
+   myself.objectId = policy_id;
    myself.objectSubId = 0;
 
    recordDependencyOn(&myself, &target, DEPENDENCY_AUTO);
@@ -820,9 +819,9 @@ AlterPolicy(AlterPolicyStmt *stmt)
    /* Clean up. */
    systable_endscan(sscan);
    relation_close(target_table, NoLock);
-   heap_close(pg_rowsecurity_rel, RowExclusiveLock);
+   heap_close(pg_policy_rel, RowExclusiveLock);
 
-   return rowsec_id;
+   return policy_id;
 }
 
 /*
@@ -832,13 +831,13 @@ AlterPolicy(AlterPolicyStmt *stmt)
 Oid
 rename_policy(RenameStmt *stmt)
 {
-   Relation        pg_rowsecurity_rel;
+   Relation        pg_policy_rel;
    Relation        target_table;
    Oid             table_id;
    Oid             opoloid;
    ScanKeyData     skey[2];
    SysScanDesc     sscan;
-   HeapTuple       rsec_tuple;
+   HeapTuple       policy_tuple;
 
    /* Get id of table.  Also handles permissions checks. */
    table_id = RangeVarGetRelidExtended(stmt->relation, AccessExclusiveLock,
@@ -848,74 +847,74 @@ rename_policy(RenameStmt *stmt)
 
    target_table = relation_open(table_id, NoLock);
 
-   pg_rowsecurity_rel = heap_open(RowSecurityRelationId, RowExclusiveLock);
+   pg_policy_rel = heap_open(PolicyRelationId, RowExclusiveLock);
 
    /* First pass -- check for conflict */
 
-   /* Add key - row security relation id. */
+   /* Add key - policy's relation id. */
    ScanKeyInit(&skey[0],
-               Anum_pg_rowsecurity_rsecrelid,
+               Anum_pg_policy_polrelid,
                BTEqualStrategyNumber, F_OIDEQ,
                ObjectIdGetDatum(table_id));
 
-   /* Add key - row security policy name. */
+   /* Add key - policy's name. */
    ScanKeyInit(&skey[1],
-               Anum_pg_rowsecurity_rsecpolname,
+               Anum_pg_policy_polname,
                BTEqualStrategyNumber, F_NAMEEQ,
                CStringGetDatum(stmt->newname));
 
-   sscan = systable_beginscan(pg_rowsecurity_rel,
-                              RowSecurityRelidPolnameIndexId, true, NULL, 2,
+   sscan = systable_beginscan(pg_policy_rel,
+                              PolicyPolrelidPolnameIndexId, true, NULL, 2,
                               skey);
 
    if (HeapTupleIsValid(systable_getnext(sscan)))
        ereport(ERROR,
                (errcode(ERRCODE_DUPLICATE_OBJECT),
-                errmsg("row-policy \"%s\" for table \"%s\" already exists",
+                errmsg("policy \"%s\" for table \"%s\" already exists",
                        stmt->newname, RelationGetRelationName(target_table))));
 
    systable_endscan(sscan);
 
    /* Second pass -- find existing policy and update */
-   /* Add key - row security relation id. */
+   /* Add key - policy's relation id. */
    ScanKeyInit(&skey[0],
-               Anum_pg_rowsecurity_rsecrelid,
+               Anum_pg_policy_polrelid,
                BTEqualStrategyNumber, F_OIDEQ,
                ObjectIdGetDatum(table_id));
 
-   /* Add key - row security policy name. */
+   /* Add key - policy's name. */
    ScanKeyInit(&skey[1],
-               Anum_pg_rowsecurity_rsecpolname,
+               Anum_pg_policy_polname,
                BTEqualStrategyNumber, F_NAMEEQ,
                CStringGetDatum(stmt->subname));
 
-   sscan = systable_beginscan(pg_rowsecurity_rel,
-                              RowSecurityRelidPolnameIndexId, true, NULL, 2,
+   sscan = systable_beginscan(pg_policy_rel,
+                              PolicyPolrelidPolnameIndexId, true, NULL, 2,
                               skey);
 
-   rsec_tuple = systable_getnext(sscan);
+   policy_tuple = systable_getnext(sscan);
 
    /* Complain if we did not find the policy */
-   if (!HeapTupleIsValid(rsec_tuple))
+   if (!HeapTupleIsValid(policy_tuple))
        ereport(ERROR,
                (errcode(ERRCODE_UNDEFINED_OBJECT),
-                errmsg("row-policy \"%s\" for table \"%s\" does not exist",
+                errmsg("policy \"%s\" for table \"%s\" does not exist",
                        stmt->subname, RelationGetRelationName(target_table))));
 
-   opoloid = HeapTupleGetOid(rsec_tuple);
+   opoloid = HeapTupleGetOid(policy_tuple);
 
-   rsec_tuple = heap_copytuple(rsec_tuple);
+   policy_tuple = heap_copytuple(policy_tuple);
 
-   namestrcpy(&((Form_pg_rowsecurity) GETSTRUCT(rsec_tuple))->rsecpolname,
+   namestrcpy(&((Form_pg_policy) GETSTRUCT(policy_tuple))->polname,
               stmt->newname);
 
-   simple_heap_update(pg_rowsecurity_rel, &rsec_tuple->t_self, rsec_tuple);
+   simple_heap_update(pg_policy_rel, &policy_tuple->t_self, policy_tuple);
 
    /* keep system catalog indexes current */
-   CatalogUpdateIndexes(pg_rowsecurity_rel, rsec_tuple);
+   CatalogUpdateIndexes(pg_policy_rel, policy_tuple);
 
-   InvokeObjectPostAlterHook(RowSecurityRelationId,
-                             HeapTupleGetOid(rsec_tuple), 0);
+   InvokeObjectPostAlterHook(PolicyRelationId,
+                             HeapTupleGetOid(policy_tuple), 0);
 
    /*
     * Invalidate relation's relcache entry so that other backends (and
@@ -926,7 +925,7 @@ rename_policy(RenameStmt *stmt)
 
    /* Clean up. */
    systable_endscan(sscan);
-   heap_close(pg_rowsecurity_rel, RowExclusiveLock);
+   heap_close(pg_policy_rel, RowExclusiveLock);
    relation_close(target_table, NoLock);
 
    return opoloid;
@@ -941,33 +940,33 @@ rename_policy(RenameStmt *stmt)
 Oid
 get_relation_policy_oid(Oid relid, const char *policy_name, bool missing_ok)
 {
-   Relation        pg_rowsecurity_rel;
+   Relation        pg_policy_rel;
    ScanKeyData     skey[2];
    SysScanDesc     sscan;
-   HeapTuple       rsec_tuple;
+   HeapTuple       policy_tuple;
    Oid             policy_oid;
 
-   pg_rowsecurity_rel = heap_open(RowSecurityRelationId, AccessShareLock);
+   pg_policy_rel = heap_open(PolicyRelationId, AccessShareLock);
 
-   /* Add key - row security relation id. */
+   /* Add key - policy's relation id. */
    ScanKeyInit(&skey[0],
-               Anum_pg_rowsecurity_rsecrelid,
+               Anum_pg_policy_polrelid,
                BTEqualStrategyNumber, F_OIDEQ,
                ObjectIdGetDatum(relid));
 
-   /* Add key - row security policy name. */
+   /* Add key - policy's name. */
    ScanKeyInit(&skey[1],
-               Anum_pg_rowsecurity_rsecpolname,
+               Anum_pg_policy_polname,
                BTEqualStrategyNumber, F_NAMEEQ,
                CStringGetDatum(policy_name));
 
-   sscan = systable_beginscan(pg_rowsecurity_rel,
-                              RowSecurityRelidPolnameIndexId, true, NULL, 2,
+   sscan = systable_beginscan(pg_policy_rel,
+                              PolicyPolrelidPolnameIndexId, true, NULL, 2,
                               skey);
 
-   rsec_tuple = systable_getnext(sscan);
+   policy_tuple = systable_getnext(sscan);
 
-   if (!HeapTupleIsValid(rsec_tuple))
+   if (!HeapTupleIsValid(policy_tuple))
    {
        if (!missing_ok)
            ereport(ERROR,
@@ -978,11 +977,11 @@ get_relation_policy_oid(Oid relid, const char *policy_name, bool missing_ok)
        policy_oid = InvalidOid;
    }
    else
-       policy_oid = HeapTupleGetOid(rsec_tuple);
+       policy_oid = HeapTupleGetOid(policy_tuple);
 
    /* Clean up. */
    systable_endscan(sscan);
-   heap_close(pg_rowsecurity_rel, AccessShareLock);
+   heap_close(pg_policy_rel, AccessShareLock);
 
    return policy_oid;
 }
index 56294552e715c8bb1516b7055e2c9c0b19355dba..2333e1bed926bba45664496a2e91ae4444507719 100644 (file)
@@ -37,7 +37,6 @@
 #include "catalog/pg_inherits_fn.h"
 #include "catalog/pg_namespace.h"
 #include "catalog/pg_opclass.h"
-#include "catalog/pg_rowsecurity.h"
 #include "catalog/pg_tablespace.h"
 #include "catalog/pg_trigger.h"
 #include "catalog/pg_type.h"
@@ -7986,6 +7985,24 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
                                   colName)));
                break;
 
+           case OCLASS_POLICY:
+
+               /*
+                * A policy can depend on a column because the column is
+                * specified in the policy's USING or WITH CHECK qual
+                * expressions.  It might be possible to rewrite and recheck
+                * the policy expression, but punt for now.  It's certainly
+                * easy enough to remove and recreate the policy; still,
+                * FIXME someday.
+                */
+               ereport(ERROR,
+                       (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+                        errmsg("cannot alter type of a column used in a policy definition"),
+                        errdetail("%s depends on column \"%s\"",
+                                  getObjectDescription(&foundObject),
+                                  colName)));
+               break;
+
            case OCLASS_DEFAULT:
 
                /*
index a753b2070088fcff5aaf1d8e61b150f56a2ddd34..c499486f01652bf25fff0b47a2bb4611fd8ff5c0 100644 (file)
@@ -502,7 +502,7 @@ ExecutorRewind(QueryDesc *queryDesc)
  * Returns true if permissions are adequate.  Otherwise, throws an appropriate
  * error if ereport_on_violation is true, or simply returns false otherwise.
  *
- * Note that this does NOT address row-level security policies (aka: RLS).  If
+ * Note that this does NOT address row level security policies (aka: RLS).  If
  * rows will be returned to the user as a result of this permission check
  * passing, then RLS also needs to be consulted (and check_enable_rls()).
  *
index c97355e8fda8bacf5245f3e958b04d82e7f5621e..25f30676f0258e32bfa34378a73dbfab624754e2 100644 (file)
@@ -1171,7 +1171,7 @@ set_subquery_pathlist(PlannerInfo *root, RelOptInfo *rel,
 
    /*
     * If the subquery has the "security_barrier" flag, it means the subquery
-    * originated from a view that must enforce row-level security.  Then we
+    * originated from a view that must enforce row level security.  Then we
     * must not push down quals that contain leaky functions.  (Ideally this
     * would be checked inside subquery_is_pushdown_safe, but since we don't
     * currently pass the RTE to that function, we must do it here.)
index fb74d6bf1f41df08ce52b25622320e2710dc3aed..f752ecc16a58dc2a289198715e6965f98815ea89 100644 (file)
@@ -177,7 +177,7 @@ standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
    glob->lastPHId = 0;
    glob->lastRowMarkId = 0;
    glob->transientPlan = false;
-   glob->has_rls = false;
+   glob->hasRowSecurity = false;
 
    /* Determine what fraction of the plan is likely to be scanned */
    if (cursorOptions & CURSOR_OPT_FAST_PLAN)
@@ -255,7 +255,7 @@ standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
    result->relationOids = glob->relationOids;
    result->invalItems = glob->invalItems;
    result->nParamExec = glob->nParamExec;
-   result->has_rls = glob->has_rls;
+   result->hasRowSecurity = glob->hasRowSecurity;
 
    return result;
 }
@@ -1208,7 +1208,7 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
         * This may add new security barrier subquery RTEs to the rangetable.
         */
        expand_security_quals(root, tlist);
-       root->glob->has_rls = parse->hasRowSecurity;
+       root->glob->hasRowSecurity = parse->hasRowSecurity;
 
        /*
         * Locate any window functions in the tlist.  (We don't need to look
index e630d0b6d81fc0219f5ebf764155560006e9b2e7..4d3fbca5969d8e4e956b27e53d6e640234883acd 100644 (file)
@@ -2109,7 +2109,7 @@ extract_query_dependencies(Node *query,
    glob.type = T_PlannerGlobal;
    glob.relationOids = NIL;
    glob.invalItems = NIL;
-   glob.has_rls = false;
+   glob.hasRowSecurity = false;
 
    MemSet(&root, 0, sizeof(root));
    root.type = T_PlannerInfo;
@@ -2119,7 +2119,7 @@ extract_query_dependencies(Node *query,
 
    *relationOids = glob.relationOids;
    *invalItems = glob.invalItems;
-   *hasRowSecurity = glob.has_rls;
+   *hasRowSecurity = glob.hasRowSecurity;
 }
 
 static bool
@@ -2135,8 +2135,8 @@ extract_query_dependencies_walker(Node *node, PlannerInfo *context)
        Query      *query = (Query *) node;
        ListCell   *lc;
 
-       /* Collect row-security information */
-       context->glob->has_rls = query->hasRowSecurity;
+       /* Collect row security information */
+       context->glob->hasRowSecurity = query->hasRowSecurity;
 
        if (query->commandType == CMD_UTILITY)
        {
index bd180e7e87ba941b30a02ddbbc5017533c7584b5..7e48958ae85cdd3d8dd0aacbe1b8ea523f2d1031 100644 (file)
@@ -5535,7 +5535,7 @@ opt_restart_seqs:
  * COMMENT ON [ [ CONVERSION | COLLATION | DATABASE | DOMAIN |
  *                 EXTENSION | EVENT TRIGGER | FOREIGN DATA WRAPPER |
  *                 FOREIGN TABLE | INDEX | [PROCEDURAL] LANGUAGE |
- *                 MATERIALIZED VIEW | ROLE | SCHEMA | SEQUENCE |
+ *                 MATERIALIZED VIEW | POLICY | ROLE | SCHEMA | SEQUENCE |
  *                 SERVER | TABLE | TABLESPACE |
  *                 TEXT SEARCH CONFIGURATION | TEXT SEARCH DICTIONARY |
  *                 TEXT SEARCH PARSER | TEXT SEARCH TEMPLATE | TYPE |
@@ -5601,6 +5601,15 @@ CommentStmt:
                    n->comment = $8;
                    $$ = (Node *) n;
                }
+           | COMMENT ON POLICY name ON any_name IS comment_text
+               {
+                   CommentStmt *n = makeNode(CommentStmt);
+                   n->objtype = OBJECT_POLICY;
+                   n->objname = lappend($6, makeString($4));
+                   n->objargs = NIL;
+                   n->comment = $8;
+                   $$ = (Node *) n;
+               }
            | COMMENT ON RULE name ON any_name IS comment_text
                {
                    CommentStmt *n = makeNode(CommentStmt);
index e7021509017dfd13ca6fb02d72da1a88dcd49157..ad983c7158b3ca7071be222fd661d777b0b90f99 100644 (file)
@@ -1715,7 +1715,7 @@ fireRIRrules(Query *parsetree, List *activeRIRs, bool forUpdatePushedDown)
            }
        }
        /*
-        * If the RTE has row-security quals, apply them and recurse into the
+        * If the RTE has row security quals, apply them and recurse into the
         * securityQuals.
         */
        if (prepend_row_security_policies(parsetree, rte, rt_index))
@@ -1727,7 +1727,7 @@ fireRIRrules(Query *parsetree, List *activeRIRs, bool forUpdatePushedDown)
            if (list_member_oid(activeRIRs, RelationGetRelid(rel)))
                    ereport(ERROR,
                            (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
-                            errmsg("infinite recursion detected in row-security policy for relation \"%s\"",
+                            errmsg("infinite recursion detected in policy for relation \"%s\"",
                                    RelationGetRelationName(rel))));
 
            /*
index 66c358cdec9b841fb53d9b99885d628acf7ef384..6c232dcf9ae3cf3d58dd290c2dc6771661ef48bd 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * rewrite/rowsecurity.c
- *    Routines to support policies for row-level security.
+ *    Routines to support policies for row level security (aka RLS).
  *
  * Policies in PostgreSQL provide a mechanism to limit what records are
  * returned to a user and what records a user is permitted to add to a table.
@@ -38,7 +38,7 @@
 #include "access/sysattr.h"
 #include "catalog/pg_class.h"
 #include "catalog/pg_inherits_fn.h"
-#include "catalog/pg_rowsecurity.h"
+#include "catalog/pg_policy.h"
 #include "catalog/pg_type.h"
 #include "miscadmin.h"
 #include "nodes/makefuncs.h"
@@ -72,8 +72,8 @@ static bool check_role_for_policy(ArrayType *policy_roles, Oid user_id);
 row_security_policy_hook_type  row_security_policy_hook = NULL;
 
 /*
- * Check the given RTE to see whether it's already had row-security quals
- * expanded and, if not, prepend any row-security rules from built-in or
+ * Check the given RTE to see whether it's already had row security quals
+ * expanded and, if not, prepend any row security rules from built-in or
  * plug-in sources to the securityQuals. The security quals are rewritten (for
  * view expansion, etc) before being added to the RTE.
  *
@@ -154,14 +154,14 @@ prepend_row_security_policies(Query* root, RangeTblEntry* rte, int rt_index)
    /*
     * Check if this is only the default-deny policy.
     *
-    * Normally, if the table has row-security enabled but there are
+    * Normally, if the table has row security enabled but there are
     * no policies, we use a default-deny policy and not allow anything.
     * However, when an extension uses the hook to add their own
     * policies, we don't want to include the default deny policy or
     * there won't be any way for a user to use an extension exclusively
     * for the policies to be used.
     */
-   if (((RowSecurityPolicy *) linitial(rowsec_policies))->rsecid
+   if (((RowSecurityPolicy *) linitial(rowsec_policies))->policy_id
            == InvalidOid)
        defaultDeny = true;
 
@@ -353,7 +353,7 @@ pull_row_security_policies(CmdType cmd, Relation relation, Oid user_id)
 
        policy = palloc0(sizeof(RowSecurityPolicy));
        policy->policy_name = pstrdup("default-deny policy");
-       policy->rsecid = InvalidOid;
+       policy->policy_id = InvalidOid;
        policy->cmd = '\0';
        policy->roles = construct_array(&role, 1, OIDOID, sizeof(Oid), true,
                                        'i');
index d85ea1bbd3ae8fa693807e289a547bfb1e7efeef..c537fe3236ced2a0256ca3cfae28ffed9470ce13 100644 (file)
@@ -207,7 +207,7 @@ CreateCachedPlan(Node *raw_parse_tree,
    plansource->generic_cost = -1;
    plansource->total_custom_cost = 0;
    plansource->num_custom_plans = 0;
-   plansource->has_rls = false;
+   plansource->hasRowSecurity = false;
    plansource->rowSecurityDisabled
        = (security_context & SECURITY_ROW_LEVEL_DISABLED) != 0;
    plansource->row_security_env = row_security;
@@ -383,7 +383,7 @@ CompleteCachedPlan(CachedPlanSource *plansource,
        extract_query_dependencies((Node *) querytree_list,
                                   &plansource->relationOids,
                                   &plansource->invalItems,
-                                  &plansource->has_rls);
+                                  &plansource->hasRowSecurity);
 
        /*
         * Also save the current search_path in the query_context.  (This
@@ -617,7 +617,7 @@ RevalidateCachedQuery(CachedPlanSource *plansource)
     */
    if (plansource->is_valid
        && !plansource->rowSecurityDisabled
-       && plansource->has_rls
+       && plansource->hasRowSecurity
        && (plansource->planUserId != GetUserId()
            || plansource->row_security_env != row_security))
        plansource->is_valid = false;
@@ -766,7 +766,7 @@ RevalidateCachedQuery(CachedPlanSource *plansource)
    extract_query_dependencies((Node *) qlist,
                               &plansource->relationOids,
                               &plansource->invalItems,
-                              &plansource->has_rls);
+                              &plansource->hasRowSecurity);
 
    /*
     * Also save the current search_path in the query_context.  (This should
index c80ef3c6f899ac01a04f3c97ea592fcdf381b91e..79244e5686512a0de81d8609e5cd5d7b5015503c 100644 (file)
@@ -866,7 +866,7 @@ equalPolicy(RowSecurityPolicy *policy1, RowSecurityPolicy *policy2)
        if (policy2 == NULL)
            return false;
 
-       if (policy1->rsecid != policy2->rsecid)
+       if (policy1->policy_id != policy2->policy_id)
            return false;
        if (policy1->cmd != policy2->cmd)
            return false;
@@ -3439,7 +3439,7 @@ RelationCacheInitializePhase3(void)
         * they are not preserved in the cache.  Note that we can never NOT
         * have a policy while relrowsecurity is true,
         * RelationBuildRowSecurity will create a single default-deny policy
-        * if there is no policy defined in pg_rowsecurity.
+        * if there is no policy defined in pg_policy.
         */
        if (relation->rd_rel->relrowsecurity && relation->rd_rsdesc == NULL)
        {
index 8bfc604eabbecb86edee5f0befebdbeb8325a081..1269ec3b28d9b371fec5d4a8d61215e393375785 100644 (file)
@@ -248,8 +248,8 @@ getSchemaData(Archive *fout, DumpOptions *dopt, int *numTablesPtr)
    getRules(fout, &numRules);
 
    if (g_verbose)
-       write_msg(NULL, "reading row-security policies\n");
-   getRowSecurity(fout, tblinfo, numTables);
+       write_msg(NULL, "reading policies\n");
+   getPolicies(fout, tblinfo, numTables);
 
    *numTablesPtr = numTables;
    return tblinfo;
index 1a2ebcb1f48fb55e2c9899109e55aa64fb940cad..43065e84b2f267ff97f08d68a8a3ade3633e177b 100644 (file)
@@ -3328,6 +3328,7 @@ _printTocEntry(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt, bool isDat
                 strcmp(te->desc, "RULE") == 0 ||
                 strcmp(te->desc, "TRIGGER") == 0 ||
                 strcmp(te->desc, "ROW SECURITY") == 0 ||
+                strcmp(te->desc, "POLICY") == 0 ||
                 strcmp(te->desc, "USER MAPPING") == 0)
        {
            /* these object types don't have separate owners */
index 69d359458bc878d3de546037bf5583a8c650d660..4175ddc823eb88bb93d2d3bf74f8b46f21ab63ff 100644 (file)
@@ -233,7 +233,7 @@ static char *myFormatType(const char *typname, int32 typmod);
 static void getBlobs(Archive *fout);
 static void dumpBlob(Archive *fout, DumpOptions *dopt, BlobInfo *binfo);
 static int dumpBlobs(Archive *fout, DumpOptions *dopt, void *arg);
-static void dumpRowSecurity(Archive *fout, DumpOptions *dopt, RowSecurityInfo *rsinfo);
+static void dumpPolicy(Archive *fout, DumpOptions *dopt, PolicyInfo *polinfo);
 static void dumpDatabase(Archive *AH, DumpOptions *dopt);
 static void dumpEncoding(Archive *AH);
 static void dumpStdStrings(Archive *AH);
@@ -2765,22 +2765,22 @@ dumpBlobs(Archive *fout, DumpOptions *dopt, void *arg)
 }
 
 /*
- * getRowSecurity
- *   get information about every row-security policy on a dumpable table.
+ * getPolicies
+ *   get information about policies on a dumpable table.
  */
 void
-getRowSecurity(Archive *fout, TableInfo tblinfo[], int numTables)
+getPolicies(Archive *fout, TableInfo tblinfo[], int numTables)
 {
    PQExpBuffer query;
    PGresult   *res;
-   RowSecurityInfo *rsinfo;
+   PolicyInfo *polinfo;
    int         i_oid;
    int         i_tableoid;
-   int         i_rsecpolname;
-   int         i_rseccmd;
-   int         i_rsecroles;
-   int         i_rsecqual;
-   int         i_rsecwithcheck;
+   int         i_polname;
+   int         i_polcmd;
+   int         i_polroles;
+   int         i_polqual;
+   int         i_polwithcheck;
    int         i,
                j,
                ntups;
@@ -2794,18 +2794,18 @@ getRowSecurity(Archive *fout, TableInfo tblinfo[], int numTables)
    {
        TableInfo  *tbinfo = &tblinfo[i];
 
-       /* Ignore row-security on tables not to be dumped */
+       /* Ignore row security on tables not to be dumped */
        if (!tbinfo->dobj.dump)
            continue;
 
        if (g_verbose)
-           write_msg(NULL, "reading row-security enabled for table \"%s\".\"%s\"\n",
+           write_msg(NULL, "reading row security enabled for table \"%s\".\"%s\"\n",
                      tbinfo->dobj.namespace->dobj.name,
                      tbinfo->dobj.name);
 
        /*
-        * Get row-security enabled information for the table. We represent
-        * RLS enabled on a table by creating RowSecurityInfo object with an
+        * Get row security enabled information for the table. We represent
+        * RLS enabled on a table by creating PolicyInfo object with an
         * empty policy.
         */
        if (tbinfo->rowsec)
@@ -2814,23 +2814,23 @@ getRowSecurity(Archive *fout, TableInfo tblinfo[], int numTables)
             * Note: use tableoid 0 so that this object won't be mistaken for
             * something that pg_depend entries apply to.
             */
-           rsinfo = pg_malloc(sizeof(RowSecurityInfo));
-           rsinfo->dobj.objType = DO_ROW_SECURITY;
-           rsinfo->dobj.catId.tableoid = 0;
-           rsinfo->dobj.catId.oid = tbinfo->dobj.catId.oid;
-           AssignDumpId(&rsinfo->dobj);
-           rsinfo->dobj.namespace = tbinfo->dobj.namespace;
-           rsinfo->dobj.name = pg_strdup(tbinfo->dobj.name);
-           rsinfo->rstable = tbinfo;
-           rsinfo->rsecpolname = NULL;
-           rsinfo->rseccmd = NULL;
-           rsinfo->rsecroles = NULL;
-           rsinfo->rsecqual = NULL;
-           rsinfo->rsecwithcheck = NULL;
+           polinfo = pg_malloc(sizeof(PolicyInfo));
+           polinfo->dobj.objType = DO_POLICY;
+           polinfo->dobj.catId.tableoid = 0;
+           polinfo->dobj.catId.oid = tbinfo->dobj.catId.oid;
+           AssignDumpId(&polinfo->dobj);
+           polinfo->dobj.namespace = tbinfo->dobj.namespace;
+           polinfo->dobj.name = pg_strdup(tbinfo->dobj.name);
+           polinfo->poltable = tbinfo;
+           polinfo->polname = NULL;
+           polinfo->polcmd = NULL;
+           polinfo->polroles = NULL;
+           polinfo->polqual = NULL;
+           polinfo->polwithcheck = NULL;
        }
 
        if (g_verbose)
-           write_msg(NULL, "reading row-security policies for table \"%s\".\"%s\"\n",
+           write_msg(NULL, "reading policies for table \"%s\".\"%s\"\n",
                      tbinfo->dobj.namespace->dobj.name,
                      tbinfo->dobj.name);
 
@@ -2843,13 +2843,13 @@ getRowSecurity(Archive *fout, TableInfo tblinfo[], int numTables)
 
        /* Get the policies for the table. */
        appendPQExpBuffer(query,
-                         "SELECT oid, tableoid, s.rsecpolname, s.rseccmd, "
-                         "CASE WHEN s.rsecroles = '{0}' THEN 'PUBLIC' ELSE "
-                         "   array_to_string(ARRAY(SELECT rolname from pg_roles WHERE oid = ANY(s.rsecroles)), ', ') END AS rsecroles, "
-                         "pg_get_expr(s.rsecqual, s.rsecrelid) AS rsecqual, "
-               "pg_get_expr(s.rsecwithcheck, s.rsecrelid) AS rsecwithcheck "
-                         "FROM pg_catalog.pg_rowsecurity s "
-                         "WHERE rsecrelid = '%u'",
+                         "SELECT oid, tableoid, pol.polname, pol.polcmd, "
+                         "CASE WHEN pol.polroles = '{0}' THEN 'PUBLIC' ELSE "
+                         "   array_to_string(ARRAY(SELECT rolname from pg_roles WHERE oid = ANY(pol.polroles)), ', ') END AS polroles, "
+                         "pg_get_expr(pol.polqual, pol.polrelid) AS polqual, "
+               "pg_get_expr(pol.polwithcheck, pol.polrelid) AS polwithcheck "
+                         "FROM pg_catalog.pg_policy pol "
+                         "WHERE polrelid = '%u'",
                          tbinfo->dobj.catId.oid);
        res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
 
@@ -2868,45 +2868,44 @@ getRowSecurity(Archive *fout, TableInfo tblinfo[], int numTables)
 
        i_oid = PQfnumber(res, "oid");
        i_tableoid = PQfnumber(res, "tableoid");
-       i_rsecpolname = PQfnumber(res, "rsecpolname");
-       i_rseccmd = PQfnumber(res, "rseccmd");
-       i_rsecroles = PQfnumber(res, "rsecroles");
-       i_rsecqual = PQfnumber(res, "rsecqual");
-       i_rsecwithcheck = PQfnumber(res, "rsecwithcheck");
+       i_polname = PQfnumber(res, "polname");
+       i_polcmd = PQfnumber(res, "polcmd");
+       i_polroles = PQfnumber(res, "polroles");
+       i_polqual = PQfnumber(res, "polqual");
+       i_polwithcheck = PQfnumber(res, "polwithcheck");
 
-       rsinfo = pg_malloc(ntups * sizeof(RowSecurityInfo));
+       polinfo = pg_malloc(ntups * sizeof(PolicyInfo));
 
        for (j = 0; j < ntups; j++)
        {
-           rsinfo[j].dobj.objType = DO_ROW_SECURITY;
-           rsinfo[j].dobj.catId.tableoid =
+           polinfo[j].dobj.objType = DO_POLICY;
+           polinfo[j].dobj.catId.tableoid =
                atooid(PQgetvalue(res, j, i_tableoid));
-           rsinfo[j].dobj.catId.oid = atooid(PQgetvalue(res, j, i_oid));
-           AssignDumpId(&rsinfo[j].dobj);
-           rsinfo[j].dobj.namespace = tbinfo->dobj.namespace;
-           rsinfo[j].rstable = tbinfo;
-           rsinfo[j].rsecpolname = pg_strdup(PQgetvalue(res, j,
-                                                        i_rsecpolname));
+           polinfo[j].dobj.catId.oid = atooid(PQgetvalue(res, j, i_oid));
+           AssignDumpId(&polinfo[j].dobj);
+           polinfo[j].dobj.namespace = tbinfo->dobj.namespace;
+           polinfo[j].poltable = tbinfo;
+           polinfo[j].polname = pg_strdup(PQgetvalue(res, j, i_polname));
 
-           rsinfo[j].dobj.name = pg_strdup(rsinfo[j].rsecpolname);
+           polinfo[j].dobj.name = pg_strdup(polinfo[j].polname);
 
-           if (PQgetisnull(res, j, i_rseccmd))
-               rsinfo[j].rseccmd = NULL;
+           if (PQgetisnull(res, j, i_polcmd))
+               polinfo[j].polcmd = NULL;
            else
-               rsinfo[j].rseccmd = pg_strdup(PQgetvalue(res, j, i_rseccmd));
+               polinfo[j].polcmd = pg_strdup(PQgetvalue(res, j, i_polcmd));
 
-           rsinfo[j].rsecroles = pg_strdup(PQgetvalue(res, j, i_rsecroles));
+           polinfo[j].polroles = pg_strdup(PQgetvalue(res, j, i_polroles));
 
-           if (PQgetisnull(res, j, i_rsecqual))
-               rsinfo[j].rsecqual = NULL;
+           if (PQgetisnull(res, j, i_polqual))
+               polinfo[j].polqual = NULL;
            else
-               rsinfo[j].rsecqual = pg_strdup(PQgetvalue(res, j, i_rsecqual));
+               polinfo[j].polqual = pg_strdup(PQgetvalue(res, j, i_polqual));
 
-           if (PQgetisnull(res, j, i_rsecwithcheck))
-               rsinfo[j].rsecwithcheck = NULL;
+           if (PQgetisnull(res, j, i_polwithcheck))
+               polinfo[j].polwithcheck = NULL;
            else
-               rsinfo[j].rsecwithcheck
-                   = pg_strdup(PQgetvalue(res, j, i_rsecwithcheck));
+               polinfo[j].polwithcheck
+                   = pg_strdup(PQgetvalue(res, j, i_polwithcheck));
        }
        PQclear(res);
    }
@@ -2914,13 +2913,13 @@ getRowSecurity(Archive *fout, TableInfo tblinfo[], int numTables)
 }
 
 /*
- * dumpRowSecurity
- *   dump the definition of the given row-security policy
+ * dumpPolicy
+ *   dump the definition of the given policy
  */
 static void
-dumpRowSecurity(Archive *fout, DumpOptions *dopt, RowSecurityInfo *rsinfo)
+dumpPolicy(Archive *fout, DumpOptions *dopt, PolicyInfo *polinfo)
 {
-   TableInfo  *tbinfo = rsinfo->rstable;
+   TableInfo  *tbinfo = polinfo->poltable;
    PQExpBuffer query;
    PQExpBuffer delqry;
    const char *cmd;
@@ -2929,23 +2928,23 @@ dumpRowSecurity(Archive *fout, DumpOptions *dopt, RowSecurityInfo *rsinfo)
        return;
 
    /*
-    * If rsecpolname is NULL, then this record is just indicating that ROW
+    * If polname is NULL, then this record is just indicating that ROW
     * LEVEL SECURITY is enabled for the table. Dump as ALTER TABLE <table>
     * ENABLE ROW LEVEL SECURITY.
     */
-   if (rsinfo->rsecpolname == NULL)
+   if (polinfo->polname == NULL)
    {
        query = createPQExpBuffer();
 
        appendPQExpBuffer(query, "ALTER TABLE %s ENABLE ROW LEVEL SECURITY;",
-                         fmtId(rsinfo->dobj.name));
+                         fmtId(polinfo->dobj.name));
 
-       ArchiveEntry(fout, rsinfo->dobj.catId, rsinfo->dobj.dumpId,
-                    rsinfo->dobj.name,
-                    rsinfo->dobj.namespace->dobj.name,
+       ArchiveEntry(fout, polinfo->dobj.catId, polinfo->dobj.dumpId,
+                    polinfo->dobj.name,
+                    polinfo->dobj.namespace->dobj.name,
                     NULL,
                     tbinfo->rolname, false,
-                    "ROW SECURITY", SECTION_NONE,
+                    "ROW SECURITY", SECTION_POST_DATA,
                     query->data, "", NULL,
                     NULL, 0,
                     NULL, NULL);
@@ -2954,19 +2953,19 @@ dumpRowSecurity(Archive *fout, DumpOptions *dopt, RowSecurityInfo *rsinfo)
        return;
    }
 
-   if (!rsinfo->rseccmd)
+   if (!polinfo->polcmd)
        cmd = "ALL";
-   else if (strcmp(rsinfo->rseccmd, "r") == 0)
+   else if (strcmp(polinfo->polcmd, "r") == 0)
        cmd = "SELECT";
-   else if (strcmp(rsinfo->rseccmd, "a") == 0)
+   else if (strcmp(polinfo->polcmd, "a") == 0)
        cmd = "INSERT";
-   else if (strcmp(rsinfo->rseccmd, "w") == 0)
+   else if (strcmp(polinfo->polcmd, "w") == 0)
        cmd = "UPDATE";
-   else if (strcmp(rsinfo->rseccmd, "d") == 0)
+   else if (strcmp(polinfo->polcmd, "d") == 0)
        cmd = "DELETE";
    else
    {
-       write_msg(NULL, "unexpected command type: '%s'\n", rsinfo->rseccmd);
+       write_msg(NULL, "unexpected command type: '%s'\n", polinfo->polcmd);
        exit_nicely(1);
    }
 
@@ -2974,28 +2973,28 @@ dumpRowSecurity(Archive *fout, DumpOptions *dopt, RowSecurityInfo *rsinfo)
    delqry = createPQExpBuffer();
 
    appendPQExpBuffer(query, "CREATE POLICY %s ON %s FOR %s",
-                     rsinfo->rsecpolname, fmtId(tbinfo->dobj.name), cmd);
+                     polinfo->polname, fmtId(tbinfo->dobj.name), cmd);
 
-   if (rsinfo->rsecroles != NULL)
-       appendPQExpBuffer(query, " TO %s", rsinfo->rsecroles);
+   if (polinfo->polroles != NULL)
+       appendPQExpBuffer(query, " TO %s", polinfo->polroles);
 
-   if (rsinfo->rsecqual != NULL)
-       appendPQExpBuffer(query, " USING %s", rsinfo->rsecqual);
+   if (polinfo->polqual != NULL)
+       appendPQExpBuffer(query, " USING %s", polinfo->polqual);
 
-   if (rsinfo->rsecwithcheck != NULL)
-       appendPQExpBuffer(query, " WITH CHECK %s", rsinfo->rsecwithcheck);
+   if (polinfo->polwithcheck != NULL)
+       appendPQExpBuffer(query, " WITH CHECK %s", polinfo->polwithcheck);
 
    appendPQExpBuffer(query, ";\n");
 
    appendPQExpBuffer(delqry, "DROP POLICY %s ON %s;\n",
-                     rsinfo->rsecpolname, fmtId(tbinfo->dobj.name));
+                     polinfo->polname, fmtId(tbinfo->dobj.name));
 
-   ArchiveEntry(fout, rsinfo->dobj.catId, rsinfo->dobj.dumpId,
-                rsinfo->dobj.name,
-                rsinfo->dobj.namespace->dobj.name,
+   ArchiveEntry(fout, polinfo->dobj.catId, polinfo->dobj.dumpId,
+                polinfo->dobj.name,
+                polinfo->dobj.namespace->dobj.name,
                 NULL,
                 tbinfo->rolname, false,
-                "ROW SECURITY", SECTION_POST_DATA,
+                "POLICY", SECTION_POST_DATA,
                 query->data, delqry->data, NULL,
                 NULL, 0,
                 NULL, NULL);
@@ -8232,8 +8231,8 @@ dumpDumpableObject(Archive *fout, DumpOptions *dopt, DumpableObject *dobj)
                         NULL, 0,
                         dumpBlobs, NULL);
            break;
-       case DO_ROW_SECURITY:
-           dumpRowSecurity(fout, dopt, (RowSecurityInfo *) dobj);
+       case DO_POLICY:
+           dumpPolicy(fout, dopt, (PolicyInfo *) dobj);
            break;
        case DO_PRE_DATA_BOUNDARY:
        case DO_POST_DATA_BOUNDARY:
@@ -15631,7 +15630,7 @@ addBoundaryDependencies(DumpableObject **dobjs, int numObjs,
            case DO_TRIGGER:
            case DO_EVENT_TRIGGER:
            case DO_DEFAULT_ACL:
-           case DO_ROW_SECURITY:
+           case DO_POLICY:
                /* Post-data objects: must come after the post-data boundary */
                addObjectDependency(dobj, postDataBound->dumpId);
                break;
index a7eb2fd9364b427ced713f531f88203fd279e906..d1d9ecbaa2d69fc773b4347e1b911188faa5df65 100644 (file)
@@ -76,7 +76,7 @@ typedef enum
    DO_POST_DATA_BOUNDARY,
    DO_EVENT_TRIGGER,
    DO_REFRESH_MATVIEW,
-   DO_ROW_SECURITY
+   DO_POLICY
 } DumpableObjectType;
 
 typedef struct _dumpableObject
@@ -210,7 +210,7 @@ typedef struct _tableInfo
    bool        hasindex;       /* does it have any indexes? */
    bool        hasrules;       /* does it have any rules? */
    bool        hastriggers;    /* does it have any triggers? */
-   bool        rowsec;         /* is row-security enabled? */
+   bool        rowsec;         /* is row security enabled? */
    bool        hasoids;        /* does it have OIDs? */
    uint32      frozenxid;      /* for restore frozen xid */
    uint32      minmxid;        /* for restore min multi xid */
@@ -453,21 +453,21 @@ typedef struct _blobInfo
 } BlobInfo;
 
 /*
- * The RowSecurityInfo struct is used to represent row policies on a table and
+ * The PolicyInfo struct is used to represent policies on a table and
  * to indicate if a table has RLS enabled (ENABLE ROW SECURITY).  If
- * rsecpolname is NULL, then the record indicates ENABLE ROW SECURITY, while if
+ * polname is NULL, then the record indicates ENABLE ROW SECURITY, while if
  * it's non-NULL then this is a regular policy definition.
  */
-typedef struct _rowSecurityInfo
+typedef struct _policyInfo
 {
    DumpableObject dobj;
-   TableInfo  *rstable;
-   char       *rsecpolname;    /* null indicates RLS is enabled on rel */
-   char       *rseccmd;
-   char       *rsecroles;
-   char       *rsecqual;
-   char       *rsecwithcheck;
-} RowSecurityInfo;
+   TableInfo  *poltable;
+   char       *polname;    /* null indicates RLS is enabled on rel */
+   char       *polcmd;
+   char       *polroles;
+   char       *polqual;
+   char       *polwithcheck;
+} PolicyInfo;
 
 /* global decls */
 extern bool force_quotes;      /* double-quotes for identifiers flag */
@@ -549,6 +549,6 @@ extern DefaultACLInfo *getDefaultACLs(Archive *fout, DumpOptions *dopt, int *num
 extern void getExtensionMembership(Archive *fout, DumpOptions *dopt, ExtensionInfo extinfo[],
                       int numExtensions);
 extern EventTriggerInfo *getEventTriggers(Archive *fout, int *numEventTriggers);
-extern void getRowSecurity(Archive *fout, TableInfo tblinfo[], int numTables);
+extern void getPolicies(Archive *fout, TableInfo tblinfo[], int numTables);
 
 #endif   /* PG_DUMP_H */
index 030bccc7e65a875ce7e0289707c77cdd2f513751..0e62af27765de642f1cfd4566e7ec16458f17c4c 100644 (file)
@@ -28,8 +28,8 @@ static const char *modulename = gettext_noop("sorter");
  * by OID.  (This is a relatively crude hack to provide semi-reasonable
  * behavior for old databases without full dependency info.)  Note: collations,
  * extensions, text search, foreign-data, materialized view, event trigger,
- * and default ACL objects can't really happen here, so the rather bogus
- * priorities for them don't matter.
+ * policies, and default ACL objects can't really happen here, so the rather
+ * bogus priorities for them don't matter.
  *
  * NOTE: object-type priorities must match the section assignments made in
  * pg_dump.c; that is, PRE_DATA objects must sort before DO_PRE_DATA_BOUNDARY,
@@ -73,7 +73,7 @@ static const int oldObjectTypePriority[] =
    13,                         /* DO_POST_DATA_BOUNDARY */
    20,                         /* DO_EVENT_TRIGGER */
    15,                         /* DO_REFRESH_MATVIEW */
-   21                          /* DO_ROW_SECURITY */
+   21                          /* DO_POLICY */
 };
 
 /*
@@ -122,7 +122,7 @@ static const int newObjectTypePriority[] =
    25,                         /* DO_POST_DATA_BOUNDARY */
    32,                         /* DO_EVENT_TRIGGER */
    33,                         /* DO_REFRESH_MATVIEW */
-   34                          /* DO_ROW_SECURITY */
+   34                          /* DO_POLICY */
 };
 
 static DumpId preDataBoundId;
@@ -1438,9 +1438,9 @@ describeDumpableObject(DumpableObject *obj, char *buf, int bufsize)
                     "BLOB DATA  (ID %d)",
                     obj->dumpId);
            return;
-       case DO_ROW_SECURITY:
+       case DO_POLICY:
            snprintf(buf, bufsize,
-                    "ROW-SECURITY POLICY (ID %d OID %u)",
+                    "POLICY (ID %d OID %u)",
                     obj->dumpId, obj->catId.oid);
            return;
        case DO_PRE_DATA_BOUNDARY:
index a062fa871fafa42cb2d893ac6d159023fc2f9267..5a9ceca0df5e6ba1da3597d9a73b5f98582289d0 100644 (file)
@@ -783,31 +783,31 @@ permissionsList(const char *pattern)
    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"
+                         "    SELECT polname\n"
+                         "    || CASE WHEN polcmd IS NOT NULL THEN\n"
+                         "           E' (' || polcmd || 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"
+                         "    || 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 rsecwithcheck IS NOT NULL THEN\n"
-                         "           E'\\n  (c): ' || pg_catalog.pg_get_expr(rsecwithcheck, rsecrelid)\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 rs.rsecroles <> '{0}' THEN\n"
+                         "    || 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 (rs.rsecroles)\n"
+                         "                   WHERE oid = ANY (polroles)\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"
+                         "    FROM pg_catalog.pg_policy pol\n"
+                         "    WHERE polrelid = c.oid), E'\\n')\n"
                          "    AS \"%s\"",
                          gettext_noop("Policies"));
 
@@ -2001,27 +2001,19 @@ describeOneTableDetails(const char *schemaname,
        /* print any row-level policies */
        if (pset.sversion >= 90500)
        {
-           appendPQExpBuffer(&buf,
-               ",\n pg_catalog.pg_get_expr(rs.rsecqual, c.oid) as \"%s\"",
-               gettext_noop("Row-security"));
-
-           if (verbose)
-               appendPQExpBuffer(&buf,
-                   "\n     LEFT JOIN pg_rowsecurity rs ON rs.rsecrelid = c.oid");
-
            printfPQExpBuffer(&buf,
-                          "SELECT rs.rsecpolname,\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"
-                          "CASE rs.rseccmd \n"
+                          "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 '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;",
+                             "FROM pg_catalog.pg_policy pol\n"
+                 "WHERE pol.polrelid = '%s' ORDER BY 1;",
                              oid);
 
            result = PSQLexec(buf.data);
index 278d3952d4d0ad6e2c2d6707d96a715f9505fb44..1bb5a8373f3d1f18438f91f116ba73f99e7b1b6f 100644 (file)
@@ -2069,7 +2069,7 @@ psql_completion(const char *text, int start, int end)
        static const char *const list_COMMENT[] =
        {"CAST", "COLLATION", "CONVERSION", "DATABASE", "EVENT TRIGGER", "EXTENSION",
            "FOREIGN DATA WRAPPER", "FOREIGN TABLE",
-           "SERVER", "INDEX", "LANGUAGE", "RULE", "SCHEMA", "SEQUENCE",
+           "SERVER", "INDEX", "LANGUAGE", "POLICY", "RULE", "SCHEMA", "SEQUENCE",
            "TABLE", "TYPE", "VIEW", "MATERIALIZED VIEW", "COLUMN", "AGGREGATE", "FUNCTION",
            "OPERATOR", "TRIGGER", "CONSTRAINT", "DOMAIN", "LARGE OBJECT",
        "TABLESPACE", "TEXT SEARCH", "ROLE", NULL};
index b670902b7d22eb24b97973b5bca43dcdbafe3030..a9290886252ad1b66ab83f025d544a39436ed3b8 100644 (file)
@@ -53,6 +53,6 @@
  */
 
 /*                         yyyymmddN */
-#define CATALOG_VERSION_NO 201411251
+#define CATALOG_VERSION_NO 201411271
 
 #endif
index 6a4913a66e57f3d6f6d0705c6798370b50e168e3..87ac9240ae9e3a990691333db4ab8ffee51d0c74 100644 (file)
@@ -147,7 +147,7 @@ typedef enum ObjectClass
    OCLASS_DEFACL,              /* pg_default_acl */
    OCLASS_EXTENSION,           /* pg_extension */
    OCLASS_EVENT_TRIGGER,       /* pg_event_trigger */
-   OCLASS_ROWSECURITY,         /* pg_rowsecurity */
+   OCLASS_POLICY,              /* pg_policy */
    MAX_OCLASS                  /* MUST BE LAST */
 } ObjectClass;
 
index 870692cf54f9e5151ed116583dbf7fa6d713227f..bde1a848fee2b28502ca3b331aa8fe37eb229b68 100644 (file)
@@ -299,11 +299,11 @@ DECLARE_UNIQUE_INDEX(pg_extension_name_index, 3081, on pg_extension using btree(
 DECLARE_UNIQUE_INDEX(pg_range_rngtypid_index, 3542, on pg_range using btree(rngtypid oid_ops));
 #define RangeTypidIndexId                  3542
 
-DECLARE_UNIQUE_INDEX(pg_rowsecurity_oid_index, 3257, on pg_rowsecurity using btree(oid oid_ops));
-#define RowSecurityOidIndexId              3257
+DECLARE_UNIQUE_INDEX(pg_policy_oid_index, 3257, on pg_policy using btree(oid oid_ops));
+#define PolicyOidIndexId               3257
 
-DECLARE_UNIQUE_INDEX(pg_rowsecurity_polname_relid_index, 3258, on pg_rowsecurity using btree(rsecrelid oid_ops, rsecpolname name_ops));
-#define RowSecurityRelidPolnameIndexId             3258
+DECLARE_UNIQUE_INDEX(pg_policy_polrelid_polname_index, 3258, on pg_policy using btree(polrelid oid_ops, polname name_ops));
+#define PolicyPolrelidPolnameIndexId               3258
 
 /* last step of initialization script: build the indexes declared above */
 BUILD_INDICES
index 22c55a94903b63cfb30d11e56d2141de9889faa3..1054cd0500be3ce8c646ea3a463964850c538968 100644 (file)
@@ -65,7 +65,7 @@ CATALOG(pg_class,1259) BKI_BOOTSTRAP BKI_ROWTYPE_OID(83) BKI_SCHEMA_MACRO
    bool        relhasrules;    /* has (or has had) any rules */
    bool        relhastriggers; /* has (or has had) any TRIGGERs */
    bool        relhassubclass; /* has (or has had) derived classes */
-   bool        relrowsecurity; /* row-security is enabled or not */
+   bool        relrowsecurity; /* row security is enabled or not */
    bool        relispopulated; /* matview currently holds query results */
    char        relreplident;   /* see REPLICA_IDENTITY_xxx constants  */
    TransactionId relfrozenxid; /* all Xids < this are frozen in this rel */
diff --git a/src/include/catalog/pg_policy.h b/src/include/catalog/pg_policy.h
new file mode 100644 (file)
index 0000000..5d377a4
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * pg_policy.h
+ *   definition of the system "policy" relation (pg_policy)
+ *
+ * Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ */
+#ifndef PG_POLICY_H
+#define PG_POLICY_H
+
+#include "catalog/genbki.h"
+
+/* ----------------
+ *     pg_policy definition. cpp turns this into
+ *     typedef struct FormData_pg_policy
+ * ----------------
+ */
+#define PolicyRelationId   3256
+
+CATALOG(pg_policy,3256)
+{
+   NameData        polname;        /* Policy name. */
+   Oid             polrelid;       /* Oid of the relation with policy. */
+   char            polcmd;         /* One of ACL_*_CHR, or \0 for all */
+
+#ifdef CATALOG_VARLEN
+   Oid             polroles[1]     /* Roles associated with policy, not-NULL */
+   pg_node_tree    polqual;        /* Policy quals. */
+   pg_node_tree    polwithcheck;   /* WITH CHECK quals. */
+#endif
+} FormData_pg_policy;
+
+/* ----------------
+ *     Form_pg_policy corresponds to a pointer to a row with
+ *     the format of pg_policy relation.
+ * ----------------
+ */
+typedef FormData_pg_policy *Form_pg_policy;
+
+/* ----------------
+ *         compiler constants for pg_policy
+ * ----------------
+ */
+#define Natts_pg_policy                6
+#define Anum_pg_policy_polname     1
+#define Anum_pg_policy_polrelid        2
+#define Anum_pg_policy_polcmd      3
+#define Anum_pg_policy_polroles        4
+#define Anum_pg_policy_polqual     5
+#define Anum_pg_policy_polwithcheck    6
+
+#endif  /* PG_POLICY_H */
diff --git a/src/include/catalog/pg_rowsecurity.h b/src/include/catalog/pg_rowsecurity.h
deleted file mode 100644 (file)
index 2638d5e..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * pg_rowsecurity.h
- *   definition of the system catalog for row-security policy (pg_rowsecurity)
- *
- * Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- */
-#ifndef PG_ROWSECURITY_H
-#define PG_ROWSECURITY_H
-
-#include "catalog/genbki.h"
-
-/* ----------------
- *     pg_rowsecurity definition. cpp turns this into
- *     typedef struct FormData_pg_rowsecurity
- * ----------------
- */
-#define RowSecurityRelationId  3256
-
-CATALOG(pg_rowsecurity,3256)
-{
-   NameData        rsecpolname;    /* Policy name. */
-   Oid             rsecrelid;      /* Oid of the relation with policy. */
-   char            rseccmd;        /* One of ACL_*_CHR, or \0 for all */
-
-#ifdef CATALOG_VARLEN
-   Oid             rsecroles[1]    /* Roles associated with policy, not-NULL */
-   pg_node_tree    rsecqual;       /* Policy quals. */
-   pg_node_tree    rsecwithcheck;  /* WITH CHECK quals. */
-#endif
-} FormData_pg_rowsecurity;
-
-/* ----------------
- *     Form_pg_rowsecurity corresponds to a pointer to a row with
- *     the format of pg_rowsecurity relation.
- * ----------------
- */
-typedef FormData_pg_rowsecurity *Form_pg_rowsecurity;
-
-/* ----------------
- *         compiler constants for pg_rowsecurity
- * ----------------
- */
-#define Natts_pg_rowsecurity               6
-#define Anum_pg_rowsecurity_rsecpolname        1
-#define Anum_pg_rowsecurity_rsecrelid      2
-#define Anum_pg_rowsecurity_rseccmd            3
-#define Anum_pg_rowsecurity_rsecroles      4
-#define Anum_pg_rowsecurity_rsecqual       5
-#define Anum_pg_rowsecurity_rsecwithcheck  6
-
-#endif  /* PG_ROWSECURITY_H */
index 3e4f815852d5659a6d0e2bae77e4a8b4a98c6213..255415d93a3f50773a5aa24071c255d7d5a51406 100644 (file)
@@ -121,7 +121,7 @@ typedef struct Query
    bool        hasRecursive;   /* WITH RECURSIVE was specified */
    bool        hasModifyingCTE;    /* has INSERT/UPDATE/DELETE in WITH */
    bool        hasForUpdate;   /* FOR [KEY] UPDATE/SHARE was specified */
-   bool        hasRowSecurity; /* Row-security policy is applied */
+   bool        hasRowSecurity; /* row security applied? */
 
    List       *cteList;        /* WITH list (of CommonTableExpr's) */
 
index 7f9eaf0df267d4cb1dad3cb86e06d78987bdb70e..48203a0d21faade68529a3cc217ce39f46a3b260 100644 (file)
@@ -70,7 +70,7 @@ typedef struct PlannedStmt
 
    int         nParamExec;     /* number of PARAM_EXEC Params used */
 
-   bool        has_rls;        /* row-security applied? */
+   bool        hasRowSecurity; /* row security applied? */
 
 } PlannedStmt;
 
index 810b9c8893b077b5cc2d3689c4612d5b86b071b0..711649687ae8f4cd404d0a85b9cb6d311da8c82c 100644 (file)
@@ -101,7 +101,7 @@ typedef struct PlannerGlobal
 
    bool        transientPlan;  /* redo plan when TransactionXmin changes? */
 
-   bool        has_rls;        /* row-security is applied? */
+   bool        hasRowSecurity; /* row security applied? */
 
 } PlannerGlobal;
 
index 8b4d5c0918faacb236a1cc6b1f3d70edebf14f60..4144b25fec75cf4dc440a3ba077d4195f8d5a649 100644 (file)
@@ -19,7 +19,7 @@
 
 typedef struct RowSecurityPolicy
 {
-   Oid                 rsecid;         /* OID of the policy */
+   Oid                 policy_id;      /* OID of the policy */
    char               *policy_name;    /* Name of the policy */
    char                cmd;            /* Type of command policy is for */
    ArrayType          *roles;          /* Array of roles policy is for */
@@ -30,8 +30,8 @@ typedef struct RowSecurityPolicy
 
 typedef struct RowSecurityDesc
 {
-   MemoryContext       rscxt;      /* row-security memory context */
-   List               *policies;   /* list of row-security policies */
+   MemoryContext       rscxt;      /* row security memory context */
+   List               *policies;   /* list of row security policies */
 } RowSecurityDesc;
 
 /* GUC variable */
index 2622ceb54bc1908c4146d4332c631a530a048c54..9e1c0000aab06bd87c25b0475c704094b9460d1e 100644 (file)
@@ -109,9 +109,9 @@ typedef struct CachedPlanSource
    double      generic_cost;   /* cost of generic plan, or -1 if not known */
    double      total_custom_cost;      /* total cost of custom plans so far */
    int         num_custom_plans;       /* number of plans included in total */
-   bool        has_rls;                /* planned with row-security? */
+   bool        hasRowSecurity;         /* planned with row security? */
    int         row_security_env;       /* row security setting when planned */
-   bool        rowSecurityDisabled;    /* is row-security disabled? */
+   bool        rowSecurityDisabled;    /* is row security disabled? */
 } CachedPlanSource;
 
 /*
index 01a9ef32ebf9158815a67fae3b4f599654c9137b..48ebf5949430cc77690e1d73de6fb84de2b74613 100644 (file)
@@ -106,7 +106,7 @@ typedef struct RelationData
    MemoryContext rd_rulescxt;  /* private memory cxt for rd_rules, if any */
    TriggerDesc *trigdesc;      /* Trigger info, or NULL if rel has none */
    /* use "struct" here to avoid needing to include rowsecurity.h: */
-   struct RowSecurityDesc *rd_rsdesc;  /* Row-security policies, or NULL */
+   struct RowSecurityDesc *rd_rsdesc;  /* row security policies, or NULL */
 
    /* data managed by RelationGetIndexList: */
    List       *rd_indexlist;   /* list of OIDs of indexes on relation */
index 376292ac2effc0990f2effc58b8ed75405d76ad0..5eb61c46aa2afedd8521372c041890cdb20ffc12 100644 (file)
@@ -173,7 +173,7 @@ EXPLAIN (COSTS OFF) SELECT * FROM document NATURAL JOIN category WHERE f_leak(dt
                              Index Cond: (pguser = "current_user"())
 (11 rows)
 
--- only owner can change row-level security
+-- only owner can change policies
 ALTER POLICY p1 ON document USING (true);    --fail
 ERROR:  must be owner of relation document
 DROP POLICY p1 ON document;                  --fail
@@ -724,7 +724,7 @@ CREATE TABLE dependent (x integer, y integer);
 CREATE POLICY d1 ON dependent FOR ALL
     TO PUBLIC
     USING (x = (SELECT d.x FROM dependee d WHERE d.y = y));
-DROP TABLE dependee; -- Should fail without CASCADE due to dependency on row-security qual?
+DROP TABLE dependee; -- Should fail without CASCADE due to dependency on row security qual?
 ERROR:  cannot drop table dependee because other objects depend on it
 DETAIL:  policy d1 on table dependent depends on table dependee
 HINT:  Use DROP ... CASCADE to drop the dependent objects too.
@@ -746,7 +746,7 @@ CREATE POLICY r1 ON rec1 USING (x = (SELECT r.x FROM rec1 r WHERE y = r.y));
 ALTER TABLE rec1 ENABLE ROW LEVEL SECURITY;
 SET SESSION AUTHORIZATION rls_regress_user1;
 SELECT * FROM rec1; -- fail, direct recursion
-ERROR:  infinite recursion detected in row-security policy for relation "rec1"
+ERROR:  infinite recursion detected in policy for relation "rec1"
 --
 -- Mutual recursion
 --
@@ -757,7 +757,7 @@ CREATE POLICY r2 ON rec2 USING (a = (SELECT x FROM rec1 WHERE y = b));
 ALTER TABLE rec2 ENABLE ROW LEVEL SECURITY;
 SET SESSION AUTHORIZATION rls_regress_user1;
 SELECT * FROM rec1;    -- fail, mutual recursion
-ERROR:  infinite recursion detected in row-security policy for relation "rec1"
+ERROR:  infinite recursion detected in policy for relation "rec1"
 --
 -- Mutual recursion via views
 --
@@ -769,7 +769,7 @@ ALTER POLICY r1 ON rec1 USING (x = (SELECT a FROM rec2v WHERE b = y));
 ALTER POLICY r2 ON rec2 USING (a = (SELECT x FROM rec1v WHERE y = b));
 SET SESSION AUTHORIZATION rls_regress_user1;
 SELECT * FROM rec1;    -- fail, mutual recursion via views
-ERROR:  infinite recursion detected in row-security policy for relation "rec1"
+ERROR:  infinite recursion detected in policy for relation "rec1"
 --
 -- Mutual recursion via .s.b views
 --
@@ -785,7 +785,7 @@ CREATE POLICY r1 ON rec1 USING (x = (SELECT a FROM rec2v WHERE b = y));
 CREATE POLICY r2 ON rec2 USING (a = (SELECT x FROM rec1v WHERE y = b));
 SET SESSION AUTHORIZATION rls_regress_user1;
 SELECT * FROM rec1;    -- fail, mutual recursion via s.b. views
-ERROR:  infinite recursion detected in row-security policy for relation "rec1"
+ERROR:  infinite recursion detected in policy for relation "rec1"
 --
 -- recursive RLS and VIEWs in policy
 --
@@ -803,9 +803,9 @@ ALTER TABLE s2 ENABLE ROW LEVEL SECURITY;
 SET SESSION AUTHORIZATION rls_regress_user1;
 CREATE VIEW v2 AS SELECT * FROM s2 WHERE y like '%af%';
 SELECT * FROM s1 WHERE f_leak(b); -- fail (infinite recursion)
-ERROR:  infinite recursion detected in row-security policy for relation "s1"
+ERROR:  infinite recursion detected in policy for relation "s1"
 INSERT INTO s1 VALUES (1, 'foo'); -- fail (infinite recursion)
-ERROR:  infinite recursion detected in row-security policy for relation "s1"
+ERROR:  infinite recursion detected in policy for relation "s1"
 SET SESSION AUTHORIZATION rls_regress_user0;
 DROP POLICY p3 on s1;
 ALTER POLICY p2 ON s2 USING (x % 2 = 0);
@@ -897,7 +897,7 @@ SET SESSION AUTHORIZATION rls_regress_user0;
 ALTER POLICY p2 ON s2 USING (x in (select a from s1 where b like '%d2%'));
 SET SESSION AUTHORIZATION rls_regress_user1;
 SELECT * FROM s1 WHERE f_leak(b);  -- fail (infinite recursion via view)
-ERROR:  infinite recursion detected in row-security policy for relation "s1"
+ERROR:  infinite recursion detected in policy for relation "s1"
 -- prepared statement with rls_regress_user0 privilege
 PREPARE p1(int) AS SELECT * FROM t1 WHERE a <= $1;
 EXECUTE p1(2);
@@ -1714,24 +1714,24 @@ WITH cte1 AS (INSERT INTO t1 VALUES (20, 'Success') RETURNING *) SELECT * FROM c
 --
 RESET SESSION AUTHORIZATION;
 ALTER POLICY p1 ON t1 RENAME TO p1; --fail
-ERROR:  row-policy "p1" for table "t1" already exists
-SELECT rsecpolname, relname
-    FROM pg_rowsecurity rs
-    JOIN pg_class pc ON (pc.oid = rs.rsecrelid)
+ERROR:  policy "p1" for table "t1" already exists
+SELECT polname, relname
+    FROM pg_policy pol
+    JOIN pg_class pc ON (pc.oid = pol.polrelid)
     WHERE relname = 't1';
rsecpolname | relname 
--------------+---------
- p1          | t1
+ polname | relname 
+---------+---------
+ p1      | t1
 (1 row)
 
 ALTER POLICY p1 ON t1 RENAME TO p2; --ok
-SELECT rsecpolname, relname
-    FROM pg_rowsecurity rs
-    JOIN pg_class pc ON (pc.oid = rs.rsecrelid)
+SELECT polname, relname
+    FROM pg_policy pol
+    JOIN pg_class pc ON (pc.oid = pol.polrelid)
     WHERE relname = 't1';
rsecpolname | relname 
--------------+---------
- p2          | t1
+ polname | relname 
+---------+---------
+ p2      | t1
 (1 row)
 
 --
@@ -2161,7 +2161,7 @@ SET row_security TO ON;
 COPY copy_t FROM STDIN; --ok
 SET row_security TO FORCE;
 COPY copy_t FROM STDIN; --fail - COPY FROM not supported by RLS.
-ERROR:  COPY FROM not supported with row security.
+ERROR:  COPY FROM not supported with row level security.
 HINT:  Use direct INSERT statements instead.
 -- Check COPY FROM as user with permissions.
 SET SESSION AUTHORIZATION rls_regress_user1;
@@ -2170,11 +2170,11 @@ COPY copy_t FROM STDIN; --fail - insufficient privilege to bypass rls.
 ERROR:  insufficient privilege to bypass row security.
 SET row_security TO ON;
 COPY copy_t FROM STDIN; --fail - COPY FROM not supported by RLS.
-ERROR:  COPY FROM not supported with row security.
+ERROR:  COPY FROM not supported with row level security.
 HINT:  Use direct INSERT statements instead.
 SET row_security TO FORCE;
 COPY copy_t FROM STDIN; --fail - COPY FROM not supported by RLS.
-ERROR:  COPY FROM not supported with row security.
+ERROR:  COPY FROM not supported with row level security.
 HINT:  Use direct INSERT statements instead.
 -- Check COPY TO as user with permissions and BYPASSRLS
 SET SESSION AUTHORIZATION rls_regress_exempt_user;
@@ -2182,11 +2182,11 @@ SET row_security TO OFF;
 COPY copy_t FROM STDIN; --ok
 SET row_security TO ON;
 COPY copy_t FROM STDIN; --fail - COPY FROM not supported by RLS.
-ERROR:  COPY FROM not supported with row security.
+ERROR:  COPY FROM not supported with row level security.
 HINT:  Use direct INSERT statements instead.
 SET row_security TO FORCE;
 COPY copy_t FROM STDIN; --fail - COPY FROM not supported by RLS.
-ERROR:  COPY FROM not supported with row security.
+ERROR:  COPY FROM not supported with row level security.
 HINT:  Use direct INSERT statements instead.
 -- Check COPY FROM as user without permissions.
 SET SESSION AUTHORIZATION rls_regress_user2;
index c79b45c53a0fd2f233a6b389056532b4308445cd..80c3351291638cc8f37194f34e0eb773564616ca 100644 (file)
@@ -1355,18 +1355,18 @@ pg_matviews| SELECT n.nspname AS schemaname,
   WHERE (c.relkind = 'm'::"char");
 pg_policies| SELECT n.nspname AS schemaname,
     c.relname AS tablename,
-    rs.rsecpolname AS policyname,
+    pol.polname AS policyname,
         CASE
-            WHEN (rs.rsecroles = '{0}'::oid[]) THEN (string_to_array('public'::text, ''::text))::name[]
+            WHEN (pol.polroles = '{0}'::oid[]) THEN (string_to_array('public'::text, ''::text))::name[]
             ELSE ARRAY( SELECT pg_authid.rolname
                FROM pg_authid
-              WHERE (pg_authid.oid = ANY (rs.rsecroles))
+              WHERE (pg_authid.oid = ANY (pol.polroles))
               ORDER BY pg_authid.rolname)
         END AS roles,
         CASE
-            WHEN (rs.rseccmd IS NULL) THEN 'ALL'::text
+            WHEN (pol.polcmd IS NULL) THEN 'ALL'::text
             ELSE
-            CASE rs.rseccmd
+            CASE pol.polcmd
                 WHEN 'r'::"char" THEN 'SELECT'::text
                 WHEN 'a'::"char" THEN 'INSERT'::text
                 WHEN 'u'::"char" THEN 'UPDATE'::text
@@ -1374,10 +1374,10 @@ pg_policies| SELECT n.nspname AS schemaname,
                 ELSE NULL::text
             END
         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
-     JOIN pg_class c ON ((c.oid = rs.rsecrelid)))
+    pg_get_expr(pol.polqual, pol.polrelid) AS qual,
+    pg_get_expr(pol.polwithcheck, pol.polrelid) AS with_check
+   FROM ((pg_policy pol
+     JOIN pg_class c ON ((c.oid = pol.polrelid)))
      LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace)));
 pg_prepared_statements| SELECT p.name,
     p.statement,
index 2c8ec118a754ccc296720f446b7069daf5daa638..c7be273ae166146fbd44a8f1afc5ba7f89e42f3e 100644 (file)
@@ -118,10 +118,10 @@ pg_opclass|t
 pg_operator|t
 pg_opfamily|t
 pg_pltemplate|t
+pg_policy|t
 pg_proc|t
 pg_range|t
 pg_rewrite|t
-pg_rowsecurity|t
 pg_seclabel|t
 pg_shdepend|t
 pg_shdescription|t
index 2d5ddb4b8328b891b24018b003f267dc35e6da6b..181043f416489dccea0ec51930f0c89928691638 100644 (file)
@@ -102,7 +102,7 @@ SELECT * FROM document NATURAL JOIN category WHERE f_leak(dtitle) ORDER BY did;
 EXPLAIN (COSTS OFF) SELECT * FROM document WHERE f_leak(dtitle);
 EXPLAIN (COSTS OFF) SELECT * FROM document NATURAL JOIN category WHERE f_leak(dtitle);
 
--- only owner can change row-level security
+-- only owner can change policies
 ALTER POLICY p1 ON document USING (true);    --fail
 DROP POLICY p1 ON document;                  --fail
 
@@ -274,7 +274,7 @@ CREATE POLICY d1 ON dependent FOR ALL
     TO PUBLIC
     USING (x = (SELECT d.x FROM dependee d WHERE d.y = y));
 
-DROP TABLE dependee; -- Should fail without CASCADE due to dependency on row-security qual?
+DROP TABLE dependee; -- Should fail without CASCADE due to dependency on row security qual?
 
 DROP TABLE dependee CASCADE;
 
@@ -659,16 +659,16 @@ WITH cte1 AS (INSERT INTO t1 VALUES (20, 'Success') RETURNING *) SELECT * FROM c
 RESET SESSION AUTHORIZATION;
 ALTER POLICY p1 ON t1 RENAME TO p1; --fail
 
-SELECT rsecpolname, relname
-    FROM pg_rowsecurity rs
-    JOIN pg_class pc ON (pc.oid = rs.rsecrelid)
+SELECT polname, relname
+    FROM pg_policy pol
+    JOIN pg_class pc ON (pc.oid = pol.polrelid)
     WHERE relname = 't1';
 
 ALTER POLICY p1 ON t1 RENAME TO p2; --ok
 
-SELECT rsecpolname, relname
-    FROM pg_rowsecurity rs
-    JOIN pg_class pc ON (pc.oid = rs.rsecrelid)
+SELECT polname, relname
+    FROM pg_policy pol
+    JOIN pg_class pc ON (pc.oid = pol.polrelid)
     WHERE relname = 't1';
 
 --