1 /*-------------------------------------------------------------------------
4 * The public API for GiST indexes. This API is exposed to
5 * individuals implementing GiST indexes, so backward-incompatible
6 * changes should be made with care.
9 * Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group
10 * Portions Copyright (c) 1994, Regents of the University of California
12 * src/include/access/gist.h
14 *-------------------------------------------------------------------------
19 #include "access/xlog.h"
20 #include "access/xlogdefs.h"
21 #include "storage/block.h"
22 #include "storage/bufpage.h"
23 #include "utils/relcache.h"
26 * amproc indexes for GiST indexes.
28 #define GIST_CONSISTENT_PROC 1
29 #define GIST_UNION_PROC 2
30 #define GIST_COMPRESS_PROC 3
31 #define GIST_DECOMPRESS_PROC 4
32 #define GIST_PENALTY_PROC 5
33 #define GIST_PICKSPLIT_PROC 6
34 #define GIST_EQUAL_PROC 7
35 #define GIST_DISTANCE_PROC 8
39 * strategy numbers for GiST opclasses that want to implement the old
42 #define RTLeftStrategyNumber 1
43 #define RTOverLeftStrategyNumber 2
44 #define RTOverlapStrategyNumber 3
45 #define RTOverRightStrategyNumber 4
46 #define RTRightStrategyNumber 5
47 #define RTSameStrategyNumber 6
48 #define RTContainsStrategyNumber 7 /* for @> */
49 #define RTContainedByStrategyNumber 8 /* for <@ */
50 #define RTOverBelowStrategyNumber 9
51 #define RTBelowStrategyNumber 10
52 #define RTAboveStrategyNumber 11
53 #define RTOverAboveStrategyNumber 12
54 #define RTOldContainsStrategyNumber 13 /* for old spelling of @> */
55 #define RTOldContainedByStrategyNumber 14 /* for old spelling of <@ */
56 #define RTKNNSearchStrategyNumber 15
59 * Page opaque data in a GiST index page.
61 #define F_LEAF (1 << 0) /* leaf page */
62 #define F_DELETED (1 << 1) /* the page has been deleted */
63 #define F_TUPLES_DELETED (1 << 2) /* some tuples on the page are dead */
64 #define F_FOLLOW_RIGHT (1 << 3) /* page to the right has no downlink */
66 typedef XLogRecPtr GistNSN;
69 * For on-disk compatibility with pre-9.3 servers, NSN is stored as two
70 * 32-bit fields on disk, same as LSNs.
72 typedef PageXLogRecPtr PageGistNSN;
74 typedef struct GISTPageOpaqueData
76 PageGistNSN nsn; /* this value must change on page split */
77 BlockNumber rightlink; /* next page if any */
78 uint16 flags; /* see bit definitions above */
79 uint16 gist_page_id; /* for identification of GiST indexes */
82 typedef GISTPageOpaqueData *GISTPageOpaque;
85 * The page ID is for the convenience of pg_filedump and similar utilities,
86 * which otherwise would have a hard time telling pages of different index
87 * types apart. It should be the last 2 bytes on the page. This is more or
88 * less "free" due to alignment considerations.
90 #define GIST_PAGE_ID 0xFF81
93 * This is the Split Vector to be returned by the PickSplit method.
94 * PickSplit should fill the indexes of tuples to go to the left side into
95 * spl_left[], and those to go to the right into spl_right[] (note the method
96 * is responsible for palloc'ing both of these arrays!). The tuple counts
97 * go into spl_nleft/spl_nright, and spl_ldatum/spl_rdatum must be set to
98 * the union keys for each side.
100 * If spl_ldatum_exists and spl_rdatum_exists are true, then we are performing
101 * a "secondary split" using a non-first index column. In this case some
102 * decisions have already been made about a page split, and the set of tuples
103 * being passed to PickSplit is just the tuples about which we are undecided.
104 * spl_ldatum/spl_rdatum then contain the union keys for the tuples already
105 * chosen to go left or right. Ideally the PickSplit method should take those
106 * keys into account while deciding what to do with the remaining tuples, ie
107 * it should try to "build out" from those unions so as to minimally expand
108 * them. If it does so, it should union the given tuples' keys into the
109 * existing spl_ldatum/spl_rdatum values rather than just setting those values
110 * from scratch, and then set spl_ldatum_exists/spl_rdatum_exists to false to
111 * show it has done this.
113 * If the PickSplit method fails to clear spl_ldatum_exists/spl_rdatum_exists,
114 * the core GiST code will make its own decision about how to merge the
115 * secondary-split results with the previously-chosen tuples, and will then
116 * recompute the union keys from scratch. This is a workable though often not
119 typedef struct GIST_SPLITVEC
121 OffsetNumber *spl_left; /* array of entries that go left */
122 int spl_nleft; /* size of this array */
123 Datum spl_ldatum; /* Union of keys in spl_left */
124 bool spl_ldatum_exists; /* true, if spl_ldatum already exists. */
126 OffsetNumber *spl_right; /* array of entries that go right */
127 int spl_nright; /* size of the array */
128 Datum spl_rdatum; /* Union of keys in spl_right */
129 bool spl_rdatum_exists; /* true, if spl_rdatum already exists. */
133 * An entry on a GiST node. Contains the key, as well as its own
134 * location (rel,page,offset) which can supply the matching pointer.
135 * leafkey is a flag to tell us if the entry is in a leaf node.
137 typedef struct GISTENTRY
146 #define GistPageGetOpaque(page) ( (GISTPageOpaque) PageGetSpecialPointer(page) )
148 #define GistPageIsLeaf(page) ( GistPageGetOpaque(page)->flags & F_LEAF)
149 #define GIST_LEAF(entry) (GistPageIsLeaf((entry)->page))
150 #define GistPageSetLeaf(page) ( GistPageGetOpaque(page)->flags |= F_LEAF)
151 #define GistPageSetNonLeaf(page) ( GistPageGetOpaque(page)->flags &= ~F_LEAF)
153 #define GistPageIsDeleted(page) ( GistPageGetOpaque(page)->flags & F_DELETED)
154 #define GistPageSetDeleted(page) ( GistPageGetOpaque(page)->flags |= F_DELETED)
155 #define GistPageSetNonDeleted(page) ( GistPageGetOpaque(page)->flags &= ~F_DELETED)
157 #define GistTuplesDeleted(page) ( GistPageGetOpaque(page)->flags & F_TUPLES_DELETED)
158 #define GistMarkTuplesDeleted(page) ( GistPageGetOpaque(page)->flags |= F_TUPLES_DELETED)
159 #define GistClearTuplesDeleted(page) ( GistPageGetOpaque(page)->flags &= ~F_TUPLES_DELETED)
161 #define GistFollowRight(page) ( GistPageGetOpaque(page)->flags & F_FOLLOW_RIGHT)
162 #define GistMarkFollowRight(page) ( GistPageGetOpaque(page)->flags |= F_FOLLOW_RIGHT)
163 #define GistClearFollowRight(page) ( GistPageGetOpaque(page)->flags &= ~F_FOLLOW_RIGHT)
165 #define GistPageGetNSN(page) ( PageXLogRecPtrGet(GistPageGetOpaque(page)->nsn))
166 #define GistPageSetNSN(page, val) ( PageXLogRecPtrSet(GistPageGetOpaque(page)->nsn, val))
169 * Vector of GISTENTRY structs; user-defined methods union and picksplit
170 * take it as one of their arguments
174 int32 n; /* number of elements */
175 GISTENTRY vector[FLEXIBLE_ARRAY_MEMBER];
178 #define GEVHDRSZ (offsetof(GistEntryVector, vector))
181 * macro to initialize a GISTENTRY
183 #define gistentryinit(e, k, r, pg, o, l) \
184 do { (e).key = (k); (e).rel = (r); (e).page = (pg); \
185 (e).offset = (o); (e).leafkey = (l); } while (0)