<literal>INSERT</literal>, <literal>UPDATE</literal>, and <literal>DELETE</literal> on
the <literal>shoelace</literal> view to someone else, but only
<literal>SELECT</literal> on <literal>shoelace_log</literal>. The rule action to
write log entries will still be executed successfully, and that
other user could see the log entries. But they could not create fake
entries, nor could they manipulate or remove existing ones. In this
case, there is no possibility of subverting the rules by convincing
the planner to alter the order of operations, because the only rule
which references <literal>shoelace_log</literal> is an unqualified
<literal>INSERT</literal>. This might not be true in more complex scenarios.
</para>
<para>
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 passed values from rows until after the view has done its work. For
example, if the view shown above had been created like this, it would
be secure:
<programlisting>
CREATE VIEW phone_number WITH (security_barrier) AS
SELECT person, phone FROM phone_data WHERE phone NOT LIKE '412%';
</programlisting>
Views created with the <literal>security_barrier</literal> may perform
far worse than views created without this option. In general, there is
no way to avoid this: the fastest possible plan must be rejected
if it may compromise security. For this reason, this option is not
enabled by default.
</para>
<para>
The query planner has more flexibility when dealing with functions that
have no side effects. Such functions are referred to as <literal>LEAKPROOF</literal>, and
include many simple, commonly used operators, such as many equality
operators. The query planner can safely allow such functions to be evaluated
at any point in the query execution process, since invoking them on rows
invisible to the user will not leak any information about the unseen rows.
Further, functions which do not take arguments or which are not passed any
arguments from the security barrier view do not have to be marked as
<literal>LEAKPROOF</literal> to be pushed down, as they never receive data
from the view. In contrast, a function that might throw an error depending
on the values received as arguments (such as one that throws an error in the
event of overflow or division by zero) is not leakproof, and could provide
significant information about the unseen rows if applied before the security
view's row filters.
</para>
<para>
For example, an index scan cannot be selected for queries on security
barrier views (or tables with row-level security policies) if an
operator used in the <literal>WHERE</literal> clause is associated with the
operator family of the index, but its underlying function is not marked
<literal>LEAKPROOF</literal>. The <xref linkend="app-psql"/> program's
<command><link linkend="app-psql-meta-command-dao">\dAo+</link></command>
meta-command is useful to list operator families and determine which of
their operators are marked as leakproof.
</para>
<para>
It is important to understand that even a view created with the
<literal>security_barrier</literal> option is intended to be secure only
in the limited sense that the contents of the invisible tuples will not be
passed to possibly-insecure functions. The user may well have other means
of making inferences about the unseen data; for example, they can see the
query plan using <command>EXPLAIN</command>, or measure the run time of
queries against the view. A malicious attacker might be able to infer
something about the amount of unseen data, or even gain some information
about the data distribution or most common values (since these things may
affect