The PostgreSQL GiST access method provides the basic GiST functionality inside PostgreSQL. Like all the Postgres access methods, it does nothing by itself -- one must define opclasses to make it work. With a little coding on your part, you can use the GiST access method to index data in a variety of ways, and support just about any query. It is much simpler to use than writing your own access method (which is a lot of work!)
We have provided some example opclasses to get you started. The boxproc.* files contain code for the gist_box_ops opclass, which uses the GiST access method just like an R-tree with box_ops. The polyproc.* files contain code for the gist_poly_ops opclass, which uses the GiST just like an R-tree with poly_ops (though the GiST is more efficient than the R-tree in this case, since it uses key compression to get better fanout!) The intproc.* and textproc.* files provide B-tree-like behavior for int and text attributes respectively. Though these are not as efficient as the native btree access method, they illustrate the flexibility of the GiST access method, and may be useful for cannibalizing when inventing new indexing schemes.
As an introduction to developing new GiST opclasses, we will step through some of these examples. We will go through the simplest project, gist_box_ops, in some detail, and then just describe some of the features of the other opclasses that are different from gist_box_ops. Probably the easiest way to write new GiST opclasses is to cannibalize some of this sample code, so it's worth looking at carefully.
The GiST access method requires you to register 7 support functions, which encapsulate the behavior of the index. We will go through each of these in detail for gist_box_ops (in order):
Naturally if you write an opclass with keys of type FOO, all references above to type BOX should be changed to FOO. If you invent a new key type (as is done in the int ops and text ops described below) you will need to define the type to Postgres. The names of the functions above are insignificant; you can use whatever names you want, as long as you follow the instructions below on inserting into the pg_amproc catalog.
Now, once you have written these functions, and successfully compiled and linked them into a shared library suitable for dynamic loading, you have to inform Postgres of your new opclass. This is a 4-step process (see boxproc.src for examples):
insert into pg_opclass values ('gist_box_ops');
That's is! Now you can just go ahead and issue a create index command to psql:
create index bix on boxtmp using gist (b gist_box_ops);
The int ops make the gist support B-tree-style lookups on int attributes. The code for the int ops is pretty similar to the box ops, with one significant difference: the key type in the int ops differs from the type of the attribute being indexed. That is, we will use this opclass to index attributes of type int, but the keys in the tree are of a new type called intrange. In order to make this happen, we need to do two things:
create index intix on inttmp using gist (i:intrange gist_irange_ops);
Note the :intrange after the name of the attribute i.
This opclass is identical to the box ops, except that the compress method converts polygons to their bounding boxes, so the key type is box even though the attribute type is polygon. This presents one minor problem -- compression of a polygon to a box is lossy, i.e. it loses some of the information in the original. The result of this is that the index may return too many tuples -- those which satisfy the search key, and possibly some more which do not. To ensure that the query executor later filters out these non-satisfying tuples, we must inform postgres of the lossy compression. This is done with the optional with clause of create index:
create index pix on polytmp using gist (p:box gist_poly_ops) with (islossy);
A note on lossy compression: In indices, the compression can be lossy only in a particular way -- it can make keys more general than they previously were (e.g. convert a polygon to its bounding box). They can not make the keys more specific (e.g. convert a polygon to the largest box that can be inscribe within it), or the index will not retrieve all the tuples that satisfy a query predicate.
Note also that the other PostgreSQL access methods do not support key compression, and hence will ignore the with (islossy) clause.
The text ops are really just the same as the int ops, except the keys are ranges of texts, rather than ints. The one problem this presents is in memory management -- since text is passed by reference, we have to be careful to pfree any texts appropriately.
If you've made it this far, you should be ready to develop your own opclasses for gists. Some points to consider are whether your key type is the same as your attribute type, whether your index is lossy, and whether your key type is passed by value or by reference. Based on these considerations, you should probably start your work by taking one of the opclasses above and modifying it to suit your needs.