mirror of
https://github.com/postgres/postgres.git
synced 2025-07-28 23:42:10 +03:00
R-tree is dead ... long live GiST.
This commit is contained in:
@ -1,14 +1,14 @@
|
||||
#
|
||||
# Makefile for the access methods module
|
||||
#
|
||||
# $PostgreSQL: pgsql/src/backend/access/Makefile,v 1.9 2003/11/29 19:51:39 pgsql Exp $
|
||||
# $PostgreSQL: pgsql/src/backend/access/Makefile,v 1.10 2005/11/07 17:36:44 tgl Exp $
|
||||
#
|
||||
|
||||
subdir = src/backend/access
|
||||
top_builddir = ../../..
|
||||
include $(top_builddir)/src/Makefile.global
|
||||
|
||||
SUBDIRS := common gist hash heap index nbtree rtree transam
|
||||
SUBDIRS := common gist hash heap index nbtree transam
|
||||
SUBDIROBJS := $(SUBDIRS:%=%/SUBSYS.o)
|
||||
|
||||
all: SUBSYS.o
|
||||
|
@ -10,7 +10,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/gist/gistproc.c,v 1.3 2005/10/15 02:49:08 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/gist/gistproc.c,v 1.4 2005/11/07 17:36:44 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -18,7 +18,7 @@
|
||||
|
||||
#include "access/gist.h"
|
||||
#include "access/itup.h"
|
||||
#include "access/rtree.h"
|
||||
#include "access/skey.h"
|
||||
#include "utils/geo_decls.h"
|
||||
|
||||
|
||||
@ -40,6 +40,47 @@ static bool rtree_internal_consistent(BOX *key, BOX *query,
|
||||
* Box ops
|
||||
**************************************************/
|
||||
|
||||
static Datum
|
||||
rt_box_union(PG_FUNCTION_ARGS)
|
||||
{
|
||||
BOX *a = PG_GETARG_BOX_P(0);
|
||||
BOX *b = PG_GETARG_BOX_P(1);
|
||||
BOX *n;
|
||||
|
||||
n = (BOX *) palloc(sizeof(BOX));
|
||||
|
||||
n->high.x = Max(a->high.x, b->high.x);
|
||||
n->high.y = Max(a->high.y, b->high.y);
|
||||
n->low.x = Min(a->low.x, b->low.x);
|
||||
n->low.y = Min(a->low.y, b->low.y);
|
||||
|
||||
PG_RETURN_BOX_P(n);
|
||||
}
|
||||
|
||||
static Datum
|
||||
rt_box_inter(PG_FUNCTION_ARGS)
|
||||
{
|
||||
BOX *a = PG_GETARG_BOX_P(0);
|
||||
BOX *b = PG_GETARG_BOX_P(1);
|
||||
BOX *n;
|
||||
|
||||
n = (BOX *) palloc(sizeof(BOX));
|
||||
|
||||
n->high.x = Min(a->high.x, b->high.x);
|
||||
n->high.y = Min(a->high.y, b->high.y);
|
||||
n->low.x = Max(a->low.x, b->low.x);
|
||||
n->low.y = Max(a->low.y, b->low.y);
|
||||
|
||||
if (n->high.x < n->low.x || n->high.y < n->low.y)
|
||||
{
|
||||
pfree(n);
|
||||
/* Indicate "no intersection" by returning NULL pointer */
|
||||
n = NULL;
|
||||
}
|
||||
|
||||
PG_RETURN_BOX_P(n);
|
||||
}
|
||||
|
||||
/*
|
||||
* The GiST Consistent method for boxes
|
||||
*
|
||||
@ -493,8 +534,6 @@ size_box(Datum dbox)
|
||||
*
|
||||
* We can use the same function since all types use bounding boxes as the
|
||||
* internal-page representation.
|
||||
*
|
||||
* This implements the same logic as the rtree internal-page strategy map.
|
||||
*/
|
||||
static bool
|
||||
rtree_internal_consistent(BOX *key, BOX *query, StrategyNumber strategy)
|
||||
|
@ -1,31 +0,0 @@
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Makefile--
|
||||
# Makefile for access/rtree
|
||||
#
|
||||
# IDENTIFICATION
|
||||
# $PostgreSQL: pgsql/src/backend/access/rtree/Makefile,v 1.11 2003/11/29 19:51:40 pgsql Exp $
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
subdir = src/backend/access/rtree
|
||||
top_builddir = ../../../..
|
||||
include $(top_builddir)/src/Makefile.global
|
||||
|
||||
OBJS = rtget.o rtproc.o rtree.o rtscan.o rtstrat.o
|
||||
|
||||
all: SUBSYS.o
|
||||
|
||||
SUBSYS.o: $(OBJS)
|
||||
$(LD) $(LDREL) $(LDOUT) SUBSYS.o $(OBJS)
|
||||
|
||||
depend dep:
|
||||
$(CC) -MM $(CFLAGS) *.c >depend
|
||||
|
||||
clean:
|
||||
rm -f SUBSYS.o $(OBJS)
|
||||
|
||||
ifeq (depend,$(wildcard depend))
|
||||
include depend
|
||||
endif
|
||||
|
@ -1,281 +0,0 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* rtget.c
|
||||
* fetch tuples from an rtree scan.
|
||||
*
|
||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/rtree/rtget.c,v 1.37 2005/10/15 02:49:09 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "postgres.h"
|
||||
|
||||
#include "access/iqual.h"
|
||||
#include "access/relscan.h"
|
||||
#include "access/rtree.h"
|
||||
#include "pgstat.h"
|
||||
|
||||
|
||||
static OffsetNumber findnext(IndexScanDesc s, OffsetNumber n,
|
||||
ScanDirection dir);
|
||||
static bool rtnext(IndexScanDesc s, ScanDirection dir);
|
||||
|
||||
|
||||
Datum
|
||||
rtgettuple(PG_FUNCTION_ARGS)
|
||||
{
|
||||
IndexScanDesc s = (IndexScanDesc) PG_GETARG_POINTER(0);
|
||||
ScanDirection dir = (ScanDirection) PG_GETARG_INT32(1);
|
||||
RTreeScanOpaque so = (RTreeScanOpaque) s->opaque;
|
||||
Page page;
|
||||
OffsetNumber offnum;
|
||||
|
||||
/*
|
||||
* If we've already produced a tuple and the executor has informed us that
|
||||
* it should be marked "killed", do so now.
|
||||
*/
|
||||
if (s->kill_prior_tuple && ItemPointerIsValid(&(s->currentItemData)))
|
||||
{
|
||||
offnum = ItemPointerGetOffsetNumber(&(s->currentItemData));
|
||||
page = BufferGetPage(so->curbuf);
|
||||
PageGetItemId(page, offnum)->lp_flags |= LP_DELETE;
|
||||
SetBufferCommitInfoNeedsSave(so->curbuf);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the next tuple that matches the search key; if asked to skip killed
|
||||
* tuples, find the first non-killed tuple that matches. Return as soon as
|
||||
* we've run out of matches or we've found an acceptable match.
|
||||
*/
|
||||
for (;;)
|
||||
{
|
||||
bool res = rtnext(s, dir);
|
||||
|
||||
if (res && s->ignore_killed_tuples)
|
||||
{
|
||||
offnum = ItemPointerGetOffsetNumber(&(s->currentItemData));
|
||||
page = BufferGetPage(so->curbuf);
|
||||
if (ItemIdDeleted(PageGetItemId(page, offnum)))
|
||||
continue;
|
||||
}
|
||||
|
||||
PG_RETURN_BOOL(res);
|
||||
}
|
||||
}
|
||||
|
||||
Datum
|
||||
rtgetmulti(PG_FUNCTION_ARGS)
|
||||
{
|
||||
IndexScanDesc s = (IndexScanDesc) PG_GETARG_POINTER(0);
|
||||
ItemPointer tids = (ItemPointer) PG_GETARG_POINTER(1);
|
||||
int32 max_tids = PG_GETARG_INT32(2);
|
||||
int32 *returned_tids = (int32 *) PG_GETARG_POINTER(3);
|
||||
RTreeScanOpaque so = (RTreeScanOpaque) s->opaque;
|
||||
bool res = true;
|
||||
int32 ntids = 0;
|
||||
|
||||
/* XXX generic implementation: loop around guts of rtgettuple */
|
||||
while (ntids < max_tids)
|
||||
{
|
||||
res = rtnext(s, ForwardScanDirection);
|
||||
if (res && s->ignore_killed_tuples)
|
||||
{
|
||||
Page page;
|
||||
OffsetNumber offnum;
|
||||
|
||||
offnum = ItemPointerGetOffsetNumber(&(s->currentItemData));
|
||||
page = BufferGetPage(so->curbuf);
|
||||
if (ItemIdDeleted(PageGetItemId(page, offnum)))
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!res)
|
||||
break;
|
||||
tids[ntids] = s->xs_ctup.t_self;
|
||||
ntids++;
|
||||
}
|
||||
|
||||
*returned_tids = ntids;
|
||||
PG_RETURN_BOOL(res);
|
||||
}
|
||||
|
||||
static bool
|
||||
rtnext(IndexScanDesc s, ScanDirection dir)
|
||||
{
|
||||
Page p;
|
||||
OffsetNumber n;
|
||||
RTreePageOpaque po;
|
||||
RTreeScanOpaque so;
|
||||
|
||||
so = (RTreeScanOpaque) s->opaque;
|
||||
|
||||
if (!ItemPointerIsValid(&(s->currentItemData)))
|
||||
{
|
||||
/* first call: start at the root */
|
||||
Assert(BufferIsValid(so->curbuf) == false);
|
||||
so->curbuf = ReadBuffer(s->indexRelation, P_ROOT);
|
||||
pgstat_count_index_scan(&s->xs_pgstat_info);
|
||||
}
|
||||
|
||||
p = BufferGetPage(so->curbuf);
|
||||
po = (RTreePageOpaque) PageGetSpecialPointer(p);
|
||||
|
||||
if (!ItemPointerIsValid(&(s->currentItemData)))
|
||||
{
|
||||
/* first call: start at first/last offset */
|
||||
if (ScanDirectionIsForward(dir))
|
||||
n = FirstOffsetNumber;
|
||||
else
|
||||
n = PageGetMaxOffsetNumber(p);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* go on to the next offset */
|
||||
n = ItemPointerGetOffsetNumber(&(s->currentItemData));
|
||||
if (ScanDirectionIsForward(dir))
|
||||
n = OffsetNumberNext(n);
|
||||
else
|
||||
n = OffsetNumberPrev(n);
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
IndexTuple it;
|
||||
RTSTACK *stk;
|
||||
|
||||
n = findnext(s, n, dir);
|
||||
|
||||
/* no match on this page, so read in the next stack entry */
|
||||
if (n == InvalidOffsetNumber)
|
||||
{
|
||||
/* if out of stack entries, we're done */
|
||||
if (so->s_stack == NULL)
|
||||
{
|
||||
ReleaseBuffer(so->curbuf);
|
||||
so->curbuf = InvalidBuffer;
|
||||
return false;
|
||||
}
|
||||
|
||||
stk = so->s_stack;
|
||||
so->curbuf = ReleaseAndReadBuffer(so->curbuf, s->indexRelation,
|
||||
stk->rts_blk);
|
||||
p = BufferGetPage(so->curbuf);
|
||||
po = (RTreePageOpaque) PageGetSpecialPointer(p);
|
||||
|
||||
if (ScanDirectionIsBackward(dir))
|
||||
n = OffsetNumberPrev(stk->rts_child);
|
||||
else
|
||||
n = OffsetNumberNext(stk->rts_child);
|
||||
so->s_stack = stk->rts_parent;
|
||||
pfree(stk);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (po->flags & F_LEAF)
|
||||
{
|
||||
ItemPointerSet(&(s->currentItemData),
|
||||
BufferGetBlockNumber(so->curbuf),
|
||||
n);
|
||||
it = (IndexTuple) PageGetItem(p, PageGetItemId(p, n));
|
||||
s->xs_ctup.t_self = it->t_tid;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
BlockNumber blk;
|
||||
|
||||
stk = (RTSTACK *) palloc(sizeof(RTSTACK));
|
||||
stk->rts_child = n;
|
||||
stk->rts_blk = BufferGetBlockNumber(so->curbuf);
|
||||
stk->rts_parent = so->s_stack;
|
||||
so->s_stack = stk;
|
||||
|
||||
it = (IndexTuple) PageGetItem(p, PageGetItemId(p, n));
|
||||
blk = ItemPointerGetBlockNumber(&(it->t_tid));
|
||||
|
||||
/*
|
||||
* Note that we release the pin on the page as we descend down the
|
||||
* tree, even though there's a good chance we'll eventually need
|
||||
* to re-read the buffer later in this scan. This may or may not
|
||||
* be optimal, but it doesn't seem likely to make a huge
|
||||
* performance difference either way.
|
||||
*/
|
||||
so->curbuf = ReleaseAndReadBuffer(so->curbuf, s->indexRelation, blk);
|
||||
p = BufferGetPage(so->curbuf);
|
||||
po = (RTreePageOpaque) PageGetSpecialPointer(p);
|
||||
|
||||
if (ScanDirectionIsBackward(dir))
|
||||
n = PageGetMaxOffsetNumber(p);
|
||||
else
|
||||
n = FirstOffsetNumber;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the offset of the next matching index entry. We begin the
|
||||
* search at offset "n" and search for matches in the direction
|
||||
* "dir". If no more matching entries are found on the page,
|
||||
* InvalidOffsetNumber is returned.
|
||||
*/
|
||||
static OffsetNumber
|
||||
findnext(IndexScanDesc s, OffsetNumber n, ScanDirection dir)
|
||||
{
|
||||
OffsetNumber maxoff;
|
||||
IndexTuple it;
|
||||
RTreePageOpaque po;
|
||||
RTreeScanOpaque so;
|
||||
Page p;
|
||||
|
||||
so = (RTreeScanOpaque) s->opaque;
|
||||
p = BufferGetPage(so->curbuf);
|
||||
|
||||
maxoff = PageGetMaxOffsetNumber(p);
|
||||
po = (RTreePageOpaque) PageGetSpecialPointer(p);
|
||||
|
||||
/*
|
||||
* If we modified the index during the scan, we may have a pointer to a
|
||||
* ghost tuple, before the scan. If this is the case, back up one.
|
||||
*/
|
||||
|
||||
if (so->s_flags & RTS_CURBEFORE)
|
||||
{
|
||||
so->s_flags &= ~RTS_CURBEFORE;
|
||||
n = OffsetNumberPrev(n);
|
||||
}
|
||||
|
||||
while (n >= FirstOffsetNumber && n <= maxoff)
|
||||
{
|
||||
it = (IndexTuple) PageGetItem(p, PageGetItemId(p, n));
|
||||
if (po->flags & F_LEAF)
|
||||
{
|
||||
if (index_keytest(it,
|
||||
RelationGetDescr(s->indexRelation),
|
||||
s->numberOfKeys, s->keyData))
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (index_keytest(it,
|
||||
RelationGetDescr(s->indexRelation),
|
||||
so->s_internalNKey, so->s_internalKey))
|
||||
break;
|
||||
}
|
||||
|
||||
if (ScanDirectionIsBackward(dir))
|
||||
n = OffsetNumberPrev(n);
|
||||
else
|
||||
n = OffsetNumberNext(n);
|
||||
}
|
||||
|
||||
if (n >= FirstOffsetNumber && n <= maxoff)
|
||||
return n; /* found a match on this page */
|
||||
else
|
||||
return InvalidOffsetNumber; /* no match, go to next page */
|
||||
}
|
@ -1,175 +0,0 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* rtproc.c
|
||||
* pg_amproc entries for rtrees.
|
||||
*
|
||||
* NOTE: for largely-historical reasons, the intersection functions should
|
||||
* return a NULL pointer (*not* an SQL null value) to indicate "no
|
||||
* intersection". The size functions must be prepared to accept such
|
||||
* a pointer and return 0. This convention means that only pass-by-reference
|
||||
* data types can be used as the output of the union and intersection
|
||||
* routines, but that's not a big problem.
|
||||
*
|
||||
*
|
||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/rtree/rtproc.c,v 1.43 2005/10/15 02:49:09 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "postgres.h"
|
||||
|
||||
#include "utils/geo_decls.h"
|
||||
|
||||
|
||||
Datum
|
||||
rt_box_union(PG_FUNCTION_ARGS)
|
||||
{
|
||||
BOX *a = PG_GETARG_BOX_P(0);
|
||||
BOX *b = PG_GETARG_BOX_P(1);
|
||||
BOX *n;
|
||||
|
||||
n = (BOX *) palloc(sizeof(BOX));
|
||||
|
||||
n->high.x = Max(a->high.x, b->high.x);
|
||||
n->high.y = Max(a->high.y, b->high.y);
|
||||
n->low.x = Min(a->low.x, b->low.x);
|
||||
n->low.y = Min(a->low.y, b->low.y);
|
||||
|
||||
PG_RETURN_BOX_P(n);
|
||||
}
|
||||
|
||||
Datum
|
||||
rt_box_inter(PG_FUNCTION_ARGS)
|
||||
{
|
||||
BOX *a = PG_GETARG_BOX_P(0);
|
||||
BOX *b = PG_GETARG_BOX_P(1);
|
||||
BOX *n;
|
||||
|
||||
n = (BOX *) palloc(sizeof(BOX));
|
||||
|
||||
n->high.x = Min(a->high.x, b->high.x);
|
||||
n->high.y = Min(a->high.y, b->high.y);
|
||||
n->low.x = Max(a->low.x, b->low.x);
|
||||
n->low.y = Max(a->low.y, b->low.y);
|
||||
|
||||
if (n->high.x < n->low.x || n->high.y < n->low.y)
|
||||
{
|
||||
pfree(n);
|
||||
/* Indicate "no intersection" by returning NULL pointer */
|
||||
n = NULL;
|
||||
}
|
||||
|
||||
PG_RETURN_BOX_P(n);
|
||||
}
|
||||
|
||||
Datum
|
||||
rt_box_size(PG_FUNCTION_ARGS)
|
||||
{
|
||||
BOX *a = PG_GETARG_BOX_P(0);
|
||||
|
||||
/* NB: size is an output argument */
|
||||
float *size = (float *) PG_GETARG_POINTER(1);
|
||||
|
||||
if (a == NULL || a->high.x <= a->low.x || a->high.y <= a->low.y)
|
||||
*size = 0.0;
|
||||
else
|
||||
*size = (float) ((a->high.x - a->low.x) * (a->high.y - a->low.y));
|
||||
|
||||
PG_RETURN_VOID();
|
||||
}
|
||||
|
||||
Datum
|
||||
rt_poly_union(PG_FUNCTION_ARGS)
|
||||
{
|
||||
POLYGON *a = PG_GETARG_POLYGON_P(0);
|
||||
POLYGON *b = PG_GETARG_POLYGON_P(1);
|
||||
POLYGON *p;
|
||||
|
||||
p = (POLYGON *) palloc0(sizeof(POLYGON)); /* zero any holes */
|
||||
p->size = sizeof(POLYGON);
|
||||
p->npts = 0;
|
||||
p->boundbox.high.x = Max(a->boundbox.high.x, b->boundbox.high.x);
|
||||
p->boundbox.high.y = Max(a->boundbox.high.y, b->boundbox.high.y);
|
||||
p->boundbox.low.x = Min(a->boundbox.low.x, b->boundbox.low.x);
|
||||
p->boundbox.low.y = Min(a->boundbox.low.y, b->boundbox.low.y);
|
||||
|
||||
/* Avoid leaking memory when handed toasted input. */
|
||||
PG_FREE_IF_COPY(a, 0);
|
||||
PG_FREE_IF_COPY(b, 1);
|
||||
|
||||
PG_RETURN_POLYGON_P(p);
|
||||
}
|
||||
|
||||
Datum
|
||||
rt_poly_inter(PG_FUNCTION_ARGS)
|
||||
{
|
||||
POLYGON *a = PG_GETARG_POLYGON_P(0);
|
||||
POLYGON *b = PG_GETARG_POLYGON_P(1);
|
||||
POLYGON *p;
|
||||
|
||||
p = (POLYGON *) palloc0(sizeof(POLYGON)); /* zero any holes */
|
||||
p->size = sizeof(POLYGON);
|
||||
p->npts = 0;
|
||||
p->boundbox.high.x = Min(a->boundbox.high.x, b->boundbox.high.x);
|
||||
p->boundbox.high.y = Min(a->boundbox.high.y, b->boundbox.high.y);
|
||||
p->boundbox.low.x = Max(a->boundbox.low.x, b->boundbox.low.x);
|
||||
p->boundbox.low.y = Max(a->boundbox.low.y, b->boundbox.low.y);
|
||||
|
||||
if (p->boundbox.high.x < p->boundbox.low.x ||
|
||||
p->boundbox.high.y < p->boundbox.low.y)
|
||||
{
|
||||
pfree(p);
|
||||
/* Indicate "no intersection" by returning NULL pointer */
|
||||
p = NULL;
|
||||
}
|
||||
|
||||
/* Avoid leaking memory when handed toasted input. */
|
||||
PG_FREE_IF_COPY(a, 0);
|
||||
PG_FREE_IF_COPY(b, 1);
|
||||
|
||||
PG_RETURN_POLYGON_P(p);
|
||||
}
|
||||
|
||||
Datum
|
||||
rt_poly_size(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Pointer aptr = PG_GETARG_POINTER(0);
|
||||
|
||||
/* NB: size is an output argument */
|
||||
float *size = (float *) PG_GETARG_POINTER(1);
|
||||
POLYGON *a;
|
||||
double xdim,
|
||||
ydim;
|
||||
|
||||
/*
|
||||
* Can't just use GETARG because of possibility that input is NULL; since
|
||||
* POLYGON is toastable, GETARG will try to inspect its value
|
||||
*/
|
||||
if (aptr == NULL)
|
||||
{
|
||||
*size = 0.0;
|
||||
PG_RETURN_VOID();
|
||||
}
|
||||
/* Now safe to apply GETARG */
|
||||
a = PG_GETARG_POLYGON_P(0);
|
||||
|
||||
if (a->boundbox.high.x <= a->boundbox.low.x ||
|
||||
a->boundbox.high.y <= a->boundbox.low.y)
|
||||
*size = 0.0;
|
||||
else
|
||||
{
|
||||
xdim = (a->boundbox.high.x - a->boundbox.low.x);
|
||||
ydim = (a->boundbox.high.y - a->boundbox.low.y);
|
||||
|
||||
*size = (float) (xdim * ydim);
|
||||
}
|
||||
|
||||
/* Avoid leaking memory when handed toasted input. */
|
||||
PG_FREE_IF_COPY(a, 0);
|
||||
|
||||
PG_RETURN_VOID();
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,493 +0,0 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* rtscan.c
|
||||
* routines to manage scans on index relations
|
||||
*
|
||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/rtree/rtscan.c,v 1.60 2005/10/15 02:49:09 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "postgres.h"
|
||||
|
||||
#include "access/genam.h"
|
||||
#include "access/rtree.h"
|
||||
#include "utils/lsyscache.h"
|
||||
#include "utils/resowner.h"
|
||||
|
||||
|
||||
/* routines defined and used here */
|
||||
static void rtregscan(IndexScanDesc s);
|
||||
static void rtdropscan(IndexScanDesc s);
|
||||
static void rtadjone(IndexScanDesc s, int op, BlockNumber blkno,
|
||||
OffsetNumber offnum);
|
||||
static void adjuststack(RTSTACK *stk, BlockNumber blkno);
|
||||
static void adjustiptr(IndexScanDesc s, ItemPointer iptr,
|
||||
int op, BlockNumber blkno, OffsetNumber offnum);
|
||||
|
||||
/*
|
||||
* Whenever we start an rtree scan in a backend, we register it in private
|
||||
* space. Then if the rtree index gets updated, we check all registered
|
||||
* scans and adjust them if the tuple they point at got moved by the
|
||||
* update. We only need to do this in private space, because when we update
|
||||
* an rtree we have a write lock on the tree, so no other process can have
|
||||
* any locks at all on it. A single transaction can have write and read
|
||||
* locks on the same object, so that's why we need to handle this case.
|
||||
*/
|
||||
|
||||
typedef struct RTScanListData
|
||||
{
|
||||
IndexScanDesc rtsl_scan;
|
||||
ResourceOwner rtsl_owner;
|
||||
struct RTScanListData *rtsl_next;
|
||||
} RTScanListData;
|
||||
|
||||
typedef RTScanListData *RTScanList;
|
||||
|
||||
/* pointer to list of local scans on rtrees */
|
||||
static RTScanList RTScans = NULL;
|
||||
|
||||
Datum
|
||||
rtbeginscan(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Relation r = (Relation) PG_GETARG_POINTER(0);
|
||||
int nkeys = PG_GETARG_INT32(1);
|
||||
ScanKey key = (ScanKey) PG_GETARG_POINTER(2);
|
||||
IndexScanDesc s;
|
||||
|
||||
s = RelationGetIndexScan(r, nkeys, key);
|
||||
|
||||
rtregscan(s);
|
||||
|
||||
PG_RETURN_POINTER(s);
|
||||
}
|
||||
|
||||
Datum
|
||||
rtrescan(PG_FUNCTION_ARGS)
|
||||
{
|
||||
IndexScanDesc s = (IndexScanDesc) PG_GETARG_POINTER(0);
|
||||
ScanKey key = (ScanKey) PG_GETARG_POINTER(1);
|
||||
RTreeScanOpaque p;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Clear all the pointers.
|
||||
*/
|
||||
ItemPointerSetInvalid(&s->currentItemData);
|
||||
ItemPointerSetInvalid(&s->currentMarkData);
|
||||
|
||||
p = (RTreeScanOpaque) s->opaque;
|
||||
if (p != NULL)
|
||||
{
|
||||
/* rescan an existing indexscan --- reset state */
|
||||
freestack(p->s_stack);
|
||||
freestack(p->s_markstk);
|
||||
p->s_stack = p->s_markstk = NULL;
|
||||
p->s_flags = 0x0;
|
||||
/* drop pins on buffers -- no locks held */
|
||||
if (BufferIsValid(p->curbuf))
|
||||
{
|
||||
ReleaseBuffer(p->curbuf);
|
||||
p->curbuf = InvalidBuffer;
|
||||
}
|
||||
if (BufferIsValid(p->markbuf))
|
||||
{
|
||||
ReleaseBuffer(p->markbuf);
|
||||
p->markbuf = InvalidBuffer;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* initialize opaque data */
|
||||
p = (RTreeScanOpaque) palloc(sizeof(RTreeScanOpaqueData));
|
||||
p->s_stack = p->s_markstk = NULL;
|
||||
p->curbuf = p->markbuf = InvalidBuffer;
|
||||
p->s_internalNKey = s->numberOfKeys;
|
||||
p->s_flags = 0x0;
|
||||
s->opaque = p;
|
||||
if (s->numberOfKeys > 0)
|
||||
p->s_internalKey = (ScanKey) palloc(sizeof(ScanKeyData) * s->numberOfKeys);
|
||||
}
|
||||
|
||||
/* Update scan key, if a new one is given */
|
||||
if (key && s->numberOfKeys > 0)
|
||||
{
|
||||
memmove(s->keyData,
|
||||
key,
|
||||
s->numberOfKeys * sizeof(ScanKeyData));
|
||||
|
||||
/*
|
||||
* Scans on internal pages use different operators than they do on
|
||||
* leaf pages. For example, if the user wants all boxes that exactly
|
||||
* match (x1,y1,x2,y2), then on internal pages we need to find all
|
||||
* boxes that contain (x1,y1,x2,y2). rtstrat.c knows how to pick the
|
||||
* opclass member to use for internal pages. In some cases we need to
|
||||
* negate the result of the opclass member.
|
||||
*/
|
||||
for (i = 0; i < s->numberOfKeys; i++)
|
||||
{
|
||||
AttrNumber attno = s->keyData[i].sk_attno;
|
||||
Oid opclass;
|
||||
Oid subtype;
|
||||
StrategyNumber orig_strategy;
|
||||
StrategyNumber int_strategy;
|
||||
Oid int_oper;
|
||||
RegProcedure int_proc;
|
||||
int int_flags;
|
||||
|
||||
opclass = s->indexRelation->rd_indclass->values[attno - 1];
|
||||
subtype = s->keyData[i].sk_subtype;
|
||||
orig_strategy = s->keyData[i].sk_strategy;
|
||||
int_strategy = RTMapToInternalOperator(orig_strategy);
|
||||
int_oper = get_opclass_member(opclass, subtype, int_strategy);
|
||||
Assert(OidIsValid(int_oper));
|
||||
int_proc = get_opcode(int_oper);
|
||||
int_flags = s->keyData[i].sk_flags;
|
||||
if (RTMapToInternalNegate(orig_strategy))
|
||||
int_flags |= SK_NEGATE;
|
||||
ScanKeyEntryInitialize(&(p->s_internalKey[i]),
|
||||
int_flags,
|
||||
attno,
|
||||
int_strategy,
|
||||
subtype,
|
||||
int_proc,
|
||||
s->keyData[i].sk_argument);
|
||||
}
|
||||
}
|
||||
|
||||
PG_RETURN_VOID();
|
||||
}
|
||||
|
||||
Datum
|
||||
rtmarkpos(PG_FUNCTION_ARGS)
|
||||
{
|
||||
IndexScanDesc s = (IndexScanDesc) PG_GETARG_POINTER(0);
|
||||
RTreeScanOpaque p;
|
||||
RTSTACK *o,
|
||||
*n,
|
||||
*tmp;
|
||||
|
||||
s->currentMarkData = s->currentItemData;
|
||||
p = (RTreeScanOpaque) s->opaque;
|
||||
if (p->s_flags & RTS_CURBEFORE)
|
||||
p->s_flags |= RTS_MRKBEFORE;
|
||||
else
|
||||
p->s_flags &= ~RTS_MRKBEFORE;
|
||||
|
||||
o = NULL;
|
||||
n = p->s_stack;
|
||||
|
||||
/* copy the parent stack from the current item data */
|
||||
while (n != NULL)
|
||||
{
|
||||
tmp = (RTSTACK *) palloc(sizeof(RTSTACK));
|
||||
tmp->rts_child = n->rts_child;
|
||||
tmp->rts_blk = n->rts_blk;
|
||||
tmp->rts_parent = o;
|
||||
o = tmp;
|
||||
n = n->rts_parent;
|
||||
}
|
||||
|
||||
freestack(p->s_markstk);
|
||||
p->s_markstk = o;
|
||||
|
||||
/* Update markbuf: make sure to bump ref count on curbuf */
|
||||
if (BufferIsValid(p->markbuf))
|
||||
{
|
||||
ReleaseBuffer(p->markbuf);
|
||||
p->markbuf = InvalidBuffer;
|
||||
}
|
||||
if (BufferIsValid(p->curbuf))
|
||||
{
|
||||
IncrBufferRefCount(p->curbuf);
|
||||
p->markbuf = p->curbuf;
|
||||
}
|
||||
|
||||
PG_RETURN_VOID();
|
||||
}
|
||||
|
||||
Datum
|
||||
rtrestrpos(PG_FUNCTION_ARGS)
|
||||
{
|
||||
IndexScanDesc s = (IndexScanDesc) PG_GETARG_POINTER(0);
|
||||
RTreeScanOpaque p;
|
||||
RTSTACK *o,
|
||||
*n,
|
||||
*tmp;
|
||||
|
||||
s->currentItemData = s->currentMarkData;
|
||||
p = (RTreeScanOpaque) s->opaque;
|
||||
if (p->s_flags & RTS_MRKBEFORE)
|
||||
p->s_flags |= RTS_CURBEFORE;
|
||||
else
|
||||
p->s_flags &= ~RTS_CURBEFORE;
|
||||
|
||||
o = NULL;
|
||||
n = p->s_markstk;
|
||||
|
||||
/* copy the parent stack from the current item data */
|
||||
while (n != NULL)
|
||||
{
|
||||
tmp = (RTSTACK *) palloc(sizeof(RTSTACK));
|
||||
tmp->rts_child = n->rts_child;
|
||||
tmp->rts_blk = n->rts_blk;
|
||||
tmp->rts_parent = o;
|
||||
o = tmp;
|
||||
n = n->rts_parent;
|
||||
}
|
||||
|
||||
freestack(p->s_stack);
|
||||
p->s_stack = o;
|
||||
|
||||
/* Update curbuf; be sure to bump ref count on markbuf */
|
||||
if (BufferIsValid(p->curbuf))
|
||||
{
|
||||
ReleaseBuffer(p->curbuf);
|
||||
p->curbuf = InvalidBuffer;
|
||||
}
|
||||
if (BufferIsValid(p->markbuf))
|
||||
{
|
||||
IncrBufferRefCount(p->markbuf);
|
||||
p->curbuf = p->markbuf;
|
||||
}
|
||||
|
||||
PG_RETURN_VOID();
|
||||
}
|
||||
|
||||
Datum
|
||||
rtendscan(PG_FUNCTION_ARGS)
|
||||
{
|
||||
IndexScanDesc s = (IndexScanDesc) PG_GETARG_POINTER(0);
|
||||
RTreeScanOpaque p;
|
||||
|
||||
p = (RTreeScanOpaque) s->opaque;
|
||||
|
||||
if (p != NULL)
|
||||
{
|
||||
freestack(p->s_stack);
|
||||
freestack(p->s_markstk);
|
||||
if (BufferIsValid(p->curbuf))
|
||||
ReleaseBuffer(p->curbuf);
|
||||
if (BufferIsValid(p->markbuf))
|
||||
ReleaseBuffer(p->markbuf);
|
||||
pfree(s->opaque);
|
||||
}
|
||||
|
||||
rtdropscan(s);
|
||||
|
||||
PG_RETURN_VOID();
|
||||
}
|
||||
|
||||
static void
|
||||
rtregscan(IndexScanDesc s)
|
||||
{
|
||||
RTScanList l;
|
||||
|
||||
l = (RTScanList) palloc(sizeof(RTScanListData));
|
||||
l->rtsl_scan = s;
|
||||
l->rtsl_owner = CurrentResourceOwner;
|
||||
l->rtsl_next = RTScans;
|
||||
RTScans = l;
|
||||
}
|
||||
|
||||
static void
|
||||
rtdropscan(IndexScanDesc s)
|
||||
{
|
||||
RTScanList l;
|
||||
RTScanList prev;
|
||||
|
||||
prev = NULL;
|
||||
|
||||
for (l = RTScans;
|
||||
l != NULL && l->rtsl_scan != s;
|
||||
l = l->rtsl_next)
|
||||
prev = l;
|
||||
|
||||
if (l == NULL)
|
||||
elog(ERROR, "rtree scan list corrupted -- could not find 0x%p",
|
||||
(void *) s);
|
||||
|
||||
if (prev == NULL)
|
||||
RTScans = l->rtsl_next;
|
||||
else
|
||||
prev->rtsl_next = l->rtsl_next;
|
||||
|
||||
pfree(l);
|
||||
}
|
||||
|
||||
/*
|
||||
* ReleaseResources_rtree() --- clean up rtree subsystem resources.
|
||||
*
|
||||
* This is here because it needs to touch this module's static var RTScans.
|
||||
*/
|
||||
void
|
||||
ReleaseResources_rtree(void)
|
||||
{
|
||||
RTScanList l;
|
||||
RTScanList prev;
|
||||
RTScanList next;
|
||||
|
||||
/*
|
||||
* Note: this should be a no-op during normal query shutdown. However, in
|
||||
* an abort situation ExecutorEnd is not called and so there may be open
|
||||
* index scans to clean up.
|
||||
*/
|
||||
prev = NULL;
|
||||
|
||||
for (l = RTScans; l != NULL; l = next)
|
||||
{
|
||||
next = l->rtsl_next;
|
||||
if (l->rtsl_owner == CurrentResourceOwner)
|
||||
{
|
||||
if (prev == NULL)
|
||||
RTScans = next;
|
||||
else
|
||||
prev->rtsl_next = next;
|
||||
|
||||
pfree(l);
|
||||
/* prev does not change */
|
||||
}
|
||||
else
|
||||
prev = l;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
rtadjscans(Relation r, int op, BlockNumber blkno, OffsetNumber offnum)
|
||||
{
|
||||
RTScanList l;
|
||||
Oid relid;
|
||||
|
||||
relid = RelationGetRelid(r);
|
||||
for (l = RTScans; l != NULL; l = l->rtsl_next)
|
||||
{
|
||||
if (RelationGetRelid(l->rtsl_scan->indexRelation) == relid)
|
||||
rtadjone(l->rtsl_scan, op, blkno, offnum);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* rtadjone() -- adjust one scan for update.
|
||||
*
|
||||
* By here, the scan passed in is on a modified relation. Op tells
|
||||
* us what the modification is, and blkno and offind tell us what
|
||||
* block and offset index were affected. This routine checks the
|
||||
* current and marked positions, and the current and marked stacks,
|
||||
* to see if any stored location needs to be changed because of the
|
||||
* update. If so, we make the change here.
|
||||
*/
|
||||
static void
|
||||
rtadjone(IndexScanDesc s,
|
||||
int op,
|
||||
BlockNumber blkno,
|
||||
OffsetNumber offnum)
|
||||
{
|
||||
RTreeScanOpaque so;
|
||||
|
||||
adjustiptr(s, &(s->currentItemData), op, blkno, offnum);
|
||||
adjustiptr(s, &(s->currentMarkData), op, blkno, offnum);
|
||||
|
||||
so = (RTreeScanOpaque) s->opaque;
|
||||
|
||||
if (op == RTOP_SPLIT)
|
||||
{
|
||||
adjuststack(so->s_stack, blkno);
|
||||
adjuststack(so->s_markstk, blkno);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* adjustiptr() -- adjust current and marked item pointers in the scan
|
||||
*
|
||||
* Depending on the type of update and the place it happened, we
|
||||
* need to do nothing, to back up one record, or to start over on
|
||||
* the same page.
|
||||
*/
|
||||
static void
|
||||
adjustiptr(IndexScanDesc s,
|
||||
ItemPointer iptr,
|
||||
int op,
|
||||
BlockNumber blkno,
|
||||
OffsetNumber offnum)
|
||||
{
|
||||
OffsetNumber curoff;
|
||||
RTreeScanOpaque so;
|
||||
|
||||
if (ItemPointerIsValid(iptr))
|
||||
{
|
||||
if (ItemPointerGetBlockNumber(iptr) == blkno)
|
||||
{
|
||||
curoff = ItemPointerGetOffsetNumber(iptr);
|
||||
so = (RTreeScanOpaque) s->opaque;
|
||||
|
||||
switch (op)
|
||||
{
|
||||
case RTOP_DEL:
|
||||
/* back up one if we need to */
|
||||
if (curoff >= offnum)
|
||||
{
|
||||
|
||||
if (curoff > FirstOffsetNumber)
|
||||
{
|
||||
/* just adjust the item pointer */
|
||||
ItemPointerSet(iptr, blkno, OffsetNumberPrev(curoff));
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* remember that we're before the current tuple
|
||||
*/
|
||||
ItemPointerSet(iptr, blkno, FirstOffsetNumber);
|
||||
if (iptr == &(s->currentItemData))
|
||||
so->s_flags |= RTS_CURBEFORE;
|
||||
else
|
||||
so->s_flags |= RTS_MRKBEFORE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case RTOP_SPLIT:
|
||||
/* back to start of page on split */
|
||||
ItemPointerSet(iptr, blkno, FirstOffsetNumber);
|
||||
if (iptr == &(s->currentItemData))
|
||||
so->s_flags &= ~RTS_CURBEFORE;
|
||||
else
|
||||
so->s_flags &= ~RTS_MRKBEFORE;
|
||||
break;
|
||||
|
||||
default:
|
||||
elog(ERROR, "unrecognized operation in rtree scan adjust: %d", op);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* adjuststack() -- adjust the supplied stack for a split on a page in
|
||||
* the index we're scanning.
|
||||
*
|
||||
* If a page on our parent stack has split, we need to back up to the
|
||||
* beginning of the page and rescan it. The reason for this is that
|
||||
* the split algorithm for rtrees doesn't order tuples in any useful
|
||||
* way on a single page. This means on that a split, we may wind up
|
||||
* looking at some heap tuples more than once. This is handled in the
|
||||
* access method update code for heaps; if we've modified the tuple we
|
||||
* are looking at already in this transaction, we ignore the update
|
||||
* request.
|
||||
*/
|
||||
static void
|
||||
adjuststack(RTSTACK *stk, BlockNumber blkno)
|
||||
{
|
||||
while (stk != NULL)
|
||||
{
|
||||
if (stk->rts_blk == blkno)
|
||||
stk->rts_child = FirstOffsetNumber;
|
||||
|
||||
stk = stk->rts_parent;
|
||||
}
|
||||
}
|
@ -1,79 +0,0 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* rtstrat.c
|
||||
* strategy map data for rtrees.
|
||||
*
|
||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/rtree/rtstrat.c,v 1.27 2005/06/24 20:53:30 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "postgres.h"
|
||||
|
||||
#include "access/rtree.h"
|
||||
|
||||
|
||||
/*
|
||||
* Here's something peculiar to rtrees that doesn't apply to most other
|
||||
* indexing structures: When we're searching a tree for a given value, we
|
||||
* can't do the same sorts of comparisons on internal node entries as we
|
||||
* do at leaves. The reason is that if we're looking for (say) all boxes
|
||||
* that are the same as (0,0,10,10), then we need to find all leaf pages
|
||||
* that overlap that region. So internally we search for overlap, and at
|
||||
* the leaf we search for equality.
|
||||
*
|
||||
* This array maps leaf search operators to the internal search operators.
|
||||
*/
|
||||
static const StrategyNumber RTOperMap[RTNStrategies] = {
|
||||
RTOverRightStrategyNumber, /* left */
|
||||
RTRightStrategyNumber, /* overleft */
|
||||
RTOverlapStrategyNumber, /* overlap */
|
||||
RTLeftStrategyNumber, /* overright */
|
||||
RTOverLeftStrategyNumber, /* right */
|
||||
RTContainsStrategyNumber, /* same */
|
||||
RTContainsStrategyNumber, /* contains */
|
||||
RTOverlapStrategyNumber, /* contained-by */
|
||||
RTAboveStrategyNumber, /* overbelow */
|
||||
RTOverAboveStrategyNumber, /* below */
|
||||
RTOverBelowStrategyNumber, /* above */
|
||||
RTBelowStrategyNumber /* overabove */
|
||||
};
|
||||
|
||||
/*
|
||||
* We may need to negate the result of the selected operator. (This could
|
||||
* be avoided by expanding the set of operators required for an opclass.)
|
||||
*/
|
||||
static const bool RTNegateMap[RTNStrategies] = {
|
||||
true, /* left */
|
||||
true, /* overleft */
|
||||
false, /* overlap */
|
||||
true, /* overright */
|
||||
true, /* right */
|
||||
false, /* same */
|
||||
false, /* contains */
|
||||
false, /* contained-by */
|
||||
true, /* overbelow */
|
||||
true, /* below */
|
||||
true, /* above */
|
||||
true /* overabove */
|
||||
};
|
||||
|
||||
|
||||
StrategyNumber
|
||||
RTMapToInternalOperator(StrategyNumber strat)
|
||||
{
|
||||
Assert(strat > 0 && strat <= RTNStrategies);
|
||||
return RTOperMap[strat - 1];
|
||||
}
|
||||
|
||||
bool
|
||||
RTMapToInternalNegate(StrategyNumber strat)
|
||||
{
|
||||
Assert(strat > 0 && strat <= RTNStrategies);
|
||||
return RTNegateMap[strat - 1];
|
||||
}
|
@ -3,7 +3,7 @@
|
||||
*
|
||||
* Resource managers definition
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/backend/access/transam/rmgr.c,v 1.20 2005/06/14 11:45:14 teodor Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/transam/rmgr.c,v 1.21 2005/11/07 17:36:45 tgl Exp $
|
||||
*/
|
||||
#include "postgres.h"
|
||||
|
||||
@ -13,7 +13,6 @@
|
||||
#include "access/heapam.h"
|
||||
#include "access/multixact.h"
|
||||
#include "access/nbtree.h"
|
||||
#include "access/rtree.h"
|
||||
#include "access/xact.h"
|
||||
#include "access/xlog_internal.h"
|
||||
#include "commands/dbcommands.h"
|
||||
@ -36,7 +35,7 @@ const RmgrData RmgrTable[RM_MAX_ID + 1] = {
|
||||
{"Heap", heap_redo, heap_desc, NULL, NULL},
|
||||
{"Btree", btree_redo, btree_desc, btree_xlog_startup, btree_xlog_cleanup},
|
||||
{"Hash", hash_redo, hash_desc, NULL, NULL},
|
||||
{"Rtree", rtree_redo, rtree_desc, NULL, NULL},
|
||||
{"Reserved 13", NULL, NULL, NULL, NULL},
|
||||
{"Gist", gist_redo, gist_desc, gist_xlog_startup, gist_xlog_cleanup},
|
||||
{"Sequence", seq_redo, seq_desc, NULL, NULL}
|
||||
};
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/commands/indexcmds.c,v 1.134 2005/10/15 02:49:15 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/commands/indexcmds.c,v 1.135 2005/11/07 17:36:45 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -226,10 +226,27 @@ DefineIndex(RangeVar *heapRelation,
|
||||
PointerGetDatum(accessMethodName),
|
||||
0, 0, 0);
|
||||
if (!HeapTupleIsValid(tuple))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("access method \"%s\" does not exist",
|
||||
accessMethodName)));
|
||||
{
|
||||
/*
|
||||
* Hack to provide more-or-less-transparent updating of old RTREE
|
||||
* indexes to GIST: if RTREE is requested and not found, use GIST.
|
||||
*/
|
||||
if (strcmp(accessMethodName, "rtree") == 0)
|
||||
{
|
||||
ereport(NOTICE,
|
||||
(errmsg("substituting access method \"gist\" for obsolete method \"rtree\"")));
|
||||
accessMethodName = "gist";
|
||||
tuple = SearchSysCache(AMNAME,
|
||||
PointerGetDatum(accessMethodName),
|
||||
0, 0, 0);
|
||||
}
|
||||
|
||||
if (!HeapTupleIsValid(tuple))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("access method \"%s\" does not exist",
|
||||
accessMethodName)));
|
||||
}
|
||||
accessMethodId = HeapTupleGetOid(tuple);
|
||||
accessMethodForm = (Form_pg_am) GETSTRUCT(tuple);
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/geo_selfuncs.c,v 1.24 2004/12/31 22:01:22 pgsql Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/geo_selfuncs.c,v 1.25 2005/11/07 17:36:45 tgl Exp $
|
||||
*
|
||||
* XXX These are totally bogus. Perhaps someone will make them do
|
||||
* something reasonable, someday.
|
||||
@ -22,19 +22,19 @@
|
||||
|
||||
|
||||
/*
|
||||
* Selectivity functions for rtrees. These are bogus -- unless we know
|
||||
* the actual key distribution in the index, we can't make a good prediction
|
||||
* of the selectivity of these operators.
|
||||
* Selectivity functions for geometric operators. These are bogus -- unless
|
||||
* we know the actual key distribution in the index, we can't make a good
|
||||
* prediction of the selectivity of these operators.
|
||||
*
|
||||
* Note: the values used here may look unreasonably small. Perhaps they
|
||||
* are. For now, we want to make sure that the optimizer will make use
|
||||
* of an r-tree index if one is available, so the selectivity had better
|
||||
* of a geometric index if one is available, so the selectivity had better
|
||||
* be fairly small.
|
||||
*
|
||||
* In general, rtrees need to search multiple subtrees in order to guarantee
|
||||
* In general, GiST needs to search multiple subtrees in order to guarantee
|
||||
* that all occurrences of the same key have been found. Because of this,
|
||||
* the estimated cost for scanning the index ought to be higher than the
|
||||
* output selectivity would indicate. rtcostestimate(), over in selfuncs.c,
|
||||
* output selectivity would indicate. gistcostestimate(), over in selfuncs.c,
|
||||
* ought to be adjusted accordingly --- but until we can generate somewhat
|
||||
* realistic numbers here, it hardly matters...
|
||||
*/
|
||||
|
@ -15,7 +15,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/selfuncs.c,v 1.191 2005/10/15 02:49:29 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/selfuncs.c,v 1.192 2005/11/07 17:36:45 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -4470,24 +4470,6 @@ btcostestimate(PG_FUNCTION_ARGS)
|
||||
PG_RETURN_VOID();
|
||||
}
|
||||
|
||||
Datum
|
||||
rtcostestimate(PG_FUNCTION_ARGS)
|
||||
{
|
||||
PlannerInfo *root = (PlannerInfo *) PG_GETARG_POINTER(0);
|
||||
IndexOptInfo *index = (IndexOptInfo *) PG_GETARG_POINTER(1);
|
||||
List *indexQuals = (List *) PG_GETARG_POINTER(2);
|
||||
Cost *indexStartupCost = (Cost *) PG_GETARG_POINTER(3);
|
||||
Cost *indexTotalCost = (Cost *) PG_GETARG_POINTER(4);
|
||||
Selectivity *indexSelectivity = (Selectivity *) PG_GETARG_POINTER(5);
|
||||
double *indexCorrelation = (double *) PG_GETARG_POINTER(6);
|
||||
|
||||
genericcostestimate(root, index, indexQuals, 0.0,
|
||||
indexStartupCost, indexTotalCost,
|
||||
indexSelectivity, indexCorrelation);
|
||||
|
||||
PG_RETURN_VOID();
|
||||
}
|
||||
|
||||
Datum
|
||||
hashcostestimate(PG_FUNCTION_ARGS)
|
||||
{
|
||||
|
@ -14,7 +14,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/resowner/resowner.c,v 1.14 2005/10/15 02:49:36 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/resowner/resowner.c,v 1.15 2005/11/07 17:36:45 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -23,7 +23,6 @@
|
||||
#include "utils/resowner.h"
|
||||
#include "access/gistscan.h"
|
||||
#include "access/hash.h"
|
||||
#include "access/rtree.h"
|
||||
#include "storage/bufmgr.h"
|
||||
#include "storage/proc.h"
|
||||
#include "utils/memutils.h"
|
||||
@ -280,7 +279,6 @@ ResourceOwnerReleaseInternal(ResourceOwner owner,
|
||||
/* Clean up index scans too */
|
||||
ReleaseResources_gist();
|
||||
ReleaseResources_hash();
|
||||
ReleaseResources_rtree();
|
||||
}
|
||||
|
||||
/* Let add-on modules get a chance too */
|
||||
|
@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (c) 2000-2005, PostgreSQL Global Development Group
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/bin/psql/tab-complete.c,v 1.138 2005/10/15 02:49:40 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/bin/psql/tab-complete.c,v 1.139 2005/11/07 17:36:45 tgl Exp $
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
@ -1025,7 +1025,7 @@ psql_completion(char *text, int start, int end)
|
||||
else if (pg_strcasecmp(prev_wd, "USING") == 0)
|
||||
{
|
||||
static const char *const index_mth[] =
|
||||
{"BTREE", "RTREE", "HASH", "GIST", NULL};
|
||||
{"BTREE", "HASH", "GIST", NULL};
|
||||
|
||||
COMPLETE_WITH_LIST(index_mth);
|
||||
}
|
||||
|
@ -9,18 +9,18 @@
|
||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/access/gist.h,v 1.50 2005/10/15 02:49:42 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/include/access/gist.h,v 1.51 2005/11/07 17:36:46 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#ifndef GIST_H
|
||||
#define GIST_H
|
||||
|
||||
#include "access/xlog.h"
|
||||
#include "access/xlogdefs.h"
|
||||
#include "storage/bufpage.h"
|
||||
#include "storage/off.h"
|
||||
#include "utils/rel.h"
|
||||
#include "access/xlog.h"
|
||||
#include "access/xlogdefs.h"
|
||||
|
||||
/*
|
||||
* amproc indexes for GiST indexes.
|
||||
@ -34,6 +34,23 @@
|
||||
#define GIST_EQUAL_PROC 7
|
||||
#define GISTNProcs 7
|
||||
|
||||
/*
|
||||
* strategy numbers for GiST opclasses that want to implement the old
|
||||
* RTREE behavior.
|
||||
*/
|
||||
#define RTLeftStrategyNumber 1
|
||||
#define RTOverLeftStrategyNumber 2
|
||||
#define RTOverlapStrategyNumber 3
|
||||
#define RTOverRightStrategyNumber 4
|
||||
#define RTRightStrategyNumber 5
|
||||
#define RTSameStrategyNumber 6
|
||||
#define RTContainsStrategyNumber 7
|
||||
#define RTContainedByStrategyNumber 8
|
||||
#define RTOverBelowStrategyNumber 9
|
||||
#define RTBelowStrategyNumber 10
|
||||
#define RTAboveStrategyNumber 11
|
||||
#define RTOverAboveStrategyNumber 12
|
||||
|
||||
/*
|
||||
* Page opaque data in a GiST index page.
|
||||
*/
|
||||
|
@ -3,7 +3,7 @@
|
||||
*
|
||||
* Resource managers definition
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/access/rmgr.h,v 1.14 2005/06/06 17:01:24 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/include/access/rmgr.h,v 1.15 2005/11/07 17:36:46 tgl Exp $
|
||||
*/
|
||||
#ifndef RMGR_H
|
||||
#define RMGR_H
|
||||
@ -23,7 +23,6 @@ typedef uint8 RmgrId;
|
||||
#define RM_HEAP_ID 10
|
||||
#define RM_BTREE_ID 11
|
||||
#define RM_HASH_ID 12
|
||||
#define RM_RTREE_ID 13
|
||||
#define RM_GIST_ID 14
|
||||
#define RM_SEQ_ID 15
|
||||
#define RM_MAX_ID RM_SEQ_ID
|
||||
|
@ -1,145 +0,0 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* rtree.h
|
||||
* common declarations for the rtree access method code.
|
||||
*
|
||||
*
|
||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/access/rtree.h,v 1.41 2005/06/24 20:53:31 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#ifndef RTREE_H
|
||||
#define RTREE_H
|
||||
|
||||
#include "access/itup.h"
|
||||
#include "access/sdir.h"
|
||||
#include "access/skey.h"
|
||||
#include "access/xlog.h"
|
||||
#include "utils/rel.h"
|
||||
|
||||
/* see rtstrat.c for what all this is about */
|
||||
#define RTNStrategies 12
|
||||
#define RTLeftStrategyNumber 1
|
||||
#define RTOverLeftStrategyNumber 2
|
||||
#define RTOverlapStrategyNumber 3
|
||||
#define RTOverRightStrategyNumber 4
|
||||
#define RTRightStrategyNumber 5
|
||||
#define RTSameStrategyNumber 6
|
||||
#define RTContainsStrategyNumber 7
|
||||
#define RTContainedByStrategyNumber 8
|
||||
#define RTOverBelowStrategyNumber 9
|
||||
#define RTBelowStrategyNumber 10
|
||||
#define RTAboveStrategyNumber 11
|
||||
#define RTOverAboveStrategyNumber 12
|
||||
|
||||
#define RTNProcs 3
|
||||
#define RT_UNION_PROC 1
|
||||
#define RT_INTER_PROC 2
|
||||
#define RT_SIZE_PROC 3
|
||||
|
||||
#define F_LEAF (1 << 0)
|
||||
|
||||
typedef struct RTreePageOpaqueData
|
||||
{
|
||||
uint32 flags;
|
||||
} RTreePageOpaqueData;
|
||||
|
||||
typedef RTreePageOpaqueData *RTreePageOpaque;
|
||||
|
||||
/*
|
||||
* When we descend a tree, we keep a stack of parent pointers.
|
||||
*/
|
||||
|
||||
typedef struct RTSTACK
|
||||
{
|
||||
struct RTSTACK *rts_parent;
|
||||
OffsetNumber rts_child;
|
||||
BlockNumber rts_blk;
|
||||
} RTSTACK;
|
||||
|
||||
/*
|
||||
* When we're doing a scan, we need to keep track of the parent stack
|
||||
* for the marked and current items. Also, rtrees have the following
|
||||
* property: if you're looking for the box (1,1,2,2), on the internal
|
||||
* nodes you have to search for all boxes that *contain* (1,1,2,2),
|
||||
* and not the ones that match it. We have a private scan key for
|
||||
* internal nodes in the opaque structure for rtrees for this reason.
|
||||
* See access/index-rtree/rtscan.c and rtstrat.c for how it gets
|
||||
* initialized. We also keep pins on the scan's current buffer and
|
||||
* marked buffer, if any: this avoids the need to invoke ReadBuffer()
|
||||
* for each tuple produced by the index scan.
|
||||
*/
|
||||
|
||||
typedef struct RTreeScanOpaqueData
|
||||
{
|
||||
struct RTSTACK *s_stack;
|
||||
struct RTSTACK *s_markstk;
|
||||
uint16 s_flags;
|
||||
int s_internalNKey;
|
||||
ScanKey s_internalKey;
|
||||
Buffer curbuf;
|
||||
Buffer markbuf;
|
||||
} RTreeScanOpaqueData;
|
||||
|
||||
typedef RTreeScanOpaqueData *RTreeScanOpaque;
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#define RTS_CURBEFORE ((uint16) (1 << 0))
|
||||
#define RTS_MRKBEFORE ((uint16) (1 << 1))
|
||||
|
||||
/* root page of an rtree */
|
||||
#define P_ROOT 0
|
||||
|
||||
/*
|
||||
* 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
|
||||
* rtscan.c for how the scan is fixed. These two contants tell us what sort
|
||||
* of operation changed the index.
|
||||
*/
|
||||
|
||||
#define RTOP_DEL 0
|
||||
#define RTOP_SPLIT 1
|
||||
|
||||
/* defined in rtree.c */
|
||||
extern void freestack(RTSTACK *s);
|
||||
|
||||
/*
|
||||
* RTree code.
|
||||
* Defined in access/rtree/
|
||||
*/
|
||||
extern Datum rtinsert(PG_FUNCTION_ARGS);
|
||||
extern Datum rtbulkdelete(PG_FUNCTION_ARGS);
|
||||
extern Datum rtbeginscan(PG_FUNCTION_ARGS);
|
||||
extern Datum rtgettuple(PG_FUNCTION_ARGS);
|
||||
extern Datum rtgetmulti(PG_FUNCTION_ARGS);
|
||||
extern Datum rtendscan(PG_FUNCTION_ARGS);
|
||||
extern Datum rtmarkpos(PG_FUNCTION_ARGS);
|
||||
extern Datum rtrestrpos(PG_FUNCTION_ARGS);
|
||||
extern Datum rtrescan(PG_FUNCTION_ARGS);
|
||||
extern Datum rtbuild(PG_FUNCTION_ARGS);
|
||||
extern void _rtdump(Relation r);
|
||||
|
||||
extern void rtree_redo(XLogRecPtr lsn, XLogRecord *record);
|
||||
extern void rtree_desc(char *buf, uint8 xl_info, char *rec);
|
||||
|
||||
/* rtscan.c */
|
||||
extern void rtadjscans(Relation r, int op, BlockNumber blkno,
|
||||
OffsetNumber offnum);
|
||||
extern void ReleaseResources_rtree(void);
|
||||
|
||||
/* rtstrat.c */
|
||||
extern StrategyNumber RTMapToInternalOperator(StrategyNumber strat);
|
||||
extern bool RTMapToInternalNegate(StrategyNumber strat);
|
||||
|
||||
#endif /* RTREE_H */
|
@ -1,23 +0,0 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* rtscan.h
|
||||
* routines defined in access/rtree/rtscan.c
|
||||
*
|
||||
*
|
||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/access/rtscan.h,v 1.18 2004/12/31 22:03:21 pgsql Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#ifndef RTSCAN_H
|
||||
#define RTSCAN_H
|
||||
|
||||
#include "storage/block.h"
|
||||
#include "storage/off.h"
|
||||
#include "utils/rel.h"
|
||||
|
||||
void rtadjscans(Relation r, int op, BlockNumber blkno, OffsetNumber offnum);
|
||||
|
||||
#endif /* RTSCAN_H */
|
@ -37,7 +37,7 @@
|
||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.305 2005/10/21 15:45:06 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.306 2005/11/07 17:36:46 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -53,6 +53,6 @@
|
||||
*/
|
||||
|
||||
/* yyyymmddN */
|
||||
#define CATALOG_VERSION_NO 200510211
|
||||
#define CATALOG_VERSION_NO 200511071
|
||||
|
||||
#endif
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/catalog/pg_am.h,v 1.38 2005/10/15 02:49:42 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/include/catalog/pg_am.h,v 1.39 2005/11/07 17:36:46 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* the genbki.sh script reads this file and generates .bki
|
||||
@ -104,8 +104,6 @@ typedef FormData_pg_am *Form_pg_am;
|
||||
* ----------------
|
||||
*/
|
||||
|
||||
DATA(insert OID = 402 ( rtree 12 3 0 f f f f f rtinsert rtbeginscan rtgettuple rtgetmulti rtrescan rtendscan rtmarkpos rtrestrpos rtbuild rtbulkdelete - rtcostestimate ));
|
||||
DESCR("r-tree index access method");
|
||||
DATA(insert OID = 403 ( btree 5 1 1 t t t t t btinsert btbeginscan btgettuple btgetmulti btrescan btendscan btmarkpos btrestrpos btbuild btbulkdelete btvacuumcleanup btcostestimate ));
|
||||
DESCR("b-tree index access method");
|
||||
#define BTREE_AM_OID 403
|
||||
|
@ -23,7 +23,7 @@
|
||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/catalog/pg_amop.h,v 1.66 2005/10/15 02:49:42 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/include/catalog/pg_amop.h,v 1.67 2005/11/07 17:36:46 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* the genbki.sh script reads this file and generates .bki
|
||||
@ -80,40 +80,6 @@ typedef FormData_pg_amop *Form_pg_amop;
|
||||
* ----------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* rtree box_ops
|
||||
*/
|
||||
|
||||
DATA(insert ( 425 0 1 f 493 ));
|
||||
DATA(insert ( 425 0 2 f 494 ));
|
||||
DATA(insert ( 425 0 3 f 500 ));
|
||||
DATA(insert ( 425 0 4 f 495 ));
|
||||
DATA(insert ( 425 0 5 f 496 ));
|
||||
DATA(insert ( 425 0 6 f 499 ));
|
||||
DATA(insert ( 425 0 7 f 498 ));
|
||||
DATA(insert ( 425 0 8 f 497 ));
|
||||
DATA(insert ( 425 0 9 f 2571 ));
|
||||
DATA(insert ( 425 0 10 f 2570 ));
|
||||
DATA(insert ( 425 0 11 f 2573 ));
|
||||
DATA(insert ( 425 0 12 f 2572 ));
|
||||
|
||||
/*
|
||||
* rtree poly_ops (supports polygons)
|
||||
*/
|
||||
|
||||
DATA(insert ( 1993 0 1 f 485 ));
|
||||
DATA(insert ( 1993 0 2 f 486 ));
|
||||
DATA(insert ( 1993 0 3 f 492 ));
|
||||
DATA(insert ( 1993 0 4 f 487 ));
|
||||
DATA(insert ( 1993 0 5 f 488 ));
|
||||
DATA(insert ( 1993 0 6 f 491 ));
|
||||
DATA(insert ( 1993 0 7 f 490 ));
|
||||
DATA(insert ( 1993 0 8 f 489 ));
|
||||
DATA(insert ( 1993 0 9 f 2575 ));
|
||||
DATA(insert ( 1993 0 10 f 2574 ));
|
||||
DATA(insert ( 1993 0 11 f 2577 ));
|
||||
DATA(insert ( 1993 0 12 f 2576 ));
|
||||
|
||||
/*
|
||||
* btree int2_ops
|
||||
*/
|
||||
|
@ -19,7 +19,7 @@
|
||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/catalog/pg_amproc.h,v 1.54 2005/07/01 19:19:03 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/include/catalog/pg_amproc.h,v 1.55 2005/11/07 17:36:46 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* the genbki.sh script reads this file and generates .bki
|
||||
@ -74,15 +74,6 @@ typedef FormData_pg_amproc *Form_pg_amproc;
|
||||
* ----------------
|
||||
*/
|
||||
|
||||
/* rtree */
|
||||
DATA(insert ( 425 0 1 193 ));
|
||||
DATA(insert ( 425 0 2 194 ));
|
||||
DATA(insert ( 425 0 3 195 ));
|
||||
DATA(insert ( 1993 0 1 197 ));
|
||||
DATA(insert ( 1993 0 2 198 ));
|
||||
DATA(insert ( 1993 0 3 199 ));
|
||||
|
||||
|
||||
/* btree */
|
||||
DATA(insert ( 397 0 1 382 ));
|
||||
DATA(insert ( 421 0 1 357 ));
|
||||
|
@ -27,7 +27,7 @@
|
||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/catalog/pg_opclass.h,v 1.66 2005/07/01 19:19:03 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/include/catalog/pg_opclass.h,v 1.67 2005/11/07 17:36:46 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* the genbki.sh script reads this file and generates .bki
|
||||
@ -94,7 +94,6 @@ DATA(insert OID = 397 ( 403 array_ops PGNSP PGUID 2277 t 0 ));
|
||||
DATA(insert OID = 423 ( 403 bit_ops PGNSP PGUID 1560 t 0 ));
|
||||
DATA(insert OID = 424 ( 403 bool_ops PGNSP PGUID 16 t 0 ));
|
||||
#define BOOL_BTREE_OPS_OID 424
|
||||
DATA(insert OID = 425 ( 402 box_ops PGNSP PGUID 603 t 0 ));
|
||||
DATA(insert OID = 426 ( 403 bpchar_ops PGNSP PGUID 1042 t 0 ));
|
||||
#define BPCHAR_BTREE_OPS_OID 426
|
||||
DATA(insert OID = 427 ( 405 bpchar_ops PGNSP PGUID 1042 t 0 ));
|
||||
@ -135,7 +134,6 @@ DATA(insert OID = 1989 ( 403 oid_ops PGNSP PGUID 26 t 0 ));
|
||||
DATA(insert OID = 1990 ( 405 oid_ops PGNSP PGUID 26 t 0 ));
|
||||
DATA(insert OID = 1991 ( 403 oidvector_ops PGNSP PGUID 30 t 0 ));
|
||||
DATA(insert OID = 1992 ( 405 oidvector_ops PGNSP PGUID 30 t 0 ));
|
||||
DATA(insert OID = 1993 ( 402 poly_ops PGNSP PGUID 604 t 0 ));
|
||||
DATA(insert OID = 1994 ( 403 text_ops PGNSP PGUID 25 t 0 ));
|
||||
#define TEXT_BTREE_OPS_OID 1994
|
||||
DATA(insert OID = 1995 ( 405 text_ops PGNSP PGUID 25 t 0 ));
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.387 2005/10/15 02:49:42 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.388 2005/11/07 17:36:46 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* The script catalog/genbki.sh reads this file and generates .bki
|
||||
@ -394,18 +394,6 @@ DATA(insert OID = 191 ( box_right PGNSP PGUID 12 f f t f i 2 16 "603 603" _
|
||||
DESCR("is right of");
|
||||
DATA(insert OID = 192 ( box_contained PGNSP PGUID 12 f f t f i 2 16 "603 603" _null_ _null_ _null_ box_contained - _null_ ));
|
||||
DESCR("contained in?");
|
||||
DATA(insert OID = 193 ( rt_box_union PGNSP PGUID 12 f f t f i 2 603 "603 603" _null_ _null_ _null_ rt_box_union - _null_ ));
|
||||
DESCR("r-tree");
|
||||
DATA(insert OID = 194 ( rt_box_inter PGNSP PGUID 12 f f t f i 2 2278 "603 603" _null_ _null_ _null_ rt_box_inter - _null_ ));
|
||||
DESCR("r-tree");
|
||||
DATA(insert OID = 195 ( rt_box_size PGNSP PGUID 12 f f t f i 2 2278 "603 2281" _null_ _null_ _null_ rt_box_size - _null_ ));
|
||||
DESCR("r-tree");
|
||||
DATA(insert OID = 197 ( rt_poly_union PGNSP PGUID 12 f f t f i 2 604 "604 604" _null_ _null_ _null_ rt_poly_union - _null_ ));
|
||||
DESCR("r-tree");
|
||||
DATA(insert OID = 198 ( rt_poly_inter PGNSP PGUID 12 f f t f i 2 2278 "604 604" _null_ _null_ _null_ rt_poly_inter - _null_ ));
|
||||
DESCR("r-tree");
|
||||
DATA(insert OID = 199 ( rt_poly_size PGNSP PGUID 12 f f t f i 2 2278 "604 2281" _null_ _null_ _null_ rt_poly_size - _null_ ));
|
||||
DESCR("r-tree");
|
||||
|
||||
/* OIDS 200 - 299 */
|
||||
|
||||
@ -668,29 +656,6 @@ DESCR("convert int4 to float4");
|
||||
DATA(insert OID = 319 ( int4 PGNSP PGUID 12 f f t f i 1 23 "700" _null_ _null_ _null_ ftoi4 - _null_ ));
|
||||
DESCR("convert float4 to int4");
|
||||
|
||||
DATA(insert OID = 320 ( rtinsert PGNSP PGUID 12 f f t f v 6 16 "2281 2281 2281 2281 2281 2281" _null_ _null_ _null_ rtinsert - _null_ ));
|
||||
DESCR("r-tree(internal)");
|
||||
DATA(insert OID = 322 ( rtgettuple PGNSP PGUID 12 f f t f v 2 16 "2281 2281" _null_ _null_ _null_ rtgettuple - _null_ ));
|
||||
DESCR("r-tree(internal)");
|
||||
DATA(insert OID = 635 ( rtgetmulti PGNSP PGUID 12 f f t f v 4 16 "2281 2281 2281 2281" _null_ _null_ _null_ rtgetmulti - _null_ ));
|
||||
DESCR("r-tree(internal)");
|
||||
DATA(insert OID = 323 ( rtbuild PGNSP PGUID 12 f f t f v 3 2278 "2281 2281 2281" _null_ _null_ _null_ rtbuild - _null_ ));
|
||||
DESCR("r-tree(internal)");
|
||||
DATA(insert OID = 324 ( rtbeginscan PGNSP PGUID 12 f f t f v 3 2281 "2281 2281 2281" _null_ _null_ _null_ rtbeginscan - _null_ ));
|
||||
DESCR("r-tree(internal)");
|
||||
DATA(insert OID = 325 ( rtendscan PGNSP PGUID 12 f f t f v 1 2278 "2281" _null_ _null_ _null_ rtendscan - _null_ ));
|
||||
DESCR("r-tree(internal)");
|
||||
DATA(insert OID = 326 ( rtmarkpos PGNSP PGUID 12 f f t f v 1 2278 "2281" _null_ _null_ _null_ rtmarkpos - _null_ ));
|
||||
DESCR("r-tree(internal)");
|
||||
DATA(insert OID = 327 ( rtrestrpos PGNSP PGUID 12 f f t f v 1 2278 "2281" _null_ _null_ _null_ rtrestrpos - _null_ ));
|
||||
DESCR("r-tree(internal)");
|
||||
DATA(insert OID = 328 ( rtrescan PGNSP PGUID 12 f f t f v 2 2278 "2281 2281" _null_ _null_ _null_ rtrescan - _null_ ));
|
||||
DESCR("r-tree(internal)");
|
||||
DATA(insert OID = 321 ( rtbulkdelete PGNSP PGUID 12 f f t f v 3 2281 "2281 2281 2281" _null_ _null_ _null_ rtbulkdelete - _null_ ));
|
||||
DESCR("r-tree(internal)");
|
||||
DATA(insert OID = 1265 ( rtcostestimate PGNSP PGUID 12 f f t f v 7 2278 "2281 2281 2281 2281 2281 2281 2281" _null_ _null_ _null_ rtcostestimate - _null_ ));
|
||||
DESCR("r-tree(internal)");
|
||||
|
||||
DATA(insert OID = 330 ( btgettuple PGNSP PGUID 12 f f t f v 2 16 "2281 2281" _null_ _null_ _null_ btgettuple - _null_ ));
|
||||
DESCR("btree(internal)");
|
||||
DATA(insert OID = 636 ( btgetmulti PGNSP PGUID 12 f f t f v 4 16 "2281 2281 2281 2281" _null_ _null_ _null_ btgetmulti - _null_ ));
|
||||
|
@ -6,7 +6,7 @@
|
||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/utils/geo_decls.h,v 1.48 2005/07/01 19:19:04 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/include/utils/geo_decls.h,v 1.49 2005/11/07 17:36:47 tgl Exp $
|
||||
*
|
||||
* NOTE
|
||||
* These routines do *not* use the float types from adt/.
|
||||
@ -406,14 +406,6 @@ extern Datum poly_circle(PG_FUNCTION_ARGS);
|
||||
extern Datum circle_poly(PG_FUNCTION_ARGS);
|
||||
extern Datum circle_area(PG_FUNCTION_ARGS);
|
||||
|
||||
/* support routines for the rtree access method (access/rtree/rtproc.c) */
|
||||
extern Datum rt_box_union(PG_FUNCTION_ARGS);
|
||||
extern Datum rt_box_inter(PG_FUNCTION_ARGS);
|
||||
extern Datum rt_box_size(PG_FUNCTION_ARGS);
|
||||
extern Datum rt_poly_size(PG_FUNCTION_ARGS);
|
||||
extern Datum rt_poly_union(PG_FUNCTION_ARGS);
|
||||
extern Datum rt_poly_inter(PG_FUNCTION_ARGS);
|
||||
|
||||
/* support routines for the GiST access method (access/gist/gistproc.c) */
|
||||
extern Datum gist_box_compress(PG_FUNCTION_ARGS);
|
||||
extern Datum gist_box_decompress(PG_FUNCTION_ARGS);
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/utils/selfuncs.h,v 1.24 2005/10/15 02:49:46 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/include/utils/selfuncs.h,v 1.25 2005/11/07 17:36:47 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -124,7 +124,6 @@ extern Selectivity estimate_hash_bucketsize(PlannerInfo *root, Node *hashkey,
|
||||
double nbuckets);
|
||||
|
||||
extern Datum btcostestimate(PG_FUNCTION_ARGS);
|
||||
extern Datum rtcostestimate(PG_FUNCTION_ARGS);
|
||||
extern Datum hashcostestimate(PG_FUNCTION_ARGS);
|
||||
extern Datum gistcostestimate(PG_FUNCTION_ARGS);
|
||||
|
||||
|
@ -46,55 +46,6 @@ CREATE INDEX onek2_u2_prtl ON onek2 USING btree(unique2 int4_ops)
|
||||
CREATE INDEX onek2_stu1_prtl ON onek2 USING btree(stringu1 name_ops)
|
||||
where onek2.stringu1 >= 'J' and onek2.stringu1 < 'K';
|
||||
--
|
||||
-- RTREE
|
||||
--
|
||||
-- rtrees use a quadratic page-splitting algorithm that takes a
|
||||
-- really, really long time. we don't test all rtree opclasses
|
||||
-- in the regression test (we check them using the sequoia 2000
|
||||
-- benchmark).
|
||||
--
|
||||
CREATE INDEX rect2ind ON fast_emp4000 USING rtree (home_base);
|
||||
SET enable_seqscan = ON;
|
||||
SET enable_indexscan = OFF;
|
||||
SET enable_bitmapscan = OFF;
|
||||
SELECT * FROM fast_emp4000
|
||||
WHERE home_base @ '(200,200),(2000,1000)'::box
|
||||
ORDER BY home_base USING <;
|
||||
home_base
|
||||
-----------------------
|
||||
(1444,403),(1346,344)
|
||||
(337,455),(240,359)
|
||||
(2 rows)
|
||||
|
||||
SELECT count(*) FROM fast_emp4000 WHERE home_base && '(1000,1000,0,0)'::box;
|
||||
count
|
||||
-------
|
||||
2
|
||||
(1 row)
|
||||
|
||||
SET enable_seqscan = OFF;
|
||||
SET enable_indexscan = ON;
|
||||
SET enable_bitmapscan = ON;
|
||||
-- there's no easy way to check that these commands actually use
|
||||
-- the index, unfortunately. (EXPLAIN would work, but its output
|
||||
-- changes too often for me to want to put an EXPLAIN in the test...)
|
||||
SELECT * FROM fast_emp4000
|
||||
WHERE home_base @ '(200,200),(2000,1000)'::box
|
||||
ORDER BY home_base USING <;
|
||||
home_base
|
||||
-----------------------
|
||||
(1444,403),(1346,344)
|
||||
(337,455),(240,359)
|
||||
(2 rows)
|
||||
|
||||
SELECT count(*) FROM fast_emp4000 WHERE home_base && '(1000,1000,0,0)'::box;
|
||||
count
|
||||
-------
|
||||
2
|
||||
(1 row)
|
||||
|
||||
DROP INDEX rect2ind;
|
||||
--
|
||||
-- GiST (rtree-equivalent opclasses only)
|
||||
--
|
||||
CREATE INDEX grect2ind ON fast_emp4000 USING gist (home_base);
|
||||
|
@ -798,18 +798,6 @@ FROM pg_amop p1 LEFT JOIN pg_opclass p2 ON amopclaid = p2.oid
|
||||
ORDER BY 1, 2, 3;
|
||||
opcamid | amopstrategy | oprname
|
||||
---------+--------------+---------
|
||||
402 | 1 | <<
|
||||
402 | 2 | &<
|
||||
402 | 3 | &&
|
||||
402 | 4 | &>
|
||||
402 | 5 | >>
|
||||
402 | 6 | ~=
|
||||
402 | 7 | ~
|
||||
402 | 8 | @
|
||||
402 | 9 | &<|
|
||||
402 | 10 | <<|
|
||||
402 | 11 | |>>
|
||||
402 | 12 | |&>
|
||||
403 | 1 | <
|
||||
403 | 1 | ~<~
|
||||
403 | 2 | <=
|
||||
@ -834,7 +822,7 @@ ORDER BY 1, 2, 3;
|
||||
783 | 10 | <<|
|
||||
783 | 11 | |>>
|
||||
783 | 12 | |&>
|
||||
(36 rows)
|
||||
(24 rows)
|
||||
|
||||
-- Check that all operators linked to by opclass entries have selectivity
|
||||
-- estimators. This is not absolutely required, but it seems a reasonable
|
||||
|
@ -67,42 +67,6 @@ CREATE INDEX onek2_u2_prtl ON onek2 USING btree(unique2 int4_ops)
|
||||
CREATE INDEX onek2_stu1_prtl ON onek2 USING btree(stringu1 name_ops)
|
||||
where onek2.stringu1 >= 'J' and onek2.stringu1 < 'K';
|
||||
|
||||
--
|
||||
-- RTREE
|
||||
--
|
||||
-- rtrees use a quadratic page-splitting algorithm that takes a
|
||||
-- really, really long time. we don't test all rtree opclasses
|
||||
-- in the regression test (we check them using the sequoia 2000
|
||||
-- benchmark).
|
||||
--
|
||||
CREATE INDEX rect2ind ON fast_emp4000 USING rtree (home_base);
|
||||
|
||||
SET enable_seqscan = ON;
|
||||
SET enable_indexscan = OFF;
|
||||
SET enable_bitmapscan = OFF;
|
||||
|
||||
SELECT * FROM fast_emp4000
|
||||
WHERE home_base @ '(200,200),(2000,1000)'::box
|
||||
ORDER BY home_base USING <;
|
||||
|
||||
SELECT count(*) FROM fast_emp4000 WHERE home_base && '(1000,1000,0,0)'::box;
|
||||
|
||||
SET enable_seqscan = OFF;
|
||||
SET enable_indexscan = ON;
|
||||
SET enable_bitmapscan = ON;
|
||||
|
||||
-- there's no easy way to check that these commands actually use
|
||||
-- the index, unfortunately. (EXPLAIN would work, but its output
|
||||
-- changes too often for me to want to put an EXPLAIN in the test...)
|
||||
SELECT * FROM fast_emp4000
|
||||
WHERE home_base @ '(200,200),(2000,1000)'::box
|
||||
ORDER BY home_base USING <;
|
||||
|
||||
SELECT count(*) FROM fast_emp4000 WHERE home_base && '(1000,1000,0,0)'::box;
|
||||
|
||||
DROP INDEX rect2ind;
|
||||
|
||||
|
||||
--
|
||||
-- GiST (rtree-equivalent opclasses only)
|
||||
--
|
||||
|
@ -212,9 +212,6 @@ index types<br />
|
||||
<a id="access_nbtree" name="access_nbtree"></a> <a
|
||||
href="../../backend/access/nbtree">access/nbtree</a> - Lehman and
|
||||
Yao's btree management algorithm<br />
|
||||
<a id="access_rtree" name="access_rtree"></a> <a
|
||||
href="../../backend/access/rtree">access/rtree</a> - used for
|
||||
indexing of 2-dimensional data<br />
|
||||
<a id="access_transam" name="access_transam"></a> <a
|
||||
href="../../backend/access/transam">access/transam</a> -
|
||||
transaction manager (BEGIN/ABORT/COMMIT)<br />
|
||||
|
Reference in New Issue
Block a user