accurately, the function that the operator is based on). If not, then the
selectivity estimator will behave as if no statistics are available, and
the planner will proceed with default or fall-back assumptions.
+ The <xref linkend="app-psql"/> program's
+ <command><link linkend="app-psql-meta-command-do-lc">\do+</link></command>
+ meta-command is useful to determine which operators are marked as leakproof.
</para>
<para>
is specified, only members of operator families whose names match that
pattern are listed.
If <literal>+</literal> is appended to the command name, each operator
- is listed with its sort operator family (if it is an ordering operator).
+ is listed with its sort operator family (if it is an ordering operator),
+ and whether its underlying function is leakproof.
</para>
</listitem>
</varlistentry>
If <replaceable class="parameter">pattern</replaceable>
is specified, only casts whose source or target types match the
pattern are listed.
- If <literal>+</literal> is appended to the command name, each object
- is listed with its associated description.
+ If <literal>+</literal> is appended to the command name, additional
+ information about each cast is shown, including whether its underlying
+ function is leakproof, and the cast's description.
</para>
</listitem>
</varlistentry>
modifier to include system objects.
If the form <literal>\df+</literal> is used, additional information
about each function is shown, including volatility,
- parallel safety, owner, security classification, access privileges,
- language, internal name (for C and internal functions only),
- and description.
+ parallel safety, owner, security classification, whether it is
+ leakproof, access privileges, language, internal name (for C and
+ internal functions only), and description.
Source code for a specific function can be seen
using <literal>\sf</literal>.
</para>
pattern or the <literal>S</literal> modifier to include system
objects.
If <literal>+</literal> is appended to the command name,
- additional information about each operator is shown, currently just
- the name of the underlying function.
+ additional information about each operator is shown, including
+ the name of the underlying function, and whether it is leakproof.
</para>
</listitem>
</varlistentry>
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
PQExpBufferData buf;
PGresult *res;
printQueryOpt myopt = pset.popt;
- static const bool translate_columns[] = {false, false, false, false, true, true, true, false, true, false, false, false, false};
+ static const bool translate_columns[] = {false, false, false, false, true, true, true, false, true, true, false, false, false, false};
/* No "Parallel" column before 9.6 */
- static const bool translate_columns_pre_96[] = {false, false, false, false, true, true, false, true, false, false, false, false};
+ static const bool translate_columns_pre_96[] = {false, false, false, false, true, true, false, true, true, false, false, false, false};
if (strlen(functypes) != strspn(functypes, "anptwS+"))
{
gettext_noop("Parallel"));
appendPQExpBuffer(&buf,
",\n pg_catalog.pg_get_userbyid(p.proowner) as \"%s\""
- ",\n CASE WHEN prosecdef THEN '%s' ELSE '%s' END AS \"%s\"",
+ ",\n CASE WHEN prosecdef THEN '%s' ELSE '%s' END AS \"%s\""
+ ",\n CASE WHEN p.proleakproof THEN '%s' ELSE '%s' END as \"%s\"",
gettext_noop("Owner"),
gettext_noop("definer"),
gettext_noop("invoker"),
- gettext_noop("Security"));
+ gettext_noop("Security"),
+ gettext_noop("yes"),
+ gettext_noop("no"),
+ gettext_noop("Leakproof?"));
appendPQExpBufferStr(&buf, ",\n ");
printACLColumn(&buf, "p.proacl");
appendPQExpBuffer(&buf,
PQExpBufferData buf;
PGresult *res;
printQueryOpt myopt = pset.popt;
+ static const bool translate_columns[] = {false, false, false, false, false, false, true, false};
initPQExpBuffer(&buf);
if (verbose)
appendPQExpBuffer(&buf,
- " o.oprcode AS \"%s\",\n",
- gettext_noop("Function"));
+ " o.oprcode AS \"%s\",\n"
+ " CASE WHEN p.proleakproof THEN '%s' ELSE '%s' END AS \"%s\",\n",
+ gettext_noop("Function"),
+ gettext_noop("yes"),
+ gettext_noop("no"),
+ gettext_noop("Leakproof?"));
appendPQExpBuffer(&buf,
" coalesce(pg_catalog.obj_description(o.oid, 'pg_operator'),\n"
" LEFT JOIN pg_catalog.pg_namespace nt0 ON nt0.oid = t0.typnamespace\n");
}
+ if (verbose)
+ appendPQExpBufferStr(&buf,
+ " LEFT JOIN pg_catalog.pg_proc p ON p.oid = o.oprcode\n");
+
if (!showSystem && !oper_pattern)
appendPQExpBufferStr(&buf, "WHERE n.nspname <> 'pg_catalog'\n"
" AND n.nspname <> 'information_schema'\n");
myopt.title = _("List of operators");
myopt.translate_header = true;
+ myopt.translate_columns = translate_columns;
+ myopt.n_translate_columns = lengthof(translate_columns);
printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
PQExpBufferData buf;
PGresult *res;
printQueryOpt myopt = pset.popt;
- static const bool translate_columns[] = {false, false, false, true, false};
+ static const bool translate_columns[] = {false, false, false, true, true, false};
initPQExpBuffer(&buf);
if (verbose)
appendPQExpBuffer(&buf,
- ",\n d.description AS \"%s\"",
+ ",\n CASE WHEN p.proleakproof THEN '%s'\n"
+ " ELSE '%s'\n"
+ " END AS \"%s\",\n"
+ " d.description AS \"%s\"",
+ gettext_noop("yes"),
+ gettext_noop("no"),
+ gettext_noop("Leakproof?"),
gettext_noop("Description"));
/*
printQueryOpt myopt = pset.popt;
bool have_where = false;
- static const bool translate_columns[] = {false, false, false, false, false, false};
+ static const bool translate_columns[] = {false, false, false, false, false, false, true};
initPQExpBuffer(&buf);
if (verbose)
appendPQExpBuffer(&buf,
- ", ofs.opfname AS \"%s\"\n",
- gettext_noop("Sort opfamily"));
+ ", ofs.opfname AS \"%s\",\n"
+ " CASE\n"
+ " WHEN p.proleakproof THEN '%s'\n"
+ " ELSE '%s'\n"
+ " END AS \"%s\"\n",
+ gettext_noop("Sort opfamily"),
+ gettext_noop("yes"),
+ gettext_noop("no"),
+ gettext_noop("Leakproof?"));
appendPQExpBufferStr(&buf,
"FROM pg_catalog.pg_amop o\n"
" LEFT JOIN pg_catalog.pg_opfamily of ON of.oid = o.amopfamily\n"
" LEFT JOIN pg_catalog.pg_namespace nsf ON of.opfnamespace = nsf.oid\n");
if (verbose)
appendPQExpBufferStr(&buf,
- " LEFT JOIN pg_catalog.pg_opfamily ofs ON ofs.oid = o.amopsortfamily\n");
+ " LEFT JOIN pg_catalog.pg_opfamily ofs ON ofs.oid = o.amopsortfamily\n"
+ " LEFT JOIN pg_catalog.pg_operator op ON op.oid = o.amopopr\n"
+ " LEFT JOIN pg_catalog.pg_proc p ON p.oid = op.oprcode\n");
if (access_method_pattern)
{
btree | integer_ops | smallint, integer, bigint
(1 row)
-\dAo+ btree float_ops
- List of operators of operator families
- AM | Operator family | Operator | Strategy | Purpose | Sort opfamily
--------+-----------------+---------------------------------------+----------+---------+---------------
- btree | float_ops | <(double precision,double precision) | 1 | search |
- btree | float_ops | <=(double precision,double precision) | 2 | search |
- btree | float_ops | =(double precision,double precision) | 3 | search |
- btree | float_ops | >=(double precision,double precision) | 4 | search |
- btree | float_ops | >(double precision,double precision) | 5 | search |
- btree | float_ops | <(real,real) | 1 | search |
- btree | float_ops | <=(real,real) | 2 | search |
- btree | float_ops | =(real,real) | 3 | search |
- btree | float_ops | >=(real,real) | 4 | search |
- btree | float_ops | >(real,real) | 5 | search |
- btree | float_ops | <(double precision,real) | 1 | search |
- btree | float_ops | <=(double precision,real) | 2 | search |
- btree | float_ops | =(double precision,real) | 3 | search |
- btree | float_ops | >=(double precision,real) | 4 | search |
- btree | float_ops | >(double precision,real) | 5 | search |
- btree | float_ops | <(real,double precision) | 1 | search |
- btree | float_ops | <=(real,double precision) | 2 | search |
- btree | float_ops | =(real,double precision) | 3 | search |
- btree | float_ops | >=(real,double precision) | 4 | search |
- btree | float_ops | >(real,double precision) | 5 | search |
-(20 rows)
+\dAo+ btree array_ops|float_ops
+ List of operators of operator families
+ AM | Operator family | Operator | Strategy | Purpose | Sort opfamily | Leakproof?
+-------+-----------------+---------------------------------------+----------+---------+---------------+------------
+ btree | array_ops | <(anyarray,anyarray) | 1 | search | | no
+ btree | array_ops | <=(anyarray,anyarray) | 2 | search | | no
+ btree | array_ops | =(anyarray,anyarray) | 3 | search | | no
+ btree | array_ops | >=(anyarray,anyarray) | 4 | search | | no
+ btree | array_ops | >(anyarray,anyarray) | 5 | search | | no
+ btree | float_ops | <(double precision,double precision) | 1 | search | | yes
+ btree | float_ops | <=(double precision,double precision) | 2 | search | | yes
+ btree | float_ops | =(double precision,double precision) | 3 | search | | yes
+ btree | float_ops | >=(double precision,double precision) | 4 | search | | yes
+ btree | float_ops | >(double precision,double precision) | 5 | search | | yes
+ btree | float_ops | <(real,real) | 1 | search | | yes
+ btree | float_ops | <=(real,real) | 2 | search | | yes
+ btree | float_ops | =(real,real) | 3 | search | | yes
+ btree | float_ops | >=(real,real) | 4 | search | | yes
+ btree | float_ops | >(real,real) | 5 | search | | yes
+ btree | float_ops | <(double precision,real) | 1 | search | | yes
+ btree | float_ops | <=(double precision,real) | 2 | search | | yes
+ btree | float_ops | =(double precision,real) | 3 | search | | yes
+ btree | float_ops | >=(double precision,real) | 4 | search | | yes
+ btree | float_ops | >(double precision,real) | 5 | search | | yes
+ btree | float_ops | <(real,double precision) | 1 | search | | yes
+ btree | float_ops | <=(real,double precision) | 2 | search | | yes
+ btree | float_ops | =(real,double precision) | 3 | search | | yes
+ btree | float_ops | >=(real,double precision) | 4 | search | | yes
+ btree | float_ops | >(real,double precision) | 5 | search | | yes
+(25 rows)
\dAo * pg_catalog.jsonb_path_ops
List of operators of operator families
as $$ begin return; end; $$;
comment on function psql_df_plpgsql () is 'some comment';
\df+ psql_df_*
- List of functions
- Schema | Name | Result data type | Argument data types | Type | Volatility | Parallel | Owner | Security | Access privileges | Language | Internal name | Description
---------+------------------+------------------+---------------------+------+------------+----------+-------------------+----------+-------------------+----------+---------------+--------------
- public | psql_df_internal | double precision | double precision | func | immutable | safe | regress_psql_user | invoker | | internal | dsin |
- public | psql_df_plpgsql | void | | func | volatile | unsafe | regress_psql_user | invoker | | plpgsql | | some comment
- public | psql_df_sql | integer | x integer | func | volatile | unsafe | regress_psql_user | definer | | sql | |
+ List of functions
+ Schema | Name | Result data type | Argument data types | Type | Volatility | Parallel | Owner | Security | Leakproof? | Access privileges | Language | Internal name | Description
+--------+------------------+------------------+---------------------+------+------------+----------+-------------------+----------+------------+-------------------+----------+---------------+--------------
+ public | psql_df_internal | double precision | double precision | func | immutable | safe | regress_psql_user | invoker | no | | internal | dsin |
+ public | psql_df_plpgsql | void | | func | volatile | unsafe | regress_psql_user | invoker | no | | plpgsql | | some comment
+ public | psql_df_sql | integer | x integer | func | volatile | unsafe | regress_psql_user | definer | no | | sql | |
(3 rows)
rollback;
CREATE PROCEDURE regress_zeropriv_proc() LANGUAGE sql AS '';
REVOKE ALL ON PROCEDURE regress_zeropriv_proc() FROM CURRENT_USER, PUBLIC;
\df+ regress_zeropriv_proc
- List of functions
- Schema | Name | Result data type | Argument data types | Type | Volatility | Parallel | Owner | Security | Access privileges | Language | Internal name | Description
---------+-----------------------+------------------+---------------------+------+------------+----------+------------------------+----------+-------------------+----------+---------------+-------------
- public | regress_zeropriv_proc | | | proc | volatile | unsafe | regress_zeropriv_owner | invoker | (none) | sql | |
+ List of functions
+ Schema | Name | Result data type | Argument data types | Type | Volatility | Parallel | Owner | Security | Leakproof? | Access privileges | Language | Internal name | Description
+--------+-----------------------+------------------+---------------------+------+------------+----------+------------------------+----------+------------+-------------------+----------+---------------+-------------
+ public | regress_zeropriv_proc | | | proc | volatile | unsafe | regress_zeropriv_owner | invoker | no | (none) | sql | |
(1 row)
CREATE TABLE regress_zeropriv_tbl (a int);
\dAc brin pg*.oid*
\dAf spgist
\dAf btree int4
-\dAo+ btree float_ops
+\dAo+ btree array_ops|float_ops
\dAo * pg_catalog.jsonb_path_ops
\dAp+ btree float_ops
\dAp * pg_catalog.uuid_ops