Now that we have seen the ideas, here is the promised example
of creating a new operator class. First, we need a set of
operators. The procedure for defining operators was discussed in
Chapter 11. For the complex_abs_ops operator class on B-trees, the
operators we require are:

absolute-value less-than (strategy 1)

absolute-value less-than-or-equal (strategy
2)

absolute-value equal (strategy 3)

absolute-value greater-than-or-equal (strategy
4)

absolute-value greater-than (strategy 5)

Suppose the code that implements these functions is stored in
the file PGROOT/src/tutorial/complex.c, which
we have compiled into PGROOT/src/tutorial/complex.so. Part
of the C code looks like this:

First, note that operators for less-than,
less-than-or-equal, equal, greater-than-or-equal, and
greater-than for complex are being
defined. We can only have one operator named, say, = and
taking type complex for both
operands. In this case we don't have any other operator = for
complex, but if we were building a
practical data type we'd probably want = to be the ordinary
equality operation for complex numbers. In that case, we'd
need to use some other operator name for complex_abs_eq.

Second, although PostgreSQL can cope with operators
having the same name as long as they have different input
data types, C can only cope with one global routine having a
given name, period. So we shouldn't name the C function
something simple like abs_eq.
Usually it's a good practice to include the data type name in
the C function name, so as not to conflict with functions for
other data types.

Third, we could have made the PostgreSQL name of the function
abs_eq, relying on PostgreSQL to distinguish it by input
data types from any other PostgreSQL function of the same name. To
keep the example simple, we make the function have the same
names at the C level and PostgreSQL level.

Finally, note that these operator functions return Boolean
values. In practice, all operators defined as index access
method strategies must return type boolean, since they must appear at the top level
of a WHERE clause to be used with an
index. (On the other hand, support functions return whatever
the particular access method expects -- in the case of the
comparison function for B-trees, a signed integer.)

The important things here are the procedure names (which are
the C functions defined above) and the restriction and join
selectivity functions. You should just use the selectivity
functions used in the example (see complex.source). Note that there are different
such functions for the less-than, equal, and greater-than cases.
These must be supplied or the optimizer will be unable to make
effective use of the index.

The next step is the registration of the comparison
"support routine" required by B-trees.
The C code that implements this is in the same file that contains
the operator procedures: