1996-08-27 23:50:29 +02:00
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
*
|
1999-02-14 00:22:53 +01:00
|
|
|
* gist.h
|
1997-09-07 07:04:48 +02:00
|
|
|
* common declarations for the GiST access method code.
|
|
|
|
*
|
1996-08-27 23:50:29 +02:00
|
|
|
*
|
2003-08-04 04:40:20 +02:00
|
|
|
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
|
2001-05-30 21:53:40 +02:00
|
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
1996-08-27 23:50:29 +02:00
|
|
|
*
|
2004-03-30 17:45:33 +02:00
|
|
|
* $PostgreSQL: pgsql/src/include/access/gist.h,v 1.40 2004/03/30 15:45:33 teodor Exp $
|
1996-08-27 23:50:29 +02:00
|
|
|
*
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
#ifndef GIST_H
|
|
|
|
#define GIST_H
|
|
|
|
|
1999-07-16 01:04:24 +02:00
|
|
|
#include "access/itup.h"
|
|
|
|
#include "access/relscan.h"
|
|
|
|
#include "access/sdir.h"
|
2000-11-21 22:16:06 +01:00
|
|
|
#include "access/xlog.h"
|
1998-01-15 20:46:37 +01:00
|
|
|
|
1997-09-07 07:04:48 +02:00
|
|
|
/*
|
2001-05-30 21:53:40 +02:00
|
|
|
* You can have as many strategies as you please in GiSTs,
|
|
|
|
* as long as your consistent method can handle them.
|
|
|
|
* The system doesn't really care what they are.
|
|
|
|
*/
|
1997-09-07 07:04:48 +02:00
|
|
|
#define GISTNStrategies 100
|
1996-08-27 23:50:29 +02:00
|
|
|
|
|
|
|
/*
|
2001-05-30 21:53:40 +02:00
|
|
|
* amproc indexes for GiST indexes.
|
|
|
|
*/
|
1997-09-07 07:04:48 +02:00
|
|
|
#define GIST_CONSISTENT_PROC 1
|
|
|
|
#define GIST_UNION_PROC 2
|
|
|
|
#define GIST_COMPRESS_PROC 3
|
|
|
|
#define GIST_DECOMPRESS_PROC 4
|
|
|
|
#define GIST_PENALTY_PROC 5
|
|
|
|
#define GIST_PICKSPLIT_PROC 6
|
|
|
|
#define GIST_EQUAL_PROC 7
|
2001-05-30 21:53:40 +02:00
|
|
|
#define GISTNProcs 7
|
|
|
|
|
1996-08-27 23:50:29 +02:00
|
|
|
|
2001-05-30 21:53:40 +02:00
|
|
|
/*
|
|
|
|
* Page opaque data in a GiST index page.
|
|
|
|
*/
|
1997-09-07 07:04:48 +02:00
|
|
|
#define F_LEAF (1 << 0)
|
1996-08-27 23:50:29 +02:00
|
|
|
|
1997-09-07 07:04:48 +02:00
|
|
|
typedef struct GISTPageOpaqueData
|
|
|
|
{
|
1997-09-08 04:41:22 +02:00
|
|
|
uint32 flags;
|
1997-09-08 23:56:23 +02:00
|
|
|
} GISTPageOpaqueData;
|
1996-08-27 23:50:29 +02:00
|
|
|
|
1997-09-07 07:04:48 +02:00
|
|
|
typedef GISTPageOpaqueData *GISTPageOpaque;
|
1996-08-27 23:50:29 +02:00
|
|
|
|
|
|
|
#define GIST_LEAF(entry) (((GISTPageOpaque) PageGetSpecialPointer((entry)->page))->flags & F_LEAF)
|
|
|
|
|
|
|
|
/*
|
1997-09-07 07:04:48 +02:00
|
|
|
* When we descend a tree, we keep a stack of parent pointers.
|
1996-08-27 23:50:29 +02:00
|
|
|
*/
|
1997-09-07 07:04:48 +02:00
|
|
|
typedef struct GISTSTACK
|
|
|
|
{
|
1996-08-27 23:50:29 +02:00
|
|
|
struct GISTSTACK *gs_parent;
|
1997-09-08 04:41:22 +02:00
|
|
|
OffsetNumber gs_child;
|
|
|
|
BlockNumber gs_blk;
|
1997-09-08 23:56:23 +02:00
|
|
|
} GISTSTACK;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
typedef struct GISTSTATE
|
|
|
|
{
|
2001-05-31 20:16:55 +02:00
|
|
|
FmgrInfo consistentFn[INDEX_MAX_KEYS];
|
|
|
|
FmgrInfo unionFn[INDEX_MAX_KEYS];
|
|
|
|
FmgrInfo compressFn[INDEX_MAX_KEYS];
|
|
|
|
FmgrInfo decompressFn[INDEX_MAX_KEYS];
|
|
|
|
FmgrInfo penaltyFn[INDEX_MAX_KEYS];
|
|
|
|
FmgrInfo picksplitFn[INDEX_MAX_KEYS];
|
|
|
|
FmgrInfo equalFn[INDEX_MAX_KEYS];
|
2001-08-22 20:24:26 +02:00
|
|
|
|
|
|
|
TupleDesc tupdesc;
|
1997-09-08 23:56:23 +02:00
|
|
|
} GISTSTATE;
|
1996-08-27 23:50:29 +02:00
|
|
|
|
2001-08-22 20:24:26 +02:00
|
|
|
#define isAttByVal( gs, anum ) (gs)->tupdesc->attrs[anum]->attbyval
|
1996-08-27 23:50:29 +02:00
|
|
|
|
|
|
|
/*
|
2001-05-30 21:53:40 +02:00
|
|
|
* When we're doing a scan, we need to keep track of the parent stack
|
|
|
|
* for the marked and current items.
|
|
|
|
*/
|
1997-09-07 07:04:48 +02:00
|
|
|
typedef struct GISTScanOpaqueData
|
|
|
|
{
|
|
|
|
struct GISTSTACK *s_stack;
|
|
|
|
struct GISTSTACK *s_markstk;
|
1997-09-08 04:41:22 +02:00
|
|
|
uint16 s_flags;
|
1997-09-07 07:04:48 +02:00
|
|
|
struct GISTSTATE *giststate;
|
1997-09-08 23:56:23 +02:00
|
|
|
} GISTScanOpaqueData;
|
1996-08-27 23:50:29 +02:00
|
|
|
|
1997-09-07 07:04:48 +02:00
|
|
|
typedef GISTScanOpaqueData *GISTScanOpaque;
|
1996-08-27 23:50:29 +02:00
|
|
|
|
|
|
|
/*
|
2001-05-30 21:53:40 +02:00
|
|
|
* When we're doing a scan and updating a tree at the same time, the
|
|
|
|
* updates may affect the scan. We use the flags entry of the scan's
|
|
|
|
* opaque space to record our actual position in response to updates
|
|
|
|
* that we can't handle simply by adjusting pointers.
|
|
|
|
*/
|
1996-08-27 23:50:29 +02:00
|
|
|
#define GS_CURBEFORE ((uint16) (1 << 0))
|
|
|
|
#define GS_MRKBEFORE ((uint16) (1 << 1))
|
|
|
|
|
|
|
|
/* root page of a gist */
|
1997-09-07 07:04:48 +02:00
|
|
|
#define GISTP_ROOT 0
|
1996-08-27 23:50:29 +02:00
|
|
|
|
|
|
|
/*
|
2001-05-30 21:53:40 +02:00
|
|
|
* When we update a relation on which we're doing a scan, we need to
|
|
|
|
* check the scan and fix it if the update affected any of the pages it
|
|
|
|
* touches. Otherwise, we can miss records that we should see. The only
|
|
|
|
* times we need to do this are for deletions and splits. See the code in
|
|
|
|
* gistscan.c for how the scan is fixed. These two constants tell us what sort
|
|
|
|
* of operation changed the index.
|
|
|
|
*/
|
1997-09-07 07:04:48 +02:00
|
|
|
#define GISTOP_DEL 0
|
|
|
|
#define GISTOP_SPLIT 1
|
1996-08-27 23:50:29 +02:00
|
|
|
|
|
|
|
/*
|
2001-05-30 21:53:40 +02:00
|
|
|
* This is the Split Vector to be returned by the PickSplit method.
|
|
|
|
*/
|
1997-09-07 07:04:48 +02:00
|
|
|
typedef struct GIST_SPLITVEC
|
|
|
|
{
|
1997-09-08 04:41:22 +02:00
|
|
|
OffsetNumber *spl_left; /* array of entries that go left */
|
|
|
|
int spl_nleft; /* size of this array */
|
2001-05-31 20:16:55 +02:00
|
|
|
Datum spl_ldatum; /* Union of keys in spl_left */
|
2001-10-25 07:50:21 +02:00
|
|
|
Datum spl_lattr[INDEX_MAX_KEYS]; /* Union of subkeys in
|
|
|
|
* spl_left */
|
|
|
|
int spl_lattrsize[INDEX_MAX_KEYS];
|
|
|
|
bool spl_lisnull[INDEX_MAX_KEYS];
|
2001-05-31 20:16:55 +02:00
|
|
|
|
1997-09-08 04:41:22 +02:00
|
|
|
OffsetNumber *spl_right; /* array of entries that go right */
|
|
|
|
int spl_nright; /* size of the array */
|
2001-05-31 20:16:55 +02:00
|
|
|
Datum spl_rdatum; /* Union of keys in spl_right */
|
2001-10-25 07:50:21 +02:00
|
|
|
Datum spl_rattr[INDEX_MAX_KEYS]; /* Union of subkeys in
|
|
|
|
* spl_right */
|
|
|
|
int spl_rattrsize[INDEX_MAX_KEYS];
|
|
|
|
bool spl_risnull[INDEX_MAX_KEYS];
|
|
|
|
|
|
|
|
int *spl_idgrp;
|
|
|
|
int *spl_ngrp; /* number in each group */
|
|
|
|
char *spl_grpflag; /* flags of each group */
|
1997-09-08 23:56:23 +02:00
|
|
|
} GIST_SPLITVEC;
|
1996-08-27 23:50:29 +02:00
|
|
|
|
|
|
|
/*
|
2001-05-31 20:16:55 +02:00
|
|
|
* An entry on a GiST node. Contains the key, as well as
|
2001-05-30 21:53:40 +02:00
|
|
|
* its own location (rel,page,offset) which can supply the matching
|
2001-05-31 20:16:55 +02:00
|
|
|
* pointer. The size of the key is in bytes, and leafkey is a flag to
|
2001-05-30 21:53:40 +02:00
|
|
|
* tell us if the entry is in a leaf node.
|
|
|
|
*/
|
1997-09-07 07:04:48 +02:00
|
|
|
typedef struct GISTENTRY
|
|
|
|
{
|
2001-05-31 20:16:55 +02:00
|
|
|
Datum key;
|
1997-09-08 04:41:22 +02:00
|
|
|
Relation rel;
|
|
|
|
Page page;
|
|
|
|
OffsetNumber offset;
|
|
|
|
int bytes;
|
|
|
|
bool leafkey;
|
1997-09-08 23:56:23 +02:00
|
|
|
} GISTENTRY;
|
1996-08-27 23:50:29 +02:00
|
|
|
|
2004-03-30 17:45:33 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Vector of GISTENTRY struct's, user-defined
|
|
|
|
* methods union andpick split takes it as one of args
|
|
|
|
*/
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
int32 n; /* number of elements */
|
|
|
|
GISTENTRY vector[1];
|
|
|
|
} GistEntryVector;
|
|
|
|
|
|
|
|
#define GEVHDRSZ ( offsetof(GistEntryVector, vector[0]) )
|
|
|
|
|
1996-08-27 23:50:29 +02:00
|
|
|
/*
|
2001-05-30 21:53:40 +02:00
|
|
|
* macro to initialize a GISTENTRY
|
|
|
|
*/
|
2001-05-31 20:16:55 +02:00
|
|
|
#define gistentryinit(e, k, r, pg, o, b, l) \
|
|
|
|
do { (e).key = (k); (e).rel = (r); (e).page = (pg); \
|
|
|
|
(e).offset = (o); (e).bytes = (b); (e).leafkey = (l); } while (0)
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2001-05-31 20:16:55 +02:00
|
|
|
/* gist.c */
|
2000-06-13 09:35:40 +02:00
|
|
|
extern Datum gistbuild(PG_FUNCTION_ARGS);
|
|
|
|
extern Datum gistinsert(PG_FUNCTION_ARGS);
|
Restructure index AM interface for index building and index tuple deletion,
per previous discussion on pghackers. Most of the duplicate code in
different AMs' ambuild routines has been moved out to a common routine
in index.c; this means that all index types now do the right things about
inserting recently-dead tuples, etc. (I also removed support for EXTEND
INDEX in the ambuild routines, since that's about to go away anyway, and
it cluttered the code a lot.) The retail indextuple deletion routines have
been replaced by a "bulk delete" routine in which the indexscan is inside
the access method. I haven't pushed this change as far as it should go yet,
but it should allow considerable simplification of the internal bookkeeping
for deletions. Also, add flag columns to pg_am to eliminate various
hardcoded tests on AM OIDs, and remove unused pg_am columns.
Fix rtree and gist index types to not attempt to store NULLs; before this,
gist usually crashed, while rtree managed not to crash but computed wacko
bounding boxes for NULL entries (which might have had something to do with
the performance problems we've heard about occasionally).
Add AtEOXact routines to hash, rtree, and gist, all of which have static
state that needs to be reset after an error. We discovered this need long
ago for btree, but missed the other guys.
Oh, one more thing: concurrent VACUUM is now the default.
2001-07-16 00:48:19 +02:00
|
|
|
extern Datum gistbulkdelete(PG_FUNCTION_ARGS);
|
1997-09-08 04:41:22 +02:00
|
|
|
extern void _gistdump(Relation r);
|
1997-09-08 23:56:23 +02:00
|
|
|
extern void gistfreestack(GISTSTACK *s);
|
|
|
|
extern void initGISTstate(GISTSTATE *giststate, Relation index);
|
2001-08-22 20:24:26 +02:00
|
|
|
extern void freeGISTstate(GISTSTATE *giststate);
|
2001-05-31 20:16:55 +02:00
|
|
|
extern void gistdentryinit(GISTSTATE *giststate, int nkey, GISTENTRY *e,
|
2001-10-25 07:50:21 +02:00
|
|
|
Datum k, Relation r, Page pg, OffsetNumber o,
|
|
|
|
int b, bool l, bool isNull);
|
1996-11-10 04:06:38 +01:00
|
|
|
|
2000-11-21 22:16:06 +01:00
|
|
|
extern void gist_redo(XLogRecPtr lsn, XLogRecord *record);
|
|
|
|
extern void gist_undo(XLogRecPtr lsn, XLogRecord *record);
|
2001-03-22 05:01:46 +01:00
|
|
|
extern void gist_desc(char *buf, uint8 xl_info, char *rec);
|
2000-11-21 22:16:06 +01:00
|
|
|
|
1996-11-10 04:06:38 +01:00
|
|
|
/* gistget.c */
|
2000-06-13 09:35:40 +02:00
|
|
|
extern Datum gistgettuple(PG_FUNCTION_ARGS);
|
2001-10-28 07:26:15 +01:00
|
|
|
|
2001-11-05 18:46:40 +01:00
|
|
|
#endif /* GIST_H */
|