unionR
* accordingly. Append the entries to either v->spl_left or
* v->spl_right, and care about the counters.
*/
if (my_choice_is_left(unionL, curl, unionR, curr))
{
if (unionL == NULL)
unionL = tmp_union;
else
unionL = my_union_implementation(unionL, tmp_union);
*left = real_index;
++left;
++(v->spl_nleft);
}
else
{
/*
* Same on the right
*/
}
}
v->spl_ldatum = DataTypeGetDatum(unionL);
v->spl_rdatum = DataTypeGetDatum(unionR);
PG_RETURN_POINTER(v);
}
</programlisting>
Notice that the <function>picksplit</function> function's result is delivered
by modifying the passed-in <structname>v</structname> structure. The return
value per se is ignored, though it's conventional to pass back the
address of <structname>v</structname>.
</para>
<para>
Like <function>penalty</function>, the <function>picksplit</function> function
is crucial to good performance of the index. Designing suitable
<function>penalty</function> and <function>picksplit</function> implementations
is where the challenge of implementing well-performing
<acronym>GiST</acronym> indexes lies.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><function>same</function></term>
<listitem>
<para>
Returns true if two index entries are identical, false otherwise.
(An <quote>index entry</quote> is a value of the index's storage type,
not necessarily the original indexed column's type.)
</para>
<para>
The <acronym>SQL</acronym> declaration of the function must look like this:
<programlisting>
CREATE OR REPLACE FUNCTION my_same(storage_type, storage_type, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT;
</programlisting>
And the matching code in the C module could then follow this skeleton:
<programlisting>
PG_FUNCTION_INFO_V1(my_same);
Datum
my_same(PG_FUNCTION_ARGS)
{
prefix_range *v1 = PG_GETARG_PREFIX_RANGE_P(0);
prefix_range *v2 = PG_GETARG_PREFIX_RANGE_P(1);
bool *result = (bool *) PG_GETARG_POINTER(2);
*result = my_eq(v1, v2);
PG_RETURN_POINTER(result);
}
</programlisting>
For historical reasons, the <function>same</function> function doesn't
just return a Boolean result; instead it has to store the flag
at the location indicated by the third argument. The return
value per se is ignored, though it's conventional to pass back the
address of that argument.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><function>distance</function></term>
<listitem>
<para>
Given an index entry <literal>p</literal> and a query value <literal>q</literal>,
this function determines the index entry's
<quote>distance</quote> from the query value. This function must be
supplied if the operator class contains any ordering operators.
A query using the ordering operator will be implemented by returning
index entries with the smallest <quote>distance</quote> values first,
so the results must be consistent with the operator's semantics.
For a leaf index entry the result just represents the distance to
the index entry; for an internal tree node, the result must be the
smallest distance that any child entry could have.
</para>
<para>
The <acronym>SQL</acronym> declaration of the function must look like this:
<programlisting>
CREATE OR REPLACE FUNCTION my_distance(internal, data_type, smallint, oid, internal)
RETURNS float8
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT;
</programlisting>
And the matching code in the C module could then follow this skeleton:
<programlisting>