supplied, it is expected that the
<function>picksplit</function> function will classify them into more than
one node; otherwise it is not possible to split the leaf tuples
across multiple pages, which is the ultimate purpose of this
operation. Therefore, if the <function>picksplit</function> function
ends up placing all the leaf tuples in the same node, the core
SP-GiST code will override that decision and generate an inner
tuple in which the leaf tuples are assigned at random to several
identically-labeled nodes. Such a tuple is marked
<literal>allTheSame</literal> to signify that this has happened. The
<function>choose</function> and <function>inner_consistent</function> functions
must take suitable care with such inner tuples.
See <xref linkend="spgist-all-the-same"/> for more information.
</para>
<para>
<function>picksplit</function> can be applied to a single leaf tuple only
in the case that the <function>config</function> function set
<structfield>longValuesOK</structfield> to true and a larger-than-a-page input
value has been supplied. In this case the point of the operation is
to strip off a prefix and produce a new, shorter leaf datum value.
The call will be repeated until a leaf datum short enough to fit on
a page has been produced. See <xref linkend="spgist-limits"/> for
more information.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><function>inner_consistent</function></term>
<listitem>
<para>
Returns set of nodes (branches) to follow during tree search.
</para>
<para>
The <acronym>SQL</acronym> declaration of the function must look like this:
<programlisting>
CREATE FUNCTION my_inner_consistent(internal, internal) RETURNS void ...
</programlisting>
The first argument is a pointer to a <structname>spgInnerConsistentIn</structname>
C struct, containing input data for the function.
The second argument is a pointer to a <structname>spgInnerConsistentOut</structname>
C struct, which the function must fill with result data.
<programlisting>
typedef struct spgInnerConsistentIn
{
ScanKey scankeys; /* array of operators and comparison values */
ScanKey orderbys; /* array of ordering operators and comparison
* values */
int nkeys; /* length of scankeys array */
int norderbys; /* length of orderbys array */
Datum reconstructedValue; /* value reconstructed at parent */
void *traversalValue; /* opclass-specific traverse value */
MemoryContext traversalMemoryContext; /* put new traverse values here */
int level; /* current level (counting from zero) */
bool returnData; /* original data must be returned? */
/* Data from current inner tuple */
bool allTheSame; /* tuple is marked all-the-same? */
bool hasPrefix; /* tuple has a prefix? */
Datum prefixDatum; /* if so, the prefix value */
int nNodes; /* number of nodes in the inner tuple */
Datum *nodeLabels; /* node label values (NULL if none) */
} spgInnerConsistentIn;
typedef struct spgInnerConsistentOut
{
int nNodes; /* number of child nodes to be visited */
int *nodeNumbers; /* their indexes in the node array */
int *levelAdds; /* increment level by this much for each */
Datum *reconstructedValues; /* associated reconstructed values */
void **traversalValues; /* opclass-specific traverse values */
double **distances; /* associated distances */
} spgInnerConsistentOut;
</programlisting>
The array <structfield>scankeys</structfield>, of length <structfield>nkeys</structfield>,