diff --git a/doc/src/sgml/ref/create_policy.sgml b/doc/src/sgml/ref/create_policy.sgml index e76c342d3da6..42d43ad7bf41 100644 --- a/doc/src/sgml/ref/create_policy.sgml +++ b/doc/src/sgml/ref/create_policy.sgml @@ -49,6 +49,8 @@ CREATE POLICY name ON WITH CHECK. When a USING 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. + Typically, no error occurs when a row is not visible, but see + for exceptions. When a WITH CHECK expression returns true for a row then that row is inserted or updated, while if false or null is returned then an error occurs. @@ -194,8 +196,9 @@ CREATE POLICY name ON SELECT), and will not be available for modification (in an UPDATE - or DELETE). Such rows are silently suppressed; no error - is reported. + or DELETE). Typically, such rows are silently + suppressed; no error is reported (but see + for exceptions). @@ -251,8 +254,10 @@ CREATE POLICY name ON INSERT or UPDATE command attempts to add rows to the table that do not pass the ALL - policy's WITH CHECK expression, the entire - command will be aborted. + policy's WITH CHECK expression (or its + USING expression, if it does not have a + WITH CHECK expression), the entire command will + be aborted. @@ -268,11 +273,50 @@ CREATE POLICY name ON SELECT policy will be returned during a SELECT query, and that queries that require SELECT permissions, such as - UPDATE, will also only see those records + UPDATE, DELETE, and + MERGE, will also only see those records that are allowed by the SELECT policy. A SELECT policy cannot have a WITH CHECK expression, as it only applies in cases where - records are being retrieved from the relation. + records are being retrieved from the relation, except as described + below. + + + If a data-modifying query has a RETURNING clause, + SELECT permissions are required on the relation, + and any newly inserted or updated rows from the relation must satisfy + the relation's SELECT policies in order to be + available to the RETURNING clause. If a newly + inserted or updated row does not satisfy the relation's + SELECT policies, an error will be thrown (inserted + or updated rows to be returned are never + silently ignored). + + + If an INSERT has an ON CONFLICT DO + NOTHING/UPDATE clause, SELECT + permissions are required on the relation, and the rows proposed for + insertion are checked using the relation's SELECT + policies. If a row proposed for insertion does not satisfy the + relation's SELECT policies, an error is thrown + (the INSERT is never silently + avoided). In addition, if the UPDATE path is + taken, the row to be updated and the new updated row are checked + against the relation's SELECT policies, and an + error is thrown if they are not satisfied (an auxiliary + UPDATE is never silently + avoided). + + + A MERGE command requires SELECT + permissions on both the source and target relations, and so each + relation's SELECT policies are applied before they + are joined, and the MERGE actions will only see + those records that are allowed by those policies. In addition, if + an UPDATE action is executed, the target relation's + SELECT policies are applied to the updated row, as + for a standalone UPDATE, except that an error is + thrown if they are not satisfied. @@ -292,10 +336,11 @@ CREATE POLICY name ON - Note that INSERT with ON CONFLICT DO - UPDATE checks INSERT policies' - WITH CHECK expressions only for rows appended - to the relation by the INSERT path. + Note that an INSERT with an ON CONFLICT + DO NOTHING/UPDATE clause will check the + INSERT policies' WITH CHECK + expressions for all rows proposed for insertion, regardless of + whether or not they end up being inserted. @@ -305,12 +350,12 @@ CREATE POLICY name ON Using UPDATE for a policy means that it will apply - to UPDATE, SELECT FOR UPDATE + to UPDATE, SELECT FOR UPDATE, and SELECT FOR SHARE commands, as well as auxiliary ON CONFLICT DO UPDATE clauses of - INSERT commands. - MERGE commands containing UPDATE - actions are affected as well. Since UPDATE + INSERT commands, and MERGE + commands containing UPDATE actions. + Since an UPDATE command involves pulling an existing record and replacing it with a new modified record, UPDATE policies accept both a USING expression and @@ -356,7 +401,8 @@ CREATE POLICY name ON USING expressions, an error will be thrown (the UPDATE path will never be silently - avoided). + avoided). The same applies to an UPDATE action + of a MERGE command. @@ -366,12 +412,18 @@ CREATE POLICY name ON Using DELETE for a policy means that it will apply - to DELETE commands. Only rows that pass this - policy will be seen by a DELETE command. There can - be rows that are visible through a SELECT that are - not available for deletion, if they do not pass the - USING expression for - the DELETE policy. + to DELETE commands and MERGE + commands containing DELETE actions. For a + DELETE command, only rows that pass this policy + will be seen by the DELETE command. There can + be rows that are visible through a SELECT policy + that are not available for deletion, if they do not pass the + USING expression for the DELETE + policy. Note, however, that a DELETE action in a + MERGE command will see rows that are visible + through SELECT policies, and if the + DELETE policy does not pass for such a row, an + error will be thrown. @@ -400,6 +452,15 @@ CREATE POLICY name ON + + summarizes how the different + types of policy apply to specific commands. In the table, + check means that the policy expression is checked and an + error is thrown if it returns false or null, whereas filter + means that the row is silently ignored if the policy expression returns + false or null. + + Policies Applied by Command Type @@ -424,8 +485,8 @@ CREATE POLICY name ON - SELECT - Existing row + SELECT / COPY ... TO + Filter existing row @@ -433,63 +494,117 @@ CREATE POLICY name ON SELECT FOR UPDATE/SHARE - Existing row + Filter existing row - Existing row + Filter existing row - INSERT / MERGE ... THEN INSERT + INSERT + + Check new row  + + If read access is required to either the existing or new row (for + example, a WHERE or RETURNING + clause that refers to columns from the relation). + + + + Check new row - New row + + + UPDATE + + Filter existing row  & + check new row  + + + Filter existing row + Check new row - INSERT ... RETURNING + DELETE - New row + Filter existing row  + + + + + Filter existing row + + + INSERT ... ON CONFLICT + + Check new row  - If read access is required to the existing or new row (for example, - a WHERE or RETURNING clause - that refers to columns from the relation). + Row proposed for insertion is checked regardless of whether or not a + conflict occurs. - New row + + Check new row  + - UPDATE / MERGE ... THEN UPDATE + ON CONFLICT DO UPDATE - Existing & new rows + Check existing & new rows  + + New row of the auxiliary UPDATE command, which + might be different from the new row of the original + INSERT command. + + - Existing row - New row + Check existing row + + Check new row  + - DELETE + MERGE + Filter source & target rows + + + + + + + MERGE ... THEN INSERT - Existing row + Check new row  + Check new row - Existing row - ON CONFLICT DO UPDATE - Existing & new rows + MERGE ... THEN UPDATE + Check new row + + Check existing row + Check new row + + + + MERGE ... THEN DELETE + + - Existing row - New row + Check existing row