head	1.32;
access;
symbols
	REL9_0_0:1.31.14.1
	REL9_1_ALPHA1:1.32
	REL9_0_RC1:1.31.14.1
	REL9_0_BETA4:1.31
	REL9_0_STABLE:1.31.0.14
	REL9_0_BETA3:1.31
	REL9_0_BETA2:1.31
	REL7_4_29:1.13
	REL8_0_25:1.15
	REL8_1_21:1.24
	REL8_2_17:1.27
	REL8_3_11:1.29
	REL8_4_4:1.31
	REL9_0_BETA1:1.31
	REL9_0_ALPHA5_BRANCH:1.31.0.12
	REL9_0_ALPHA5:1.31
	REL7_4_28:1.13
	REL8_0_24:1.15
	REL8_1_20:1.24
	REL8_2_16:1.27
	REL8_3_10:1.29
	REL8_4_3:1.31
	REL9_0_ALPHA4:1.31
	REL9_0_ALPHA4_BRANCH:1.31.0.10
	REL8_5_ALPHA3:1.31
	REL8_5_ALPHA3_BRANCH:1.31.0.8
	REL7_4_27:1.13
	REL8_0_23:1.15
	REL8_1_19:1.24
	REL8_2_15:1.27
	REL8_3_9:1.29
	REL8_4_2:1.31
	REL8_5_ALPHA2:1.31
	REL8_5_ALPHA2_BRANCH:1.31.0.6
	REL7_4_26:1.13
	REL8_0_22:1.15
	REL8_1_18:1.24
	REL8_2_14:1.27
	REL8_3_8:1.29
	REL8_4_1:1.31
	REL8_5_ALPHA1:1.31
	REL8_5_ALPHA1_BRANCH:1.31.0.4
	REL8_4_STABLE:1.31.0.2
	REL8_4_0:1.31
	REL8_4_RC2:1.31
	REL8_4_RC1:1.30
	REL8_4_BETA2:1.30
	REL8_4_BETA1:1.30
	REL7_4_25:1.13
	REL8_0_21:1.15
	REL8_1_17:1.24
	REL8_2_13:1.27
	REL8_3_7:1.29
	REL7_4_24:1.13
	REL8_0_20:1.15
	REL8_1_16:1.24
	REL8_2_12:1.27
	REL8_3_6:1.29
	REL7_4_23:1.13
	REL8_0_19:1.15
	REL8_1_15:1.24
	REL8_2_11:1.27
	REL8_3_5:1.29
	REL7_4_22:1.13
	REL8_0_18:1.15
	REL8_1_14:1.24
	REL8_2_10:1.27
	REL8_3_4:1.29
	REL7_4_21:1.13
	REL8_0_17:1.15
	REL8_1_13:1.24
	REL8_2_9:1.27
	REL8_3_3:1.29
	REL7_4_20:1.13
	REL8_0_16:1.15
	REL8_1_12:1.24
	REL8_2_8:1.27
	REL8_3_2:1.29
	REL8_2_7:1.27
	REL8_3_1:1.29
	REL8_3_STABLE:1.29.0.2
	REL8_3_0:1.29
	REL8_3_RC2:1.29
	REL7_3_21:1.11
	REL7_4_19:1.13
	REL8_0_15:1.15
	REL8_1_11:1.24
	REL8_2_6:1.27
	REL8_3_RC1:1.29
	REL8_3_BETA4:1.29
	REL8_3_BETA3:1.29
	REL8_3_BETA2:1.28
	REL8_3_BETA1:1.28
	REL7_3_20:1.11
	REL7_4_18:1.13
	REL8_0_14:1.15
	REL8_1_10:1.24
	REL8_2_5:1.27
	REL7_3_19:1.11
	REL7_4_17:1.13
	REL8_0_13:1.15
	REL8_1_9:1.24
	REL8_2_4:1.27
	REL8_0_12:1.15
	REL8_1_8:1.24
	REL8_2_3:1.27
	REL7_3_18:1.11
	REL7_4_16:1.13
	REL8_0_11:1.15
	REL8_1_7:1.24
	REL8_2_2:1.27
	REL8_0_10:1.15
	REL8_1_6:1.24
	REL8_2_1:1.27
	REL7_4_15:1.13
	REL7_3_17:1.11
	REL8_2_STABLE:1.27.0.2
	REL8_2_0:1.27
	REL8_2_RC1:1.27
	REL8_2_BETA3:1.27
	REL8_2_BETA2:1.27
	REL8_1_5:1.24
	REL8_0_9:1.15
	REL7_4_14:1.13
	REL7_3_16:1.11
	REL8_2_BETA1:1.26
	REL7_3_15:1.11
	REL7_4_13:1.13
	REL8_0_8:1.15
	REL8_1_4:1.24
	REL7_3_14:1.11
	REL7_4_12:1.13
	REL8_0_7:1.15
	REL8_1_3:1.24
	REL7_3_13:1.11
	REL7_4_11:1.13
	REL8_0_6:1.15
	REL8_1_2:1.24
	REL7_3_12:1.11
	REL7_4_10:1.13
	REL8_0_5:1.15
	REL8_1_1:1.24
	REL8_1_STABLE:1.24.0.2
	REL8_1_0:1.24
	REL8_1_0RC1:1.23
	REL8_1_0BETA4:1.23
	REL8_1_0BETA3:1.21
	REL7_3_11:1.11
	REL7_4_9:1.13
	REL8_0_4:1.15
	REL8_1_0BETA2:1.21
	REL8_1_0BETA1:1.21
	REL7_2_8:1.11
	REL7_3_10:1.11
	REL7_4_8:1.13
	REL8_0_3:1.15
	REL8_0_2:1.15
	REL7_2_7:1.11
	REL7_3_9:1.11
	REL7_4_7:1.13
	REL8_0_1:1.15
	REL8_0_STABLE:1.15.0.4
	REL8_0_0:1.15.0.2
	REL8_0_0RC5:1.15
	REL8_0_0RC4:1.14
	REL8_0_0RC3:1.14
	REL8_0_0RC2:1.14
	REL8_0_0RC1:1.14
	REL8_0_0BETA5:1.14
	REL8_0_0BETA4:1.14
	REL7_4_6:1.13
	REL7_3_8:1.11
	REL7_2_6:1.11
	REL8_0_0BETA3:1.14
	REL8_0_0BETA2:1.14
	REL7_2_5:1.11
	REL7_4_5:1.13
	REL7_3_7:1.11
	REL7_4_4:1.13
	REL8_0_0BETA1:1.14
	REL7_4_3:1.13
	REL7_4_2:1.13
	REL7_3_6:1.11
	REL7_4_1:1.13
	REL7_3_5:1.11
	REL7_4:1.13
	REL7_4_RC2:1.13
	REL7_4_STABLE:1.13.0.2
	REL7_4_RC1:1.13
	REL7_4_BETA5:1.12
	REL7_4_BETA4:1.12
	REL7_4_BETA3:1.11
	REL7_4_BETA2:1.11
	WIN32_DEV:1.11.0.6
	REL7_4_BETA1:1.11
	REL7_3_4:1.11
	REL7_3_2:1.11
	REL7_2_4:1.11
	REL7_3_STABLE:1.11.0.4
	REL7_2_3:1.11
	REL7_2_STABLE:1.11.0.2
	REL7_2:1.11
	REL7_2_RC2:1.11
	REL7_2_RC1:1.11
	REL7_2_BETA5:1.11
	REL7_2_BETA4:1.10
	REL7_2_BETA3:1.9
	REL7_2_BETA2:1.9
	REL7_2_BETA1:1.9
	REL7_1_2:1.7
	REL7_1_STABLE:1.7.0.2
	REL7_1_BETA:1.5
	REL7_1_BETA3:1.6
	REL7_1_BETA2:1.6
	REL7_1:1.7
	REL7_0_PATCHES:1.5.0.4
	REL7_0:1.5
	REL6_5_PATCHES:1.5.0.2
	REL6_5:1.5
	REL6_4:1.4.0.2
	release-6-3:1.2;
locks; strict;
comment	@# @;


1.32
date	2010.08.17.04.37.20;	author petere;	state Exp;
branches;
next	1.31;

1.31
date	2009.06.12.19.48.53;	author tgl;	state Exp;
branches
	1.31.14.1;
next	1.30;

1.30
date	2008.04.14.17.05.32;	author tgl;	state Exp;
branches;
next	1.29;

1.29
date	2007.11.13.23.36.26;	author tgl;	state Exp;
branches;
next	1.28;

1.28
date	2007.01.31.20.56.17;	author momjian;	state Exp;
branches;
next	1.27;

1.27
date	2006.10.23.18.10.31;	author petere;	state Exp;
branches;
next	1.26;

1.26
date	2006.03.10.19.10.48;	author momjian;	state Exp;
branches;
next	1.25;

1.25
date	2005.11.07.17.36.44;	author tgl;	state Exp;
branches;
next	1.24;

1.24
date	2005.11.04.23.14.00;	author petere;	state Exp;
branches;
next	1.23;

1.23
date	2005.10.21.13.59.05;	author tgl;	state Exp;
branches;
next	1.22;

1.22
date	2005.10.21.01.41.28;	author tgl;	state Exp;
branches;
next	1.21;

1.21
date	2005.07.02.20.08.27;	author momjian;	state Exp;
branches;
next	1.20;

1.20
date	2005.06.29.01.23.49;	author momjian;	state Exp;
branches;
next	1.19;

1.19
date	2005.06.20.14.53.32;	author tgl;	state Exp;
branches;
next	1.18;

1.18
date	2005.05.17.00.59.30;	author neilc;	state Exp;
branches;
next	1.17;

1.17
date	2005.04.09.03.52.43;	author momjian;	state Exp;
branches;
next	1.16;

1.16
date	2005.03.31.03.54.38;	author momjian;	state Exp;
branches;
next	1.15;

1.15
date	2005.01.08.22.13.25;	author tgl;	state Exp;
branches;
next	1.14;

1.14
date	2003.11.29.19.51.37;	author pgsql;	state Exp;
branches;
next	1.13;

1.13
date	2003.10.31.22.41.21;	author tgl;	state Exp;
branches;
next	1.12;

1.12
date	2003.09.29.18.18.35;	author momjian;	state Exp;
branches;
next	1.11;

1.11
date	2002.01.09.00.52.37;	author petere;	state Exp;
branches;
next	1.10;

1.10
date	2001.11.21.05.53.41;	author thomas;	state Exp;
branches;
next	1.9;

1.9
date	2001.10.12.23.32.33;	author momjian;	state Exp;
branches;
next	1.8;

1.8
date	2001.05.17.21.50.16;	author petere;	state Exp;
branches;
next	1.7;

1.7
date	2001.01.24.03.40.33;	author momjian;	state Exp;
branches;
next	1.6;

1.6
date	2000.12.22.21.51.57;	author petere;	state Exp;
branches;
next	1.5;

1.5
date	98.12.29.02.24.15;	author thomas;	state Exp;
branches;
next	1.4;

1.4
date	98.07.29.06.49.59;	author thomas;	state Exp;
branches;
next	1.3;

1.3
date	98.04.04.16.35.21;	author thomas;	state Exp;
branches;
next	1.2;

1.2
date	98.03.01.20.46.10;	author thomas;	state Exp;
branches;
next	1.1;

1.1
date	98.03.01.08.15.53;	author thomas;	state Exp;
branches;
next	;

1.31.14.1
date	2010.08.17.04.37.16;	author petere;	state Exp;
branches;
next	;


desc
@@


1.32
log
@Spell and markup checking
@
text
@<!-- $PostgreSQL: pgsql/doc/src/sgml/gist.sgml,v 1.31 2009/06/12 19:48:53 tgl Exp $ -->

<chapter id="GiST">
<title>GiST Indexes</title>

   <indexterm>
    <primary>index</primary>
    <secondary>GiST</secondary>
   </indexterm>

<sect1 id="gist-intro">
 <title>Introduction</title>

 <para>
   <acronym>GiST</acronym> stands for Generalized Search Tree.  It is a
   balanced, tree-structured access method, that acts as a base template in
   which to implement arbitrary indexing schemes. B-trees, R-trees and many
   other indexing schemes can be implemented in <acronym>GiST</acronym>.
 </para>

 <para>
  One advantage of <acronym>GiST</acronym> is that it allows the development
  of custom data types with the appropriate access methods, by
  an expert in the domain of the data type, rather than a database expert.
 </para>

  <para>
    Some of the information here is derived from the University of California
    at Berkeley's GiST Indexing Project
    <ulink url="http://gist.cs.berkeley.edu/">web site</ulink> and
    Marcel Kornacker's thesis,
    <ulink url="http://www.sai.msu.su/~megera/postgres/gist/papers/concurrency/access-methods-for-next-generation.pdf.gz">
    Access Methods for Next-Generation Database Systems</ulink>.
    The <acronym>GiST</acronym>
    implementation in <productname>PostgreSQL</productname> is primarily
    maintained by Teodor Sigaev and Oleg Bartunov, and there is more
    information on their
    <ulink url="http://www.sai.msu.su/~megera/postgres/gist/">web site</ulink>.
  </para>

</sect1>

<sect1 id="gist-extensibility">
 <title>Extensibility</title>

 <para>
   Traditionally, implementing a new index access method meant a lot of
   difficult work.  It was necessary to understand the inner workings of the
   database, such as the lock manager and Write-Ahead Log.  The
   <acronym>GiST</acronym> interface has a high level of abstraction,
   requiring the access method implementer only to implement the semantics of
   the data type being accessed.  The <acronym>GiST</acronym> layer itself
   takes care of concurrency, logging and searching the tree structure.
 </para>

 <para>
   This extensibility should not be confused with the extensibility of the
   other standard search trees in terms of the data they can handle.  For
   example, <productname>PostgreSQL</productname> supports extensible B-trees
   and hash indexes. That means that you can use
   <productname>PostgreSQL</productname> to build a B-tree or hash over any
   data type you want. But B-trees only support range predicates
   (<literal>&lt;</literal>, <literal>=</literal>, <literal>&gt;</literal>),
   and hash indexes only support equality queries.
 </para>

 <para>
   So if you index, say, an image collection with a
   <productname>PostgreSQL</productname> B-tree, you can only issue queries
   such as <quote>is imagex equal to imagey</quote>, <quote>is imagex less
   than imagey</quote> and <quote>is imagex greater than imagey</quote>.
   Depending on how you define <quote>equals</quote>, <quote>less than</quote>
   and <quote>greater than</quote> in this context, this could be useful.
   However, by using a <acronym>GiST</acronym> based index, you could create
   ways to ask domain-specific questions, perhaps <quote>find all images of
   horses</quote> or <quote>find all over-exposed images</quote>.
 </para>

 <para>
   All it takes to get a <acronym>GiST</acronym> access method up and running
   is to implement seven user-defined methods, which define the behavior of
   keys in the tree. Of course these methods have to be pretty fancy to
   support fancy queries, but for all the standard queries (B-trees,
   R-trees, etc.) they're relatively straightforward. In short,
   <acronym>GiST</acronym> combines extensibility along with generality, code
   reuse, and a clean interface.
  </para>

</sect1>

<sect1 id="gist-implementation">
 <title>Implementation</title>

 <para>
   There are seven methods that an index operator class for
   <acronym>GiST</acronym> must provide. Correctness of the index is ensured
   by proper implementation of the <function>same</>, <function>consistent</>
   and <function>union</> methods, while efficiency (size and speed) of the
   index will depend on the <function>penalty</> and <function>picksplit</>
   methods.
   The remaining two methods are <function>compress</> and
   <function>decompress</>, which allow an index to have internal tree data of
   a different type than the data it indexes. The leaves are to be of the
   indexed data type, while the other tree nodes can be of any C struct (but
   you still have to follow <productname>PostgreSQL</> data type rules here,
   see about <literal>varlena</> for variable sized data). If the tree's
   internal data type exists at the SQL level, the <literal>STORAGE</> option
   of the <command>CREATE OPERATOR CLASS</> command can be used.
 </para>

 <variablelist>
    <varlistentry>
     <term><function>consistent</></term>
     <listitem>
      <para>
       Given an index entry <literal>p</> and a query value <literal>q</>,
       this function determines whether the index entry is
       <quote>consistent</> with the query; that is, could the predicate
       <quote><replaceable>indexed_column</>
       <replaceable>indexable_operator</> <literal>q</></quote> be true for
       any row represented by the index entry?  For a leaf index entry this is
       equivalent to testing the indexable condition, while for an internal
       tree node this determines whether it is necessary to scan the subtree
       of the index represented by the tree node.  When the result is
       <literal>true</>, a <literal>recheck</> flag must also be returned.
       This indicates whether the predicate is certainly true or only possibly
       true.  If <literal>recheck</> = <literal>false</> then the index has
       tested the predicate condition exactly, whereas if <literal>recheck</>
       = <literal>true</> the row is only a candidate match.  In that case the
       system will automatically evaluate the
       <replaceable>indexable_operator</> against the actual row value to see
       if it is really a match.  This convention allows
       <acronym>GiST</acronym> to support both lossless and lossy index
       structures.
      </para>

      <para>
        The <acronym>SQL</> declaration of the function must look like this:

<programlisting>
CREATE OR REPLACE FUNCTION my_consistent(internal, data_type, smallint, oid, internal)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT;
</programlisting>

        And the matching code in the C module could then follow this skeleton:

<programlisting>
Datum       my_consistent(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(my_consistent);

Datum
my_consistent(PG_FUNCTION_ARGS)
{
    GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
    data_type  *query = PG_GETARG_DATA_TYPE_P(1);
    StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
    /* Oid subtype = PG_GETARG_OID(3); */
    bool       *recheck = (bool *) PG_GETARG_POINTER(4);
    data_type  *key = DatumGetDataType(entry-&gt;key);
    bool        retval;

    /*
     * determine return value as a function of strategy, key and query.
     *
     * Use GIST_LEAF(entry) to know where you're called in the index tree,
     * which comes handy when supporting the = operator for example (you could
     * check for non empty union() in non-leaf nodes and equality in leaf
     * nodes).
     */

    *recheck = true;        /* or false if check is exact */

    PG_RETURN_BOOL(retval);
}
</programlisting>

       Here, <varname>key</> is an element in the index and <varname>query</>
       the value being looked up in the index. The <literal>StrategyNumber</>
       parameter indicates which operator of your operator class is being
       applied &mdash; it matches one of the operator numbers in the
       <command>CREATE OPERATOR CLASS</> command.  Depending on what operators
       you have included in the class, the data type of <varname>query</> could
       vary with the operator, but the above skeleton assumes it doesn't.
      </para>

     </listitem>
    </varlistentry>

    <varlistentry>
     <term><function>union</></term>
     <listitem>
      <para>
       This method consolidates information in the tree.  Given a set of
       entries, this function generates a new index entry that represents
       all the given entries.
      </para>

      <para>
        The <acronym>SQL</> declaration of the function must look like this:

<programlisting>
CREATE OR REPLACE FUNCTION my_union(internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT;
</programlisting>

        And the matching code in the C module could then follow this skeleton:

<programlisting>
Datum       my_union(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(my_union);

Datum
my_union(PG_FUNCTION_ARGS)
{
    GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
    GISTENTRY  *ent = entryvec-&gt;vector;
    data_type  *out,
               *tmp,
               *old;
    int         numranges,
                i = 0;

    numranges = entryvec-&gt;n;
    tmp = DatumGetDataType(ent[0].key);
    out = tmp;

    if (numranges == 1)
    {
        out = data_type_deep_copy(tmp);

        PG_RETURN_DATA_TYPE_P(out);
    }

    for (i = 1; i &lt; numranges; i++)
    {
        old = out;
        tmp = DatumGetDataType(ent[i].key);
        out = my_union_implementation(out, tmp);
    }

    PG_RETURN_DATA_TYPE_P(out);
}
</programlisting>
      </para>

      <para>
        As you can see, in this skeleton we're dealing with a data type
        where <literal>union(X, Y, Z) = union(union(X, Y), Z)</>. It's easy
        enough to support data types where this is not the case, by
        implementing the proper union algorithm in this
        <acronym>GiST</> support method.
      </para>

      <para>
        The <function>union</> implementation function should return a
        pointer to newly <function>palloc()</>ed memory. You can't just
        return whatever the input is.
      </para>
     </listitem>
    </varlistentry>

    <varlistentry>
     <term><function>compress</></term>
     <listitem>
      <para>
       Converts the data item into a format suitable for physical storage in
       an index page.
      </para>

      <para>
        The <acronym>SQL</> declaration of the function must look like this:

<programlisting>
CREATE OR REPLACE FUNCTION my_compress(internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT;
</programlisting>

        And the matching code in the C module could then follow this skeleton:

<programlisting>
Datum       my_compress(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(my_compress);

Datum
my_compress(PG_FUNCTION_ARGS)
{
    GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
    GISTENTRY  *retval;

    if (entry-&gt;leafkey)
    {
        /* replace entry-&gt;key with a compressed version */
        compressed_data_type *compressed_data = palloc(sizeof(compressed_data_type));

        /* fill *compressed_data from entry-&gt;key ... */

        retval = palloc(sizeof(GISTENTRY));
        gistentryinit(*retval, PointerGetDatum(compressed_data),
                      entry-&gt;rel, entry-&gt;page, entry-&gt;offset, FALSE);
    }
    else
    {
        /* typically we needn't do anything with non-leaf entries */
        retval = entry;
    }

    PG_RETURN_POINTER(retval);
}
</programlisting>
      </para>

      <para>
       You have to adapt <replaceable>compressed_data_type</> to the specific
       type you're converting to in order to compress your leaf nodes, of
       course.
      </para>

      <para>
        Depending on your needs, you could also need to care about
        compressing <literal>NULL</> values in there, storing for example
        <literal>(Datum) 0</> like <literal>gist_circle_compress</> does.
      </para>
     </listitem>
    </varlistentry>

    <varlistentry>
     <term><function>decompress</></term>
     <listitem>
      <para>
       The reverse of the <function>compress</function> method.  Converts the
       index representation of the data item into a format that can be
       manipulated by the database.
      </para>

      <para>
        The <acronym>SQL</> declaration of the function must look like this:

<programlisting>
CREATE OR REPLACE FUNCTION my_decompress(internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT;
</programlisting>

        And the matching code in the C module could then follow this skeleton:

<programlisting>
Datum       my_decompress(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(my_decompress);

Datum
my_decompress(PG_FUNCTION_ARGS)
{
    PG_RETURN_POINTER(PG_GETARG_POINTER(0));
}
</programlisting>

        The above skeleton is suitable for the case where no decompression
        is needed.
      </para>
     </listitem>
    </varlistentry>

    <varlistentry>
     <term><function>penalty</></term>
     <listitem>
      <para>
       Returns a value indicating the <quote>cost</quote> of inserting the new
       entry into a particular branch of the tree.  Items will be inserted
       down the path of least <function>penalty</function> in the tree.
      </para>

      <para>
        The <acronym>SQL</> declaration of the function must look like this:

<programlisting>
CREATE OR REPLACE FUNCTION my_penalty(internal, internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT;  -- in some cases penalty functions need not be strict
</programlisting>

        And the matching code in the C module could then follow this skeleton:

<programlisting>
Datum       my_penalty(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(my_penalty);

Datum
my_penalty(PG_FUNCTION_ARGS)
{
    GISTENTRY  *origentry = (GISTENTRY *) PG_GETARG_POINTER(0);
    GISTENTRY  *newentry = (GISTENTRY *) PG_GETARG_POINTER(1);
    float      *penalty = (float *) PG_GETARG_POINTER(2);
    data_type  *orig = DatumGetDataType(origentry-&gt;key);
    data_type  *new = DatumGetDataType(newentry-&gt;key);

    *penalty = my_penalty_implementation(orig, new);
    PG_RETURN_POINTER(penalty);
}
</programlisting>
      </para>

      <para>
        The <function>penalty</> function is crucial to good performance of
        the index. It'll get used at insertion time to determine which branch
        to follow when choosing where to add the new entry in the tree. At
        query time, the more balanced the index, the quicker the lookup.
      </para>
     </listitem>
    </varlistentry>

    <varlistentry>
     <term><function>picksplit</></term>
     <listitem>
      <para>
       When an index page split is necessary, this function decides which
       entries on the page are to stay on the old page, and which are to move
       to the new page.
      </para>

      <para>
        The <acronym>SQL</> declaration of the function must look like this:

<programlisting>
CREATE OR REPLACE FUNCTION my_picksplit(internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT;
</programlisting>

        And the matching code in the C module could then follow this skeleton:

<programlisting>
Datum       my_picksplit(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(my_picksplit);

Datum
my_picksplit(PG_FUNCTION_ARGS)
{
    GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
    OffsetNumber maxoff = entryvec-&gt;n - 1;
    GISTENTRY  *ent = entryvec-&gt;vector;
    GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
    int         i,
                nbytes;
    OffsetNumber *left,
               *right;
    data_type  *tmp_union;
    data_type  *unionL;
    data_type  *unionR;
    GISTENTRY **raw_entryvec;

    maxoff = entryvec-&gt;n - 1;
    nbytes = (maxoff + 1) * sizeof(OffsetNumber);

    v-&gt;spl_left = (OffsetNumber *) palloc(nbytes);
    left = v-&gt;spl_left;
    v-&gt;spl_nleft = 0;

    v-&gt;spl_right = (OffsetNumber *) palloc(nbytes);
    right = v-&gt;spl_right;
    v-&gt;spl_nright = 0;

    unionL = NULL;
    unionR = NULL;

    /* Initialize the raw entry vector. */
    raw_entryvec = (GISTENTRY **) malloc(entryvec-&gt;n * sizeof(void *));
    for (i = FirstOffsetNumber; i &lt;= maxoff; i = OffsetNumberNext(i))
        raw_entryvec[i] = &amp;(entryvec-&gt;vector[i]);

    for (i = FirstOffsetNumber; i &lt;= maxoff; i = OffsetNumberNext(i))
    {
        int         real_index = raw_entryvec[i] - entryvec-&gt;vector;

        tmp_union = DatumGetDataType(entryvec-&gt;vector[real_index].key);
        Assert(tmp_union != NULL);

        /*
         * Choose where to put the index entries and update unionL and 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-&gt;spl_nleft);
        }
        else
        {
            /*
             * Same on the right
             */
        }
    }

    v-&gt;spl_ldatum = DataTypeGetDatum(unionL);
    v-&gt;spl_rdatum = DataTypeGetDatum(unionR);
    PG_RETURN_POINTER(v);
}
</programlisting>
      </para>

      <para>
        Like <function>penalty</>, the <function>picksplit</> function
        is crucial to good performance of the index.  Designing suitable
        <function>penalty</> and <function>picksplit</> implementations
        is where the challenge of implementing well-performing
        <acronym>GiST</> indexes lies.
      </para>
     </listitem>
    </varlistentry>

    <varlistentry>
     <term><function>same</></term>
     <listitem>
      <para>
       Returns true if two index entries are identical, false otherwise.
      </para>

      <para>
        The <acronym>SQL</> declaration of the function must look like this:

<programlisting>
CREATE OR REPLACE FUNCTION my_same(internal, internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT;
</programlisting>

        And the matching code in the C module could then follow this skeleton:

<programlisting>
Datum       my_same(PG_FUNCTION_ARGS);
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 doesn't
        just return a Boolean result; instead it has to store the flag
        at the location indicated by the third argument.
      </para>
     </listitem>
    </varlistentry>

  </variablelist>

</sect1>

<sect1 id="gist-examples">
 <title>Examples</title>

 <para>
  The <productname>PostgreSQL</productname> source distribution includes
  several examples of index methods implemented using
  <acronym>GiST</acronym>.  The core system currently provides text search
  support (indexing for <type>tsvector</> and <type>tsquery</>) as well as
  R-Tree equivalent functionality for some of the built-in geometric data types
  (see <filename>src/backend/access/gist/gistproc.c</>).  The following
  <filename>contrib</> modules also contain <acronym>GiST</acronym>
  operator classes:

 <variablelist>
  <varlistentry>
   <term><filename>btree_gist</></term>
   <listitem>
    <para>B-tree equivalent functionality for several data types</para>
   </listitem>
  </varlistentry>

  <varlistentry>
   <term><filename>cube</></term>
   <listitem>
    <para>Indexing for multidimensional cubes</para>
   </listitem>
  </varlistentry>

  <varlistentry>
   <term><filename>hstore</></term>
   <listitem>
    <para>Module for storing (key, value) pairs</para>
   </listitem>
  </varlistentry>

  <varlistentry>
   <term><filename>intarray</></term>
   <listitem>
    <para>RD-Tree for one-dimensional array of int4 values</para>
   </listitem>
  </varlistentry>

  <varlistentry>
   <term><filename>ltree</></term>
   <listitem>
    <para>Indexing for tree-like structures</para>
   </listitem>
  </varlistentry>

  <varlistentry>
   <term><filename>pg_trgm</></term>
   <listitem>
    <para>Text similarity using trigram matching</para>
   </listitem>
  </varlistentry>

  <varlistentry>
   <term><filename>seg</></term>
   <listitem>
    <para>Indexing for <quote>float ranges</quote></para>
   </listitem>
  </varlistentry>
 </variablelist>
 </para>

</sect1>

<sect1 id="gist-recovery">
 <title>Crash Recovery</title>

 <para>
  Usually, replay of the WAL log is sufficient to restore the integrity
  of a GiST index following a database crash.  However, there are some
  corner cases in which the index state is not fully rebuilt.  The index
  will still be functionally correct, but there might be some performance
  degradation.  When this occurs, the index can be repaired by
  <command>VACUUM</>ing its table, or by rebuilding the index using
  <command>REINDEX</>.  In some cases a plain <command>VACUUM</> is
  not sufficient, and either <command>VACUUM FULL</> or <command>REINDEX</>
  is needed.  The need for one of these procedures is indicated by occurrence
  of this log message during crash recovery:
<programlisting>
LOG:  index NNN/NNN/NNN needs VACUUM or REINDEX to finish crash recovery
</programlisting>
  or this log message during routine index insertions:
<programlisting>
LOG:  index "FOO" needs VACUUM or REINDEX to finish crash recovery
</programlisting>
  If a plain <command>VACUUM</> finds itself unable to complete recovery
  fully, it will return a notice:
<programlisting>
NOTICE:  index "FOO" needs VACUUM FULL or REINDEX to finish crash recovery
</programlisting>
 </para>
</sect1>

</chapter>
@


1.31
log
@Improve documentation about GiST opclass support functions.
Dimitri Fontaine
@
text
@d1 1
a1 1
<!-- $PostgreSQL: pgsql/doc/src/sgml/gist.sgml,v 1.30 2008/04/14 17:05:32 tgl Exp $ -->
d105 1
a105 1
   you still have to follow <productname>PostgreSQL</> datatype rules here,
d564 1
a564 1
        just return a boolean result; instead it has to store the flag
a585 1
 </para>
d589 1
a589 1
   <term>btree_gist</term>
d591 1
a591 1
    <para>B-Tree equivalent functionality for several data types</para>
d596 1
a596 1
   <term>cube</term>
d603 1
a603 1
   <term>hstore</term>
d610 1
a610 1
   <term>intarray</term>
d617 1
a617 1
   <term>ltree</term>
d624 1
a624 1
   <term>pg_trgm</term>
d631 1
a631 1
   <term>seg</term>
d637 1
@


1.31.14.1
log
@Spell and markup checking
@
text
@d1 1
a1 1
<!-- $PostgreSQL: pgsql/doc/src/sgml/gist.sgml,v 1.31 2009/06/12 19:48:53 tgl Exp $ -->
d105 1
a105 1
   you still have to follow <productname>PostgreSQL</> data type rules here,
d564 1
a564 1
        just return a Boolean result; instead it has to store the flag
d586 1
d590 1
a590 1
   <term><filename>btree_gist</></term>
d592 1
a592 1
    <para>B-tree equivalent functionality for several data types</para>
d597 1
a597 1
   <term><filename>cube</></term>
d604 1
a604 1
   <term><filename>hstore</></term>
d611 1
a611 1
   <term><filename>intarray</></term>
d618 1
a618 1
   <term><filename>ltree</></term>
d625 1
a625 1
   <term><filename>pg_trgm</></term>
d632 1
a632 1
   <term><filename>seg</></term>
a637 1
 </para>
@


1.30
log
@Push index operator lossiness determination down to GIST/GIN opclass
"consistent" functions, and remove pg_amop.opreqcheck, as per recent
discussion.  The main immediate benefit of this is that we no longer need
8.3's ugly hack of requiring @@@@@@ rather than @@@@ to test weight-using tsquery
searches on GIN indexes.  In future it should be possible to optimize some
other queries better than is done now, by detecting at runtime whether the
index match is exact or not.

Tom Lane, after an idea of Heikki's, and with some help from Teodor.
@
text
@d1 1
a1 1
<!-- $PostgreSQL: pgsql/doc/src/sgml/gist.sgml,v 1.29 2007/11/13 23:36:26 tgl Exp $ -->
d28 4
a31 3
    Some of the information here is derived from the University of California at
    Berkeley's GiST Indexing Project
    <ulink url="http://gist.cs.berkeley.edu/">web site</ulink> and 
d33 1
a33 1
    Marcel Kornacker's thesis, Access Methods for Next-Generation Database Systems</ulink>.
d38 1
a38 1
    <ulink url="http://www.sai.msu.su/~megera/postgres/gist/">website</ulink>.
d51 1
a51 1
   requiring the access method implementer to only implement the semantics of
d55 1
a55 1
 
d66 1
a66 1
 
d71 1
a71 1
   than imagey</quote> and <quote>is imagex greater than imagey</quote>?
d93 1
a93 1
 
d96 13
a108 1
   <acronym>GiST</acronym> must provide:
d113 1
a113 1
     <term>consistent</term>
d116 19
a134 7
       Given a predicate <literal>p</literal> on a tree page, and a user
       query, <literal>q</literal>, this method will return false if it is
       certain that both <literal>p</literal> and <literal>q</literal> cannot
       be true for a given data item.  For a true result, a
       <literal>recheck</> flag must also be returned; this indicates whether
       the predicate implies the query (<literal>recheck</> = false) or
       not (<literal>recheck</> = true).
d136 52
d192 1
a192 1
     <term>union</term>
d196 66
a261 2
       entries, this function generates a new predicate that is true for all
       the entries.
d267 1
a267 1
     <term>compress</term>
d273 56
d333 1
a333 1
     <term>decompress</term>
d340 27
d371 1
a371 1
     <term>penalty</term>
d375 1
a375 1
       entry into a particular branch of the tree.  items will be inserted
d378 38
d420 1
a420 1
     <term>picksplit</term>
d423 101
a523 3
       When a page split is necessary, this function decides which entries on
       the page are to stay on the old page, and which are to move to the new
       page.
d529 1
a529 1
     <term>same</term>
d532 34
a565 1
       Returns true if two entries are identical, false otherwise.
d585 1
a585 1
  operator classes: 
d587 1
a587 1
 
@


1.29
log
@Clean up some stray references to tsearch2.
@
text
@d1 1
a1 1
<!-- $PostgreSQL: pgsql/doc/src/sgml/gist.sgml,v 1.28 2007/01/31 20:56:17 momjian Exp $ -->
d106 4
a109 1
       be true for a given data item.
@


1.28
log
@Update documentation on may/can/might:

Standard English uses "may", "can", and "might" in different ways:

        may - permission, "You may borrow my rake."

        can - ability, "I can lift that log."

        might - possibility, "It might rain today."

Unfortunately, in conversational English, their use is often mixed, as
in, "You may use this variable to do X", when in fact, "can" is a better
choice.  Similarly, "It may crash" is better stated, "It might crash".

Also update two error messages mentioned in the documenation to match.
@
text
@d1 1
a1 1
<!-- $PostgreSQL: pgsql/doc/src/sgml/gist.sgml,v 1.27 2006/10/23 18:10:31 petere Exp $ -->
d184 3
a186 2
  <acronym>GiST</acronym>.  The core system currently provides R-Tree
  equivalent functionality for some of the built-in geometric data types
d208 7
a240 7

  <varlistentry>
   <term>tsearch2</term>
   <listitem>
    <para>Full text indexing</para>
   </listitem>
  </varlistentry>
@


1.27
log
@Spellchecking and such
@
text
@d1 1
a1 1
<!-- $PostgreSQL: pgsql/doc/src/sgml/gist.sgml,v 1.26 2006/03/10 19:10:48 momjian Exp $ -->
d251 1
a251 1
  will still be functionally correct, but there may be some performance
@


1.26
log
@Make $PostgreSQL CVS tags consistent for SGML files.
@
text
@d1 1
a1 1
<!-- $PostgreSQL: pgsql/doc/src/sgml/advanced.sgml,v 1.49 2005/04/09 03:52:43 momjian Exp $ -->
d202 1
a202 1
    <para>Indexing for multi-dimensional cubes</para>
@


1.25
log
@R-tree is dead ... long live GiST.
@
text
@d1 1
a1 3
<!--
$PostgreSQL: pgsql/doc/src/sgml/gist.sgml,v 1.24 2005/11/04 23:14:00 petere Exp $
-->
@


1.24
log
@Spellchecking run, final cleanups
@
text
@d2 1
a2 1
$PostgreSQL: pgsql/doc/src/sgml/gist.sgml,v 1.23 2005/10/21 13:59:05 tgl Exp $
d8 5
a16 8
   <indexterm>
    <primary>index</primary>
    <secondary>GiST</secondary>
   </indexterm>
   <indexterm>
    <primary>GiST</primary>
    <see>index</see>
   </indexterm>
d19 1
a19 1
   which to implement arbitrary indexing schemes. B+-trees, R-trees and many
d60 4
a63 4
   example, <productname>PostgreSQL</productname> supports extensible B+-trees
   and R-trees. That means that you can use
   <productname>PostgreSQL</productname> to build a B+-tree or R-tree over any
   data type you want. But B+-trees only support range predicates
d65 1
a65 1
   and R-trees only support n-D range queries (contains, contained, equals).
d70 1
a70 1
   <productname>PostgreSQL</productname> B+-tree, you can only issue queries
d84 1
a84 1
   support fancy queries, but for all the standard queries (B+-trees,
@


1.23
log
@Update obsolete URL, per Chris.
@
text
@d2 1
a2 1
$PostgreSQL: pgsql/doc/src/sgml/gist.sgml,v 1.22 2005/10/21 01:41:28 tgl Exp $
d55 1
a55 1
   requiring the access method implementor to only implement the semantics of
d190 1
a190 1
  equivalent functionality for some of the built-in geometric datatypes
d200 1
a200 1
    <para>B-Tree equivalent functionality for several datatypes</para>
@


1.22
log
@Clean up some obsolete statements about GiST indexes, and add a section
documenting GiST crash recovery procedures, as requested some time ago
by Teodor.  (The GiST chapter doesn't seem quite the right place for
the latter, but I'm not sure what else to do with it.)
@
text
@d2 1
a2 1
$PostgreSQL: pgsql/doc/src/sgml/gist.sgml,v 1.21 2005/07/02 20:08:27 momjian Exp $
d36 1
a36 1
    <ulink url="http://citeseer.nj.nec.com/448594.html">
@


1.21
log
@Remove GIST concurrency limitations section.

Christopher Kings-Lynne
@
text
@d2 1
a2 1
$PostgreSQL: pgsql/doc/src/sgml/gist.sgml,v 1.20 2005/06/29 01:23:49 momjian Exp $
d8 1
a8 1
<sect1 id="intro">
d47 1
a47 1
<sect1 id="extensibility">
d95 1
a95 1
<sect1 id="implementation">
d183 1
a183 1
<sect1 id="examples">
d187 7
a193 2
  To see example implementations of index methods implemented using
  <acronym>GiST</acronym>, examine the following contrib modules:
d200 1
a200 1
    <para>B-Tree</para>
d221 1
a221 1
    <para>Indexing for tree-like stuctures</para>
d226 1
a226 1
   <term>rtree_gist</term>
d228 1
a228 1
    <para>R-Tree</para>
d235 1
a235 1
    <para>Storage and indexed access for <quote>float ranges</quote></para>
d240 1
a240 1
   <term>tsearch and tsearch2</term>
d249 29
@


1.20
log
@Improved words spacing.

Victor Y. Yegorov
@
text
@d2 1
a2 1
$PostgreSQL: pgsql/doc/src/sgml/gist.sgml,v 1.19 2005/06/20 14:53:32 tgl Exp $
a182 19
<sect1 id="limitations">
 <title>Limitations</title>

 <para>
  The current implementation of <acronym>GiST</acronym> within
  <productname>PostgreSQL</productname> has some major limitations:
  <acronym>GiST</acronym> index access is not concurrent, and the
  <acronym>GiST</acronym> interface doesn't allow the development of certain
  data types, such as digital trees (see papers by Aoki et al).
 </para>

 <para>
  Solutions to the concurrency problems appear in Marcel Kornacker's
  thesis; however these ideas have not yet been put into practice in the
  <productname>PostgreSQL</productname> implementation.
 </para>

</sect1>

@


1.19
log
@Remove statement that GiST indexes aren't WAL-logged.
@
text
@d2 1
a2 1
$PostgreSQL: pgsql/doc/src/sgml/gist.sgml,v 1.18 2005/05/17 00:59:30 neilc Exp $
d34 2
a35 2
    Berkeley's GiST Indexing Project<ulink
    url="http://gist.cs.berkeley.edu/">web site</ulink> and 
d37 2
a38 2
    Marcel Kornacker's thesis, Access Methods for Next-Generation Database Systems
    </ulink>.   The <acronym>GiST</acronym>
d41 2
a42 2
    information on their<ulink url="http://www.sai.msu.su/~megera/postgres/gist/">
    website</ulink>.
@


1.18
log
@GiST improvements:

- make sure we always invoke user-supplied GiST methods in a short-lived
  memory context. This means the backend isn't exposed to any memory leaks
  that be in those methods (in fact, it is probably a net loss for most
  GiST methods to bother manually freeing memory now). This also means
  we can do away with a lot of ugly manual memory management in the
  GiST code itself.

- keep the current page of a GiST index scan pinned, rather than doing a
  ReadBuffer() for each tuple produced by the scan. Since ReadBuffer() is
  expensive, this is a perf. win

- implement dead tuple killing for GiST indexes (which is easy to do, now
  that we keep a pin on the current scan page). Now all the builtin indexes
  implement dead tuple killing.

- cleanup a lot of ugly code in GiST
@
text
@d2 1
a2 1
$PostgreSQL: pgsql/doc/src/sgml/gist.sgml,v 1.17 2005/04/09 03:52:43 momjian Exp $
d189 1
a189 1
  <acronym>GiST</acronym> access is not concurrent; the
d191 1
a191 3
  data types, such as digital trees (see papers by Aoki et al); and there
  is not yet any support for write-ahead logging of updates in
  <acronym>GiST</acronym> indexes.
a199 6
 <para>
  The lack of write-ahead logging is just a small matter of programming,
  but since it isn't done yet, a crash could render a <acronym>GiST</acronym>
  index inconsistent, forcing a <command>REINDEX</command>.
 </para>

@


1.17
log
@We don't put URL's in ulink's because the URL is always generated, but
we can put words in ulink and the URL will still be printed.

per Peter
@
text
@d2 1
a2 1
$PostgreSQL: pgsql/doc/src/sgml/gist.sgml,v 1.16 2005/03/31 03:54:38 momjian Exp $
d205 1
a205 1
  index inconsistent, forcing a REINDEX.
@


1.16
log
@Adjust SGML ulink tags to the URL is always displayed in our printed docs.
@
text
@d2 1
a2 1
$PostgreSQL: pgsql/doc/src/sgml/gist.sgml,v 1.15 2005/01/08 22:13:25 tgl Exp $
d34 5
a38 4
    Berkeley's GiST Indexing Project web site, <ulink
    url="http://gist.cs.berkeley.edu/"></ulink>, and Marcel Kornacker's
    thesis, Access Methods for Next-Generation Database Systems,
    <ulink url="http://citeseer.nj.nec.com/448594.html"></ulink>.   The <acronym>GiST</acronym>
d41 2
a42 2
    information on their website: <ulink
    url="http://www.sai.msu.su/~megera/postgres/gist/"></>.
@


1.15
log
@Some more small improvements in response to 7.4 interactive docs comments.
@
text
@d2 1
a2 1
$PostgreSQL: pgsql/doc/src/sgml/gist.sgml,v 1.14 2003/11/29 19:51:37 pgsql Exp $
d33 5
a37 6
    Some of the information here is derived from <ulink
    url="http://gist.cs.berkeley.edu/">the University of California at
    Berkeley's GiST Indexing Project web site</ulink> and Marcel Kornacker's
    thesis, 
    <ulink url="http://citeseer.nj.nec.com/448594.html">Access Methods for
    Next-Generation Database Systems</ulink>.   The <acronym>GiST</acronym>
@


1.14
log
@
$Header: -> $PostgreSQL Changes ...
@
text
@d2 1
a2 1
$PostgreSQL: /cvsroot/pgsql-server/doc/src/sgml/gist.sgml,v 1.13 2003/10/31 22:41:21 tgl Exp $
d5 1
a5 1
<chapter Id="GiST">
d12 8
@


1.13
log
@Rewrite GiST documentation into something actually useful.

Christopher Kings-Lynne
@
text
@d2 1
a2 1
$Header$
@


1.12
log
@This patch makes a few incremental improvements to geqo.sgml and
arch-dev.sgml

Neil Conway
@
text
@d5 259
a263 109
<Chapter Id="gist">
<DocInfo>
<AuthorGroup>
<Author>
<FirstName>Gene</FirstName>
<Surname>Selkov</Surname>
</Author>
</AuthorGroup>
<Date>Transcribed 1998-02-19</Date>
</DocInfo>
<Title>GiST Indexes</Title>

<Para>
The information about GIST is at
 <ULink url="http://GiST.CS.Berkeley.EDU:8000/gist/">http://GiST.CS.Berkeley.EDU:8000/gist/</ULink>

with more on different indexing and sorting schemes at
<ULink url="http://s2k-ftp.CS.Berkeley.EDU:8000/personal/jmh/">http://s2k-ftp.CS.Berkeley.EDU:8000/personal/jmh/</ULink>.

And there is more interesting reading at
<ULink url="http://epoch.cs.berkeley.edu:8000/">http://epoch.cs.berkeley.edu:8000/</ULink> and
<ULink url="http://www.sai.msu.su/~megera/postgres/gist/">http://www.sai.msu.su/~megera/postgres/gist/</ULink>.
</para>

<Para>
<Note>
<Title>Author</Title>
<Para>
This extraction from an email sent by 
Eugene Selkov, Jr. (<email>selkovjr@@mcs.anl.gov</email>)
contains good information
on GiST. Hopefully we will learn more in the future and update this information.
- thomas 1998-03-01
</Para>
</Note>
</para>
<Para>
Well, I can't say I quite understand what's going on, but at least
I (almost) succeeded in porting GiST examples to linux. The GiST access
method is already in the postgres tree (<FileName>src/backend/access/gist</FileName>).
</para>
<Para>
<ULink url="ftp://s2k-ftp.cs.berkeley.edu/pub/gist/pggist/pggist.tgz">Examples at Berkeley</ULink>
come with an overview of the methods and demonstrate spatial index 
mechanisms for 2D boxes, polygons, integer intervals and text
(see also <ULink url="http://gist.cs.berkeley.edu:8000/gist/">GiST at Berkeley</ULink>).
In the box example, we
are supposed to see a performance gain when using the GiST index; it did
work for me but I do not have a reasonably large collection of boxes
to check that. Other examples also worked, except polygons: I got an 
error doing

<ProgramListing>
test=> CREATE INDEX pix ON polytmp
test-> USING GIST (p:box gist_poly_ops) WITH (ISLOSSY);
ERROR:  cannot open pix

(PostgreSQL 6.3               Sun Feb  1 14:57:30 EST 1998)
</ProgramListing>
</para>
<Para>
I could not get sense of this error message; it appears to be something
we'd rather ask the developers about (see also Note 4 below). What I
would suggest here is that someone of you linux guys (linux==gcc?) fetch the 
original sources quoted above and apply my patch (see attachment) and 
tell us what you feel about it. Looks cool to me, but I would not like 
to hold it up while there are so many competent people around.
</para>
<Para>
A few notes on the sources:
</para>
<Para>
1. I failed to make use of the original (HP-UX) Makefile and rearranged
   the Makefile from the ancient postgres95 tutorial to do the job. I tried
   to keep it generic, but I am a very poor makefile writer -- just did
   some monkey work. Sorry about that, but I guess it is now a little
   more portable that the original makefile.
</para>
<Para>
2. I built the example sources right under pgsql/src (just extracted the
   tar file there). The aforementioned Makefile assumes it is one level
   below pgsql/src (in our case, in pgsql/src/pggist).
</para>
<Para>
3. The changes I made to the *.c files were all about #include's,
   function prototypes and typecasting. Other than that, I just threw 
   away a bunch of unused vars and added a couple parentheses to please
   gcc. I hope I did not screw up too much :)
</para>
<Para>
4. There is a comment in polyproc.sql:

<ProgramListing>
-- -- there's a memory leak in rtree poly_ops!!
-- -- CREATE INDEX pix2 ON polytmp USING RTREE (p poly_ops);
</ProgramListing>

   Roger that!! I thought it could be related to a number of
   <ProductName>PostgreSQL</ProductName> versions
   back and tried the query. My system went nuts and I had to shoot down
   the postmaster in about ten minutes.
</para>

<Para>
I will continue to look into GiST for a while, but I would also
appreciate
more examples of R-tree usage.
</para>
</Chapter>
@


1.11
log
@Make spelling of operating system names match official version closely.
And listing QNX 6 as both supported and unsupported is probably not helpful.
@
text
@d1 4
@


1.10
log
@Deprecate 'current' for date/time input.
Fix up references to "PostgreSQL" rather than "Postgres". Was roughly
 evenly split between the two before. ref/ files not yet done.
@
text
@d73 1
a73 1
1. I failed to make use of the original (HPUX) Makefile and rearranged
@


1.9
log
@Uppercase keywords where appropriate.
@
text
@d99 1
a99 1
   <ProductName>Postgres</ProductName> versions
@


1.8
log
@Change "indices" to "indexes", per OED.
@
text
@d54 2
a55 2
test=> create index pix on polytmp
test-> using gist (p:box gist_poly_ops) with (islossy);
d95 1
a95 1
-- -- create index pix2 on polytmp using rtree (p poly_ops);
@


1.7
log
@Update
@
text
@d11 1
a11 1
<Title>GiST Indices</Title>
@


1.6
log
@Make use of <email> tag for marking up email addresses.
@
text
@d18 1
a18 1
<ULink url="http://s2k-ftp.CS.Berkeley.EDU:8000/personal/jmh/">http://s2k-ftp.CS.Berkeley.EDU:8000/personal/jmh/</ULink>
d20 3
a22 2
And there is more interesting reading at the Berkely database site at 
<ULink url="http://epoch.cs.berkeley.edu:8000/">http://epoch.cs.berkeley.edu:8000/</ULink>.
@


1.5
log
@Clean up to ensure tag completion as required by the newest versions
 of Norm's Modular Style Sheets and jade/docbook.
From Vince Vielhaber <vev@@michvhf.com>.
@
text
@d28 2
a29 2
This extraction from an e-mail sent by 
<ULink url="mailto:selkovjr@@mcs.anl.gov">Eugene Selkov Jr.</ULink>
@


1.4
log
@Add id field to chapter and book tags to allow output file names
 to be meaningful.
@
text
@d22 1
a22 1

d35 1
a35 1

d40 1
a40 1

d59 1
a59 1

d67 1
a67 1

d70 1
a70 1

d77 1
a77 1

d82 1
a82 1

d88 1
a88 1

d101 1
a101 1

d107 1
a107 1

@


1.3
log
@Clean up formatting.
Add more URL links for GiST information.
@
text
@d1 1
a1 1
<Chapter>
@


1.2
log
@Fix a few typos. Try <Note><Title>Author</Title>... for author credit.
@
text
@d14 11
@


1.1
log
@SGML source for new documentation.
@
text
@d15 1
a15 1
<Title>Caveat</Title>
d21 1
a21 1
- thomas
d42 2
a43 2
test=> create index pix on polytmp using gist (p:box gist_poly_ops) with
(islossy);
d62 1
a62 2
   the Makefile from the ancient postgres95 tutorial to do the job. I
tried
@
