with functions for other data types.
</para>
</listitem>
<listitem>
<para>
We could have made the SQL name
of the function <filename>abs_eq</filename>, relying on
<productname>PostgreSQL</productname> to distinguish it by
argument data types from any other SQL function of the same name.
To keep the example simple, we make the function have the same
names at the C level and SQL level.
</para>
</listitem>
</itemizedlist>
</para>
<para>
The next step is the registration of the support routine required
by B-trees. The example C code that implements this is in the same
file that contains the operator functions. This is how we declare
the function:
<programlisting>
CREATE FUNCTION complex_abs_cmp(complex, complex)
RETURNS integer
AS '<replaceable>filename</replaceable>'
LANGUAGE C IMMUTABLE STRICT;
</programlisting>
</para>
<para>
Now that we have the required operators and support routine,
we can finally create the operator class:
<programlisting><![CDATA[
CREATE OPERATOR CLASS complex_abs_ops
DEFAULT FOR TYPE complex USING btree AS
OPERATOR 1 < ,
OPERATOR 2 <= ,
OPERATOR 3 = ,
OPERATOR 4 >= ,
OPERATOR 5 > ,
FUNCTION 1 complex_abs_cmp(complex, complex);
]]>
</programlisting>
</para>
<para>
And we're done! It should now be possible to create
and use B-tree indexes on <type>complex</type> columns.
</para>
<para>
We could have written the operator entries more verbosely, as in:
<programlisting>
OPERATOR 1 < (complex, complex) ,
</programlisting>
but there is no need to do so when the operators take the same data type
we are defining the operator class for.
</para>
<para>
The above example assumes that you want to make this new operator class the
default B-tree operator class for the <type>complex</type> data type.
If you don't, just leave out the word <literal>DEFAULT</literal>.
</para>
</sect2>
<sect2 id="xindex-opfamily">
<title>Operator Classes and Operator Families</title>
<para>
So far we have implicitly assumed that an operator class deals with
only one data type. While there certainly can be only one data type in
a particular index column, it is often useful to index operations that
compare an indexed column to a value of a different data type. Also,
if there is use for a cross-data-type operator in connection with an
operator class, it is often the case that the other data type has a
related operator class of its own. It is helpful to make the connections
between related classes explicit, because this can aid the planner in
optimizing SQL queries (particularly for B-tree operator classes, since
the planner contains a great deal of knowledge about how to work with them).
</para>
<para>
To handle these needs, <productname>PostgreSQL</productname>
uses the concept of an <firstterm>operator
family</firstterm><indexterm><primary>operator family</primary></indexterm>.
An operator family contains one or more operator classes, and can also
contain indexable operators and corresponding support functions that
belong to the family as a whole but not to any single class within the
family. We say that such operators and functions are <quote>loose</quote>
within the family, as opposed to being bound into a specific class.
Typically each operator class contains single-data-type operators
while cross-data-type operators are loose in the family.
</para>
<para>
All the operators and functions in an operator family must have compatible
semantics, where the compatibility requirements are set by the index
method. You might therefore wonder why bother to single out particular
subsets of the family as operator classes; and indeed for many purposes
the class divisions