<literal>OPERATOR(<replaceable>schema</replaceable>.=) ANY</literal>
and <literal>CASE WHEN <replaceable>expression</replaceable></literal>.
</para>
<para>
A general-purpose extension usually should not assume that it's been
installed into a secure schema, which means that even schema-qualified
references to its own objects are not entirely risk-free. For
example, if the extension has defined a
function <literal>myschema.myfunc(bigint)</literal> then a call such
as <literal>myschema.myfunc(42)</literal> could be captured by a
hostile function <literal>myschema.myfunc(integer)</literal>. Be
careful that the data types of function and operator parameters exactly
match the declared argument types, using explicit casts where necessary.
</para>
</sect3>
<sect3 id="extend-extensions-security-scripts">
<title>Security Considerations for Extension Scripts</title>
<para>
An extension installation or update script should be written to guard
against search-path-based attacks occurring when the script executes.
If an object reference in the script can be made to resolve to some
other object than the script author intended, then a compromise might
occur immediately, or later when the mis-defined extension object is
used.
</para>
<para>
DDL commands such as <command>CREATE FUNCTION</command>
and <command>CREATE OPERATOR CLASS</command> are generally secure,
but beware of any command having a general-purpose expression as a
component. For example, <command>CREATE VIEW</command> needs to be
vetted, as does a <literal>DEFAULT</literal> expression
in <command>CREATE FUNCTION</command>.
</para>
<para>
Sometimes an extension script might need to execute general-purpose
SQL, for example to make catalog adjustments that aren't possible via
DDL. Be careful to execute such commands with a
secure <varname>search_path</varname>; do <emphasis>not</emphasis>
trust the path provided by <command>CREATE/ALTER EXTENSION</command>
to be secure. Best practice is to temporarily
set <varname>search_path</varname> to <literal>pg_catalog,
pg_temp</literal> and insert references to the extension's
installation schema explicitly where needed. (This practice might
also be helpful for creating views.) Examples can be found in
the <filename>contrib</filename> modules in
the <productname>PostgreSQL</productname> source code distribution.
</para>
<para>
Secure cross-extension references typically require schema-qualification
of the names of the other extension's objects, using the
<literal>@extschema:<replaceable>name</replaceable>@</literal>
syntax, in addition to careful matching of argument types for functions
and operators.
</para>
</sect3>
</sect2>
<sect2 id="extend-extensions-example">
<title>Extension Example</title>
<para>
Here is a complete example of an <acronym>SQL</acronym>-only
extension, a two-element composite type that can store any type of value
in its slots, which are named <quote>k</quote> and <quote>v</quote>. Non-text
values are automatically coerced to text for storage.
</para>
<para>
The script file <filename>pair--1.0.sql</filename> looks like this:
<programlisting><![CDATA[
-- complain if script is sourced in psql, rather than via CREATE EXTENSION
\echo Use "CREATE EXTENSION pair" to load this file. \quit
CREATE TYPE pair AS ( k text, v text );
CREATE FUNCTION pair(text, text)
RETURNS pair LANGUAGE SQL AS 'SELECT ROW($1, $2)::@extschema@.pair;';
CREATE OPERATOR ~> (LEFTARG = text, RIGHTARG = text, FUNCTION = pair);
-- "SET search_path" is easy to get right, but qualified names perform better.
CREATE FUNCTION lower(pair)
RETURNS pair LANGUAGE SQL
AS 'SELECT ROW(lower($1.k), lower($1.v))::@extschema@.pair;'