distance function's result values can be any finite <type>float8</type>
values, so long as the relative order of the result values matches the
order returned by the ordering operator. (Infinity and minus infinity
are used internally to handle cases such as nulls, so it is not
recommended that <function>distance</function> functions return these values.)
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><function>fetch</function></term>
<listitem>
<para>
Converts the compressed index representation of a data item into the
original data type, for index-only scans. The returned data must be an
exact, non-lossy copy of the originally indexed value.
</para>
<para>
The <acronym>SQL</acronym> declaration of the function must look like this:
<programlisting>
CREATE OR REPLACE FUNCTION my_fetch(internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT;
</programlisting>
The argument is a pointer to a <structname>GISTENTRY</structname> struct. On
entry, its <structfield>key</structfield> field contains a non-NULL leaf datum in
compressed form. The return value is another <structname>GISTENTRY</structname>
struct, whose <structfield>key</structfield> field contains the same datum in its
original, uncompressed form. If the opclass's compress function does
nothing for leaf entries, the <function>fetch</function> method can return the
argument as-is. Or, if the opclass does not have a compress function,
the <function>fetch</function> method can be omitted as well, since it would
necessarily be a no-op.
</para>
<para>
The matching code in the C module could then follow this skeleton:
<programlisting>
PG_FUNCTION_INFO_V1(my_fetch);
Datum
my_fetch(PG_FUNCTION_ARGS)
{
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
input_data_type *in = DatumGetPointer(entry->key);
fetched_data_type *fetched_data;
GISTENTRY *retval;
retval = palloc(sizeof(GISTENTRY));
fetched_data = palloc(sizeof(fetched_data_type));
/*
* Convert 'fetched_data' into the a Datum of the original datatype.
*/
/* fill *retval from fetched_data. */
gistentryinit(*retval, PointerGetDatum(converted_datum),
entry->rel, entry->page, entry->offset, FALSE);
PG_RETURN_POINTER(retval);
}
</programlisting>
</para>
<para>
If the compress method is lossy for leaf entries, the operator class
cannot support index-only scans, and must not define
a <function>fetch</function> function.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><function>options</function></term>
<listitem>
<para>
Allows definition of user-visible parameters that control operator
class behavior.
</para>
<para>
The <acronym>SQL</acronym> declaration of the function must look like this:
<programlisting>
CREATE OR REPLACE FUNCTION my_options(internal)
RETURNS void
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT;
</programlisting>
</para>
<para>
The function is passed a pointer to a <structname>local_relopts</structname>
struct, which needs to be filled with a set of operator class
specific options. The options can be accessed from other support
functions using the <literal>PG_HAS_OPCLASS_OPTIONS()</literal> and
<literal>PG_GET_OPCLASS_OPTIONS()</literal> macros.
</para>
<para>
An example implementation of my_options() and parameters use
from other support functions are given below:
<programlisting>
typedef enum MyEnumType
{
MY_ENUM_ON,
MY_ENUM_OFF,
MY_ENUM_AUTO
} MyEnumType;
typedef struct
{
int32 vl_len_; /* varlena header (do not touch directly!) */
int int_param; /* integer parameter */
double real_param; /*