diff options
Diffstat (limited to '')
-rw-r--r-- | doc/src/sgml/html/sql-createpolicy.html | 361 |
1 files changed, 361 insertions, 0 deletions
diff --git a/doc/src/sgml/html/sql-createpolicy.html b/doc/src/sgml/html/sql-createpolicy.html new file mode 100644 index 0000000..15c9e9c --- /dev/null +++ b/doc/src/sgml/html/sql-createpolicy.html @@ -0,0 +1,361 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>CREATE POLICY</title><link rel="stylesheet" type="text/css" href="stylesheet.css" /><link rev="made" href="pgsql-docs@lists.postgresql.org" /><meta name="generator" content="DocBook XSL Stylesheets Vsnapshot" /><link rel="prev" href="sql-createopfamily.html" title="CREATE OPERATOR FAMILY" /><link rel="next" href="sql-createprocedure.html" title="CREATE PROCEDURE" /></head><body id="docContent" class="container-fluid col-10"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="5" align="center">CREATE POLICY</th></tr><tr><td width="10%" align="left"><a accesskey="p" href="sql-createopfamily.html" title="CREATE OPERATOR FAMILY">Prev</a> </td><td width="10%" align="left"><a accesskey="u" href="sql-commands.html" title="SQL Commands">Up</a></td><th width="60%" align="center">SQL Commands</th><td width="10%" align="right"><a accesskey="h" href="index.html" title="PostgreSQL 16.2 Documentation">Home</a></td><td width="10%" align="right"> <a accesskey="n" href="sql-createprocedure.html" title="CREATE PROCEDURE">Next</a></td></tr></table><hr /></div><div class="refentry" id="SQL-CREATEPOLICY"><div class="titlepage"></div><a id="id-1.9.3.75.1" class="indexterm"></a><div class="refnamediv"><h2><span class="refentrytitle">CREATE POLICY</span></h2><p>CREATE POLICY — define a new row-level security policy for a table</p></div><div class="refsynopsisdiv"><h2>Synopsis</h2><pre class="synopsis"> +CREATE POLICY <em class="replaceable"><code>name</code></em> ON <em class="replaceable"><code>table_name</code></em> + [ AS { PERMISSIVE | RESTRICTIVE } ] + [ FOR { ALL | SELECT | INSERT | UPDATE | DELETE } ] + [ TO { <em class="replaceable"><code>role_name</code></em> | PUBLIC | CURRENT_ROLE | CURRENT_USER | SESSION_USER } [, ...] ] + [ USING ( <em class="replaceable"><code>using_expression</code></em> ) ] + [ WITH CHECK ( <em class="replaceable"><code>check_expression</code></em> ) ] +</pre></div><div class="refsect1" id="id-1.9.3.75.5"><h2>Description</h2><p> + The <code class="command">CREATE POLICY</code> command defines a new row-level + security policy for a table. Note that row-level security must be + enabled on the table (using <code class="command">ALTER TABLE ... ENABLE ROW LEVEL + SECURITY</code>) in order for created policies to be applied. + </p><p> + A policy grants the permission to select, insert, update, or delete rows + that match the relevant policy expression. Existing table rows are + checked against the expression specified in <code class="literal">USING</code>, + while new rows that would be created via <code class="literal">INSERT</code> + or <code class="literal">UPDATE</code> are checked against the expression specified + in <code class="literal">WITH CHECK</code>. When a <code class="literal">USING</code> + expression returns true for a given row then that row is visible to the + user, while if false or null is returned then the row is not visible. + When a <code class="literal">WITH CHECK</code> expression returns true for a row + then that row is inserted or updated, while if false or null is returned + then an error occurs. + </p><p> + For <code class="command">INSERT</code>, <code class="command">UPDATE</code>, and + <code class="command">MERGE</code> statements, + <code class="literal">WITH CHECK</code> expressions are enforced after + <code class="literal">BEFORE</code> triggers are fired, and before any actual data + modifications are made. Thus a <code class="literal">BEFORE ROW</code> trigger may + modify the data to be inserted, affecting the result of the security + policy check. <code class="literal">WITH CHECK</code> expressions are enforced + before any other constraints. + </p><p> + Policy names are per-table. Therefore, one policy name can be used for many + different tables and have a definition for each table which is appropriate to + that table. + </p><p> + Policies can be applied for specific commands or for specific roles. The + default for newly created policies is that they apply for all commands and + roles, unless otherwise specified. Multiple policies may apply to a single + command; see below for more details. + <a class="xref" href="sql-createpolicy.html#SQL-CREATEPOLICY-SUMMARY" title="Table 292. Policies Applied by Command Type">Table 292</a> summarizes how the different types + of policy apply to specific commands. + </p><p> + For policies that can have both <code class="literal">USING</code> + and <code class="literal">WITH CHECK</code> expressions (<code class="literal">ALL</code> + and <code class="literal">UPDATE</code>), if no <code class="literal">WITH CHECK</code> + expression is defined, then the <code class="literal">USING</code> expression will be + used both to determine which rows are visible (normal + <code class="literal">USING</code> case) and which new rows will be allowed to be + added (<code class="literal">WITH CHECK</code> case). + </p><p> + If row-level security is enabled for a table, but no applicable policies + exist, a <span class="quote">“<span class="quote">default deny</span>”</span> policy is assumed, so that no rows will + be visible or updatable. + </p></div><div class="refsect1" id="id-1.9.3.75.6"><h2>Parameters</h2><div class="variablelist"><dl class="variablelist"><dt><span class="term"><em class="replaceable"><code>name</code></em></span></dt><dd><p> + The name of the policy to be created. This must be distinct from the + name of any other policy for the table. + </p></dd><dt><span class="term"><em class="replaceable"><code>table_name</code></em></span></dt><dd><p> + The name (optionally schema-qualified) of the table the + policy applies to. + </p></dd><dt><span class="term"><code class="literal">PERMISSIVE</code></span></dt><dd><p> + Specify that the policy is to be created as a permissive policy. + All permissive policies which are applicable to a given query will + be combined together using the Boolean <span class="quote">“<span class="quote">OR</span>”</span> operator. By creating + permissive policies, administrators can add to the set of records + which can be accessed. Policies are permissive by default. + </p></dd><dt><span class="term"><code class="literal">RESTRICTIVE</code></span></dt><dd><p> + Specify that the policy is to be created as a restrictive policy. + All restrictive policies which are applicable to a given query will + be combined together using the Boolean <span class="quote">“<span class="quote">AND</span>”</span> operator. By creating + restrictive policies, administrators can reduce the set of records + which can be accessed as all restrictive policies must be passed for + each record. + </p><p> + Note that there needs to be at least one permissive policy to grant + access to records before restrictive policies can be usefully used to + reduce that access. If only restrictive policies exist, then no records + will be accessible. When a mix of permissive and restrictive policies + are present, a record is only accessible if at least one of the + permissive policies passes, in addition to all the restrictive + policies. + </p></dd><dt><span class="term"><em class="replaceable"><code>command</code></em></span></dt><dd><p> + The command to which the policy applies. Valid options are + <code class="command">ALL</code>, <code class="command">SELECT</code>, + <code class="command">INSERT</code>, <code class="command">UPDATE</code>, + and <code class="command">DELETE</code>. + <code class="command">ALL</code> is the default. + See below for specifics regarding how these are applied. + </p></dd><dt><span class="term"><em class="replaceable"><code>role_name</code></em></span></dt><dd><p> + The role(s) to which the policy is to be applied. The default is + <code class="literal">PUBLIC</code>, which will apply the policy to all roles. + </p></dd><dt><span class="term"><em class="replaceable"><code>using_expression</code></em></span></dt><dd><p> + Any <acronym class="acronym">SQL</acronym> conditional expression (returning + <code class="type">boolean</code>). The conditional expression cannot contain + any aggregate or window functions. This expression will be added + to queries that refer to the table if row-level security is enabled. + Rows for which the expression returns true will be visible. Any + rows for which the expression returns false or null will not be + visible to the user (in a <code class="command">SELECT</code>), and will not be + available for modification (in an <code class="command">UPDATE</code> + or <code class="command">DELETE</code>). Such rows are silently suppressed; no error + is reported. + </p></dd><dt><span class="term"><em class="replaceable"><code>check_expression</code></em></span></dt><dd><p> + Any <acronym class="acronym">SQL</acronym> conditional expression (returning + <code class="type">boolean</code>). The conditional expression cannot contain + any aggregate or window functions. This expression will be used in + <code class="command">INSERT</code> and <code class="command">UPDATE</code> queries against + the table if row-level security is enabled. Only rows for which the + expression evaluates to true will be allowed. An error will be thrown + if the expression evaluates to false or null for any of the records + inserted or any of the records that result from the update. Note that + the <em class="replaceable"><code>check_expression</code></em> is + evaluated against the proposed new contents of the row, not the + original contents. + </p></dd></dl></div><div class="refsect2" id="id-1.9.3.75.6.3"><h3>Per-Command Policies</h3><div class="variablelist"><dl class="variablelist"><dt id="SQL-CREATEPOLICY-ALL"><span class="term"><code class="literal">ALL</code></span> <a href="#SQL-CREATEPOLICY-ALL" class="id_link">#</a></dt><dd><p> + Using <code class="literal">ALL</code> for a policy means that it will apply + to all commands, regardless of the type of command. If an + <code class="literal">ALL</code> policy exists and more specific policies + exist, then both the <code class="literal">ALL</code> policy and the more + specific policy (or policies) will be applied. + Additionally, <code class="literal">ALL</code> policies will be applied to + both the selection side of a query and the modification side, using + the <code class="literal">USING</code> expression for both cases if only + a <code class="literal">USING</code> expression has been defined. + </p><p> + As an example, if an <code class="literal">UPDATE</code> is issued, then the + <code class="literal">ALL</code> policy will be applicable both to what the + <code class="literal">UPDATE</code> will be able to select as rows to be + updated (applying the <code class="literal">USING</code> expression), + and to the resulting updated rows, to check if they are permitted + to be added to the table (applying the <code class="literal">WITH CHECK</code> + expression, if defined, and the <code class="literal">USING</code> expression + otherwise). If an <code class="command">INSERT</code> + or <code class="command">UPDATE</code> command attempts to add rows to the + table that do not pass the <code class="literal">ALL</code> + policy's <code class="literal">WITH CHECK</code> expression, the entire + command will be aborted. + </p></dd><dt id="SQL-CREATEPOLICY-SELECT"><span class="term"><code class="literal">SELECT</code></span> <a href="#SQL-CREATEPOLICY-SELECT" class="id_link">#</a></dt><dd><p> + Using <code class="literal">SELECT</code> for a policy means that it will apply + to <code class="literal">SELECT</code> queries and whenever + <code class="literal">SELECT</code> permissions are required on the relation the + policy is defined for. The result is that only those records from the + relation that pass the <code class="literal">SELECT</code> policy will be + returned during a <code class="literal">SELECT</code> query, and that queries + that require <code class="literal">SELECT</code> permissions, such as + <code class="literal">UPDATE</code>, will also only see those records + that are allowed by the <code class="literal">SELECT</code> policy. + A <code class="literal">SELECT</code> policy cannot have a <code class="literal">WITH + CHECK</code> expression, as it only applies in cases where + records are being retrieved from the relation. + </p></dd><dt id="SQL-CREATEPOLICY-INSERT"><span class="term"><code class="literal">INSERT</code></span> <a href="#SQL-CREATEPOLICY-INSERT" class="id_link">#</a></dt><dd><p> + Using <code class="literal">INSERT</code> for a policy means that it will apply + to <code class="literal">INSERT</code> commands and <code class="literal">MERGE</code> + commands that contain <code class="literal">INSERT</code> actions. + Rows being inserted that do + not pass this policy will result in a policy violation error, and the + entire <code class="literal">INSERT</code> command will be aborted. + An <code class="literal">INSERT</code> policy cannot have + a <code class="literal">USING</code> expression, as it only applies in cases + where records are being added to the relation. + </p><p> + Note that <code class="literal">INSERT</code> with <code class="literal">ON CONFLICT DO + UPDATE</code> checks <code class="literal">INSERT</code> policies' + <code class="literal">WITH CHECK</code> expressions only for rows appended + to the relation by the <code class="literal">INSERT</code> path. + </p></dd><dt id="SQL-CREATEPOLICY-UPDATE"><span class="term"><code class="literal">UPDATE</code></span> <a href="#SQL-CREATEPOLICY-UPDATE" class="id_link">#</a></dt><dd><p> + Using <code class="literal">UPDATE</code> for a policy means that it will apply + to <code class="literal">UPDATE</code>, <code class="literal">SELECT FOR UPDATE</code> + and <code class="literal">SELECT FOR SHARE</code> commands, as well as + auxiliary <code class="literal">ON CONFLICT DO UPDATE</code> clauses of + <code class="literal">INSERT</code> commands. + <code class="literal">MERGE</code> commands containing <code class="literal">UPDATE</code> + actions are affected as well. Since <code class="literal">UPDATE</code> + involves pulling an existing record and replacing it with a new + modified record, <code class="literal">UPDATE</code> + policies accept both a <code class="literal">USING</code> expression and + a <code class="literal">WITH CHECK</code> expression. + The <code class="literal">USING</code> expression determines which records + the <code class="literal">UPDATE</code> command will see to operate against, + while the <code class="literal">WITH CHECK</code> expression defines which + modified rows are allowed to be stored back into the relation. + </p><p> + Any rows whose updated values do not pass the + <code class="literal">WITH CHECK</code> expression will cause an error, and the + entire command will be aborted. If only a <code class="literal">USING</code> + clause is specified, then that clause will be used for both + <code class="literal">USING</code> and <code class="literal">WITH CHECK</code> cases. + </p><p> + Typically an <code class="literal">UPDATE</code> command also needs to read + data from columns in the relation being updated (e.g., in a + <code class="literal">WHERE</code> clause or a <code class="literal">RETURNING</code> + clause, or in an expression on the right hand side of the + <code class="literal">SET</code> clause). In this case, + <code class="literal">SELECT</code> rights are also required on the relation + being updated, and the appropriate <code class="literal">SELECT</code> or + <code class="literal">ALL</code> policies will be applied in addition to + the <code class="literal">UPDATE</code> policies. Thus the user must have + access to the row(s) being updated through a <code class="literal">SELECT</code> + or <code class="literal">ALL</code> policy in addition to being granted + permission to update the row(s) via an <code class="literal">UPDATE</code> + or <code class="literal">ALL</code> policy. + </p><p> + When an <code class="literal">INSERT</code> command has an auxiliary + <code class="literal">ON CONFLICT DO UPDATE</code> clause, if the + <code class="literal">UPDATE</code> path is taken, the row to be updated is + first checked against the <code class="literal">USING</code> expressions of + any <code class="literal">UPDATE</code> policies, and then the new updated row + is checked against the <code class="literal">WITH CHECK</code> expressions. + Note, however, that unlike a standalone <code class="literal">UPDATE</code> + command, if the existing row does not pass the + <code class="literal">USING</code> expressions, an error will be thrown (the + <code class="literal">UPDATE</code> path will <span class="emphasis"><em>never</em></span> be silently + avoided). + </p></dd><dt id="SQL-CREATEPOLICY-DELETE"><span class="term"><code class="literal">DELETE</code></span> <a href="#SQL-CREATEPOLICY-DELETE" class="id_link">#</a></dt><dd><p> + Using <code class="literal">DELETE</code> for a policy means that it will apply + to <code class="literal">DELETE</code> commands. Only rows that pass this + policy will be seen by a <code class="literal">DELETE</code> command. There can + be rows that are visible through a <code class="literal">SELECT</code> that are + not available for deletion, if they do not pass the + <code class="literal">USING</code> expression for + the <code class="literal">DELETE</code> policy. + </p><p> + In most cases a <code class="literal">DELETE</code> command also needs to read + data from columns in the relation that it is deleting from (e.g., + in a <code class="literal">WHERE</code> clause or a + <code class="literal">RETURNING</code> clause). In this case, + <code class="literal">SELECT</code> rights are also required on the relation, + and the appropriate <code class="literal">SELECT</code> or + <code class="literal">ALL</code> policies will be applied in addition to + the <code class="literal">DELETE</code> policies. Thus the user must have + access to the row(s) being deleted through a <code class="literal">SELECT</code> + or <code class="literal">ALL</code> policy in addition to being granted + permission to delete the row(s) via a <code class="literal">DELETE</code> or + <code class="literal">ALL</code> policy. + </p><p> + A <code class="literal">DELETE</code> policy cannot have a <code class="literal">WITH + CHECK</code> expression, as it only applies in cases where + records are being deleted from the relation, so that there is no + new row to check. + </p></dd></dl></div><div class="table" id="SQL-CREATEPOLICY-SUMMARY"><p class="title"><strong>Table 292. Policies Applied by Command Type</strong></p><div class="table-contents"><table class="table" summary="Policies Applied by Command Type" border="1"><colgroup><col /><col /><col /><col class="update-using" /><col class="update-check" /><col /></colgroup><thead><tr><th rowspan="2">Command</th><th><code class="literal">SELECT/ALL policy</code></th><th><code class="literal">INSERT/ALL policy</code></th><th colspan="2"><code class="literal">UPDATE/ALL policy</code></th><th><code class="literal">DELETE/ALL policy</code></th></tr><tr><th><code class="literal">USING expression</code></th><th><code class="literal">WITH CHECK expression</code></th><th><code class="literal">USING expression</code></th><th><code class="literal">WITH CHECK expression</code></th><th><code class="literal">USING expression</code></th></tr></thead><tbody><tr><td><code class="command">SELECT</code></td><td>Existing row</td><td>—</td><td>—</td><td>—</td><td>—</td></tr><tr><td><code class="command">SELECT FOR UPDATE/SHARE</code></td><td>Existing row</td><td>—</td><td>Existing row</td><td>—</td><td>—</td></tr><tr><td><code class="command">INSERT</code> / <code class="command">MERGE ... THEN INSERT</code></td><td>—</td><td>New row</td><td>—</td><td>—</td><td>—</td></tr><tr><td><code class="command">INSERT ... RETURNING</code></td><td> + New row <a href="#ftn.RLS-SELECT-PRIV" class="footnote"><sup class="footnote" id="RLS-SELECT-PRIV">[a]</sup></a> + </td><td>New row</td><td>—</td><td>—</td><td>—</td></tr><tr><td><code class="command">UPDATE</code> / <code class="command">MERGE ... THEN UPDATE</code></td><td> + Existing & new rows <a href="sql-createpolicy.html#ftn.RLS-SELECT-PRIV" class="footnoteref"><sup class="footnoteref">[a]</sup></a> + </td><td>—</td><td>Existing row</td><td>New row</td><td>—</td></tr><tr><td><code class="command">DELETE</code></td><td> + Existing row <a href="sql-createpolicy.html#ftn.RLS-SELECT-PRIV" class="footnoteref"><sup class="footnoteref">[a]</sup></a> + </td><td>—</td><td>—</td><td>—</td><td>Existing row</td></tr><tr><td><code class="command">ON CONFLICT DO UPDATE</code></td><td>Existing & new rows</td><td>—</td><td>Existing row</td><td>New row</td><td>—</td></tr></tbody><tbody class="footnotes"><tr><td colspan="6"><div id="ftn.RLS-SELECT-PRIV" class="footnote"><p><a href="#RLS-SELECT-PRIV" class="para"><sup class="para">[a] </sup></a> + If read access is required to the existing or new row (for example, + a <code class="literal">WHERE</code> or <code class="literal">RETURNING</code> clause + that refers to columns from the relation). + </p></div></td></tr></tbody></table></div></div><br class="table-break" /></div><div class="refsect2" id="id-1.9.3.75.6.4"><h3>Application of Multiple Policies</h3><p> + When multiple policies of different command types apply to the same command + (for example, <code class="literal">SELECT</code> and <code class="literal">UPDATE</code> + policies applied to an <code class="literal">UPDATE</code> command), then the user + must have both types of permissions (for example, permission to select rows + from the relation as well as permission to update them). Thus the + expressions for one type of policy are combined with the expressions for + the other type of policy using the <code class="literal">AND</code> operator. + </p><p> + When multiple policies of the same command type apply to the same command, + then there must be at least one <code class="literal">PERMISSIVE</code> policy + granting access to the relation, and all of the + <code class="literal">RESTRICTIVE</code> policies must pass. Thus all the + <code class="literal">PERMISSIVE</code> policy expressions are combined using + <code class="literal">OR</code>, all the <code class="literal">RESTRICTIVE</code> policy + expressions are combined using <code class="literal">AND</code>, and the results are + combined using <code class="literal">AND</code>. If there are no + <code class="literal">PERMISSIVE</code> policies, then access is denied. + </p><p> + Note that, for the purposes of combining multiple policies, + <code class="literal">ALL</code> policies are treated as having the same type as + whichever other type of policy is being applied. + </p><p> + For example, in an <code class="literal">UPDATE</code> command requiring both + <code class="literal">SELECT</code> and <code class="literal">UPDATE</code> permissions, if + there are multiple applicable policies of each type, they will be combined + as follows: + +</p><pre class="programlisting"> +<em class="replaceable"><code>expression</code></em> from RESTRICTIVE SELECT/ALL policy 1 +AND +<em class="replaceable"><code>expression</code></em> from RESTRICTIVE SELECT/ALL policy 2 +AND +... +AND +( + <em class="replaceable"><code>expression</code></em> from PERMISSIVE SELECT/ALL policy 1 + OR + <em class="replaceable"><code>expression</code></em> from PERMISSIVE SELECT/ALL policy 2 + OR + ... +) +AND +<em class="replaceable"><code>expression</code></em> from RESTRICTIVE UPDATE/ALL policy 1 +AND +<em class="replaceable"><code>expression</code></em> from RESTRICTIVE UPDATE/ALL policy 2 +AND +... +AND +( + <em class="replaceable"><code>expression</code></em> from PERMISSIVE UPDATE/ALL policy 1 + OR + <em class="replaceable"><code>expression</code></em> from PERMISSIVE UPDATE/ALL policy 2 + OR + ... +) +</pre></div></div><div class="refsect1" id="id-1.9.3.75.7"><h2>Notes</h2><p> + You must be the owner of a table to create or change policies for it. + </p><p> + While policies will be applied for explicit queries against tables + in the database, 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 that is a 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 to 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 of keys with external meanings. + </p><p> + Generally, the system will enforce filter conditions imposed using + security policies prior to qualifications that appear in user queries, + in order to prevent inadvertent exposure of the protected data to + user-defined functions which might not be trustworthy. However, + functions and operators marked by the system (or the system + administrator) as <code class="literal">LEAKPROOF</code> may be evaluated before + policy expressions, as they are assumed to be trustworthy. + </p><p> + Since policy expressions + are added to the user's query directly, they will be run with the rights of + the user running the overall query. Therefore, users who are using a given + policy must be able to access any tables or functions referenced in the + expression or they will simply receive a permission denied error when + attempting to query the table that has row-level security enabled. + This does not change how views + work, however. As with normal queries and views, permission checks and + policies for the tables which are referenced by a view will use the view + owner's rights and any policies which apply to the view owner, except if + the view is defined using the <code class="literal">security_invoker</code> option + (see <a class="link" href="sql-createview.html" title="CREATE VIEW"><code class="command">CREATE VIEW</code></a>). + </p><p> + No separate policy exists for <code class="command">MERGE</code>. Instead, the policies + defined for <code class="command">SELECT</code>, <code class="command">INSERT</code>, + <code class="command">UPDATE</code>, and <code class="command">DELETE</code> are applied + while executing <code class="command">MERGE</code>, depending on the actions that are + performed. + </p><p> + Additional discussion and practical examples can be found + in <a class="xref" href="ddl-rowsecurity.html" title="5.8. Row Security Policies">Section 5.8</a>. + </p></div><div class="refsect1" id="id-1.9.3.75.8"><h2>Compatibility</h2><p> + <code class="command">CREATE POLICY</code> is a <span class="productname">PostgreSQL</span> + extension. + </p></div><div class="refsect1" id="id-1.9.3.75.9"><h2>See Also</h2><span class="simplelist"><a class="xref" href="sql-alterpolicy.html" title="ALTER POLICY"><span class="refentrytitle">ALTER POLICY</span></a>, <a class="xref" href="sql-droppolicy.html" title="DROP POLICY"><span class="refentrytitle">DROP POLICY</span></a>, <a class="xref" href="sql-altertable.html" title="ALTER TABLE"><span class="refentrytitle">ALTER TABLE</span></a></span></div></div><div class="navfooter"><hr /><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="sql-createopfamily.html" title="CREATE OPERATOR FAMILY">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="sql-commands.html" title="SQL Commands">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="sql-createprocedure.html" title="CREATE PROCEDURE">Next</a></td></tr><tr><td width="40%" align="left" valign="top">CREATE OPERATOR FAMILY </td><td width="20%" align="center"><a accesskey="h" href="index.html" title="PostgreSQL 16.2 Documentation">Home</a></td><td width="40%" align="right" valign="top"> CREATE PROCEDURE</td></tr></table></div></body></html>
\ No newline at end of file |