speedups in execution
of queries that use the operator. But if you provide them, you must be
sure that they are right! Incorrect use of an optimization clause can
result in slow queries, subtly wrong output, or other Bad Things.
You can always leave out an optimization clause if you are not sure
about it; the only consequence is that queries might run slower than
they need to.
</para>
<para>
Additional optimization clauses might be added in future versions of
<productname>PostgreSQL</productname>. The ones described here are all
the ones that release &version; understands.
</para>
<para>
It is also possible to attach a planner support function to the function
that underlies an operator, providing another way of telling the system
about the behavior of the operator.
See <xref linkend="xfunc-optimization"/> for more information.
</para>
<sect2 id="xoper-commutator">
<title><literal>COMMUTATOR</literal></title>
<para>
The <literal>COMMUTATOR</literal> clause, if provided, names an operator that is the
commutator of the operator being defined. We say that operator A is the
commutator of operator B if (x A y) equals (y B x) for all possible input
values x, y. Notice that B is also the commutator of A. For example,
operators <literal><</literal> and <literal>></literal> for a particular data type are usually each others'
commutators, and operator <literal>+</literal> is usually commutative with itself.
But operator <literal>-</literal> is usually not commutative with anything.
</para>
<para>
The left operand type of a commutable operator is the same as the
right operand type of its commutator, and vice versa. So the name of
the commutator operator is all that <productname>PostgreSQL</productname>
needs to be given to look up the commutator, and that's all that needs to
be provided in the <literal>COMMUTATOR</literal> clause.
</para>
<para>
It's critical to provide commutator information for operators that
will be used in indexes and join clauses, because this allows the
query optimizer to <quote>flip around</quote> such a clause to the forms
needed for different plan types. For example, consider a query with
a WHERE clause like <literal>tab1.x = tab2.y</literal>, where <literal>tab1.x</literal>
and <literal>tab2.y</literal> are of a user-defined type, and suppose that
<literal>tab2.y</literal> is indexed. The optimizer cannot generate an
index scan unless it can determine how to flip the clause around to
<literal>tab2.y = tab1.x</literal>, because the index-scan machinery expects
to see the indexed column on the left of the operator it is given.
<productname>PostgreSQL</productname> will <emphasis>not</emphasis> simply
assume that this is a valid transformation — the creator of the
<literal>=</literal> operator must specify that it is valid, by marking the
operator with commutator information.
</para>
</sect2>
<sect2 id="xoper-negator">
<title><literal>NEGATOR</literal></title>
<para>
The <literal>NEGATOR</literal> clause, if provided, names an operator that is the
negator of the operator being defined. We say that operator A
is the negator of operator B if both return Boolean results and
(x A y) equals NOT (x B y) for all possible inputs x, y.
Notice that B is also the negator of A.
For example, <literal><</literal> and <literal>>=</literal> are a negator pair for most data types.
An operator can never validly be its own negator.
</para>
<para>
Unlike commutators, a pair of unary operators could validly be marked
as each other's negators; that would mean (A x) equals NOT (B x)
for all x.
</para>
<para>
An operator's negator must have the same left and/or right operand types
as the operator